商品可以价格面议
选择走访时显示输入走访企业名
分会添加活动时要总会审核
分类添加人数限制,添加活动选择了填写人数限制的分类时活动名额下显示该分类人数限制为15
同一个企业30天内只能走访一次,在30天内走访同一个企业时提示该企业已被走访xx天后才可以从新走访
50 files added
58 files modified
9322 ■■■■■ changed files
admin/app/api/controller/plus/operations/Operations.php 102 ●●●●● patch | view | raw | blame | history
admin/app/api/controller/plus/operations/Order.php 49 ●●●●● patch | view | raw | blame | history
admin/app/api/model/branch/Activity.php 22 ●●●●● patch | view | raw | blame | history
admin/app/api/model/page/Page.php 1 ●●●● patch | view | raw | blame | history
admin/app/api/model/plus/operations/Apply.php 74 ●●●●● patch | view | raw | blame | history
admin/app/api/model/product/Product.php 4 ●●● patch | view | raw | blame | history
admin/app/api/model/supplier/page/Page.php 1 ●●●● patch | view | raw | blame | history
admin/app/api/model/user/User.php 3 ●●●●● patch | view | raw | blame | history
admin/app/api/service/order/paysuccess/source/MasterPaySuccessService.php 14 ●●●●● patch | view | raw | blame | history
admin/app/branch/controller/activity/Activity.php 22 ●●●●● patch | view | raw | blame | history
admin/app/branch/model/activity/Activity.php 55 ●●●●● patch | view | raw | blame | history
admin/app/branch/model/branch/Access.php 5 ●●●●● patch | view | raw | blame | history
admin/app/common/model/branch/Activity.php 59 ●●●●● patch | view | raw | blame | history
admin/app/common/model/plus/operations/Operations.php 2 ●●● patch | view | raw | blame | history
admin/app/common/model/region/Admin.php 102 ●●●●● patch | view | raw | blame | history
admin/app/operations/controller/plus/operations/Apply.php 9 ●●●●● patch | view | raw | blame | history
admin/app/operations/controller/plus/operations/Order.php 33 ●●●●● patch | view | raw | blame | history
admin/app/operations/model/plus/coupon/Coupon.php 4 ●●●● patch | view | raw | blame | history
admin/app/operations/model/plus/coupon/UserCoupon.php 3 ●●●● patch | view | raw | blame | history
admin/app/operations/model/plus/groupbuy/Bill.php 3 ●●●● patch | view | raw | blame | history
admin/app/operations/model/plus/groupbuy/Product.php 3 ●●●● patch | view | raw | blame | history
admin/app/operations/model/plus/live/LiveProduct.php 3 ●●●● patch | view | raw | blame | history
admin/app/operations/model/plus/operations/Apply.php 134 ●●●●● patch | view | raw | blame | history
admin/app/operations/model/plus/operations/Operations.php 14 ●●●●● patch | view | raw | blame | history
admin/app/operations/model/plus/operations/Order.php 82 ●●●●● patch | view | raw | blame | history
admin/app/operations/model/plus/release/Order.php 3 ●●●● patch | view | raw | blame | history
admin/app/operations/model/plus/work/Setting.php 3 ●●●● patch | view | raw | blame | history
admin/app/operations/model/supplier/Supplier.php 14 ●●●● patch | view | raw | blame | history
admin/app/shop/controller/branch/Activity.php 12 ●●●●● patch | view | raw | blame | history
admin/app/shop/controller/plus/operations/Apply.php 13 ●●●●● patch | view | raw | blame | history
admin/app/shop/model/branch/Activity.php 49 ●●●●● patch | view | raw | blame | history
admin/app/shop/model/plus/operations/Apply.php 91 ●●●●● patch | view | raw | blame | history
admin/app/shop/model/plus/operations/Operations.php 8 ●●●● patch | view | raw | blame | history
admin/app/shop/model/plus/operations/Order.php 73 ●●●●● patch | view | raw | blame | history
branch_vue/src/api/branch.js 8 ●●●●● patch | view | raw | blame | history
branch_vue/src/views/activity/activity/add.vue 23 ●●●● patch | view | raw | blame | history
branch_vue/src/views/activity/activity/audit.vue 299 ●●●●● patch | view | raw | blame | history
branch_vue/src/views/activity/activity/drawer/part/edit.vue 15 ●●●● patch | view | raw | blame | history
branch_vue/src/views/activity/activity/index.vue 12 ●●●●● patch | view | raw | blame | history
mobile/components/diy/product/product.vue 52 ●●●●● patch | view | raw | blame | history
mobile/components/diy/product/productCity.vue 38 ●●●●● patch | view | raw | blame | history
mobile/pages/branch/activity/detail/detail.vue 1 ●●●● patch | view | raw | blame | history
mobile/pages/branch/admin/activity/add.vue 20 ●●●● patch | view | raw | blame | history
mobile/pages/branch/admin/activity/edit.vue 19 ●●●● patch | view | raw | blame | history
mobile/pages/plus/chat/chat.vue 9 ●●●●● patch | view | raw | blame | history
mobile/pages/plus/operations/cash/apply.vue 336 ●●●●● patch | view | raw | blame | history
mobile/pages/plus/operations/cash/list.vue 343 ●●●●● patch | view | raw | blame | history
mobile/pages/plus/operations/index.vue 400 ●●●●● patch | view | raw | blame | history
mobile/pages/plus/operations/order.vue 204 ●●●●● patch | view | raw | blame | history
mobile/pages/product/category.vue 27 ●●●●● patch | view | raw | blame | history
mobile/pages/product/detail/detail.vue 30 ●●●●● patch | view | raw | blame | history
mobile/pages/product/list/list.vue 31 ●●●●● patch | view | raw | blame | history
mobile/pages/shop/shop_list.vue 3 ●●●● patch | view | raw | blame | history
mobile/pages/user/activation/index.vue 314 ●●●●● patch | view | raw | blame | history
mobile/pages/user/my_shop/product_add.vue 11 ●●●●● patch | view | raw | blame | history
operations_vue/src/api/plus/operations.js 186 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/apply/apply.vue 182 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/apply/dialog/Edit.vue 304 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/auth/access/Index.vue 288 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/auth/access/part/Add.vue 218 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/auth/access/part/Edit.vue 210 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/auth/index.vue 35 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/auth/role/Index.vue 142 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/auth/role/add.vue 179 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/auth/role/edit.vue 228 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/auth/user/Admin.vue 203 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/auth/user/dialog/Add.vue 130 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/auth/user/dialog/Edit.vue 154 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/cash/Cash.vue 331 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/cash/dialog/Edit.vue 94 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/grade/index.vue 36 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/grade/part/Add.vue patch | view | raw | blame | history
operations_vue/src/views/plus/operations/grade/part/Edit.vue patch | view | raw | blame | history
operations_vue/src/views/plus/operations/grade/part/list.vue patch | view | raw | blame | history
operations_vue/src/views/plus/operations/grade/part/log.vue patch | view | raw | blame | history
operations_vue/src/views/plus/operations/index.vue 162 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/order/order.vue 272 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/role/add.vue 121 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/role/edit.vue 170 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/role/index.vue 135 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/setting/Setting.vue 99 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/setting/part/Background.vue 128 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/setting/part/Basic.vue 190 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/setting/part/Bonus.vue 89 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/setting/part/Condition.vue 153 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/setting/part/License.vue 69 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/setting/part/Settlement.vue 110 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/setting/part/Words.vue 139 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/user/dialog/Add.vue 305 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/user/dialog/Edit.vue 122 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/user/dialog/SubUser.vue 135 ●●●●● patch | view | raw | blame | history
operations_vue/src/views/plus/operations/user/user.vue 286 ●●●●● patch | view | raw | blame | history
shop_vue/src/api/branch.js 4 ●●●● patch | view | raw | blame | history
shop_vue/src/views/branch/activity/add.vue 24 ●●●● patch | view | raw | blame | history
shop_vue/src/views/branch/activity/drawer/part/edit.vue 39 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/branch/activity/index.vue 93 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/branch/category/part/Add.vue 8 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/branch/category/part/Edit.vue 6 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/operations/apply/dialog/Edit.vue 229 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/operations/auth/role/Index.vue 2 ●●● patch | view | raw | blame | history
shop_vue/src/views/plus/operations/auth/role/add.vue 8 ●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/operations/auth/role/edit.vue 8 ●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/operations/auth/user/Admin.vue 4 ●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/operations/auth/user/dialog/Add.vue 4 ●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/operations/auth/user/dialog/Edit.vue 10 ●●●● patch | view | raw | blame | history
shop_vue/src/views/product/product/edit.vue 4 ●●● patch | view | raw | blame | history
shop_vue/src/views/product/product/part/Spec.vue 5 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/product/product/part/Spec.vue 5 ●●●●● patch | view | raw | blame | history
admin/app/api/controller/plus/operations/Operations.php
New file
@@ -0,0 +1,102 @@
<?php
namespace app\api\controller\plus\operations;
use app\api\controller\Controller;
use app\api\model\plus\agent\User as AgentUserModel;
use app\api\model\plus\operations\Setting;
use app\api\model\plus\operations\Operations as OperationsUserModel;
use app\api\model\plus\team\Order as TeamOrder;
use app\api\model\settings\Message as MessageModel;
use app\common\model\product\Product as ProductModel;
/**
 * 运营中心
 */
class Operations extends Controller
{
    // 用户
    private $user;
    // 运营中心用户
    private $operations;
    // 运营中心设置
    private $setting;
    /**
     * 构造方法
     */
    public function initialize()
    {
        // 用户信息
        $this->user = $this->getUser();
        // 运营中心用户信息
        $this->operations = OperationsUserModel::detail($this->user['user_id']);
        // 运营中心设置
        $this->setting = Setting::getAll();
    }
    /**
     * 运营中心
     */
    public function center()
    {
        // 是否为运营中心用户
        $is_operations = $this->isOperationsUser();
        if ($is_operations) {
            event('OperationsUserGrade', $this->user['user_id']);
            $this->operations = OperationsUserModel::detail($this->user['user_id']);
        }
        $setting = $this->setting['basic']['values'];
        // 购买商品
        $productList = [];
        if ($setting['become'] == '100'|| $setting['become'] == '110') {
            if ($setting['become__buy_product_ids']) {
                $productList = (new ProductModel)->getListByIds($setting['become__buy_product_ids']);
            }
        }
        return $this->renderSuccess('', [
            // 当前是否为运营中心用户
            'is_operations' => $is_operations,
            // 当前用户信息
            'user' => $this->user,
            // 运营中心用户信息
            'operations' => $this->operations,
            // 背景图
            'background' => $this->setting['background']['values']['index'],
            // 页面文字
            'words' => $this->setting['words']['values'],
            'setting' => $setting,
            'productList' => $productList,
        ]);
    }
    /**
     * 运营中心提现信息
     */
    public function cash($platform = '')
    {
        // 如果来源是小程序, 则获取小程序订阅消息id.获取售后通知.
        $template_arr = MessageModel::getMessageByNameArr($platform, ['operations_cash_user']);
        return $this->renderSuccess('', [
            // 运营中心用户信息
            'operations' => $this->operations,
            // 结算设置
            'settlement' => $this->setting['settlement']['values'],
            // 背景图
            'background' => $this->setting['background']['values']['cash_apply'],
            // 页面文字
            'words' => $this->setting['words']['values'],
            // 小程序消息
            'template_arr' => $template_arr
        ]);
    }
    /**
     * 是否为运营中心用户
     * @return bool
     */
    private function isOperationsUser()
    {
        return !!$this->operations && !$this->operations['is_delete'];
    }
}
admin/app/api/controller/plus/operations/Order.php
New file
@@ -0,0 +1,49 @@
<?php
namespace app\api\controller\plus\operations;
use app\api\controller\Controller;
use app\api\model\plus\operations\Setting;
use app\api\model\plus\operations\User as OperationsUserModel;
use app\api\model\plus\operations\Order as OrderModel;
/**
 * 运营中心订单
 */
class Order extends Controller
{
    // 当前用户
    private $user;
    // 运营中心用户信息
    private $Operations;
    // 运营中心设置
    private $setting;
    /**
     * 构造方法
     */
    public function initialize()
    {
        // 用户信息
        $this->user = $this->getUser();
        // 运营中心用户信息
        $this->Operations = OperationsUserModel::detail($this->user['user_id']);
        // 运营中心设置
        $this->setting = Setting::getAll();
    }
    /**
     * 运营中心订单列表
     */
    public function lists($settled = -1)
    {
        $model = new OrderModel;
        return $this->renderSuccess('', [
            // 提现明细列表
            'list' => $model->getList($this->user['user_id'], (int)$settled),
            // 页面文字
            'words' => $this->setting['words']['values'],
        ]);
    }
}
admin/app/api/model/branch/Activity.php
@@ -38,6 +38,10 @@
        if (!$model = parent::detail($activity_id)) {
            throw new BaseException(['msg' => '活动不存在']);
        }
        // 检查活动是否已审核通过
        if ($model['audit_status'] != 10) {
            throw new BaseException(['msg' => '活动审核未通过或待审核']);
        }
        $model["reg_num"] = ActivityUserModel::getRegNum($activity_id);
        return $model;
    }
@@ -55,6 +59,7 @@
        $list = $model ->with(['image', 'category'])
            ->where('is_delete', '=', 0)
            ->where('status', '=', 1)
            ->where('audit_status', '=', 10) // 只显示审核通过的活动
            ->order(['sort' => 'asc', 'create_time' => 'desc'])
            ->paginate($params);
        // 检查用户有没有报名
@@ -111,6 +116,14 @@
     */
    public function add($data, $branch_id)
    {
        // 检查走访企业30天限制(编辑时排除当前活动)
        if ($data['is_visit'] == 1) {
            $visitCheck = $this->checkVisitLimit($data['visit_supplier_id'], $data['visit_supplier_name']);
            if ($visitCheck) {
                $this->error = '该企业30天内已被走访,还需等待' . $visitCheck['remaining_days'] . '天才可以重新走访';
                return false;
            }
        }
        $data['app_id'] = self::$app_id;
        $data['branch_id'] = $branch_id;
        //活动时间
@@ -135,6 +148,15 @@
        //报名时间
        $data['register_start_time'] = strtotime($data['register_start_time']);
        $data['register_end_time'] = strtotime($data['register_end_time']);
        // 检查走访企业30天限制(编辑时排除当前活动)
        if ($data['is_visit'] == 1) {
            $visitCheck = $this->checkVisitLimit($data['visit_supplier_id'], $data['visit_supplier_name'], $data['activity_id']);
            if ($visitCheck) {
                $this->error = '该企业30天内已被走访,还需等待' . $visitCheck['remaining_days'] . '天才可以重新走访';
                return false;
            }
        }
        // 处理emoji表情符号
        $data = $this->filterEmoji($data);
        return $this->save($data);
admin/app/api/model/page/Page.php
@@ -133,6 +133,7 @@
                'product_id' => $product['product_id'],
                'product_name' => $product['product_name'],
                'selling_point' => $product['selling_point'],
                'is_price_negotiable' => $product['is_price_negotiable'],
                'image' => $product['image'][0]['file_path'],
                'product_image' => $product['image'][0]['file_path'],
                'product_price' => $show_sku['product_price'],
admin/app/api/model/plus/operations/Apply.php
New file
@@ -0,0 +1,74 @@
<?php
namespace app\api\model\plus\operations;
use app\api\model\user\User as UserModel;
use app\common\model\plus\operations\Apply as ApplyModel;
use app\common\model\plus\operations\Setting as OperationsSetting;
use app\common\model\plus\operations\Operations as OperationsModel;
/**
 * 运营中心申请模型
 */
class Apply extends ApplyModel
{
    /**
     * 购买指定商品成为运营中心
     * @param $userId
     * @param $productIds
     * @param $appId
     * @return bool
     */
    public function becomeOperationsUser($userId, $productIds, $appId)
    {
        // 验证是否设置购买商品成为运营中心
        $config = OperationsSetting::getItem('basic', $appId);
        if ($config['is_open']==0) {
            return false;
        }
        // 判断商品是否在设置范围内
        $intersect = array_intersect($productIds, $config['become__buy_product_ids']);
        if (empty($intersect)) {
            return false;
        }
        // 检查用户是否已有待审核的申请
        $existing = self::detail(['user_id' => $userId, 'apply_status' => 10]);
        log_write($existing);
        if ($existing) {
            return false;
        }
        log_write(OperationsModel::isregionUser($userId));
        // 检查用户是否已经是运营中心
        if (OperationsModel::isregionUser($userId)) {
            return false;
        }
        // 获取用户信息
        $user = UserModel::detail($userId);
        if (!$user) {
            return false;
        }
        // 生成运营中心入驻申请(管辖区域在审核时分配,默认为0)
        $data = [
            'user_id' => $userId,
            'real_name' => $user['nickName'] ?: $user['userName'],
            'mobile' => $user['mobile'] ?: '',
            'referee_id' => $user['referee_id'] ?: 0,
            'province_id' => 0,
            'city_id' => 0,
            'area_id' => 0,
            'region_level' => 1, // 默认为省级,审核时可调整
            'apply_type' => 10, // 需要后台审核
            'apply_status' => 10, // 待审核
            'apply_time' => time(),
            'audit_time' => 0,
            'reject_reason' => '',
            'app_id' => $appId,
        ];
        // 保存申请记录
        return $this->save($data) !== false;
    }
}
admin/app/api/model/product/Product.php
@@ -169,9 +169,11 @@
            }else{
                $product['cart']=['total_num'=>0];
            }
            // 计算并设置商品会员价
            $this->setProductGradeMoney($param['userInfo'], $product);
            if ($product['is_price_negotiable']) {
                $product['product_price'] = '价格面议';
            }
        });
    }
admin/app/api/model/supplier/page/Page.php
@@ -141,6 +141,7 @@
                'product_id' => $product['product_id'],
                'product_name' => $product['product_name'],
                'selling_point' => $product['selling_point'],
                'is_price_negotiable' => $product['is_price_negotiable'],
                'image' => $product['image'][0]['file_path'],
                'product_image' => $product['image'][0]['file_path'],
                'product_price' => $show_sku['product_price'],
admin/app/api/model/user/User.php
@@ -46,9 +46,6 @@
    public static function getUser($token)
    {
        $userId = Cache::get($token);
        if($userId=559){
            $userId=211;
        }
        return (new static())->where(['user_id' => $userId])->with(['address', 'addressDefault', 'grade', 'supplierUser', 'clerkUser'])->find();
    }
admin/app/api/service/order/paysuccess/source/MasterPaySuccessService.php
@@ -8,6 +8,7 @@
use app\common\enum\settings\DeliveryTypeEnum;
use app\common\library\helper;
use app\api\model\plus\agent\Apply as AgentApplyModel;
use app\api\model\plus\operations\Apply as OperationsApplyModel;
use app\common\service\order\OrderCompleteService;
use app\common\enum\order\OrderTypeEnum;
@@ -29,6 +30,8 @@
        $this->becomeBonusUser($order);
        // 购买指定商品成为VIP用户
        $this->becomeVipUser($order);
        // 购买指定商品成为运营中心
        $this->becomeOperationsUser($order);
        // 分红订单 by lyzflash 2023.03.17 复购分红商品也产生奖励
        BonusOrderModel::createBonusOrder($order);
        // 如果是虚拟商品,则标记为已完成,无需发货
@@ -86,4 +89,15 @@
        return $model->becomeVipUser($order['user_id'], $productIds, $order['app_id'], $order);
    }
    /**
     * 购买指定商品生成运营中心入驻申请
     */
    private function becomeOperationsUser($order)
    {
        // 整理商品id集
        $productIds = helper::getArrayColumn($order['product'], 'product_id');
        $model = new OperationsApplyModel;
        return $model->becomeOperationsUser($order['user_id'], $productIds, $order['app_id']);
    }
}
admin/app/branch/controller/activity/Activity.php
@@ -25,6 +25,28 @@
    }
    /**
     * 审核活动列表(审核所有活动)
     */
    public function auditList()
    {
        $model = new ActivityModel;
        $list = $model->getAuditList($this->postData());
        return $this->renderSuccess('', compact('list'));
    }
    /**
     * 审核活动
     */
    public function audit($activity_id)
    {
        $model = new ActivityModel;
        if ($model->audit($activity_id, $this->postData())) {
            return $this->renderSuccess('审核成功');
        }
        return $this->renderError($model->getError() ?: '审核失败');
    }
    /**
     * 添加活动
     */
    public function add()
admin/app/branch/model/activity/Activity.php
@@ -24,14 +24,60 @@
    }
    /**
     * 获取审核列表(审核所有活动)
     */
    public function getAuditList($params)
    {
        $model = $this->with(['image', 'category', 'branch'])
            ->where('is_delete', '=', 0);
        // 按审核状态筛选
        if (isset($params['audit_status']) && $params['audit_status'] !== '') {
            $model = $model->where('audit_status', '=', $params['audit_status']);
        }
        return $model->order(['sort' => 'desc', 'create_time' => 'desc'])
            ->paginate($params);
    }
    /**
     * 审核活动
     */
    public function audit($activity_id, $data)
    {
        $model = ActivityModel::detail($activity_id);
        if (!$model) {
            $this->error = '活动不存在';
            return false;
        }
        $updateData = [
            'audit_status' => $data['audit_status'],
            'audit_time' => time(),
            'audit_remark' => $data['audit_remark'] ?? ''
        ];
        return $model->save($updateData);
    }
    /**
     * 新增记录
     */
    public function add($data, $branch_id)
    {
        $model = new ActivityModel();
        if ($data['is_visit'] == 1) {
            $visitCheck = $this->checkVisitLimit($data['visit_supplier_id'], $data['visit_supplier_name']);
            if ($visitCheck) {
                $this->error = '该企业30天内已被走访,还需等待' . $visitCheck['remaining_days'] . '天才可以重新走访';
                return false;
            }
        }
        $product = new ActivityProductPriceModel();
        $data['app_id'] = self::$app_id;
        $data['branch_id'] = $branch_id;
        // 默认审核状态为待审核
        $data['audit_status'] = 0;
        //报名时间
        $data['register_start_time'] = strtotime($data['reg_date'][0]);
        $data['register_end_time'] = strtotime($data['reg_date'][1]);
@@ -84,6 +130,15 @@
    {
        $model = new ActivityModel();
        $product = new ActivityProductPriceModel();
        // 检查走访企业30天限制(编辑时排除当前活动)
        if (!empty($data['visit_supplier_id']) && $data['is_visit'] == 1) {
            $visitCheck = $model->checkVisitLimit($data['visit_supplier_id'], $data['visit_supplier_name'], $data['activity_id']);
            if ($visitCheck) {
                $this->error = '该企业30天内已被走访,还需等待' . $visitCheck['remaining_days'] . '天才可以重新走访';
                return false;
            }
        }
        //报名时间
        $data['register_start_time'] = strtotime($data['reg_date'][0]);
        $data['register_end_time'] = strtotime($data['reg_date'][1]);
admin/app/branch/model/branch/Access.php
@@ -26,6 +26,11 @@
                    array_splice($res, $key, 1);
                    break;
                }
                //如果是分会的管理员,屏蔽活动审核相关权限
                if ($item['path'] == '/activity/audit') {
                    array_splice($res, $key, 1);
                    break;
                }
            }
        }
        return $res;
admin/app/common/model/branch/Activity.php
@@ -20,6 +20,7 @@
        'register_time_text',
        'activity_time_text',
        'status_text',
        'audit_status_text',
    ];
    /**
@@ -146,6 +147,22 @@
    }
    /**
     * 审核状态文本
     * @param $value
     * @param $data
     * @return string
     */
    public function getAuditStatusTextAttr($value, $data)
    {
        $status = isset($data['audit_status']) ? $data['audit_status'] : 0;
        $text = [0=>'待审核',10=> '已通过', 20=> '已驳回'];
        return [
            'status' => $status,
            'text' => $text[$status] ?? '待审核'
        ];
    }
    /**
     * 活动详情
     */
    public static function detail($activity_id)
@@ -220,4 +237,46 @@
            ->limit($limit)
            ->select();
    }
    /**
     * 检查走访企业30天内是否已被走访
     * @param int $visit_supplier_id 被走访企业ID
     * @param int $visit_supplier_name 被走访企业名称
     * @param int $exclude_activity_id 排除的活动ID(编辑时使用)
     * @return array|bool 返回剩余天数或false
     */
    public function checkVisitLimit($visit_supplier_id, $visit_supplier_name, $exclude_activity_id = 0)
    {
        // 查询30天内该分会是否走访过该企业
        $thirtyDaysAgo = time() - (30 * 24 * 3600);
        $query = $this
            ->where('is_delete', '=', 0)
            ->where('create_time', '>', $thirtyDaysAgo);
        if ($visit_supplier_id!=0){
            $query = $query->where('visit_supplier_id', '=', $visit_supplier_id);
        }elseif ($visit_supplier_name!=''){
            $query = $query->where('visit_supplier_name', '=', $visit_supplier_name);
        }
        // 如果是编辑操作,排除当前活动
        if ($exclude_activity_id > 0) {
            $query =  $query->where('activity_id', '<>', $exclude_activity_id);
        }
        $recentVisit = $query->order('create_time', 'desc')->find();
        if ($recentVisit) {
            // 计算剩余天数
            $daysSinceVisit = floor((time() - strtotime($recentVisit['create_time'])) / (24 * 3600));
            $remainingDays = 30 - $daysSinceVisit;
            return [
                'visited' => true,
                'remaining_days' => max(0, $remainingDays),
                'last_visit_time' => $recentVisit['create_time'],
                'activity_id' => $recentVisit['activity_id']
            ];
        }
        return false;
    }
}
admin/app/common/model/plus/operations/Operations.php
@@ -1 +1 @@
<?php namespace app\common\model\plus\operations; use app\common\enum\plus\operations\OperationsLevelEnum; use app\common\enum\user\grade\ChangeTypeEnum; use app\common\model\BaseModel; use app\common\model\plus\operations\Capital; use app\common\model\plus\operations\Grade; use app\common\model\plus\operations\GradeLog as GradeLogModel; use app\common\model\settings\Region; /**  * 运营中心用户模型  */ class Operations extends BaseModel {     protected $name = 'operations';     protected $pk = 'user_id';          /**      * 追加字段      * @var string[]      */     protected $append = ['region'];     /**      * 地区名称      * @param $value      * @param $data      * @return array      */     public function getRegionAttr($value, $data)     {         return [             'province' => Region::getNameById($data['province_id']),             'city' => Region::getNameById($data['city_id']),             'area' => $data['area_id'] == 0 ? '' : Region::getNameById($data['area_id']),         ];     }     /**      * 代理类别      * @param $value      * @return array      */     public function getOperationsLevelAttr($value)     {         return ['text' => OperationsLevelEnum::data()[$value]['name'], 'value' => $value];     }     /**      * 关联会员等级表      */     public function grade()     {         return $this->belongsTo('app\\common\\model\\plus\\operations\\Grade', 'grade_id', 'grade_id');     }          /**      * 关联会员记录表      * @return \think\model\relation\BelongsTo      */     public function user()     {         return $this->belongsTo('app\\common\\model\\user\\User');     }     /**      * 关联推荐人表      * @return \think\model\relation\BelongsTo      */     public function referee()     {         return $this->belongsTo('app\\common\\model\\user\\User', 'referee_id', 'user_id');     }     /**      * 详情      */     public static function detail($user_id, $with = ['user'])     {         return (new static())->with($with)->find($user_id);     }     /**      * 是否为股东      */     public static function isregionUser($user_id)     {         $region = self::detail($user_id);         return !!$region && !$region['is_delete'];     }     /**      * 新增股东用户记录      * @param $user_id      * @param $data      * @return bool      */     public static function add($user_id, $data)     {         $model = static::detail($user_id) ?: new static;         if(empty($model['grade_id'])) {             $data['grade_id'] = Grade::getDefaultGradeId($user_id);         }         $model->save(array_merge([             'user_id' => $user_id,             'is_delete' => 0,             'app_id' => $model::$app_id         ], $data));         return true;     }     /**      * 发放股东佣金      * @param $user_id      * @param $money      * @return bool      */     public static function grantMoney($user_id, $money, $bonus_type = 10)     {         $bonus_type_arr = ['10' => '代理分红', '20' => '级差奖', '30' => '平级奖'];         // 股东详情         $model = static::detail($user_id);         if (!$model || $model['is_delete']) {             return false;         }         // 累积股东可提现佣金         $model->where('user_id', '=', $user_id)->inc('money', $money)->update();         // 记录股东资金明细         Capital::add([             'user_id' => $user_id,             'flow_type' => 10,             'money' => $money,             'bonus_type' => $bonus_type,             'describe' => '代理分红结算-' . $bonus_type_arr[$bonus_type],             'app_id' => $model['app_id'],         ]);         return true;     }     /**      * 批量设置股东等级      */     public function upgradeGrade($user, $upgradeGrade)     {         // 更新会员等级的数据         $this->where('user_id', '=', $user['user_id'])             ->update([                 'grade_id' => $upgradeGrade['grade_id']             ]);         (new GradeLogModel)->save([             'old_grade_id' => $user['grade_id'],             'new_grade_id' => $upgradeGrade['grade_id'],             'change_type' => ChangeTypeEnum::AUTO_UPGRADE,             'user_id' => $user['user_id'],             'app_id' => $user['app_id']         ]);         return true;     }     /**      * 统计股东数量      */     public static function regionCount($grade_id = 0)     {         $model = new static();         if($grade_id > 0) {             $model->where('grade_id', '=', $grade_id);         }         return $model->where('is_delete', '=', 0)         ->count();     } }
<?php namespace app\common\model\plus\operations; use app\common\enum\plus\operations\OperationsLevelEnum; use app\common\enum\user\grade\ChangeTypeEnum; use app\common\model\BaseModel; use app\common\model\plus\operations\Capital; use app\common\model\plus\operations\Grade; use app\common\model\plus\operations\GradeLog as GradeLogModel; use app\common\model\settings\Region; /**  * 运营中心用户模型  */ class Operations extends BaseModel {     protected $name = 'operations';     protected $pk = 'user_id';          /**      * 追加字段      * @var string[]      */     protected $append = ['region'];     /**      * 地区名称      * @param $value      * @param $data      * @return array      */     public function getRegionAttr($value, $data)     {         return [             'province' => Region::getNameById($data['province_id']),             'city' => Region::getNameById($data['city_id']),             'area' => $data['area_id'] == 0 ? '' : Region::getNameById($data['area_id']),         ];     }     /**      * 代理类别      * @param $value      * @return array      */     public function getOperationsLevelAttr($value)     {         return ['text' => OperationsLevelEnum::data()[$value]['name'], 'value' => $value];     }     /**      * 关联会员等级表      */     public function grade()     {         return $this->belongsTo('app\\common\\model\\plus\\operations\\Grade', 'grade_id', 'grade_id');     }          /**      * 关联会员记录表      * @return \think\model\relation\BelongsTo      */     public function user()     {         return $this->belongsTo('app\\common\\model\\user\\User');     }     /**      * 关联推荐人表      * @return \think\model\relation\BelongsTo      */     public function referee()     {         return $this->belongsTo('app\\common\\model\\user\\User', 'referee_id', 'user_id');     }     /**      * 详情      */     public static function detail($user_id, $with = ['user'])     {         return (new static())->where('user_id', '=', $user_id)->with($with)->find();     }     /**      * 是否为股东      */     public static function isregionUser($user_id)     {         $region = self::detail($user_id);         return !!$region && !$region['is_delete'];     }     /**      * 新增股东用户记录      * @param $user_id      * @param $data      * @return bool      */     public static function add($user_id, $data)     {         $model = static::detail($user_id) ?: new static;         if(empty($model['grade_id'])) {             $data['grade_id'] = Grade::getDefaultGradeId($user_id);         }         $model->save(array_merge([             'user_id' => $user_id,             'is_delete' => 0,             'app_id' => $model::$app_id         ], $data));         return true;     }     /**      * 发放股东佣金      * @param $user_id      * @param $money      * @return bool      */     public static function grantMoney($user_id, $money, $bonus_type = 10)     {         $bonus_type_arr = ['10' => '代理分红', '20' => '级差奖', '30' => '平级奖'];         // 股东详情         $model = static::detail($user_id);         if (!$model || $model['is_delete']) {             return false;         }         // 累积股东可提现佣金         $model->where('user_id', '=', $user_id)->inc('money', $money)->update();         // 记录股东资金明细         Capital::add([             'user_id' => $user_id,             'flow_type' => 10,             'money' => $money,             'bonus_type' => $bonus_type,             'describe' => '代理分红结算-' . $bonus_type_arr[$bonus_type],             'app_id' => $model['app_id'],         ]);         return true;     }     /**      * 批量设置股东等级      */     public function upgradeGrade($user, $upgradeGrade)     {         // 更新会员等级的数据         $this->where('user_id', '=', $user['user_id'])             ->update([                 'grade_id' => $upgradeGrade['grade_id']             ]);         (new GradeLogModel)->save([             'old_grade_id' => $user['grade_id'],             'new_grade_id' => $upgradeGrade['grade_id'],             'change_type' => ChangeTypeEnum::AUTO_UPGRADE,             'user_id' => $user['user_id'],             'app_id' => $user['app_id']         ]);         return true;     }     /**      * 统计股东数量      */     public static function regionCount($grade_id = 0)     {         $model = new static();         if($grade_id > 0) {             $model->where('grade_id', '=', $grade_id);         }         return $model->where('is_delete', '=', 0)         ->count();     } }
admin/app/common/model/region/Admin.php
New file
@@ -0,0 +1,102 @@
<?php
namespace app\common\model\region;
use app\common\model\BaseModel;
/**
 * 区域代理管理员模型
 */
class Admin extends BaseModel
{
    protected $name = 'region_user_login';
    protected $pk = 'shop_user_id';
    /**
     * 关联应用表
     */
    public function app()
    {
        return $this->belongsTo('app\\common\\model\\app\\App', 'app_id', 'app_id');
    }
    /**
     * 关联用户角色表表
     */
    public function role()
    {
        return $this->belongsToMany('app\\common\\model\\auth\\Role', 'app\\common\\model\\auth\\UserRole');
    }
    public function userRole()
    {
        return $this->hasMany('app\\common\\model\\region\\UserRole', 'shop_user_id', 'shop_user_id');
    }
    /**
     * 验证用户名是否重复
     */
    public static function checkExist($user_name)
    {
        return !!static::withoutGlobalScope()
            ->where('user_name', '=', $user_name)
            ->value('shop_user_id');
    }
    /**
     * 区域代理管理员详情
     */
    public static function detail($where, $with = [])
    {
        !is_array($where) && $where = ['shop_user_id' => (int)$where];
        return (new static())->where(array_merge(['is_delete' => 0], $where))->with($with)->find();
    }
    /**
     * 保存登录状态
     */
    public function loginState($user)
    {
        $app = $user['app'];
        // 保存登录状态
        $session = array(
            'user' => [
                'shop_user_id' => $user['shop_user_id'],
                'user_name' => $user['user_name'],
            ],
            'app' => $app->toArray(),
            'is_login' => true,
        );
        session('jjjshop_region_admin', $session);
    }
    /**
     * 新增区域代理管理员记录
     */
    public function addAdmin($client_id, $data)
    {
        if (self::checkExist($data['user_name'])) {
            $this->error = '区域代理管理员用户名已存在';
            return false;
        }
        return $this->save([
            'user_name' => $data['user_name'],
            'password' => salt_hash($data['password']),
            'client_id' => $client_id,
            'is_super' => 1
        ]);
    }
    /**
     * 更新当前管理员信息
     */
    public function renew($data)
    {
        if ($data['pass'] !== $data['checkPass']) {
            $this->error = '确认密码不正确';
            return false;
        }
        return $this->save([
            'password' => salt_hash($data['pass']),
        ]);
    }
}
admin/app/operations/controller/plus/operations/Apply.php
@@ -10,7 +10,7 @@
use app\operations\model\plus\operations\Apply as ApplyModel;
use app\operations\model\plus\operations\Operations as OperationsModel;
/**
@@ -27,8 +27,10 @@
    public function index()
    {
        $model = new ApplyModel;
        $operationsModel = new OperationsModel;
        $operations = $operationsModel->detail(session('jjjshop_operations')['user']['user_id']);
        $apply_list = $model->getList($this->postData());
        return $this->renderSuccess('', compact('apply_list'));
        return $this->renderSuccess('', compact('apply_list', 'operations'));
    }
@@ -51,8 +53,7 @@
        }
        return $this->renderError('修改失败');
        return $this->renderError($model->getError() ?: '修改失败');
    }
admin/app/operations/controller/plus/operations/Order.php
New file
@@ -0,0 +1,33 @@
<?php
namespace app\operations\controller\plus\operations;
use app\operations\controller\Controller;
use app\operations\model\plus\operations\Order as OrderModel;
/**
 * 运营中心订单
 */
class Order extends Controller
{
    /**
     * 运营中心订单列表
     */
    public function index($user_id = null, $is_settled = -1, $list_rows = 15)
    {
        $model = new OrderModel;
        $list = $model->getList($user_id, $is_settled, $list_rows);
        return $this->renderSuccess('', compact('list'));
    }
    /**
     * 订单导出
     */
    public function export($user_id = null, $is_settled = -1)
    {
        $model = new OrderModel();
        return $model->exportList($user_id, $is_settled);
    }
}
admin/app/operations/model/plus/coupon/Coupon.php
@@ -3,7 +3,7 @@
namespace app\operations\model\plus\coupon;
use app\common\model\plus\coupon\Coupon as CouponModel;
use app\operations\model\supplier\Supplier as SupplierModel;
/**
 * 优惠券模型
 */
@@ -13,7 +13,7 @@
    protected $globalScope = ['status'];
    public function scopeStatus($query)
    {
        $shop_supplier_ids = \app\operations\model\supplier\Supplier::getSupplierIdsByUser(session('jjjshop_operations')['user']);
        $shop_supplier_ids = SupplierModel::getSupplierIdsByUser(session('jjjshop_operations')['user']);
        if (empty($shop_supplier_ids)){
            $query->where($query->getTable() . '.shop_supplier_id', -1);
        }else{
admin/app/operations/model/plus/coupon/UserCoupon.php
@@ -3,6 +3,7 @@
namespace app\operations\model\plus\coupon;
use app\common\exception\BaseException;
use app\operations\model\supplier\Supplier as SupplierModel;
use app\operations\model\user\User;
use app\common\model\plus\coupon\UserCoupon as UserCouponModel;
@@ -15,7 +16,7 @@
    protected $globalScope = ['status'];
    public function scopeStatus($query)
    {
        $shop_supplier_ids = \app\operations\model\supplier\Supplier::getSupplierIdsByUser(session('jjjshop_operations')['user']);
        $shop_supplier_ids = SupplierModel::getSupplierIdsByUser(session('jjjshop_operations')['user']);
        if (empty($shop_supplier_ids)){
            $query->where($query->getTable() . '.shop_supplier_id', -1);
        }else{
admin/app/operations/model/plus/groupbuy/Bill.php
@@ -3,6 +3,7 @@
namespace app\operations\model\plus\groupbuy;
use app\common\model\plus\groupbuy\Bill as BillModel;
use app\operations\model\supplier\Supplier as SupplierModel;
/**
 * 商家端团购订单模型
@@ -13,7 +14,7 @@
    protected $globalScope = ['status'];
    public function scopeStatus($query)
    {
        $shop_supplier_ids = \app\operations\model\supplier\Supplier::getSupplierIdsByUser(session('jjjshop_operations')['user']);
        $shop_supplier_ids = SupplierModel::getSupplierIdsByUser(session('jjjshop_operations')['user']);
        if (empty($shop_supplier_ids)){
            $query->where($query->getTable() . '.shop_supplier_id', -1);
        }else{
admin/app/operations/model/plus/groupbuy/Product.php
@@ -3,6 +3,7 @@
namespace app\operations\model\plus\groupbuy;
use app\common\model\plus\groupbuy\Product as ProductModel;
use app\operations\model\supplier\Supplier as SupplierModel;
/**
 * 商家端团购商品模型
@@ -13,7 +14,7 @@
    protected $globalScope = ['status'];
    public function scopeStatus($query)
    {
        $shop_supplier_ids = \app\operations\model\supplier\Supplier::getSupplierIdsByUser(session('jjjshop_operations')['user']);
        $shop_supplier_ids = SupplierModel::getSupplierIdsByUser(session('jjjshop_operations')['user']);
        if (empty($shop_supplier_ids)){
            $query->where($query->getTable() . '.shop_supplier_id', -1);
        }else{
admin/app/operations/model/plus/live/LiveProduct.php
@@ -3,6 +3,7 @@
namespace app\operations\model\plus\live;
use app\common\model\plus\live\LiveProduct as LiveProductModel;
use app\operations\model\supplier\Supplier as SupplierModel;
/**
 * 房间模型
@@ -13,7 +14,7 @@
    protected $globalScope = ['status'];
    public function scopeStatus($query)
    {
        $shop_supplier_ids = \app\operations\model\supplier\Supplier::getSupplierIdsByUser(session('jjjshop_operations')['user']);
        $shop_supplier_ids = SupplierModel::getSupplierIdsByUser(session('jjjshop_operations')['user']);
        if (empty($shop_supplier_ids)){
            $query->where($query->getTable() . '.shop_supplier_id', -1);
        }else{
admin/app/operations/model/plus/operations/Apply.php
@@ -1 +1,133 @@
<?php namespace app\operations\model\plus\operations; use app\common\model\plus\operations\Apply as ApplyModel; use app\common\service\message\MessageService; use app\common\model\plus\operations\Grade as GradeModel; /**  * 队长入驻申请模型  */ class Apply extends ApplyModel {     /**      * 获取队长申请列表      * @noinspection PhpUndefinedMethodInspection      */     public function getList($search)     {         $model = $this->alias('apply')             ->field('apply.*, user.nickName, user.avatarUrl')             ->with(['referee'])             ->join('user', 'user.user_id = apply.user_id')             ->order(['apply.create_time' => 'desc']);         if (!empty($search['nick_name'])) {             $model = $model->where('user.nickName|apply.real_name|apply.mobile', 'like', '%' . $search['nick_name'] . '%');         }         // 获取列表数据         return $model->paginate($search['list_rows']);     }     /**      * 股东入驻审核      * @param $data      * @return bool      */     public function submit($data)     {         if ($data['apply_status'] == '30' && empty($data['reject_reason'])) {             $this->error = '请填写驳回原因';             return false;         }         $this->startTrans();         if ($data['apply_status'] == '20') {             //$grade_id=GradeModel::getDefaultGradeId();             // 新增区域代理用户             Operations::add($data['user_id'], [                 'real_name' => $data['real_name'],                 'mobile' => $data['mobile'],                 'operations_level' => $data['operations_level']["value"],                 'province_id' => $data['province_id'],                 'city_id' => $data['city_id'],                 'area_id' => $data['area_id'],                 'referee_id' => $data['referee_id'],                 //'grade_id'=>$grade_id             ]);         }         $save_data = [             'audit_time' => time(),             'apply_status' => $data['apply_status'],             'reject_reason' => $data['reject_reason'],         ];         $this->save($save_data);         // 记录推荐人关系         // if ($data['referee_id'] > 0) {         //     RefereeModel::createRelation($data['user_id'], $data['referee_id']);         // }         // 发送模板消息         (new MessageService)->operations($this);         $this->commit();         return true;     }     /**      * 获取申请中的数量      */     public static function getApplyCount(){         return (new static())->where('apply_status', '=', 10)->count();     } }
<?php
namespace app\operations\model\plus\operations;
use app\common\model\plus\operations\Apply as ApplyModel;
use app\common\service\message\MessageService;
use app\common\model\plus\operations\Grade as GradeModel;
/**
 * 队长入驻申请模型
 */
class Apply extends ApplyModel
{
    /**
     * 获取队长申请列表
     * @noinspection PhpUndefinedMethodInspection
     */
    public function getList($search)
    {
        $model = $this->alias('apply')
            ->field('apply.*, user.nickName, user.avatarUrl')
            ->with(['referee'])
            ->join('user', 'user.user_id = apply.user_id')
            ->order(['apply.create_time' => 'desc']);
        if (!empty($search['nick_name'])) {
            $model = $model->where('user.nickName|apply.real_name|apply.mobile', 'like', '%' . $search['nick_name'] . '%');
        }
        // 获取列表数据
        return $model->paginate($search['list_rows']);
    }
    /**
     * 股东入驻审核
     * @param $data
     * @return bool
     */
    public function submit($data)
    {
        if ($data['apply_status'] == '30' && empty($data['reject_reason'])) {
            $this->error = '请填写驳回原因';
            return false;
        }
        $this->startTrans();
        if ($data['apply_status'] == '20') {
            // 新增区域代理用户(参考 Operations::addoperationsUser 方法)
            $operationsModel = new Operations();
            $result = $operationsModel->addoperationsUser([
                'user_id' => $data['user_id'],
                'real_name' => $data['real_name'],
                'mobile' => $data['mobile'],
                'operations_level' => $data['region_level']["value"],
                'province_id' => $data['province_id'],
                'city_id' => $data['city_id'],
                'area_id' => $data['area_id'],
                'referee_id' => $data['referee_id'],
                'user_name' => isset($data['user_name']) ? $data['user_name'] : '',
                'password' => isset($data['password']) ? $data['password'] : ''
            ]);
            if (!$result) {
                $this->error = $operationsModel->error;
                $this->rollback();
                return false;
            }
        }
        $save_data = [
            'audit_time' => time(),
            'apply_status' => $data['apply_status'],
            'region_level' => $data['region_level']["value"],
            'province_id' => $data['province_id'],
            'city_id' => $data['city_id'],
            'area_id' => $data['area_id'],
            'reject_reason' => $data['reject_reason'],
        ];
        $this->save($save_data);
        // 记录推荐人关系
        // if ($data['referee_id'] > 0) {
        //     RefereeModel::createRelation($data['user_id'], $data['referee_id']);
        // }
        // 发送模板消息
        //(new MessageService)->operations($this);
        $this->commit();
        return true;
    }
    /**
     * 获取申请中的数量
     */
    public static function getApplyCount(){
        return (new static())->where('apply_status', '=', 10)->count();
    }
}
admin/app/operations/model/plus/operations/Operations.php
@@ -116,7 +116,7 @@
            // 处理管理员账号
            $userLoginModel = new UserLoginModel();
            $admin = $userLoginModel->where('user_id', '=', $data['user_id'])->where('is_super', '=', 1)->find();
            if ($userLoginModel->detail(['real_name'=>$data['real_name'],'user_id'=>['neq'=>$data['user_id']]])){
            if ($userLoginModel->detail(['user_name'=>$data['user_name'],'user_id'=>['neq'=>$data['user_id']]])){
                throw new \Exception('该账号已存在');
            }
            // 如果传入了用户名,则更新或创建管理员账号
@@ -132,7 +132,7 @@
                ];
                
                if (!empty($data['password'])) {
                    $loginData['user_name'] = salt_hash($data['user_name']);
                    $loginData['user_name'] = $data['user_name'];
                    $loginData['password'] = salt_hash($data['password']);
                }
                
@@ -282,8 +282,9 @@
                $result = $this->save($saveData);
            }
            $userLoginModel = new UserLoginModel();
            if ($userLoginModel->detail(['real_name'=>$data['real_name']])){
                throw new \Exception('该账号已存在');
            if ($userLoginModel->detail(['user_name'=>$data['user_name']])){
                $this->error = '该账号已存在';
                return false;
            }
            // 创建管理员账号
            if (isset($data['user_name']) && !empty($data['user_name'])) {
@@ -300,9 +301,10 @@
                ];
                
                if (!$userLoginModel->save($loginData)) {
                    throw new \Exception('管理员账号创建失败');
                    $this->error = '管理员账号创建失败';
                    return false;
                }
                $role_id = RoleModel::where('operations_level','=',$data['operations_level'])->value('role_id');
                $role_id = RoleModel::where('region_level','=',$data['operations_level'])->value('role_id');
                // 这里可以分配默认角色ID,暂时不分配
                $model = new UserRole();
                $add_arr[] = [
admin/app/operations/model/plus/operations/Order.php
New file
@@ -0,0 +1,82 @@
<?php
namespace app\operations\model\plus\operations;
use app\common\model\plus\operations\Order as OrderModel;
use app\common\model\plus\operations\Operations as OperationsUserModel;
use app\common\service\order\OrderService;
use app\operations\service\order\ExportService;
/**
 * 运营中心订单模型
 */
class Order extends OrderModel
{
    // 定义全局的查询范围
    protected $globalScope = ['status'];
    public function scopeStatus($query)
    {
        $region=OperationsUserModel::detail(session('jjjshop_operations')['user']['user_id']);
        $where=['first_user_id|second_user_id|third_user_id'=>$region['user_id']];
        $query->where($where);
    }
    /**
     * 获取运营中心订单列表
     */
    public function getList($user_id = null, $is_settled = -1, $list_rows = 15)
    {
        $model = $this;
        // 检索查询条件
        if ($user_id > 1) {
            $model = $model->where('first_user_id|second_user_id|third_user_id', '=', $user_id);
        }
        if ($is_settled > -1) {
            $model = $model->where('is_settled', '=', $is_settled);
        }
        // 获取运营中心订单列表
        $data = $model->with([
            'agent_first',
            'agent_second',
            'agent_third'
        ])
            ->order(['create_time' => 'desc'])
            ->paginate($list_rows);
        if ($data->isEmpty()) {
            return $data;
        }
        // 获取订单的主信息
        $with = ['product' => ['image', 'refund'], 'address', 'user'];
        return OrderService::getOrderList($data, 'order_master', $with);
    }
    /**
     * 订单导出
     */
    public function exportList($user_id = null, $is_settled = -1)
    {
        $model = $this;
        // 检索查询条件
        if ($user_id > 1) {
            $model = $model->where('first_user_id|second_user_id|third_user_id', '=', $user_id);
        }
        if ($is_settled > -1) {
            $model = $model->where('is_settled', '=', $is_settled);
        }
        // 获取运营中心订单列表
        $data = $model->with([
            'agent_first',
            'agent_second',
            'agent_third'
        ])
            ->order(['create_time' => 'desc'])
            ->select();
        if ($data->isEmpty()) {
            return $data;
        }
        // 获取订单的主信息
        $with = ['product' => ['image', 'refund'], 'address', 'user'];
        $list = OrderService::getOrderList($data, 'order_master', $with);
        // 导出excel文件
        (new Exportservice)->operationsOrderList($list);
    }
}
admin/app/operations/model/plus/release/Order.php
@@ -4,6 +4,7 @@
use app\common\model\plus\release\Order as OrderModel;
use app\common\model\plus\release\SupplyUser as SupplyUserModel;
use app\operations\model\supplier\Supplier as SupplierModel;
use app\operations\service\order\ExportService;
/**
@@ -15,7 +16,7 @@
    protected $globalScope = ['status'];
    public function scopeStatus($query)
    {
        $shop_supplier_ids = \app\operations\model\supplier\Supplier::getSupplierIdsByUser(session('jjjshop_operations')['user']);
        $shop_supplier_ids = SupplierModel::getSupplierIdsByUser(session('jjjshop_operations')['user']);
        if (empty($shop_supplier_ids)){
            $query->where($query->getTable() . '.shop_supplier_id', -1);
        }else{
admin/app/operations/model/plus/work/Setting.php
@@ -2,6 +2,7 @@
namespace app\operations\model\plus\work;
use app\operations\model\supplier\Supplier as SupplierModel;
use think\facade\Cache;
use app\common\model\plus\work\Setting as SettingModel;
@@ -11,7 +12,7 @@
    protected $globalScope = ['status'];
    public function scopeStatus($query)
    {
        $shop_supplier_ids = \app\operations\model\supplier\Supplier::getSupplierIdsByUser(session('jjjshop_operations')['user']);
        $shop_supplier_ids = SupplierModel::getSupplierIdsByUser(session('jjjshop_operations')['user']);
        if (empty($shop_supplier_ids)){
            $query->where($query->getTable() . '.shop_supplier_id', -1);
        }else{
admin/app/operations/model/supplier/Supplier.php
@@ -12,7 +12,7 @@
use app\operations\model\order\Order as OrderModel; // by yj
use app\operations\model\store\Coupon as StoreCouponModel; // by yj
use app\operations\service\order\ExportService;
use app\common\model\plus\region\User as RegionUserModel;
use app\common\model\plus\operations\Operations as OperationsUserModel;
/**
 * 后台管理员登录模型
@@ -23,9 +23,9 @@
    protected $globalScope = ['status'];
    public function scopeStatus($query)
    {
        $region=RegionUserModel::detail(session('jjjshop_operations')['user']['user_id']);
        $region=OperationsUserModel::detail(session('jjjshop_operations')['user']['user_id']);
        $where=[];
        $region_level=$region['region_level']['value'];
        $region_level=$region['operations_level']['value'];
        if ($region_level == 1){
            $where[$query->getTable() . '.province_id']=$region['province_id'];
        }else if($region_level == 2){
@@ -271,8 +271,8 @@
    public static function getAll($user=null)
    {
        $model = new static();
        $store=session('jjjshop_operations');
        $region=RegionUserModel::detail($store['user']['user_id']);
        /*$store=session('jjjshop_operations');
        $region=OperationsUserModel::detail($store['user']['user_id']);
        $where=[];
        $region_level=$region['region_level']['value'];
        if ($region_level == 1){
@@ -281,9 +281,9 @@
            $where['city_id']=$region['city_id'];
        }else if($region_level == 3){
            $where['region_id']=$region['area_id'];
        }
        }*/
        // 查询列表数据
        return $model->field(['shop_supplier_id,name,supplier_type'])->where($where)->where('is_delete', '=', '0')
        return $model->field(['shop_supplier_id,name,supplier_type'])/*->where($where)*/->where('is_delete', '=', '0')
            ->order(['create_time' => 'desc'])
            ->select();
    }
admin/app/shop/controller/branch/Activity.php
@@ -25,6 +25,18 @@
    }
    /**
     * 审核活动
     */
    public function audit($activity_id)
    {
        $model = new ActivityModel;
        if ($model->audit($activity_id, $this->postData())) {
            return $this->renderSuccess('审核成功');
        }
        return $this->renderError($model->getError() ?: '审核失败');
    }
    /**
     * 添加活动
     */
    public function add()
admin/app/shop/controller/plus/operations/Apply.php
@@ -34,27 +34,16 @@
    /**
     * 审核队长
     */
    public function editApplyStatus($apply_id)
    {
        $model = ApplyModel::detail($apply_id);
        if ($model->submit($this->postData())) {
            return $this->renderSuccess('修改成功');
        }
        return $this->renderError('修改失败');
        return $this->renderError($model->getError() ?: '修改失败');
    }
admin/app/shop/model/branch/Activity.php
@@ -15,11 +15,37 @@
     */
    public function getList($params)
    {
        return $this->with(['image', 'category', 'branch'])
            ->where('is_delete', '=', 0)
            ->order(['sort' => 'desc', 'create_time' => 'desc'])
        $model = $this->with(['image', 'category', 'branch'])
            ->where('is_delete', '=', 0);
        // 按审核状态筛选
        if (isset($params['audit_status']) && $params['audit_status'] !== '') {
            $model = $model->where('audit_status', '=', $params['audit_status']);
        }
        return $model->order(['sort' => 'desc', 'create_time' => 'desc'])
            ->paginate($params);
    }
    /**
     * 审核活动
     */
    public function audit($activity_id, $data)
    {
        $model = $this->detail($activity_id);
        if (!$model) {
            $this->error = '活动不存在';
            return false;
        }
        $updateData = [
            'audit_status' => $data['audit_status'],
            'audit_time' => time(),
            'audit_remark' => $data['audit_remark'] ?? ''
        ];
        return $model->save($updateData);
    }
    /**
@@ -27,6 +53,14 @@
     */
    public function add($data)
    {
        // 检查走访企业30天限制(编辑时排除当前活动)
        if ($data['is_visit'] == 1) {
            $visitCheck = $this->checkVisitLimit($data['visit_supplier_id'], $data['visit_supplier_name']);
            if ($visitCheck) {
                $this->error = '该企业30天内已被走访,还需等待' . $visitCheck['remaining_days'] . '天才可以重新走访';
                return false;
            }
        }
        $data['app_id'] = self::$app_id;
        //报名时间
        $data['register_start_time'] = strtotime($data['reg_date'][0]);
@@ -46,6 +80,15 @@
     */
    public function edit($data)
    {
        // 检查走访企业30天限制(编辑时排除当前活动)
        if ($data['is_visit'] == 1) {
            $visitCheck = $this->checkVisitLimit($data['visit_supplier_id'], $data['visit_supplier_name'], $data['activity_id']);
            if ($visitCheck) {
                $this->error = '该企业30天内已被走访,还需等待' . $visitCheck['remaining_days'] . '天才可以重新走访';
                return false;
            }
        }
        $data['app_id'] = self::$app_id;
        //报名时间
        $data['register_start_time'] = strtotime($data['reg_date'][0]);
        $data['register_end_time'] = strtotime($data['reg_date'][1]);
admin/app/shop/model/plus/operations/Apply.php
@@ -1 +1,90 @@
<?php namespace app\shop\model\plus\operations; use app\common\model\plus\operations\Apply as ApplyModel; use app\common\service\message\MessageService; use app\common\model\plus\operations\Grade as GradeModel; /**  * 队长入驻申请模型  */ class Apply extends ApplyModel {     /**      * 获取队长申请列表      * @noinspection PhpUndefinedMethodInspection      */     public function getList($search)     {         $model = $this->alias('apply')             ->field('apply.*, user.nickName, user.avatarUrl')             ->with(['referee'])             ->join('user', 'user.user_id = apply.user_id')             ->order(['apply.create_time' => 'desc']);         if (!empty($search['nick_name'])) {             $model = $model->where('user.nickName|apply.real_name|apply.mobile', 'like', '%' . $search['nick_name'] . '%');         }         // 获取列表数据         return $model->paginate($search['list_rows']);     }     /**      * 股东入驻审核      * @param $data      * @return bool      */     public function submit($data)     {         if ($data['apply_status'] == '30' && empty($data['reject_reason'])) {             $this->error = '请填写驳回原因';             return false;         }         $this->startTrans();         if ($data['apply_status'] == '20') {             //$grade_id=GradeModel::getDefaultGradeId();             // 新增区域代理用户             Operations::add($data['user_id'], [                 'real_name' => $data['real_name'],                 'mobile' => $data['mobile'],                 'operations_level' => $data['operations_level']["value"],                 'province_id' => $data['province_id'],                 'city_id' => $data['city_id'],                 'area_id' => $data['area_id'],                 'referee_id' => $data['referee_id'],                 //'grade_id'=>$grade_id             ]);         }         $save_data = [             'audit_time' => time(),             'apply_status' => $data['apply_status'],             'reject_reason' => $data['reject_reason'],         ];         $this->save($save_data);         // 记录推荐人关系         // if ($data['referee_id'] > 0) {         //     RefereeModel::createRelation($data['user_id'], $data['referee_id']);         // }         // 发送模板消息         (new MessageService)->operations($this);         $this->commit();         return true;     }     /**      * 获取申请中的数量      */     public static function getApplyCount(){         return (new static())->where('apply_status', '=', 10)->count();     } }
<?php
namespace app\shop\model\plus\operations;
use app\common\model\plus\operations\Apply as ApplyModel;
/**
 * 队长入驻申请模型
 */
class Apply extends ApplyModel
{
    /**
     * 获取队长申请列表
     * @noinspection PhpUndefinedMethodInspection
     */
    public function getList($search)
    {
        $model = $this->alias('apply')
            ->field('apply.*, user.nickName, user.avatarUrl')
            ->with(['referee'])
            ->join('user', 'user.user_id = apply.user_id')
            ->order(['apply.create_time' => 'desc']);
        if (!empty($search['nick_name'])) {
            $model = $model->where('user.nickName|apply.real_name|apply.mobile', 'like', '%' . $search['nick_name'] . '%');
        }
        // 获取列表数据
        return $model->paginate($search['list_rows']);
    }
    /**
     * 股东入驻审核
     * @param $data
     * @return bool
     */
    public function submit($data)
    {
        if ($data['apply_status'] == '30' && empty($data['reject_reason'])) {
            $this->error = '请填写驳回原因';
            return false;
        }
        $this->startTrans();
        if ($data['apply_status'] == '20') {
            // 新增区域代理用户(参考 Operations::addoperationsUser 方法)
            $operationsModel = new Operations();
            $result = $operationsModel->addoperationsUser([
                'user_id' => $data['user_id'],
                'real_name' => $data['real_name'],
                'mobile' => $data['mobile'],
                'operations_level' => $data['region_level']['value'],
                'province_id' => $data['province_id'],
                'city_id' => $data['city_id'],
                'area_id' => $data['area_id'],
                'referee_id' => $data['referee_id'],
                'user_name' => isset($data['user_name']) ? $data['user_name'] : '',
                'password' => isset($data['password']) ? $data['password'] : ''
            ]);
            if (!$result) {
                $this->error = $operationsModel->error;
                $this->rollback();
                return false;
            }
        }
        $save_data = [
            'audit_time' => time(),
            'apply_status' => $data['apply_status'],
            'region_level' => $data['region_level']['value'],
            'province_id' => $data['province_id'],
            'city_id' => $data['city_id'],
            'area_id' => $data['area_id'],
            'reject_reason' => $data['reject_reason'],
        ];
        $this->save($save_data);
        // 记录推荐人关系
        // if ($data['referee_id'] > 0) {
        //     RefereeModel::createRelation($data['user_id'], $data['referee_id']);
        // }
        // 发送模板消息
        // (new MessageService)->region($this);
        $this->commit();
        return true;
    }
    /**
     * 获取申请中的数量
     */
    public static function getApplyCount(){
        return (new static())->where('apply_status', '=', 10)->count();
    }
}
admin/app/shop/model/plus/operations/Operations.php
@@ -116,7 +116,7 @@
            // 处理管理员账号
            $userLoginModel = new UserLoginModel();
            $admin = $userLoginModel->where('user_id', '=', $data['user_id'])->where('is_super', '=', 1)->find();
            if ($userLoginModel->detail(['real_name'=>$data['real_name'],'user_id'=>['neq'=>$data['user_id']]])){
            if ($userLoginModel->detail(['user_name'=>$data['user_name'],'user_id'=>['neq'=>$data['user_id']]])){
                throw new \Exception('该账号已存在');
            }
            // 如果传入了用户名,则更新或创建管理员账号
@@ -145,7 +145,7 @@
                    // 创建新的管理员账号
                    $loginData['create_time'] = time();
                    $loginData['is_super'] = 1;
                    $role_id = RoleModel::where('operations_level','=',$checkData['operations_level'])->value('role_id');
                    $role_id = RoleModel::where('region_level','=',$checkData['operations_level'])->value('role_id');
                    $loginData['role_id'] = $role_id;
                    
                    if (!$userLoginModel->save($loginData)) {
@@ -282,7 +282,7 @@
                $result = $this->save($saveData);
            }
            $userLoginModel = new UserLoginModel();
            if ($userLoginModel->detail(['real_name'=>$data['real_name']])){
            if ($userLoginModel->detail(['user_name'=>$data['user_name']])){
                throw new \Exception('该账号已存在');
            }
            // 创建管理员账号
@@ -302,7 +302,7 @@
                if (!$userLoginModel->save($loginData)) {
                    throw new \Exception('管理员账号创建失败');
                }
                $role_id = RoleModel::where('operations_level','=',$data['operations_level'])->value('role_id');
                $role_id = RoleModel::where('region_level','=',$data['operations_level'])->value('role_id');
                // 这里可以分配默认角色ID,暂时不分配
                $model = new UserRole();
                $add_arr[] = [
admin/app/shop/model/plus/operations/Order.php
New file
@@ -0,0 +1,73 @@
<?php
namespace app\shop\model\plus\operations;
use app\common\model\plus\operations\Order as OrderModel;
use app\common\service\order\OrderService;
use app\shop\service\order\ExportService;
/**
 * 运营中心订单模型
 */
class Order extends OrderModel
{
    /**
     * 获取运营中心订单列表
     */
    public function getList($user_id = null, $is_settled = -1, $list_rows = 15)
    {
        $model = $this;
        // 检索查询条件
        if ($user_id > 1) {
            $model = $model->where('first_user_id|second_user_id|third_user_id', '=', $user_id);
        }
        if ($is_settled > -1) {
            $model = $model->where('is_settled', '=', $is_settled);
        }
        // 获取运营中心订单列表
        $data = $model->with([
            'agent_first',
            'agent_second',
            'agent_third'
        ])
            ->order(['create_time' => 'desc'])
            ->paginate($list_rows);
        if ($data->isEmpty()) {
            return $data;
        }
        // 获取订单的主信息
        $with = ['product' => ['image', 'refund'], 'address', 'user'];
        return OrderService::getOrderList($data, 'order_master', $with);
    }
    /**
     * 订单导出
     */
    public function exportList($user_id = null, $is_settled = -1)
    {
        $model = $this;
        // 检索查询条件
        if ($user_id > 1) {
            $model = $model->where('first_user_id|second_user_id|third_user_id', '=', $user_id);
        }
        if ($is_settled > -1) {
            $model = $model->where('is_settled', '=', $is_settled);
        }
        // 获取运营中心订单列表
        $data = $model->with([
            'agent_first',
            'agent_second',
            'agent_third'
        ])
            ->order(['create_time' => 'desc'])
            ->select();
        if ($data->isEmpty()) {
            return $data;
        }
        // 获取订单的主信息
        $with = ['product' => ['image', 'refund'], 'address', 'user'];
        $list = OrderService::getOrderList($data, 'order_master', $with);
        // 导出excel文件
        (new Exportservice)->operationsOrderList($list);
    }
}
branch_vue/src/api/branch.js
@@ -92,6 +92,14 @@
  deleteActivity(data, errorback) {
    return request._post('/branch/activity.activity/delete', data, errorback);
  },
  /*活动审核列表*/
  activityAuditList(data, errorback) {
    return request._post('/branch/activity.activity/auditList', data, errorback);
  },
  /*活动审核*/
  auditActivity(data, errorback) {
    return request._post('/branch/activity.activity/audit', data, errorback);
  },
  activityStatus(data, errorback) {
    return request._post('/branch/activity.activity/status', data, errorback);
  },
branch_vue/src/views/activity/activity/add.vue
@@ -15,7 +15,7 @@
        <el-input v-model="form.name" placeholder="请输入活动标题" class="max-w460"></el-input>
      </el-form-item>
      <el-form-item label="活动分类" prop="category_id">
        <el-select v-model="form.category_id" placeholder="请选择">
        <el-select v-model="form.category_id" placeholder="请选择" @change="handleCategoryChange">
          <el-option v-for="(item, index) in category" :key="index" :label="item.name" :value="item.category_id"></el-option>
        </el-select>
      </el-form-item>
@@ -45,6 +45,9 @@
          <el-radio :label="1">是</el-radio>
          <el-radio :label="0">否</el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item v-if="form.is_visit" label="被走访企业名称" prop="visit_supplier_name">
        <el-input v-model="form.visit_supplier_name" placeholder="商户没有入驻时,请输入被走访企业名称" class="max-w460"></el-input>
      </el-form-item>
      <el-form-item label="被走访企业" prop="visit_supplier_id" v-if="form.is_visit">
        <el-row>
@@ -80,7 +83,7 @@
        <el-input v-model="form.limit_num" placeholder="请输入活动名额" class="max-w460">
          <template slot="append">人</template>
        </el-input>
        <div class="gray9">0为不限制人数</div>
        <div class="gray9">0为不限制人数{{selectedCategory.limit_num?(',该分类最多'+selectedCategory.limit_num+'人'):''}}</div>
      </el-form-item>
      <el-form-item label="联系电话" prop="phone">
        <el-input v-model="form.phone" placeholder="请输入联系电话" class="max-w460"></el-input>
@@ -240,6 +243,8 @@
      },
      /*活动类别*/
      category: [],
      /*选中的分类信息*/
      selectedCategory: null,
      loading: false,
      upload_type: 'image', // 封面image 分享海报pic
      open_branch: false,
@@ -298,7 +303,9 @@
        .then(res => {
          self.category = res.data.category;
          if(self.category.length > 0){
            self.form.category_id = self.catgory[0].category_id;
            self.form.category_id = self.category[0].category_id;
            // 设置默认选中的分类信息
            self.selectedCategory = self.category[0];
          }
        })
        .catch(error => {
@@ -306,6 +313,16 @@
        });
    },
    /*处理分类选择变化*/
    handleCategoryChange(value) {
      // 根据选中的category_id找到对应的分类对象
      const selected = this.category.find(item => item.category_id === value);
      this.selectedCategory = selected || null;
      // 可以在这里添加其他业务逻辑,比如根据分类显示不同的表单字段等
      console.log('选中的分类信息:', this.selectedCategory);
    },
    /*添加活动*/
    onSubmit() {
      let self = this;
branch_vue/src/views/activity/activity/audit.vue
New file
@@ -0,0 +1,299 @@
<template>
  <div>
    <div class="common-level-rail">
      <el-select v-model="searchForm.audit_status" placeholder="审核状态" clearable @change="handleSearch">
        <el-option label="待审核" :value="0"></el-option>
        <el-option label="已通过" :value="10"></el-option>
        <el-option label="已驳回" :value="20"></el-option>
      </el-select>
    </div>
    <div class="table-wrap">
      <el-table :data="tableData" style="width: 100%" v-loading="loading">
        <el-table-column prop="activity_id" label="活动ID" width="60"></el-table-column>
        <el-table-column prop="image_id" label="封面图" width="80">
          <template slot-scope="scope">
            <img v-img-url="'image.file_path',scope.row" width="40" height="40" />
          </template>
        </el-table-column>
        <el-table-column prop="name" label="活动标题" min-width="150">
          <template slot-scope="{ row }">
            <div>{{ row.name }}</div>
            <el-tag size="small" type="info">{{ row.branch.name }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="category.name" label="活动分类" width="120"></el-table-column>
        <el-table-column prop="fee" label="活动费用" width="90"></el-table-column>
        <el-table-column prop="limit_num" label="已报人数/总人数" width="120">
          <template slot-scope="{ row }">
            {{ row.total }}/{{ row.limit_num || '不限制' }}
          </template>
        </el-table-column>
        <el-table-column prop="register_status" label="报名状态" width="100">
          <template slot-scope="{ row }">
            <el-tag :type="tagType(row.status_text.reg_status)">{{ row.status_text.reg_status_text }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="activity_status" label="活动状态" width="100">
          <template slot-scope="{ row }">
            <el-tag :type="tagType(row.status_text.status)">{{ row.status_text.status_text }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="audit_status" label="审核状态" width="100">
          <template slot-scope="{ row }">
            <el-tag :type="auditStatusType(row.audit_status_text.status)">
              {{ row.audit_status_text.text }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="create_time" label="创建时间" width="140"></el-table-column>
        <el-table-column prop="status" label="是否显示" width="100">
            <template slot-scope="scope">
                <el-switch v-model="scope.row.status" :active-value="1" :inactive-value="0" active-text="显示" inactive-text="隐藏" :width="55" @change="statusSet($event, scope.row)"></el-switch>
            </template>
        </el-table-column>
        <el-table-column prop="name" label="操作" width="180">
          <template slot-scope="scope">
            <el-button @click="onDetail(scope.row.activity_id, false)" type="text" size="small">查看</el-button>
            <el-button @click="showAuditDialog(scope.row)" type="text" size="small" v-if="scope.row.audit_status === 0">审核</el-button>
            <el-button @click="onDetail(scope.row.activity_id, true)" type="text" size="small">编辑</el-button>
            <el-button @click="onDelete(scope.row)" type="text" size="small">删除</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>
    <!-- 活动详情 -->
    <Detail ref="activityDetail" :open="open_detail" @getList="getTableList" @close="closeDrawerDetail"></Detail>
    <!-- 审核对话框 -->
    <el-dialog title="审核活动" :visible.sync="auditDialogVisible" width="500px">
      <el-form :model="auditForm" label-width="80px">
        <el-form-item label="活动名称">
          <span>{{ auditForm.activity_name }}</span>
        </el-form-item>
        <el-form-item label="所属分会">
          <span>{{ auditForm.branch_name }}</span>
        </el-form-item>
        <el-form-item label="审核结果">
          <el-radio-group v-model="auditForm.audit_status">
            <el-radio :label="10">通过</el-radio>
            <el-radio :label="20">驳回</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="审核备注" v-if="auditForm.audit_status === 20">
          <el-input
            type="textarea"
            :rows="4"
            v-model="auditForm.audit_remark"
            placeholder="请输入驳回原因"
          ></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer">
        <el-button @click="auditDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="submitAudit">确定</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import BranchApi from '@/api/branch.js';
import Detail from './drawer/detail.vue';
export default {
  components: {
    Detail
  },
  data() {
    return {
      /*分类*/
      categoryData: [],
      /*表单数据*/
      tableData: [],
      /*是否打开添加弹窗*/
      open_add: false,
      /*是否打开编辑弹窗*/
      open_edit: false,
      /*当前编辑的对象*/
      userModel: {},
      commentData: [],
      loading: true,
      /*一页多少条*/
      pageSize: 20,
      /*一共多少条数据*/
      totalDataNumber: 0,
      /*当前是第几页*/
      curPage: 1,
      tagTypeData: ['info', '', 'success'],
      open_detail: false,
      /*审核相关*/
      auditDialogVisible: false,
      auditForm: {
        activity_id: 0,
        activity_name: '',
        branch_name: '',
        audit_status: 10,
        audit_remark: ''
      },
      /*搜索条件*/
      searchForm: {
        audit_status: ''
      },
    };
  },
  created() {
    /*获取列表*/
    this.getTableList();
  },
  methods: {
    /*获取活动列表*/
    getTableList() {
      let self = this;
      let Params = {};
      Params.page = self.curPage;
      Params.list_rows = self.pageSize;
      // 添加审核状态筛选
      if (self.searchForm.audit_status !== '') {
        Params.audit_status = self.searchForm.audit_status;
      }
      BranchApi.activityAuditList(Params, true)
        .then(data => {
          self.loading = false;
          self.tableData = data.data.list.data;
          self.totalDataNumber = data.data.list.total;
        })
        .catch(error => {
          self.loading = false;
        });
    },
    /*选择第几页*/
    handleCurrentChange(val) {
      let self = this;
      self.curPage = val;
      self.loading = true;
      self.getTableList();
    },
    /*每页多少条*/
    handleSizeChange(val) {
      this.curPage = 1;
      this.pageSize = val;
      this.getTableList();
    },
    // 查看
    onDetail(id, isEdit){
      this.open_detail = true;
      this.$refs.activityDetail.getDetail(id, isEdit)
    },
    // 详情抽屉关闭回调
    closeDrawerDetail(e) {
      this.open_detail = false;
      if (e) {
        this.getTableList();
      }
    },
    /*删除*/
    onDelete(e) {
      let self = this;
      self
        .$confirm('此操作将永久删除该记录, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
        .then(() => {
          self.loading = true;
          BranchApi.deleteActivity(
            {
              activity_id: e.activity_id
            },
            true
          )
            .then(data => {
              self.$message({
                message: data.msg,
                type: 'success'
              });
              self.loading = false;
              self.getTableList();
            })
            .catch(error => {});
        })
        .catch(() => {});
    },
    /* 启用禁用*/
    statusSet(state, row){
        let self = this;
        BranchApi.activityStatus({
            activity_id: row.activity_id,
            status: state
            }).then(data => {
            self.$message({
                message: '操作成功',
                type: 'success'
            });
        });
    },
    tagType(e) {
      return this.tagTypeData[e];
    },
    auditStatusType(e) {
      const typeMap = { 0: 'warning', 10: 'success', 20: 'danger' };
      return typeMap[e] || 'info';
    },
    /*显示审核对话框*/
    showAuditDialog(row) {
      this.auditForm = {
        activity_id: row.activity_id,
        activity_name: row.name,
        branch_name: row.branch.name,
        audit_status: 10,
        audit_remark: ''
      };
      this.auditDialogVisible = true;
    },
    /*提交审核*/
    submitAudit() {
      if (this.auditForm.audit_status === 20 && !this.auditForm.audit_remark) {
        this.$message.warning('请输入驳回原因');
        return;
      }
      BranchApi.auditActivity(this.auditForm, true)
        .then(data => {
          this.$message.success(data.msg);
          this.auditDialogVisible = false;
          this.getTableList();
        })
        .catch(error => {});
    },
    /*搜索*/
    handleSearch() {
      this.curPage = 1;
      this.getTableList();
    },
  }
};
</script>
<style></style>
branch_vue/src/views/activity/activity/drawer/part/edit.vue
@@ -13,7 +13,7 @@
      </el-form-item> -->
      <el-form-item label="活动标题" prop="name"><el-input v-model="form.name" placeholder="请输入活动标题" class="max-w460"></el-input></el-form-item>
      <el-form-item label="活动分类" prop="category_id">
        <el-select v-model="form.category_id" placeholder="请选择">
        <el-select v-model="form.category_id" placeholder="请选择" @change="handleCategoryChange">
          <el-option v-for="(item, index) in category" :key="index" :label="item.name" :value="item.category_id"></el-option>
        </el-select>
      </el-form-item>
@@ -43,6 +43,9 @@
          <el-radio :label="1">是</el-radio>
          <el-radio :label="0">否</el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item v-if="form.is_visit" label="被走访企业名称" prop="visit_supplier_name" key="visit_supplier_name">
        <el-input v-model="form.visit_supplier_name" placeholder="商户没有入驻时,请输入被走访企业名称" class="max-w460"></el-input>
      </el-form-item>
      <el-form-item label="被走访企业" prop="visit_supplier_id" key="visit_supplier_id" v-if="form.is_visit">
        <el-row>
@@ -78,7 +81,7 @@
        <el-input v-model="form.limit_num" placeholder="请输入活动名额" class="max-w460">
          <template slot="append">人</template>
        </el-input>
        <div class="gray9">0为不限制人数</div>
        <div class="gray9">0为不限制人数{{selectedCategory.limit_num?(',该分类最多'+selectedCategory.limit_num+'人'):''}}</div>
      </el-form-item>
      <el-form-item label="联系电话" prop="phone">
        <el-input v-model="form.phone" placeholder="请输入联系电话" class="max-w460"></el-input>
@@ -239,6 +242,14 @@
    };
  },
  props: ['form', 'category'],
  computed: {
    selectedCategory() {
      if (!this.category || this.category.length === 0 || !this.form.category_id) {
        return {};
      }
      return this.category.find(item => item.category_id === this.form.category_id) || {};
    }
  },
  methods: {
    /*上传*/
    openUpload(t) {
branch_vue/src/views/activity/activity/index.vue
@@ -27,6 +27,13 @@
            <el-tag :type="tagType(row.status_text.status)">{{ row.status_text.status_text }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="audit_status" label="审核状态" width="100">
          <template slot-scope="{ row }">
            <el-tag :type="auditStatusType(row.audit_status_text.status)">
              {{ row.audit_status_text.text }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="create_time" label="创建时间" width="140"></el-table-column>
        <el-table-column prop="status" label="是否显示" width="100">
            <template slot-scope="scope">
@@ -205,6 +212,11 @@
      return this.tagTypeData[e];
    },
    auditStatusType(e) {
      const typeMap = { 0: 'warning', 10: 'success', 20: 'danger' };
      return typeMap[e] || 'info';
    },
    qrcode(row){
      this.code_id = row.activity_id;
      this.isQrcode = true;
mobile/components/diy/product/product.vue
@@ -28,11 +28,14 @@
                                    <!-- 商品价格 -->
                                    <view class="price d-s-c mt10">
                                        <view v-if="itemData.style.show.productPrice" class="theme-price">
                                            <text v-if="product.is_price_negotiable">价格面议</text>
                                            <template v-else>
                                            <text>¥</text>
                                            <text class="">{{ product.product_price }}</text>
                                            </template>
                                        </view>
                                        <view class="ml10 gray9 text-d-line f28"
                                            v-if="itemData.style.show.linePrice && product.line_price > 0">
                                            v-if="itemData.style.show.linePrice && product.line_price > 0 && !product.is_price_negotiable">
                                            <text>¥</text>
                                            <text>{{ product.line_price }}</text>
                                        </view>
@@ -51,7 +54,7 @@
                                <!-- 单规格商品显示购物车操作 -->
                                <template v-else>
                                    <view class="cart-btn-add" v-if="!item.cart.total_num || item.cart.total_num <= 0"
                                        @click.stop="addToCart(item,index)">
                                        @click.stop="handleCartItemAction(item,index)">
                                        <text class="icon iconfont icon-jia"></text>
                                    </view>
                                    <view class="cart-number-controller" v-else>
@@ -59,7 +62,7 @@
                                            <text class="icon iconfont icon-jian"></text>
                                        </view>
                                        <view class="cart-number">{{ item.cart.total_num }}</view>
                                        <view class="cart-btn-add" @click.stop="increaseCart(item,index)">
                                        <view class="cart-btn-add" @click.stop="handleCartItemAction(item,index)">
                                            <text class="icon iconfont icon-jia"></text>
                                        </view>
                                    </view>
@@ -79,11 +82,14 @@
                                    {{ product.product_name }}</view>
                                <view class="price d-s-c">
                                    <view v-if="itemData.style.show.productPrice == 1" class="theme-price">
                                        <text v-if="product.is_price_negotiable">价格面议</text>
                                        <template v-else>
                                        <text class="f22">¥</text>
                                        <text class="">{{ product.product_price }}</text>
                                        </template>
                                    </view>
                                    <view class="ml20 gray9 text-d-line"
                                        v-if="itemData.style.show.linePrice == 1 && product.line_price > 0"><text
                                        v-if="itemData.style.show.linePrice == 1 && product.line_price > 0 && !product.is_price_negotiable"><text
                                            class="f22">¥</text>{{ product.line_price }}</view>
                                </view>
                            </view>
@@ -105,11 +111,14 @@
                                        {{ product.product_name }}</view>
                                    <view class="price d-s-c f12">
                                        <view v-if="itemData.style.show.productPrice == 1" class="theme-price">
                                            <text v-if="product.is_price_negotiable">价格面议</text>
                                            <template v-else>
                                            <text>¥</text>
                                            <text class="">{{ product.product_price }}</text>
                                            </template>
                                        </view>
                                        <view class="ml10 gray9 text-d-line"
                                            v-if="itemData.style.show.linePrice == 1 && product.line_price > 0">
                                            v-if="itemData.style.show.linePrice == 1 && product.line_price > 0 && !product.is_price_negotiable">
                                            ¥{{ product.line_price }}</view>
                                    </view>
                                </view>
@@ -137,6 +146,39 @@
            gotoDetail(e) {
                let url = '/pages/product/detail/detail?product_id=' + e;
                this.gotoPage(url);
            },
            /*处理购物车操作 - 价格面议商品特殊处理*/
            handleCartItemAction(item, index) {
                // 如果是价格面议商品,提示联系客服
                if (item.is_price_negotiable) {
                    uni.showModal({
                        title: '温馨提示',
                        content: '该商品为价格面议商品,请联系客服咨询具体价格',
                        confirmText: '联系客服',
                        cancelText: '取消',
                        success: (res) => {
                            if (res.confirm) {
                                // 跳转到商品详情页联系客服
                                this.gotoDetail(item.product_id);
                            }
                        }
                    });
                } else {
                    // 非价格面议商品,正常添加到购物车
                    this.addToCart(item, index);
                }
            },
            /*添加到购物车*/
            addToCart(item, index) {
                // 这里实现具体的添加购物车逻辑
                console.log('添加到购物车:', item.product_id);
                // 示例实现
                uni.showToast({
                    title: '已添加到购物车',
                    icon: 'success'
                });
            }
        }
    };
mobile/components/diy/product/productCity.vue
@@ -75,10 +75,13 @@
                                <view v-if="itemData.style.show.productName == 1" class="product-title">{{ product.product_name }}</view>
                                <view class="price d-s-c">
                                    <view v-if="itemData.style.show.productPrice == 1" class="red">
                                        <text v-if="product.is_price_negotiable">价格面议</text>
                                        <template v-else>
                                        <text class="f22">¥</text>
                                        <text class="">{{ product.product_price }}</text>
                                        </template>
                                    </view>
                                    <view class="ml20 gray9 text-d-line" v-if="itemData.style.show.linePrice == 1 && product.line_price > 0"><text
                                    <view class="ml20 gray9 text-d-line" v-if="itemData.style.show.linePrice == 1 && product.line_price > 0 && !product.is_price_negotiable"><text
                                         class="f22">¥</text>{{ product.line_price }}</view>
                                </view>
                            </view>
@@ -138,6 +141,39 @@
                    return true;
                }
                return false;
            },
            /*处理购物车操作 - 价格面议商品特殊处理*/
            handleCartItemAction(item, index) {
                // 如果是价格面议商品,提示联系客服
                if (item.is_price_negotiable) {
                    uni.showModal({
                        title: '温馨提示',
                        content: '该商品为价格面议商品,请联系客服咨询具体价格',
                        confirmText: '联系客服',
                        cancelText: '取消',
                        success: (res) => {
                            if (res.confirm) {
                                // 跳转到商品详情页联系客服
                                this.gotoDetail(item.product_id);
                            }
                        }
                    });
                } else {
                    // 非价格面议商品,正常添加到购物车
                    this.addToCart(item, index);
                }
            },
            /*添加到购物车*/
            addToCart(item, index) {
                // 这里实现具体的添加购物车逻辑
                console.log('添加到购物车:', item.product_id);
                // 示例实现
                uni.showToast({
                    title: '已添加到购物车',
                    icon: 'success'
                });
            }
        }
    };
mobile/pages/branch/activity/detail/detail.vue
@@ -61,6 +61,7 @@
                        <view class="activity-item" v-if="activityData.is_visit == 1">
                            <view class="gray6 f24">走访企业</view>
                            <view class="info">{{activityData.visitSupplier?activityData.visitSupplier.name:''}}</view>
                            <view class="info">{{activityData.visit_supplier_name?activityData.visit_supplier_name:''}}</view>
                        </view>
                        <view class="activity-item"
                            v-if="activityData.is_visit == 0 && activityData.space_supplier_id > 0">
mobile/pages/branch/admin/activity/add.vue
@@ -60,6 +60,10 @@
                            @change="onChangeVisit" />
                    </view>
                    <view class="form-item d-b-c border-b-e" v-if="is_checked_visit">
                        <view class="item-title">被走访企业名称</view>
                        <input type="text" v-model="formData.visit_supplier_name" class="ww100" placeholder="商户没有入驻时,请输入被走访企业名称" />
                    </view>
                    <view class="form-item d-b-c border-b-e" v-if="is_checked_visit">
                        <view class="item-title">被走访企业</view>
                        <view class="d-s-c" @click="selectSupplier('visit')">
                            <view class="make-item input-box flex-1">{{visit_supplier_name||'请选择'}}</view>
@@ -83,6 +87,9 @@
                        <view class="item-title">活动名额(人)</view>
                        <input type="number" v-model="formData.limit_num" class="tr flex-1"
                            placeholder='请输入活动名额,0表示不限制' />
                    </view>
                    <view class="form-item d-b-c border-b-e" v-if="selectedCategory.limit_num > 0">
                        <view class="gray9 pt10">该分类最多{{selectedCategory.limit_num}}人</view>
                    </view>
                    <view class="form-item d-b-c border-b-e">
                        <view class="item-title">报名开始时间</view>
@@ -302,6 +309,14 @@
        },
        created() {
            this.getCategoryList();
        },
        computed: {
            selectedCategory() {
                if (!this.category || this.category.length === 0 || this.category_index === '') {
                    return {};
                }
                return this.category[this.category_index] || {};
            }
        },
        methods: {
            // 提交
@@ -609,10 +624,9 @@
            },
            insertImage() {
                this.isupload = true;
                this.upload_type = 'insertImage'
                this.upload_type = 'insertImage';
            }
        }
        },
    }
</script>
mobile/pages/branch/admin/activity/edit.vue
@@ -60,6 +60,10 @@
                            @change="onChangeVisit" />
                    </view>
                    <view class="form-item d-b-c border-b-e" v-if="is_checked_visit">
                        <view class="item-title">被走访企业名称</view>
                        <input type="text" v-model="formData.visit_supplier_name" class="ww100" placeholder="商户没有入驻时,请输入被走访企业名称" />
                    </view>
                    <view class="form-item d-b-c border-b-e" v-if="is_checked_visit">
                        <view class="item-title">被走访企业</view>
                        <view class="d-s-c" @click="selectSupplier('visit')">
                            <view class="make-item input-box flex-1">{{visit_supplier_name||'请选择'}}</view>
@@ -83,6 +87,9 @@
                        <view class="item-title">活动名额(人)</view>
                        <input type="number" v-model="formData.limit_num" class="tr flex-1"
                            placeholder='请输入活动名额,0表示不限制' />
                    </view>
                    <view class="form-item d-b-c border-b-e" v-if="selectedCategory.limit_num > 0">
                        <view class="gray9 pt10">该分类最多{{selectedCategory.limit_num}}人</view>
                    </view>
                    <view class="form-item d-b-c border-b-e">
                        <view class="item-title">报名开始时间</view>
@@ -306,6 +313,14 @@
        mounted() {
            this.getData();
        },
        computed: {
            selectedCategory() {
                if (!this.category || this.category.length === 0 || this.category_index === '') {
                    return {};
                }
                return this.category[this.category_index] || {};
            }
        },
        methods: {
            getData() {
                let self = this;
@@ -488,7 +503,6 @@
                this.formData.category_id = this.category[this.category_index].category_id;
            },
            // 打开企业选择弹窗
            selectSupplier(e) {
                this.supplier_type = e;
                this.open_supplier = true;
@@ -632,8 +646,7 @@
            },
            insertImage() {
                this.isupload = true;
                this.upload_type = 'insertImage'
                this.upload_type = 'insertImage';
            }
        }
    }
mobile/pages/plus/chat/chat.vue
@@ -23,7 +23,8 @@
                                </view>
                                <view>
                                    <view class="pro_txtname">{{getJSON(item.content).product_name}}</view>
                                    <view class="pro_price">¥{{getJSON(item.content).product_price}}</view>
                                    <view class="pro_price sendpro_price" v-if="getJSON(item.content).is_price_negotiable">价格面议</view>
                                    <view class="pro_price" v-else>¥{{getJSON(item.content).product_price}}</view>
                                </view>
                            </view>
                        </view>
@@ -56,7 +57,8 @@
                                    </view>
                                    <view>
                                        <view class="pro_name">{{productDetail.product_name}}</view>
                                        <view class="pro_price sendpro_price">¥{{productDetail.product_price}}</view>
                                        <view class="pro_price sendpro_price" v-if="productDetail.is_price_negotiable">价格面议</view>
                                        <view class="pro_price sendpro_price" v-else>¥{{productDetail.product_price}}</view>
                                    </view>
                                    <button class="pro_btn" @click="sendProduct">发送商家</button>
                                    <view class="close_pro" @click="is_product=false"><text class="icon iconfont icon-guanbi"></text></view>
@@ -551,7 +553,8 @@
                let params = {
                    product_name: self.productDetail.product_name,
                    product_img: self.productDetail.product_image,
                    product_price: self.productDetail.product_price
                    product_price: self.productDetail.product_price,
                    is_price_negotiable: self.productDetail.is_price_negotiable || 0
                }
                params = JSON.stringify(params)
                let data = JSON.stringify({
mobile/pages/plus/operations/cash/apply.vue
New file
@@ -0,0 +1,336 @@
<template>
    <view class="apply-cash" v-if="!loadding">
        <!--申请成功-->
        <view class="form-wrap f30">
            <form @submit="formSubmit" @reset="formReset">
                <view class="p-0-20 pt30 txje">
                    {{ words.cash_apply.words.money.value }}<text class="f26 gray9 ml30">{{ words.cash_apply.words.min_money.value+operations.settlement.min_money+'元' }}</text>
                </view>
                <view class="p-0-20 ">
                    <view class="withd-bc">
                        <view class="withd-bct">
                            <view style="height: 100%;display: flex;align-items: center;">
                                <text style="font-size: 48rpx;">¥</text>
                                <input class="tx-inpt" name="money" v-model="money" type="number" @input="moneyInput()"/>
                            </view>
                        </view>
                        <view class="withd-bcb">
                            {{ words.cash_apply.words.capital.value }}{{operations.operations.money}}元,提现手续费比例{{fee_rate}}%,<text @click="getAll" style="color: #0479FF;">全部提现</text>
                        </view>
                        <view class="withd-bcb">
                            当前应扣除手续费<text class="redEe">{{fee_money}}元</text>
                            ,实际到账<text class="redEe">{{real_money}}元</text>
                        </view>
                    </view>
                </view>
                <view class="p20 f32 gray3 txbt">提现方式</view>
                <view class="form-item p20">
                    <view class="ww100">
                        <template v-if="hasType('10')">
                            <view class="p-30-0 border-b">
                                <view class="d-b-c" :class="withdraw_type==10?'active':''" @click="TabType(10)">
                                    <view class="d-s-c flex-1">
                                        <image style="width: 28rpx;height: 28rpx;margin-right: 22rpx;" src="/static/wx.png" mode=""></image>
                                        <text class="f26 gray3">微信支付</text>
                                    </view>
                                    <text class="icon iconfont icon-xuanze"></text>
                                </view>
                            </view>
                        </template>
                        <template v-if="hasType('20')">
                            <view class="p-30-0 border-b">
                                <view class="d-b-c" :class="withdraw_type==20?'active':''" @click="TabType(20)">
                                    <view class="d-s-c flex-1">
                                        <image style="width: 28rpx;height: 28rpx;margin-right: 22rpx;" src="/static/zfb.png" mode=""></image>
                                        <text class="f26 gray3">支付宝</text>
                                    </view>
                                    <text class="icon iconfont icon-xuanze"></text>
                                </view>
                                <template v-if="withdraw_type==20">
                                    <view class="mt20">
                                        <input class="p20 border-tb" name="alipay_name" type="text" value="" placeholder-class="grary" placeholder="请输入姓名" />
                                    </view>
                                    <view class="mt20">
                                        <input class="p20 border-tb" name="alipay_account" type="text" value="" placeholder-class="grary" placeholder="请输入支付宝账号" />
                                    </view>
                                </template>
                            </view>
                        </template>
                        <template v-if="hasType('30')">
                            <view class="p-30-0 border-b">
                                <view class="d-b-c" :class="withdraw_type==30?'active':''" @click="TabType(30)">
                                    <view class="d-s-c flex-1">
                                        <image style="width: 28rpx;height: 22rpx;margin-right: 22rpx;" src="/static/yinxingqia.png" mode=""></image>
                                        <text class="f26 gray3">银行卡</text>
                                    </view>
                                    <text class="icon iconfont icon-xuanze"></text>
                                </view>
                                <template v-if="withdraw_type==30">
                                    <view class="mt20">
                                        <input class="p20 border-tb" name="real_name" type="text" value="" placeholder-class="grary" placeholder="请输入开户姓名" />
                                    </view>
                                    <view class="mt20">
                                        <input class="p20 border-tb" name="bank_name" type="text" value="" placeholder-class="grary" placeholder="请输入开户行名称" />
                                    </view>
                                    <view class="mt20">
                                        <input class="p20 border-tb" name="bank_account" type="text" value="" placeholder-class="grary" placeholder="请输入开户行地址" />
                                    </view>
                                    <view class="mt20">
                                        <input class="p20 border-tb" name="bank_card" type="text" value="" placeholder-class="grary" placeholder="请输入银行卡号" />
                                    </view>
                                </template>
                            </view>
                        </template>
                    </view>
                </view>
                <view class="d-c-c mt60" style="border: 16rpx solid #F2F2F2">
                    <button type="primary" class="btn-red flex-1" form-type="submit">{{ words.cash_apply.words.submit.value }}</button>
                </view>
                <view class="fb mt20 p-0-20 gray6" v-if="explain">提现说明:</view>
                <view class="mt10 p20" v-if="explain" style="white-space: pre-wrap;">{{explain}}</view>
            </form>
        </view>
    </view>
</template>
<script>
    export default {
        components: {},
        data() {
            return {
                loadding: true,
                /*是否加载完成*/
                indicatorDots: true,
                autoplay: true,
                interval: 2000,
                duration: 500,
                /*支付类别*/
                withdraw_type: 10,
                isData: false,
                operations: {},
                payType: [],
                words: {},
                /*小程序订阅消息*/
                temlIds: [],
                money: '',
                fee_rate:0,
                fee_money:0,
                real_money:0,
                explain:''
            }
        },
        mounted() {
            /*获取数据*/
            this.getData();
        },
        methods: {
            /*获取数据*/
            getData() {
                let self = this;
                uni.showLoading({
                    title: '加载中'
                });
                self.loadding = true;
                self._get('plus.operations.operations/cash', {
                    platform: self.getPlatform()
                }, function(res) {
                    self.operations = res.data;
                    self.words = res.data.words;
                    self.payType = self.operations.settlement.pay_type;
                    self.operations.isData = true;
                    self.temlIds = res.data.template_arr;
                    self.fee_rate=Number(self.operations.settlement.fee_rate)||0;
                    self.explain = self.operations.settlement.explain;
                    self.loadding = false;
                    uni.hideLoading();
                });
            },
            /*切换提现方式*/
            TabType(e) {
                let self = this;
                this.withdraw_type = e;
            },
            /*判断是否存在*/
            hasType(e) {
                if (this.payType.indexOf(e) != -1) {
                    return true;
                } else {
                    return false;
                }
            },
            getAll() {
                this.money = this.operations.operations.money;
                this.checkFee();
            },
            moneyInput(e){
                this.checkFee();
            },
            checkFee(){
                if(Number(this.money)>0){
                    this.fee_money=(Number(this.money)*Number(this.fee_rate)/100).toFixed(2);
                    this.real_money=(Number(this.money)-Number(this.fee_money)).toFixed(2);
                }else{
                    this.fee_money=0;
                    this.real_money=0;
                }
            },
            /*申请*/
            formSubmit: function(e) {
                let self = this;
                var formdata = e.detail.value;
                formdata.fee_rate=self.fee_rate;
                formdata.fee_money=self.fee_money;
                formdata.real_money=self.real_money;
                formdata.money=self.money;
                formdata.pay_type = self.withdraw_type;
                var data = JSON.stringify(formdata);
                let callback = function() {
                    uni.showLoading({
                        title: '正在提交',
                        mask: true
                    })
                    self._post('plus.operations.cash/submit', {
                        data: data
                    }, function(data) {
                        uni.hideLoading();
                        uni.showToast({
                            title: '申请成功',
                            duration: 2000,
                            icon: 'success'
                        });
                        setTimeout(function(){
                            uni.navigateBack(-1);
                        },200);
                    });
                }
                self.subMessage(self.temlIds, callback);
            },
        }
    }
</script>
<style>
    page {
        background-color: #F2F2F2;
    }
    .txje {
        font-size: 32rpx;
        font-family: PingFang SC;
        font-weight: 500;
        color: #333333;
        margin-top: 16rpx;
    }
    .apply-cash {
        /* padding-top: 16rpx; */
    }
    .form-wrap {
        /* border-radius: 20rpx; */
        background: #FFFFFF;
        /* box-shadow: 0 0 16rpx 0 rgba(0, 0, 0, .2); */
    }
    .form-item {
        margin-bottom: 20rpx;
        display: flex;
        justify-content: flex-start;
        align-items: center;
        font-size: 28rpx;
    }
    .form-item .field-name {
        width: 140rpx;
    }
    .form-item input {
        font-size: 28rpx;
    }
    .txbt {
        border-top: 16rpx solid #F2F2F2;
    }
    .form-item .text-price {
        padding: 0 10rpx;
        height: 80rpx;
        line-height: 80rpx;
        border-radius: 40rpx;
        border: 1px solid #CCCCCC;
    }
    .agreement-content {
        max-height: 60vh;
        overflow-y: auto;
    }
    .iconfont.icon-xuanze {
        font-size: 30rpx;
    }
    .form-item .active .iconfont.icon-xuanze {
        color: #FF5649;
    }
    .apply-cash .btn-red {
        height: 88rpx;
        line-height: 88rpx;
        border-radius: 44rpx;
        background: #FF5649;
        border-color: #FF5649;
        border: none;
        font-size: 32rpx;
    }
    .withd-b {
        background-color: #FFFFFF;
        margin-bottom: 97rpx;
    }
    .withd-bct {
        height: 92rpx;
        padding-top: 59rpx;
        padding-right: 49rpx;
        display: flex;
        justify-content: space-between;
        align-items: center;
        border-bottom: 1rpx solid #d0d0d0;
    }
    .tx-inpt {
        background-color: #FFFFFF;
        font-size: 48rpx;
        line-height: 92rpx;
    }
    .withd-bcb {
        font-size: 26rpx;
        color: #999999;
        padding: 27rpx 0 49rpx 0;
    }
    .withdrawal-btn {
        margin: 0 30rpx;
        background-color: #f36a24;
        height: 60rpx;
        line-height: 60rpx;
        color: #FFFFFF;
        text-align: center;
        border-radius: 30rpx;
        padding: 0;
        font-size: 24rpx;
    }
    .border-tb{
        border: none;
        border-top: 1rpx solid #eeeeee;
        border-bottom: 1rpx solid #eeeeee;
    }
</style>
mobile/pages/plus/operations/cash/list.vue
New file
@@ -0,0 +1,343 @@
<template>
    <view class="cash-list-vip">
        <view class="cash-tabs">
            <view class="tab-item" :class="{ active: currentTab === -1 }" @click="switchTab(-1)">
                全部
            </view>
            <view class="tab-item" :class="{ active: currentTab === 10 }" @click="switchTab(10)">
                待审核
            </view>
            <view class="tab-item" :class="{ active: currentTab === 20 }" @click="switchTab(20)">
                审核通过
            </view>
            <view class="tab-item" :class="{ active: currentTab === 30 }" @click="switchTab(30)">
                已驳回
            </view>
        </view>
        <view class="cash-list">
            <view class="cash-item" v-for="item in cashList" :key="item.id">
                <view class="cash-header">
                    <view class="cash-no">提现单号:{{ item.cash_no }}</view>
                    <view class="cash-status" :class="{
                        'pending': item.apply_status === 10,
                        'approved': item.apply_status === 20,
                        'rejected': item.apply_status === 30,
                        'paid': item.apply_status === 40
                    }">
                        {{ getStatusText(item.apply_status) }}
                    </view>
                </view>
                <view class="cash-content">
                    <view class="cash-info">
                        <view class="info-item">
                            <view class="label">提现金额</view>
                            <view class="value">¥{{ item.money }}</view>
                        </view>
                        <view class="info-item">
                            <view class="label">手续费</view>
                            <view class="value">¥{{ item.fee_money }}</view>
                        </view>
                        <view class="info-item">
                            <view class="label">实际到账</view>
                            <view class="value red">¥{{ item.real_money }}</view>
                        </view>
                        <view class="info-item">
                            <view class="label">提现方式</view>
                            <view class="value">{{ getPayTypeText(item.pay_type) }}</view>
                        </view>
                    </view>
                </view>
                <view class="cash-footer">
                    <view class="cash-time">{{ item.create_time }}</view>
                </view>
                <view class="reject-reason" v-if="item.apply_status === 30 && item.reject_reason">
                    驳回原因:{{ item.reject_reason }}
                </view>
            </view>
            <view class="no-data" v-if="cashList.length === 0">
                暂无提现记录
            </view>
        </view>
        <!-- 加载更多 -->
        <view class="load-more" v-if="cashList.length > 0 && hasMore">
            <view @click="loadMore">点击加载更多</view>
        </view>
    </view>
</template>
<script>
    export default {
        data() {
            return {
                titel: '提现明细',
                currentTab: -1, // -1: 全部, 10: 待审核, 20: 审核通过, 30: 已驳回
                page: 1,
                hasMore: true,
                cashList: []
            };
        },
        onLoad() {
            this.loadData();
        },
        methods: {
            // 加载数据
            loadData() {
                let self = this;
                uni.showLoading({ title: '加载中' });
                let params = {
                    page: self.page
                };
                if (self.currentTab !== -1) {
                    params.status = self.currentTab;
                }
                self._get('plus.vip.cash/lists', params, function(res) {
                    uni.hideLoading();
                    if (self.page === 1) {
                        self.cashList = res.data.list.data;
                    } else {
                        self.cashList = [...self.cashList, ...res.data.list.data];
                    }
                    // 判断是否还有更多数据
                    self.hasMore = res.data.list.last_page > res.data.list.current_page;
                });
            },
            // 切换标签页
            switchTab(tab) {
                if (this.currentTab !== tab) {
                    this.currentTab = tab;
                    this.page = 1;
                    this.hasMore = true;
                    this.loadData();
                }
            },
            // 加载更多
            loadMore() {
                if (this.hasMore) {
                    this.page++;
                    this.loadData();
                }
            },
            // 获取状态文本
            getStatusText(status) {
                const statusMap = {
                    10: '待审核',
                    20: '审核通过',
                    30: '已驳回',
                    40: '已打款'
                };
                return statusMap[status] || '未知';
            },
            // 获取状态样式类
            getStatusClass(status) {
                const classMap = {
                    10: 'pending',
                    20: 'approved',
                    30: 'rejected',
                    40: 'paid'
                };
                return classMap[status] || '';
            },
            // 获取提现方式文本
            getPayTypeText(type) {
                const typeMap = {
                    10: '微信',
                    20: '支付宝',
                    30: '银行卡'
                };
                return typeMap[type] || '未知';
            },
            goback() {
                uni.navigateBack();
            }
        }
    }
</script>
<style lang="scss">
    .cash-list-vip {
        min-height: 100vh;
        background: #f5f5f5;
    }
    .head_top {
        position: absolute;
        width: 100%;
        padding-top: var(--status-bar-height);
        height: 30px;
        line-height: 30px;
        color: #FFFFFF;
        font-size: 32rpx;
        z-index: 2;
    }
    .reg180 {
        padding-right: 20rpx;
        text-align: right;
        transform: rotateY(180deg);
        position: absolute;
        bottom: 0;
    }
    .icon-jiantou {
        color: #FFFFFF;
        font-size: 30rpx;
    }
    .cash-tabs {
        display: flex;
        background: #fff;
        margin-bottom: 20rpx;
        .tab-item {
            flex: 1;
            text-align: center;
            padding: 30rpx 0;
            font-size: 28rpx;
            color: #666;
            position: relative;
            &.active {
                color: #FF5649;
                font-weight: bold;
                &::after {
                    content: '';
                    position: absolute;
                    bottom: 0;
                    left: 50%;
                    transform: translateX(-50%);
                    width: 60rpx;
                    height: 6rpx;
                    background: #FF5649;
                    border-radius: 3rpx;
                }
            }
        }
    }
    .cash-list {
        .cash-item {
            background: #fff;
            margin-bottom: 20rpx;
            .cash-header {
                display: flex;
                justify-content: space-between;
                align-items: center;
                padding: 20rpx 30rpx;
                border-bottom: 1rpx solid #f5f5f5;
                .cash-no {
                    font-size: 26rpx;
                    color: #999;
                }
                .cash-status {
                    font-size: 26rpx;
                    &.pending {
                        color: #FF9900;
                    }
                    &.approved {
                        color: #07c160;
                    }
                    &.rejected {
                        color: #FF5649;
                    }
                    &.paid {
                        color: #07c160;
                    }
                }
            }
            .cash-content {
                padding: 30rpx;
                border-bottom: 1rpx solid #f5f5f5;
                .cash-info {
                    .info-item {
                        display: flex;
                        justify-content: space-between;
                        margin-bottom: 20rpx;
                        &:last-child {
                            margin-bottom: 0;
                        }
                        .label {
                            font-size: 28rpx;
                            color: #666;
                        }
                        .value {
                            font-size: 28rpx;
                            color: #333;
                            &.red {
                                color: #FF5649;
                            }
                        }
                    }
                }
            }
            .cash-footer {
                padding: 20rpx 30rpx;
                .cash-time {
                    font-size: 24rpx;
                    color: #999;
                }
            }
            .reject-reason {
                padding: 20rpx 30rpx;
                background: #fff9f9;
                font-size: 26rpx;
                color: #FF5649;
                border-top: 1rpx solid #f5f5f5;
            }
        }
        .no-data {
            text-align: center;
            padding: 100rpx 0;
            color: #999;
            font-size: 28rpx;
        }
    }
    .load-more {
        text-align: center;
        padding: 30rpx;
        view {
            display: inline-block;
            padding: 15rpx 30rpx;
            background: #f5f5f5;
            border-radius: 30rpx;
            font-size: 28rpx;
            color: #666;
        }
    }
</style>
mobile/pages/plus/operations/index.vue
New file
@@ -0,0 +1,400 @@
<template>
    <view class="index-operations o-h" v-if="!loadding" :data-theme='theme()' :class="theme() || ''">
        <!-- #ifdef MP-WEIXIN || APP-PLUS -->
        <view class="ww100" :style="'height:'+topBarTop()+'px;'"></view>
        <view class="tc  head_top" :style="topBarHeight() == 0 ? '': 'height:'+topBarHeight()+'px;'">
            <view class="reg180" @click="goback"><text class="icon iconfont icon-jiantou"></text></view>
            <view class="fb">{{titel}}</view>
        </view>
        <!-- #endif -->
        <!--头部图片-->
        <view class="banner d-c-c d-c">
            <image :src="top_background" mode="aspectFill"></image>
        </view>
        <!--是运营中心用户-->
        <template v-if="is_operations && isData">
            <!--金额信息-->
            <view class="operations-wrap pr m-0-20" style="margin-top: 300rpx;">
                <view class="d-b-c border-b pb30 f28 lh150 user-info">
                    <view class="d-b-c">
                        <view class="photo">
                            <image :src="user.avatarUrl" mode="aspectFill"></image>
                        </view>
                        <view class="user-name">
                            <view class="gray3 f32">{{ user.nickName }}</view>
                            <view class="mt10">
                                <text class="gray3 f28">{{ info_words.index.words.referee.value }}:</text>
                                <text class="f28 gray3">{{ operations.referee ? operations.referee.nickName : '平台' }}</text>
                            </view>
                        </view>
                    </view>
                </view>
                <view class="d-s-c p-30-0 top_dash">
                    <view class="flex-1 d-c-c d-c">
                        <view class="redF6">
                            <text class="f24">¥</text>
                            <text class="f40">{{ operations.money }}</text>
                        </view>
                        <view class="pt20 f26 gray3">{{ info_words.index.words.money.value }}</view>
                    </view>
                    <view class="flex-1 d-c-c d-c">
                        <view class="">
                            <text class="f24">¥</text>
                            <text class="f40">{{ operations.freeze_money }}</text>
                        </view>
                        <view class="pt20 f28 gray3">{{ info_words.index.words.freeze_money.value }}</view>
                    </view>
                    <view class="flex-1 d-c-c d-c">
                        <view class="">
                            <text class="f24">¥</text>
                            <text class="f40">{{ operations.total_money }}</text>
                        </view>
                        <view class="pt20 f28 gray3">{{ info_words.index.words.total_money.value }}</view>
                    </view>
                </view>
                <view class="d-c-c pt30">
                    <button type="primary" class="btn-gcred theme-btn flex-1" @click="gotoCash">{{ info_words.index.words.cash.value }}</button>
                </view>
            </view>
            <!--图标入口-->
            <view class="operations-wrap m-0-20 p30 d-s-c f-w mt20 bg-white">
                <view class="d-c-c d-c flex-1" @click="gotoPage('/pages/plus/operations/cash/list')">
                    <view>
                        <image class="operations_index_img" src="../../../static/icon/icon-zijinmingxi.png" mode=""></image>
                    </view>
                    <text class="pt10 f26 mt20">{{ info_words.cash_list.title.value }}</text>
                </view>
                <view class="d-c-c d-c flex-1" @click="gotoPage('/pages/plus/operations/order')">
                    <view>
                        <image class="operations_index_img" src="../../../static/icon/icon-fenxiaodingdan.png" mode=""></image>
                    </view>
                    <text class="pt10 f26 mt20">{{ info_words.order.title.value }}</text>
                </view>
                <!-- <view class="d-c-c d-c flex-1" @click="gotoPage('/pages/agent/team/team')">
                    <view>
                        <image class="operations_index_img" src="../../../static/icon/icon-tuandui.png" mode=""></image>
                    </view>
                    <text class="pt10 f26 mt20">{{ info_words.team.title.value }}</text>
                </view> -->
                <!-- <view class="d-c-c d-c flex-1" @click="gotoPage('/pages/plus/operations/qrcode')">
                    <view>
                        <image class="operations_index_img" src="../../../static/icon/icon-erweima.png" mode=""></image>
                    </view>
                    <text class="pt10 f26 mt20">{{ info_words.qrcode.title.value }}</text>
                </view> -->
            </view>
        </template>
        <!--不是运营中心用户-->
        <template v-if="!is_operations && isData">
            <view class="no-operations">
                <view class="mt50 p-0-20 red f34 tc">{{ info_words.index.words.not_region.value }}</view>
                <view class="section-product" v-if="setting.become=='100'">
                    <view class="p30 f28 d-c-c">您需要购买以下任意一款商品才能申请{{ info_words.index.words.region.value }}</view>
                    <view @click="gotoProductDetail(item.product_id)" class="item" :class="index==productList.length-1?'noborder':'border-b-e'" v-for="(item, index) in productList" :key="index">
                        <image :src="item.product_image" class="cover" mode="aspectFit"></image>
                        <view class="info">
                            <view class="title">{{ item.product_name }}</view>
                            <view class="describe">{{ item.product_sku.product_attr }}</view>
                            <view class="level-box count_choose">
                                <view class="price">
                                    ¥
                                    <text class="num">{{ item.product_sku.product_price }}</text>
                                </view>
                            </view>
                        </view>
                        <view class="icon-box pl20">
                            <text class="icon iconfont icon-jiantou f50"></text>
                        </view>
                    </view>
                </view>
            </view>
        </template>
    </view>
</template>
<script>
    export default {
        data() {
            return {
                /*是否加载完成*/
                loadding: true,
                indicatorDots: true,
                autoplay: true,
                interval: 2000,
                duration: 500,
                /*是否为运营中心用户*/
                is_operations: false,
                isData: false,
                operations: {},
                /*顶部背景*/
                top_background: '',
                /*基本信息*/
                info_words: {},
                words: {},
                user: {},
                titel: '',
                setting: {},
                productList: {},
            };
        },
        onLoad(e) {
            if (e.is_operations) {
                this.is_operations = e.is_operations;
            }
        },
        onShow() {
            uni.showLoading({
                title: '加载中'
            });
            /*获取个人中心数据*/
            this.getData();
        },
        methods: {
            /*获取数据*/
            getData() {
                let self = this;
                self._get('plus.operations.operations/center', {}, function(data) {
                    self.info_words = data.data.words;
                    uni.setNavigationBarTitle({
                        title: self.info_words.index.title.value != '' ? self.info_words.index.title.value : self.info_words.index.title
                            .default
                    });
                    self.titel = data.data.words.index.title.value
                    self.is_operations = data.data.is_operations;
                    self.top_background = data.data.background;
                    self.operations = data.data.operations;
                    self.user = data.data.user;
                    self.setting = data.data.setting;
                    self.productList = data.data.productList;
                    self.isData = true;
                    self.loadding = false;
                    uni.hideLoading();
                });
            },
            /*去提现*/
            gotoCash() {
                this.gotoPage('/pages/plus/operations/cash/apply');
            },
            goback() {
                uni.navigateBack();
            },
            /*跳转产品详情*/
            gotoProductDetail(e) {
                let url = 'pages/product/detail/detail?product_id=' + e
                this.gotoPage(url);
            },
        }
    };
</script>
<style lang="scss">
    page {
        background-color: #f9f9f9;
    }
    .index-operations .banner {
        position: absolute;
        width: 750rpx;
        height: 348rpx;
        z-index: 0;
        min-height: 167rpx;
        background-repeat: no-repeat;
        background-size: 100%;
    }
    .index-operations .banner image {
        width: 100%;
    }
    .no-operations {
        margin-top: 348rpx;
        position: relative;
        background: #fff;
        border-radius: 20rpx;
        margin-left: 20rpx;
        margin-right: 20rpx;
        padding-bottom: 40rpx;
    }
    .operations-wrap {
        background: #FFFFFF;
        background-size: 100% 100%;
        padding: 31rpx 25rpx 36rpx 25rpx;
        box-shadow: 0px 8rpx 3rpx 0px rgba(6,0,1,0.03);
        border-radius: 20rpx;
    }
    .index-operations .operations-wrap .iconfont {
        font-size: 60rpx;
    }
    .index-operations .btn-gcred {
        height: 88rpx;
        line-height: 88rpx;
        border-radius: 44rpx;
        background: #FF5649;
        border-color: #FF5649;
    }
    .reg180 {
        padding-right: 20rpx;
        text-align: right;
        transform: rotateY(180deg);
        position: absolute;
        bottom: 0;
    }
    .icon-jiantou {
        color: #FFFFFF;
        font-size: 30rpx;
    }
    .head_top {
        position: absolute;
        width: 100%;
        padding-top: var(--status-bar-height);
        height: 30px;
        line-height: 30px;
        color: #FFFFFF;
        font-size: 32rpx;
        z-index: 2;
    }
    .top_dash {
        border-bottom: 1rpx dashed #D9D9D9;
        padding-bottom: 9px;
    }
    .operations_index_img {
        width: 78rpx;
        height: 78rpx;
    }
    .user-info .photo,
    .user-info .photo image {
        width: 100rpx;
        height: 100rpx;
        border-radius: 50%;
    }
    .user-info .photo {
        padding-right: 20rpx;
    }
    /* 商品列表样式 */
    .section-product .item {
        margin: 0 26rpx;
        display: flex;
        align-items: center;
        padding-bottom: 29rpx;
        padding-top: 29rpx;
    }
    .section-product .cover {
        width: 150rpx;
        height: 150rpx;
        border-radius: 8px;
    }
    .section-product .info {
        flex: 1;
        padding-left: 30rpx;
        box-sizing: border-box;
        overflow: hidden;
    }
    .section-product .title {
        width: 100%;
        font-size: 26rpx;
        display: -webkit-box;
        overflow: hidden;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
    }
    .vender .list .describe {
        width: 100%;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .section-product .describe {
        margin-top: 20rpx;
        font-size: 24rpx;
        color: #999999;
        display: -webkit-box;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 3;
        overflow: hidden;
    }
    .section-product .price {
        color: #F6220C;
        font-size: 24rpx;
    }
    .section-product .price .num {
        padding: 0 4rpx;
        font-size: 32rpx;
    }
    .section-product .level-box {
        margin-top: 20rpx;
        display: flex;
        justify-content: space-between;
        align-items: center;
    }
    .section-product .level-box .key {
        font-size: 24rpx;
        color: #999999;
    }
    .section-product .level-box .num-wrap {
        display: flex;
        justify-content: flex-end;
        align-items: center;
    }
    .section-product .level-box .icon-box {
        width: 33rpx;
        height: 33rpx;
        border: 1px solid #c5c5c5;
        background: #f2f2f2;
    }
    .section-product .level-box .icon-box .gray {
        color: #cccccc;
    }
    .section-product .level-box .icon-box .gray3 {
        color: #333333;
    }
    .section-product .level-box .text-wrap {
        margin: 0 20rpx;
        height: 33rpx;
        border: none;
        background: none;
    }
    .section-product .level-box .text-wrap input {
        padding: 0 4rpx;
        height: 33rpx;
        line-height: 1;
        width: 40rpx;
        font-size: 32rpx;
        text-align: center;
        display: flex;
        align-items: center;
        min-height: 33rpx;
    }
    .section-product .icon-jiantou {
        color: #999;
    }
</style>
mobile/pages/plus/operations/order.vue
New file
@@ -0,0 +1,204 @@
<template>
    <view>
        <view class="top-tabbar">
            <view :class="state_active == item.value? 'tab-item active' : 'tab-item'" @click="stateFunc(item.value)" v-for="(item,index) in tableList"
             :key="index">{{item.text}}</view>
        </view>
        <!--列表-->
        <scroll-view scroll-y="true" class="scroll-Y" :style="'height:' + scrollviewHigh + 'px;'" lower-threshold="50"
         @scrolltolower="scrolltolowerFunc">
            <view class=" ">
                <view class="border-b p-0-30 bg-white pt10 mt20" v-for="(item,index) in tableData" :key="index">
                    <view class="d-b-c f24 item-top">
                        <text>订单号{{ item.order_master.order_no }}</text>
                        <text class="blue" v-if="item.is_settled==1"> 已结算</text>
                        <text class="green" v-else>未结算</text>
                    </view>
                    <view class="d-b-c item-center">
                        <view class="operations-order-photo">
                            <image :src="item.user.avatarUrl" mode="aspectFill"></image>
                        </view>
                        <view class="flex-1 ml20 f24">
                            <view class="d-b-c">
                                <text class="gray3 f28">{{ item.user.nickName }}</text>
                                <text class="gray3 f28" v-if="item.first_user_id == user_id ">+¥{{ item.first_money }}</text>
                                <text class="gray3 f28" v-if="item.second_user_id == user_id ">+¥{{ item.second_money }}</text>
                                <text class="gray3 f28" v-if="item.third_user_id == user_id ">+¥{{ item.third_money }}</text>
                            </view>
                            <view class="d-b-c">
                                <text class="gray9 f22">消费金额:¥{{ item.order_price }}</text>
                            </view>
                        </view>
                    </view>
                    <view class="item-bottom">
                        <text class="gray9">{{item.create_time}}</text>
                    </view>
                </view>
                <!-- 没有记录 -->
                <view class="d-c-c p30" v-if="tableData.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>
        </scroll-view>
    </view>
</template>
<script>
    import uniLoadMore from "@/components/uni-load-more.vue";
    export default {
        components: {
            uniLoadMore
        },
        data() {
            return {
                /*手机高度*/
                phoneHeight: 0,
                /*可滚动视图区域高度*/
                scrollviewHigh: 0,
                /*状态选中*/
                state_active: -1,
                /*数据列表*/
                tableData: [],
                settled: -1,
                page: 1,
                no_more: false,
                loading: true,
                tableList: [],
                list_rows: 15,
                user_id: 0
            }
        },
        computed: {
            /*加载中状态*/
            loadingType() {
                if (this.loading) {
                    return 1;
                } else {
                    if (this.tableData.length != 0 && this.no_more) {
                        return 2;
                    } else {
                        return 0;
                    }
                }
            }
        },
        mounted() {
            /*初始化*/
            this.init();
            this.user_id = this.getUserId();
            /*获取数据*/
            this.getData();
        },
        methods: {
            /*初始化*/
            init() {
                let self = this;
                uni.getSystemInfo({
                    success(res) {
                        self.phoneHeight = res.windowHeight;
                        // 计算组件的高度
                        let view = uni.createSelectorQuery().select('.top-tabbar');
                        view.boundingClientRect(data => {
                            let h = self.phoneHeight - data.height;
                            self.scrollviewHigh = h;
                        }).exec();
                    }
                });
            },
            /*获取数据*/
            getData() {
                let self = this;
                self.loading = true;
                self._get('plus.operations.order/lists', {
                    settled: self.state_active,
                    page: self.page ||1,
                    list_rows: self.list_rows,
                }, function(data) {
                    self.loading = false;
                    // 导航栏数据
                    self.tableList = [{
                        value: -1,
                        text: data.data.words.order.words.all.value,
                    }, {
                        value: 0,
                        text: data.data.words.order.words.unsettled.value,
                    }, {
                        value: 1,
                        text: data.data.words.order.words.settled.value,
                    }];
                    self.tableData = self.tableData.concat(data.data.list.data);
                    self.last_page = data.data.list.last_page;
                    if (self.last_page <= 1) {
                        self.no_more = true;
                    }
                });
            },
            /*切换*/
            stateFunc(e) {
                let self = this;
                if(e!=self.state_active){
                    self.tableData = [];
                    self.page = 1;
                    self.state_active = e;
                    self.getData();
                }
            },
            /*可滚动视图区域到底触发*/
            scrolltolowerFunc() {
                let self = this;
                if (self.no_more) {
                    return;
                }
                self.page++;
                if (self.page <= self.last_page) {
                    self.getData();
                } else {
                    self.no_more = true;
                }
            }
        }
    }
</script>
<style lang="scss">
    .operations-order-photo,
    .operations-order-photo image {
        width: 96rpx;
        height: 96rpx;
        border-radius: 50%;
    }
    .tab-item{
        font-size: 28rpx;
    }
    .tab-item.active{
        font-weight: normal;
        font-size: 28rpx;
    }
    .tab-item.active::after{
        width: 57rpx;
        height: 6rpx;
        background-color: #ff5649;
    }
    .item-top{
        height: 54rpx;
        line-height: 54rpx;
        border-bottom: 1rpx solid #eeeeee;
        color: #999999;
    }
    .item-bottom{
        height: 73rpx;
        line-height: 73rpx;
        border-top: 1rpx solid #eeeeee;
    }
    .item-center{
        height: 122rpx;
    }
</style>
mobile/pages/product/category.vue
@@ -70,7 +70,8 @@
                                    <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
                                            <view class="f24 shop_red" v-if="item.is_price_negotiable">价格面议</view>
                                            <view class="f24 shop_red" v-else>¥<text
                                                    class="f32 fb">{{item.product_price}}</text></view>
                                        </view>
                                        <!-- 购物车操作组件 -->
@@ -88,7 +89,7 @@
                                            <template v-else>
                                                <view class="cart-btn-add"
                                                    v-if="!item.cart.total_num || item.cart.total_num <= 0"
                                                    @click.stop="addToCart(item,index)">
                                                    @click.stop="handleCartItemAction(item,index)">
                                                    <text class="icon iconfont icon-jia"></text>
                                                </view>
                                                <view class="cart-number-controller" v-else>
@@ -509,6 +510,28 @@
                }
            },
            // 处理购物车操作 - 价格面议商品特殊处理
            handleCartItemAction(product, index) {
                // 如果是价格面议商品,提示联系客服
                if (product.is_price_negotiable) {
                    uni.showModal({
                        title: '温馨提示',
                        content: '该商品为价格面议商品,请联系客服咨询具体价格',
                        confirmText: '联系客服',
                        cancelText: '取消',
                        success: (res) => {
                            if (res.confirm) {
                                // 跳转到商品详情页联系客服
                                this.gotoList2(product.product_id);
                            }
                        }
                    });
                } else {
                    // 非价格面议商品,正常添加到购物车
                    this.directlyAddToCart(product, index);
                }
            },
            // 添加到购物车(单规格商品)
            addToCart(product, index) {
                this.directlyAddToCart(product, index);
mobile/pages/product/detail/detail.vue
@@ -104,13 +104,16 @@
                        <view class="d-s-c pr ww100 mb16">
                            <view class="new-price theme-price">
                                <text class="fn mr10" v-if="detail.is_user_grade">会员价</text>
                                <text v-if="detail.is_price_negotiable">价格面议</text>
                                <template v-else>
                                <text>¥</text>
                                <text class="num">{{ detail.product_sku.product_price }}</text>
                                <text class="num" v-if="detail.spec_type == 20 && detail.product_sku.product_price != detail.product_max_price">
                                    -{{ detail.product_max_price }}
                                </text>
                                </template>
                            </view>
                            <text v-if="underline_price_show" class="old-price ">¥{{ detail.product_sku.line_price }}</text>
                            <text v-if="underline_price_show && !detail.is_price_negotiable" class="old-price ">¥{{ detail.product_sku.line_price }}</text>
                            <!--分享-->
                            <view class="share-box">
                                <button @click="showShare">
@@ -313,9 +316,9 @@
                    <button class="add-cart-no" style="border-radius: 40rpx;margin-right: 20rpx;">暂未开始售卖</button>
                </template>
                <template v-else>
                    <button v-if="!room_id == true && !is_virtual && !ispresale" class="add-cart" @click="openPopup('card')">加入购物车</button>
                    <button v-if="!room_id == true && !is_virtual && !ispresale" class="add-cart" @click="handlePriceNegotiableAction('card')">加入购物车</button>
                    <button v-else class="add-cart-no">加入购物车</button>
                    <button class="buy" v-if="!ispresale" @click="openPopup('order')">立即购买</button>
                    <button class="buy" v-if="!ispresale" @click="handlePriceNegotiableAction('order')">立即购买</button>
                    <button class="buy ispresale" v-else @click="openPopup('deposit')">
                        <template v-if="activeName == 'advance'">
                            <view class="f28">支付定金</view>
@@ -846,6 +849,27 @@
            }
        },
        /*处理价格面议商品的操作*/
        handlePriceNegotiableAction(actionType) {
            // 如果是价格面议商品,提示联系客服
            if (this.detail.is_price_negotiable) {
                uni.showModal({
                    title: '温馨提示',
                    content: '该商品为价格面议商品,请联系客服咨询具体价格',
                    confirmText: '联系客服',
                    cancelText: '取消',
                    success: (res) => {
                        if (res.confirm) {
                            this.openService();
                        }
                    }
                });
            } else {
                // 非价格面议商品,正常执行原逻辑
                this.openPopup(actionType);
            }
        },
        /*关闭客服*/
        closeMpservice() {
            this.isMpservice = false;
mobile/pages/product/list/list.vue
@@ -74,8 +74,11 @@
                                <view class="shop_body_t_item_info_others_sales">累计成交:{{item.product_sales}}笔</view>
                            </view> -->
                            <view class="shop_body_t_item_info_price">
                                <view class="f20 redF6" v-if="item.is_price_negotiable">价格面议</view>
                                <template v-else>
                                <view class="f20 redF6">¥<text class="f32">{{item.product_price}}</text></view>
                                <view class="f20 huaxianjia">¥<text class="24">{{item.line_price}}</text></view>
                                </template>
                            </view>
                            <!-- 购物车操作组件 -->
                            <view class="cart-action">
@@ -213,9 +216,6 @@
                selectedProduct: null,
                selectedSpecs: [],
                quantity: 1,
                page: 1,
                last_page: 1,
                category_id: 0,
            };
        },
        computed: {
@@ -404,6 +404,31 @@
                }
            },
            // 处理列表项购物车操作
            handleListItemCartAction(product, index) {
                // 如果是价格面议商品,提示联系客服
                if (product.is_price_negotiable) {
                    uni.showModal({
                        title: '温馨提示',
                        content: '该商品为价格面议商品,请联系客服咨询具体价格',
                        confirmText: '联系客服',
                        cancelText: '取消',
                        success: (res) => {
                            if (res.confirm) {
                                // 这里可以跳转到客服页面或显示联系方式
                                uni.showToast({
                                    title: '请联系客服咨询',
                                    icon: 'none'
                                });
                            }
                        }
                    });
                } else {
                    // 非价格面议商品,正常添加到购物车
                    this.directlyAddToCart(product, index);
                }
            },
            // 添加到购物车(单规格商品)
            addToCart(product, index) {
                this.directlyAddToCart(product, index);
mobile/pages/shop/shop_list.vue
@@ -76,7 +76,8 @@
                                    <image :src="item1.image[0].file_path"></image>
                                </view>
                                <view class="shop_list_body_item_product_item_price">
                                    <view class="f22 red">¥
                                    <view class="f22 red" v-if="item1.is_price_negotiable">价格面议</view>
                                    <view class="f22 red" v-else>¥
                                        <text class="f32">
                                            {{item1.product_price}}
                                        </text>
mobile/pages/user/activation/index.vue
New file
@@ -0,0 +1,314 @@
<template>
    <view class="container">
        <!-- 搜索区域 -->
        <view class="search-box">
            <view class="search-input">
                <input
                    type="text"
                    v-model="searchKeyword"
                    placeholder="请输入激活码"
                    placeholder-class="placeholder-class"
                    @confirm="searchActivationCode" />
                <text class="icon iconfont icon-sousuo" @click="searchActivationCode"></text>
            </view>
        </view>
        <view style="display: flex;justify-content: space-between;">
            <view >
                未使用:{{wsy}}
            </view>
            <view >
                已使用:{{ysy}}
            </view>
        </view>
        <!-- 激活码列表 -->
        <view class="activation-list">
            <view class="list-header">
                <text class="header-item">激活码</text>
                <text class="header-item">状态</text>
                <text class="header-item">类型</text>
            </view>
            <view class="list-content">
                <view class="list-item" v-for="(item, index) in activationList" :key="index">
                    <view class="item-content">
                        <view class="item-code" @longpress="copyActivationCode(item.activation_code)">
                            <text class="code-text">{{ item.activation_code }}</text>
                        </view>
                        <view class="item-status">
                            <text :class="['status', item.status == 0 ? 'unused' : 'used']">
                                {{ item.status == 0 ? '未使用' : '已使用' }}
                            </text>
                        </view>
                        <view class="item-type">
                            <text class="type">{{ item.type_text }}</text>
                        </view>
                    </view>
                    <view class="item-footer">
                        <text class="time">创建时间:{{ item.create_time }}</text>
                        <text class="time" v-if="item.use_time">使用时间:{{ item.use_time }}</text>
                    </view>
                </view>
            </view>
            <!-- 空状态 -->
            <view class="empty-box" v-if="activationList.length === 0 && !loading">
                <view class="empty-icon">
                    <text class="icon iconfont icon-wushuju"></text>
                </view>
                <text class="empty-text">暂无激活码</text>
            </view>
        </view>
        <!-- 加载更多 -->
        <view class="load-more" v-if="loading">
            <text>加载中...</text>
        </view>
    </view>
</template>
<script>
    export default {
        data() {
            return {
                // 搜索关键词
                searchKeyword: '',
                // 激活码列表
                activationList: [],
                wsy:[],
                ysy:[],
                // 分页信息
                page: 1,
                // 每页条数
                listRows: 10,
                // 是否正在加载
                loading: false,
                // 是否还有更多数据
                hasMore: true
            }
        },
        onLoad() {
            // 页面加载时获取数据
            this.getActivationCodeList();
        },
        onReachBottom() {
            // 上拉加载更多
            if (this.hasMore && !this.loading) {
                this.page++;
                this.getActivationCodeList();
            }
        },
        methods: {
            // 获取激活码列表
            getActivationCodeList() {
                let self=this;
                if (self.loading) return;
                self.loading = true;
                const params = {
                    page: self.page,
                    list_rows: self.listRows,
                    activation_code: self.searchKeyword
                };
                self._get('user.ActivationCode/list',params,res=>{
                    const mockData = res.data.list.data;
                    self.wsy= res.data.wsy
                    self.ysy= res.data.ysy
                    if (self.page === 1) {
                        self.activationList = mockData;
                    } else {
                        self.activationList = [...self.activationList, ...mockData];
                    }
                    self.hasMore = mockData.length >= self.listRows;
                    self.loading = false;
                })
            },
            // 搜索激活码
            searchActivationCode() {
                this.page = 1;
                this.getActivationCodeList();
            },
            // 复制激活码
            copyActivationCode(code) {
                let self = this;
                uni.setClipboardData({
                    data: code,
                    success: function() {
                        self.showSuccess('激活码已复制到剪贴板');
                    },
                    fail: function() {
                        self.showError('复制失败');
                    }
                });
            },
        }
    }
</script>
<style lang="scss" scoped>
    .container {
        min-height: 100vh;
        background-color: #f5f5f5;
        padding: 20rpx;
    }
    .search-box {
        background-color: #fff;
        padding: 20rpx;
        margin-bottom: 20rpx;
        border-radius: 10rpx;
    }
    .search-input {
        display: flex;
        align-items: center;
        height: 70rpx;
        background-color: #f7f7f7;
        border-radius: 35rpx;
        padding: 0 20rpx;
        input {
            flex: 1;
            font-size: 28rpx;
            color: #333;
        }
        .icon {
            font-size: 36rpx;
            color: #999;
        }
    }
    .placeholder-class {
        color: #999;
        font-size: 28rpx;
    }
    .activation-list {
        background-color: #fff;
        border-radius: 10rpx;
        overflow: hidden;
    }
    .list-header {
        display: flex;
        background-color: #f7f7f7;
        padding: 20rpx;
        border-bottom: 1rpx solid #eee;
        .header-item {
            flex: 1;
            text-align: center;
            font-size: 28rpx;
            color: #666;
            font-weight: bold;
        }
    }
    .list-content {
        .list-item {
            padding: 20rpx;
            border-bottom: 1rpx solid #eee;
            &:last-child {
                border-bottom: none;
            }
            .item-content {
                display: flex;
                align-items: center;
                margin-bottom: 10rpx;
                .item-code {
                    flex: 1;
                    .code-text {
                        font-size: 28rpx;
                        color: #333;
                        font-weight: bold;
                    }
                }
                .item-status {
                    flex: 1;
                    text-align: center;
                    .status {
                        padding: 5rpx 15rpx;
                        border-radius: 20rpx;
                        font-size: 24rpx;
                    }
                    .unused {
                        background-color: #e8f4ff;
                        color: #1890ff;
                    }
                    .used {
                        background-color: #f0f0f0;
                        color: #999;
                    }
                }
                .item-type {
                    flex: 1;
                    text-align: center;
                    .type {
                        font-size: 24rpx;
                        color: #666;
                    }
                }
            }
            .item-footer {
                display: flex;
                flex-direction: column;
                .time {
                    font-size: 20rpx;
                    color: #999;
                    margin-bottom: 5rpx;
                }
                .time:last-child {
                    margin-bottom: 0;
                }
            }
        }
    }
    .empty-box {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        padding: 100rpx 0;
        .empty-icon {
            margin-bottom: 20rpx;
            .icon {
                font-size: 100rpx;
                color: #ccc;
            }
        }
        .empty-text {
            font-size: 28rpx;
            color: #999;
        }
    }
    .load-more {
        text-align: center;
        padding: 20rpx;
        font-size: 24rpx;
        color: #999;
    }
</style>
mobile/pages/user/my_shop/product_add.vue
@@ -75,6 +75,17 @@
                </view>
                <view class="form-item">
                    <view class="item-label">价格面议</view>
                    <view class="radio-group">
                        <view class="radio-item" :class="{ active: form.model.is_price_negotiable === 1 }"
                            @click="form.model.is_price_negotiable = 1">是</view>
                        <view class="radio-item" :class="{ active: form.model.is_price_negotiable === 0 }"
                            @click="form.model.is_price_negotiable = 0">否</view>
                    </view>
                    <view class="form-tips">开启后,移动端将显示"价格面议"而非具体价格</view>
                </view>
                <view class="form-item">
                    <view class="item-label">商品图片</view>
                    <view class="uploader">
                        <view class="uploader-item" v-for="(item, index) in form.model.image" :key="index">
operations_vue/src/api/plus/operations.js
New file
@@ -0,0 +1,186 @@
import request from '@/utils/request'
let OperationsApi = {
    /*插件列表*/
    plusList(data, errorback) {
        return request._post('/operations/plus.plus/index', data, errorback);
    },
    /*入驻申请列表*/
    applyList(data, errorback) {
        return request._post('/operations/plus.operations.apply/index', data, errorback);
    },
    /*运营中心审核*/
    editApplyStatus(data, errorback) {
        return request._post('/operations/plus.operations.apply/editApplyStatus', data, errorback);
    },
    /*运营中心列表*/
    operationsList(data, errorback) {
        return request._post('/operations/plus.operations.operations/index', data, errorback);
    },
    /*查看下级用户*/
    operationsUserFans(data, errorback) {
        return request._post('/operations/plus.operations.operations/fans', data, errorback);
    },
    /*修改运营中心*/
    toOperationsEdit(data, errorback) {
        return request._get('/operations/plus.operations.operations/edit', data, errorback);
    },
    /*修改运营中心*/
    operationsEdit(data, errorback) {
        return request._post('/operations/plus.operations.operations/edit', data, errorback);
    },
    /*删除运营中心用户*/
    deleteOperations(data, errorback) {
        return request._post('/operations/plus.operations.operations/delete', data, errorback);
    },
    /*添加运营中心*/
    addOperationsUser(data, errorback) {
        return request._post('/operations/plus.operations.operations/add', data, errorback);
    },
    /*提现申请*/
    cash(data, errorback) {
        return request._post('/operations/plus.operations.cash/index', data, errorback);
    },
    /*运营中心提现审核*/
    cashSubmit(data, errorback) {
        return request._post('/operations/plus.operations.cash/submit', data, errorback);
    },
    /*微信打款*/
    WxPay(data, errorback) {
        return request._post('/operations/plus.operations.cash/wechat_pay', data, errorback);
    },
    /*运营中心确认打款*/
    money(data, errorback) {
        return request._post('/operations/plus.operations.cash/money', data, errorback);
    },
    /*运营中心设置*/
    operationsSet(data, errorback) {
        return request._post('/operations/plus.operations.setting/index', data, errorback);
    },
    /*运营中心设置-基础设置*/
    basic(data, errorback) {
        return request._post('/operations/plus.operations.setting/basic', data, errorback);
    },
    /*运营中心设置-条件*/
    condition(data, errorback) {
        return request._post('/operations/plus.operations.setting/condition', data, errorback);
    },
    /*运营中心设置-分红设置*/
    bonus(data, errorback) {
        return request._post('/operations/plus.operations.setting/bonus', data, errorback);
    },
    /*运营中心设置-结算设置*/
    settlement(data, errorback) {
        return request._post('/operations/plus.operations.setting/settlement', data, errorback);
    },
    /*运营中心设置-自定义文字*/
    words(data, errorback) {
        return request._post('/operations/plus.operations.setting/words', data, errorback);
    },
    /*运营中心设置-申请协议*/
    license(data, errorback) {
        return request._post('/operations/plus.operations.setting/license', data, errorback);
    },
    /*运营中心设置-页面背景*/
    background(data, errorback) {
        return request._post('/operations/plus.operations.setting/background', data, errorback);
    },
    /*运营中心权限管理*/
    /*权限列表*/
    operationsAccessList(data, errorback) {
        return request._post('/operations/plus.operations.access/index', data, errorback);
    },
    /*添加权限*/
    operationsAccessAdd(data, errorback) {
        return request._post('/operations/plus.operations.access/add', data, errorback);
    },
    /*修改权限*/
    operationsAccessEdit(data, errorback) {
        return request._post('/operations/plus.operations.access/edit', data, errorback);
    },
    /*删除权限*/
    operationsAccessDelete(data, errorback) {
        return request._post('/operations/plus.operations.access/delete', data, errorback);
    },
    /*权限状态修改*/
    operationsAccessStatus(data, errorback) {
        return request._post('/operations/plus.operations.access/status', data, errorback);
    },
    /*运营中心角色管理*/
    /*角色列表*/
    operationsRoleList(data, errorback) {
        return request._post('/operations/plus.operations.role/index', data, errorback);
    },
    /*添加角色需要的数据*/
    operationsRoleAddInfo(data, errorback) {
        return request._get('/operations/plus.operations.role/addInfo', data, errorback);
    },
    /*添加角色*/
    operationsRoleAdd(data, errorback) {
        return request._post('/operations/plus.operations.role/add', data, errorback);
    },
    /*修改角色需要的数据*/
    operationsRoleEditInfo(data, errorback) {
        return request._get('/operations/plus.operations.role/editInfo', data, errorback);
    },
    /*修改角色*/
    operationsRoleEdit(data, errorback) {
        return request._post('/operations/plus.operations.role/edit', data, errorback);
    },
    /*删除角色*/
    operationsRoleDelete(data, errorback) {
        return request._post('/operations/plus.operations.role/delete', data, errorback);
    },
    /*运营中心管理员管理*/
    /*管理员列表*/
    operationsAdminList(data, errorback) {
        return request._post('/operations/plus.operations.user/index', data, errorback);
    },
    /*添加管理员*/
    operationsAdminAdd(data, errorback) {
        return request._post('/operations/plus.operations.user/add', data, errorback);
    },
    /*修改管理员需要的数据*/
    operationsAdminEditInfo(data, errorback) {
        return request._get('/operations/plus.operations.user/edit', data, errorback);
    },
    /*修改管理员*/
    operationsAdminEdit(data, errorback) {
        return request._post('/operations/plus.operations.user/edit', data, errorback);
    },
    /*删除管理员*/
    operationsAdminDelete(data, errorback) {
        return request._post('/operations/plus.operations.user/delete', data, errorback);
    },
    /*等级管理*/
    /*等级列表*/
    operationsGradeList(data, errorback) {
        return request._post('/operations/plus.operations.grade/index', data, errorback);
    },
    /*添加等级*/
    operationsGradeAdd(data, errorback) {
        return request._post('/operations/plus.operations.grade/add', data, errorback);
    },
    /*修改等级*/
    operationsGradeEdit(data, errorback) {
        return request._post('/operations/plus.operations.grade/edit', data, errorback);
    },
    /*删除等级*/
    operationsGradeDelete(data, errorback) {
        return request._post('/operations/plus.operations.grade/delete', data, errorback);
    },
    /*运营中心订单*/
    /*订单列表*/
    operationsOrder(data, errorback) {
        return request._post('/operations/plus.operations.order/index', data, errorback);
    },
}
export default OperationsApi;
operations_vue/src/views/plus/operations/apply/apply.vue
New file
@@ -0,0 +1,182 @@
<template>
  <!--
          作者:luoyiming
          时间:2020-06-01
          描述:插件中心-分销-入驻申请
      -->
  <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.nick_name" placeholder="请输入昵称/姓名/手机号"></el-input></el-form-item>
        <el-form-item><el-button type="primary" @click="onSubmit">查询</el-button></el-form-item>
      </el-form>
    </div>
    <!--内容-->
    <div class="product-content">
      <div class="table-wrap">
        <el-table :data="tableData" size="small" border style="width: 100%" v-loading="loading">
          <el-table-column prop="user_id" label="用户ID" width="60"></el-table-column>
          <el-table-column prop="nickName" label="微信头像" width="70">
            <template slot-scope="scope">
              <img class="radius" v-img-url="scope.row.avatarUrl" width="30" height="30" />
            </template>
          </el-table-column>
          <el-table-column prop="nickName" label="    微信昵称"></el-table-column>
          <el-table-column prop="real_name" label="姓名"></el-table-column>
          <el-table-column prop="mobile" label="手机号">
            <template slot-scope="scope">
              <p class="text-ellipsis">{{ scope.row.mobile }}</p>
            </template>
          </el-table-column>
          <el-table-column prop="" label="代理级别/区域">
           <template slot-scope="scope">
             <div>{{scope.row.region_level.text}}</div>
             <div>
               <span>{{scope.row.region.province}}</span>
               <span v-if="scope.row.region_level.value>1">{{scope.row.region.city}}</span>
               <span v-if="scope.row.region_level.value>2">{{scope.row.region.area}}</span>
             </div>
           </template>
         </el-table-column>
          <!-- <el-table-column prop="referee.value" label="推荐人"></el-table-column> -->
          <el-table-column prop="apply_status" label="审核状态">
            <template slot-scope="scope">
              <span :class="{
                red: scope.row.apply_status.value == 10,
                green: scope.row.apply_status.value == 20,
                gray: scope.row.apply_status.value == 30 }">
                {{ scope.row.apply_status.text }}
              </span>
            </template>
          </el-table-column>
          <el-table-column prop="apply_type" label="审核方式    "></el-table-column>
          <el-table-column prop="apply_time" label="申请时间" width="135"></el-table-column>
          <el-table-column fixed="right" label="操作" width="50">
            <template slot-scope="scope">
              <div>
                <el-button v-if="scope.row.apply_status.value == 10" @click="editClick(scope.row)" type="text" size="small" v-auth="'/plus/operations/apply/editApplyStatus'">
                  审核
                </el-button>
                <el-button v-if="scope.row.apply_status.value == 30" @click="editClick(scope.row)" type="text" size="small">查看</el-button>
              </div>
            </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>
    <Edit v-if="open_edit" :operations="operations" :open_edit="open_edit" :form="userModel" @closeDialog="closeDialogFunc($event, 'edit')"></Edit>
  </div>
</template>
<script>
import OperationsApi from '@/api/plus/operations.js';
import Edit from './dialog/Edit.vue';
export default {
  components: {
    /*编辑组件*/
    Edit
  },
  data() {
    return {
      /*是否加载完成*/
      loading: true,
      /*列表数据*/
      tableData: [],
      /*一页多少条*/
      pageSize: 20,
      /*一共多少条数据*/
      totalDataNumber: 0,
      /*当前是第几页*/
      curPage: 1,
      formInline: {
        nick_name: ''
      },
      operations:{},
      /*是否打开编辑弹窗*/
      open_edit: false,
      /*当前编辑的对象*/
      userModel: {}
    };
  },
  created() {
    /*获取列表*/
    this.getData();
  },
  methods: {
    /*选择第几页*/
    handleCurrentChange(val) {
      let self = this;
      self.curPage = val;
      self.loading = true;
      self.getData();
    },
    /*获取数据*/
    getData() {
      let self = this;
      let Params = {};
      Params.page = self.curPage;
      Params.list_rows = self.pageSize;
      Params.nick_name = this.formInline.nick_name;
      OperationsApi.applyList(Params, true)
        .then(data => {
          self.loading = false;
          self.tableData = data.data.apply_list.data;
          self.operations = data.data.operations;
          self.totalDataNumber = data.data.apply_list.total;
        })
        .catch(error => {});
    },
    //搜索
    onSubmit() {
      this.curPage = 1;
      this.getData();
    },
    /*每页多少条*/
    handleSizeChange(val) {
      this.curPage = 1;
      this.getData();
    },
    /*打开弹出层编辑*/
    editClick(item) {
      this.userModel = item;
      this.open_edit = true;
    },
    /*关闭弹窗*/
    closeDialogFunc(e, f) {
      if (f == 'add') {
        this.open_add = e.openDialog;
        if (e.type == 'success') {
          this.getData();
        }
      }
      if (f == 'edit') {
        this.open_edit = e.openDialog;
        if (e.type == 'success') {
          this.getData();
        }
      }
    }
  }
};
</script>
<style></style>
operations_vue/src/views/plus/operations/apply/dialog/Edit.vue
New file
@@ -0,0 +1,304 @@
<template>
  <!--
          作者:luoyiming
          时间:2020-06-01
          描述:插件中心-分销-代理审核
      -->
  <div v-if="status != 30">
    <el-dialog title="代理审核" :visible.sync="dialogVisible" @close="dialogFormVisible" :close-on-click-modal="false" :close-on-press-escape="false" width="600px">
      <el-form :model="form" ref="formRef" label-width="120px">
        <el-form-item label="审核状态">
          <el-radio-group v-model="form.apply_status" @change="handleStatusChange">
            <el-radio label="20">审核通过</el-radio>
            <el-radio label="30">驳回</el-radio>
          </el-radio-group>
        </el-form-item>
        <!-- 审核通过时显示区域和级别选择 -->
        <div v-if="form.apply_status == 20">
          <el-form-item label="运营中心级别">
            <el-select v-model="form.region_level" placeholder="请选择级别" @change="handleLevelChange">
              <el-option label="市级" :value="2" :disabled="operations.operations_level.value != 1"></el-option>
              <el-option label="区县级" :value="3" :disabled="operations.operations_level.value == 3"></el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="省/直辖市">
            <el-select v-model="form.province_id" disabled placeholder="请选择省份" @change="handleProvinceChange" >
              <el-option
                v-for="item in provinceList"
                :key="item.id"
                :label="item.name"
                :value="item.id">
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="城市" v-if="form.region_level >= 2">
            <el-select v-model="form.city_id" placeholder="请选择城市" @change="handleCityChange"  :disabled="operations.operations_level.value != 1">
              <el-option
                v-for="item in cityList"
                :key="item.id"
                :label="item.name"
                :value="item.id">
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="区县" v-if="form.region_level == 3">
            <el-select v-model="form.area_id" placeholder="请选择区县" :disabled="!form.city_id">
              <el-option
                v-for="item in areaList"
                :key="item.id"
                :label="item.name"
                :value="item.id">
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="登录账号" prop="user_name">
            <el-input type="text" v-model="form.user_name" autocomplete="off" placeholder="请输入登录账号"></el-input>
          </el-form-item>
          <el-form-item label="登录密码" prop="password">
            <el-input type="password" v-model="form.password" autocomplete="off" placeholder="请输入登录密码"></el-input>
          </el-form-item>
        </div>
        <!-- 驳回时显示驳回原因 -->
        <div v-if="form.apply_status == 30">
          <el-form-item label="驳回原因">
            <el-input v-model="form.reject_reason" type="textarea" :rows="3" placeholder="请输入驳回原因"></el-input>
          </el-form-item>
        </div>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible">取 消</el-button>
        <el-button type="primary" @click="editApplyStatus" :loading="loading">确 定</el-button>
      </div>
    </el-dialog>
  </div>
  <div v-else>
    <el-dialog title="驳回原因" :visible.sync="dialogVisible" @close="dialogFormVisible" :close-on-click-modal="false" :close-on-press-escape="false">
      <p>{{ reject_reason }}</p>
    </el-dialog>
  </div>
</template>
<script>
import OperationsApi from '@/api/plus/operations.js';
import DataApi from '@/api/data.js';
export default {
  data() {
    return {
      status: '',
      reject_reason: '',
      loading: false,
      /*地区数据*/
      regionData: [],
      /*已存在的运营中心列表*/
      existingOperations: []
    };
  },
  props: ['open_edit', 'form', 'operations'],
  created() {
    this.dialogVisible = this.open_edit;
    this.status = this.form.apply_status.value;
    this.form.province_id = this.operations.province_id;
    this.form.city_id = this.operations.city_id;
    this.form.area_id = this.operations.area_id;
    this.form.region_level = this.operations.operations_level.value+1;
    if (this.status == 30) {
      this.reject_reason = this.form.reject_reason;
    } else {
      // 如果是待审核状态,默认设置为省级
      if (!this.form.region_level) {
        this.form.region_level = 1;
      }
      // 加载地区数据和已存在的运营中心列表
      this.getRegionData();
    }
  },
  computed: {
    /*获取省份列表*/
    provinceList() {
      return Object.values(this.regionData).filter(item => item.level === 1);
    },
    /*获取城市列表*/
    cityList() {
      if (this.form.province_id && this.regionData[this.form.province_id]) {
        const provinceData = this.regionData[this.form.province_id];
        if (provinceData.city) {
          return Object.values(provinceData.city);
        }
      }
      return [];
    },
    /*获取区/县列表*/
    areaList() {
      if (this.form.city_id && this.form.province_id && this.regionData[this.form.province_id]) {
        const provinceData = this.regionData[this.form.province_id];
        if (provinceData.city && provinceData.city[this.form.city_id]) {
          const cityData = provinceData.city[this.form.city_id];
          if (cityData.region) {
            return Object.values(cityData.region);
          }
        }
      }
      return [];
    }
  },
  methods: {
    /*获取地区数据*/
    getRegionData() {
      let self = this;
      DataApi.getRegion({}, true)
        .then(res => {
          self.regionData = res.data.regionData;
        })
        .catch(() => {});
    },
    /*获取已存在的运营中心列表*/
    getExistingOperations() {
      let self = this;
      OperationsApi.operationsList({}, true)
        .then(res => {
          self.existingOperations = res.data.list || [];
        })
        .catch(() => {});
    },
    /*省份改变*/
    handleProvinceChange(val) {
      this.form.city_id = 0;
      this.form.area_id = 0;
      // 省份改变时,重新计算级别是否禁用
      this.$forceUpdate();
    },
    /*城市改变*/
    handleCityChange(val) {
      this.form.area_id = 0;
    },
    /*级别改变*/
    handleLevelChange(val) {
      // 切换级别时清空下级区域
      if (val < 2) {
        this.form.city_id = 0;
        this.form.area_id = 0;
      }
      if (val < 3) {
        this.form.area_id = 0;
      }
    },
    /*审核状态改变*/
    handleStatusChange(val) {
      // 切换到审核通过时,加载数据
      if (val == 20) {
        if (this.regionData.length === 0) {
          this.getRegionData();
        }
        if (this.existingOperations.length === 0) {
          this.getExistingOperations();
        }
      }
    },
    /*修改用户*/
    editApplyStatus() {
      // 验证审核通过时的必填项
      if (this.form.apply_status == 20) {
        if (!this.form.region_level) {
          this.$message.error('请选择运营中心级别');
          return;
        }
        if (!this.form.province_id) {
          this.$message.error('请选择省份');
          return;
        }
        if (this.form.region_level >= 2 && !this.form.city_id) {
          this.$message.error('请选择城市');
          return;
        }
        if (this.form.region_level == 3 && !this.form.area_id) {
          this.$message.error('请选择区县');
          return;
        }
        if (!this.form.user_name) {
          this.$message.error('请输入登录账号');
          return;
        }
        if (!this.form.password) {
          this.$message.error('请输入登录密码');
          return;
        }
        if (this.form.password.length < 6) {
          this.$message.error('密码长度不能少于6位');
          return;
        }
      } else {
        // 驳回时必须填写原因
        if (!this.form.reject_reason) {
          this.$message.error('请输入驳回原因');
          return;
        }
      }
      this.loading = true;
      let self = this;
      let params = {
        apply_id: this.form.apply_id,
        apply_status: this.form.apply_status,
        real_name: this.form.real_name,
        mobile: this.form.mobile,
        user_id: this.form.user_id,
        referee_id: this.form.referee_id,
        region_level: {
          value: this.form.region_level,
          text: this.form.region_level == 1 ? '省级' : (this.form.region_level == 2 ? '市级' : '区县级')
        },
        province_id: this.form.province_id,
        city_id: this.form.city_id || 0,
        area_id: this.form.area_id || 0,
        user_name: this.form.user_name || '',
        password: this.form.password || '',
        reject_reason: this.form.reject_reason || ''
      };
      OperationsApi.editApplyStatus(params, true)
        .then(data => {
          self.$message({
            message: '恭喜你,修改成功',
            type: 'success'
          });
          self.dialogFormVisible(true);
        })
        .catch(error => {
          this.loading = false;
        });
    },
    /*关闭弹窗*/
    dialogFormVisible(e) {
      if (e) {
        this.$emit('closeDialog', {
          type: 'success',
          openDialog: false
        });
      } else {
        this.$emit('closeDialog', {
          type: 'error',
          openDialog: false
        });
      }
    }
  }
};
</script>
<style></style>
operations_vue/src/views/plus/operations/auth/access/Index.vue
New file
@@ -0,0 +1,288 @@
<template>
  <!--
        作者:参考 access/Index.vue
        时间:2026-01-20
        描述:区域代理商-菜单&权限
    -->
  <div class="product">
    <!--添加菜单&权限-->
    <div class="common-level-rail d-b-c">
      <el-button size="small" type="primary" @click="addClick" icon="el-icon-plus">添加菜单&权限</el-button>
      <el-form :inline="true" :model="formSearch" size="small">
        <el-form-item>
          <el-checkbox v-model="formSearch.is_menu" @change="changeIsMenuFunc">只显示菜单</el-checkbox>
          <el-checkbox v-model="formSearch.pack_up" @change="changePackUpFunc">收起</el-checkbox>
        </el-form-item>
      </el-form>
    </div>
    <!--内容-->
    <div class="product-content">
      <div class="table-wrap">
        <div>
          <el-table
            size="small"
            :data="tableData"
            style="width: 100%;margin-bottom: 20px;"
            row-key="access_id"
            border
            default-expand-all
            ref="theTable"
            :tree-props="{ children: 'children' }"
            v-loading="loading"
          >
            <el-table-column prop="name" label="菜单名称">
              <template slot-scope="scope">
                <span v-if="scope.row.path=='/plus'" class="fb red f18">
                  {{scope.row.name}}
                </span>
                <span v-else>
                  {{scope.row.name}}
                </span>
              </template>
            </el-table-column>
            <el-table-column prop="path" label="路径"></el-table-column>
            <el-table-column prop="is_route" label="类别" width="90">
              <template slot-scope="scope">
                <span v-if="scope.row.is_route==1">页面</span>
                <span v-if="scope.row.is_route==0">按钮</span>
                <span v-if="scope.row.is_route==2">独立单页面</span>
              </template>
            </el-table-column>
            <el-table-column prop="is_show" label="是否显示" width="80">
              <template slot-scope="scope">
                <el-switch
                  v-model="scope.row.is_show"
                  :active-value="1"
                  :inactive-value="0"
                  @change="isShowFunc(scope.row)"
                  active-color="#13ce66"
                  inactive-color="#cccccc"
                ></el-switch>
              </template>
            </el-table-column>
            <el-table-column prop="sort" label="排序" width="60"></el-table-column>
            <el-table-column prop="create_time" label="添加时间" width="140"></el-table-column>
            <el-table-column prop="name" label="操作" width="230">
              <template slot-scope="scope">
                <el-button @click="addClick(scope.row,'copy')" type="text" size="small" v-if="scope.row.path!='/plus'">一键复制</el-button>
                <el-button @click="addClick(scope.row,'child')" type="text" size="small">添加子菜单</el-button>
                <el-button @click="editClick(scope.row)" type="text" size="small">编辑</el-button>
                <el-button @click="deleteClick(scope.row)" type="text" size="small" v-if="scope.row.path!='/plus'">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
        </div>
      </div>
    </div>
    <!--添加-->
    <Add v-if="open_add" :open_add="open_add" :add_type="add_type" :rawData="rawData" :selectModel="selectModel" @closeDialog="closeDialogFunc($event, 'add')"></Add>
    <!--编辑-->
    <Edit v-if="open_edit" :open_edit="open_edit" :rawData="rawData" :selectModel="selectModel" @closeDialog="closeDialogFunc($event, 'edit')"></Edit>
  </div>
</template>
<script>
import PlusApi from '@/api/plus/region.js';
import Edit from './part/Edit.vue';
import Add from './part/Add.vue';
import { deepClone } from '@/utils/base.js';
export default {
  components: {
    /*编辑组件*/
    Edit: Edit,
    Add: Add
  },
  data() {
    return {
      /*是否正在加载*/
      loading: true,
      /*筛选搜索*/
      formSearch: {
        /*是否只显示菜单*/
        is_menu: false,
        /*是否收起*/
        pack_up: false
      },
      /*原始数据*/
      rawData: [],
      /*表格数据*/
      tableData: [],
      /*是否打开添加弹窗*/
      open_add: false,
      /*添加类型*/
      add_type:'',
      /*选中的对象*/
      selectModel:{},
      /*是否打开编辑弹窗*/
      open_edit: false,
      /*当前编辑的对象*/
      userModel: {},
    };
  },
  created() {
    /*获取列表*/
    this.getTableList();
  },
  methods: {
    /*列表是否只显示菜单*/
    changeIsMenuFunc(e) {
      let list = deepClone(this.rawData);
      if (e) {
        this.showScreen(list, 1);
        this.tableData = list;
      } else {
        this.tableData = list;
      }
    },
    /*是否显示开关*/
    isShowFunc(e) {
      let self = this;
      PlusApi.regionAccessStatus({ access_id: e.access_id, status: e.is_show }, true)
        .then(data => {
          if (data.code == 1) {
            self.$message({
              message: data.msg,
              type: 'success'
            });
            self.getTableList();
          }
        })
        .catch(error => {
          self.loading = false;
        });
    },
    /*是否收起*/
    changePackUpFunc(e) {
      this.forArr(this.tableData, !e);
    },
    /*列表收起*/
    forArr(arr, isExpand) {
      arr.forEach(i => {
        this.$refs.theTable.toggleRowExpansion(i, isExpand);
        if (i.children) {
          this.forArr(i.children, isExpand);
        }
      });
    },
    /*切换显示类别*/
    changeShowFunc(e) {
      let list = deepClone(this.rawData);
      if (e == 'all') {
        this.tableData = list;
      } else {
        let type;
        if (e == 'show') {
          type = 1;
        }
        if (e == 'hide') {
          type = 0;
        }
        this.showScreen(list, type);
        this.tableData = list;
      }
    },
    /*显示筛选*/
    showScreen(list, type) {
      for (let i = 0; i < list.length; i++) {
        let item = list[i];
        if (typeof item.is_menu != 'undefined' && item.is_menu != type) {
          list.splice(i, 1);
          i--;
        } else {
          if (item.children.length > 0) {
            this.showScreen(item.children, type);
          }
        }
      }
    },
    /*获取列表*/
    getTableList() {
      let self = this;
      let Params = {};
      PlusApi.regionAccessList(Params, true)
        .then(res => {
          self.loading = false;
          self.rawData = res.data;
          self.tableData = res.data;
        })
        .catch(error => {
          self.loading = false;
        });
    },
    /*打开添加*/
    addClick(e,type) {
      if(e&&typeof(e)!='undefined'){
        this.add_type=type;
        this.selectModel=deepClone(e);
      }else{
        this.parents_id=0;
      }
      this.open_add = true;
    },
    /*打开编辑*/
    editClick(item) {
      this.selectModel = item;
      this.open_edit = true;
    },
    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();
        }
      }
    },
    /*删除用户*/
    deleteClick(row) {
      let self = this;
      self
        .$confirm('删除后不可恢复,确认删除该记录吗?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
        .then(() => {
          self.loading = true;
          PlusApi.regionAccessDelete(
            {
              access_id: row.access_id
            },
            true
          )
            .then(data => {
              if (data.code == 1) {
                self.loading = false;
                self.$message({
                  message: data.msg,
                  type: 'success'
                });
                self.getTableList();
              }
            })
            .catch(error => {
              self.loading = false;
            });
        })
        .catch(() => {});
    }
  }
};
</script>
operations_vue/src/views/plus/operations/auth/access/part/Add.vue
New file
@@ -0,0 +1,218 @@
<template>
  <!--
        作者:参考 access/part/Add.vue
        时间:2026-01-20
        描述:区域代理商权限管理-添加菜单&权限
    -->
  <el-dialog title="添加菜单&权限" :visible.sync="dialogVisible" @close="dialogFormVisible" :close-on-click-modal="false" :close-on-press-escape="false">
    <el-form size="small" :model="formData" :rules="formRules" ref="form">
      <!--菜单名称-->
      <el-form-item label="菜单名称" prop="name" :label-width="formLabelWidth">
        <el-input v-model="formData.name" autocomplete="off" placeholder="请输入菜单名称"></el-input>
      </el-form-item>
      <!--类型-->
      <el-form-item label="类型" prop="name" :label-width="formLabelWidth">
        <el-radio-group v-model="formData.is_route">
          <el-radio :label="1">页面</el-radio>
          <el-radio :label="0">按钮</el-radio>
          <el-radio :label="2">独立单页面</el-radio>
        </el-radio-group>
      </el-form-item>
      <!--上级菜单-->
      <el-form-item label="上级菜单" prop="parent_id" :label-width="formLabelWidth">
        <el-cascader size="small" v-model="parentsVal" :options="accessList" :props="propsParam" @change="handleChange"></el-cascader>
      </el-form-item>
      <!--路径-->
      <el-form-item label="路径" prop="path" :label-width="formLabelWidth">
        <el-input v-model="formData.path" autocomplete="off" placeholder="请输入组件文件路径"></el-input>
        <p>提示:对应前端给的文件路径,例如:/index/index</p>
      </el-form-item>
      <!--图标-->
      <el-form-item label="图标" :label-width="formLabelWidth">
        <el-input v-model="formData.icon" autocomplete="off" placeholder="请输入icon"></el-input>
        <p>提示:请选择系统提供的图标</p>
      </el-form-item>
      <!--是否是菜单-->
      <el-form-item label="是否是菜单" :label-width="formLabelWidth" v-if="formData.is_route==1">
        <el-radio-group v-model="formData.is_menu">
          <el-radio :label="1">是</el-radio>
          <el-radio :label="0">否</el-radio>
        </el-radio-group>
      </el-form-item>
      <!--是否显示-->
      <el-form-item label="是否显示" :label-width="formLabelWidth">
        <el-radio-group v-model="formData.is_show">
          <el-radio :label="1">是</el-radio>
          <el-radio :label="0">否</el-radio>
        </el-radio-group>
      </el-form-item>
      <!--重定向-->
      <el-form-item label="重定向" :label-width="formLabelWidth" v-if="formData.is_route == 1">
        <el-input v-model="formData.redirect_name" autocomplete="off" placeholder="请输入重定向地址"></el-input>
      </el-form-item>
      <!--备注-->
      <el-form-item label="备注" prop="sort" :label-width="formLabelWidth">
        <el-input v-model="formData.remark" placeholder="请输入备注" type="textarea"></el-input>
      </el-form-item>
      <!--排序-->
      <el-form-item label="排序" prop="sort" :label-width="formLabelWidth">
        <el-input v-model="formData.sort" placeholder="请输入排序" type="number"></el-input>
      </el-form-item>
    </el-form>
    <!--操作按钮-->
    <div slot="footer" class="dialog-footer">
      <el-button @click="dialogFormVisible">取 消</el-button>
      <el-button type="primary" @click="onSubmit()" :disabled="loading">确 定</el-button>
    </div>
  </el-dialog>
</template>
<script>
import PlusApi from '@/api/plus/region.js';
import { deepClone, formatModel } from '@/utils/base.js';
export default {
  data() {
    return {
      /*是否加载中*/
      loading: false,
      /*form表单数据对象*/
      formData: {
        /*菜单名称*/
        name: '',
        /*路由地址*/
        path: '',
        /*组件名*/
        views: '',
        /*别名*/
        alias: '',
        /*图标*/
        icon: '',
        /*是否是菜单*/
        is_menu: 0,
        /*是否是路由*/
        is_route: 1,
        /*是否显示*/
        is_show: 1,
        /*排序*/
        sort: 1,
        /*父集ID*/
        parent_id: 0
      },
      /*验证规则*/
      formRules: {
        name: [{ required: true, message: '请输入菜单名称', trigger: 'blur' }],
        path: [{ required: true, message: '请输入路径', trigger: 'blur' }],
        views: [{ required: true, message: '请输入组件名称', trigger: 'blur' }],
        alias: [{ required: true, message: '请输入别名', trigger: 'blur' }]
      },
      /*当前父集ID*/
      parentsVal: [],
      /*菜单列表*/
      accessList: [],
      /*排序*/
      srot: '1',
      /*左边长度*/
      formLabelWidth: '120px',
      /*是否显示*/
      dialogVisible: false,
      /*展示数据*/
      propsParam: {
        label: 'name',
        value: 'access_id',
        checkStrictly: true
      }
    };
  },
  props: {
    open_add: Boolean,
    add_type: String,
    rawData: Array,
    selectModel: Object
  },
  created() {
    this.dialogVisible = this.open_add;
    this.accessList = deepClone(this.rawData);
    this.accessList.unshift({ name: '顶级菜单', access_id: 0 });
    if (this.add_type == 'copy') {
      this.formData = formatModel(this.formData, this.selectModel);
      this.findParentsID(this.accessList);
    } else if (this.add_type == 'child') {
      this.formData.parent_id = this.selectModel.access_id;
      this.findParentsID(this.accessList);
    }
  },
  methods: {
    /*选择菜单*/
    handleChange(e) {},
    /*查找父集id*/
    findParentsID(list){
      let flag=false;
      for(let i=0;i<list.length;i++){
        let item=list[i];
        if(item.access_id==this.formData.parent_id){
          this.parentsVal.unshift(item.access_id);
          flag=true;
          break;
        }else{
          let children=item.children;
          if(typeof children!='undefined'&&children.length>0){
              if(this.findParentsID(children)){
                this.parentsVal.unshift(item.access_id);
                flag=true;
                break;
              }
          }
        }
      }
      return flag;
    },
    /*添加菜单*/
    onSubmit() {
      let self = this;
      let params = this.formData;
      if (self.parentsVal.length > 0) {
        params.parent_id = self.parentsVal[self.parentsVal.length - 1];
      }
      self.$refs.form.validate(valid => {
        if (valid) {
          self.loading = true;
          PlusApi.regionAccessAdd(params, true)
            .then(res => {
              if (res.code == 1) {
                self.$message({
                  message: res.msg,
                  type: 'success'
                });
                self.dialogFormVisible(true);
                self.loading = false;
              }
            })
            .catch(error => {
              self.loading = false;
            });
        }
      });
    },
    /*关闭弹窗*/
    dialogFormVisible(e) {
      if (e) {
        this.$emit('closeDialog', {
          type: 'success',
          openDialog: false
        });
      } else {
        this.$emit('closeDialog', {
          type: 'error',
          openDialog: false
        });
      }
    }
  }
};
</script>
<style></style>
operations_vue/src/views/plus/operations/auth/access/part/Edit.vue
New file
@@ -0,0 +1,210 @@
<template>
  <!--
        作者:参考 access/part/Edit.vue
        时间:2026-01-20
        描述:区域代理商权限管理-修改菜单&权限
    -->
  <el-dialog title="修改菜单&权限" :visible.sync="dialogVisible" @close="dialogFormVisible" :close-on-click-modal="false" :close-on-press-escape="false">
    <el-form size="small" :model="formData" :rules="formRules" ref="form">
      <!--菜单名称-->
      <el-form-item label="菜单名称" prop="name" :label-width="formLabelWidth">
        <el-input v-model="formData.name" autocomplete="off" placeholder="请输入菜单名称"></el-input>
      </el-form-item>
      <!--类型-->
      <el-form-item label="类型" prop="name" :label-width="formLabelWidth">
        <el-radio-group v-model="formData.is_route">
          <el-radio :label="1">页面</el-radio>
          <el-radio :label="0">按钮</el-radio>
          <el-radio :label="2">独立单页面</el-radio>
        </el-radio-group>
      </el-form-item>
      <!--上级菜单-->
      <el-form-item label="上级菜单" prop="parent_id" :label-width="formLabelWidth">
        <el-cascader size="small" v-model="parentsVal" :options="accessList" :props="propsParam" @change="handleChange"></el-cascader>
      </el-form-item>
      <!--路径-->
      <el-form-item label="路径" prop="path" :label-width="formLabelWidth">
        <el-input v-model="formData.path" autocomplete="off" placeholder="请输入组件文件路径" :disabled="formData.path=='/plus'"></el-input>
        <p>提示:对应前端给的文件路径,例如:index/index</p>
      </el-form-item>
      <!--图标-->
      <el-form-item label="图标" :label-width="formLabelWidth">
        <el-input v-model="formData.icon" autocomplete="off" placeholder="请输入icon"></el-input>
        <p>提示:请选择系统提供的图标</p>
      </el-form-item>
      <!--是否是菜单-->
      <el-form-item label="是否是菜单" :label-width="formLabelWidth" v-if="formData.is_route==1">
        <el-radio-group v-model="formData.is_menu">
          <el-radio :label="1">是</el-radio>
          <el-radio :label="0">否</el-radio>
        </el-radio-group>
      </el-form-item>
      <!--是否显示-->
      <el-form-item label="是否显示" :label-width="formLabelWidth">
        <el-radio-group v-model="formData.is_show">
          <el-radio :label="1">是</el-radio>
          <el-radio :label="0">否</el-radio>
        </el-radio-group>
      </el-form-item>
      <!--重定向-->
      <el-form-item label="重定向" :label-width="formLabelWidth" v-if="formData.is_route == 1">
        <el-input v-model="formData.redirect_name" autocomplete="off" placeholder="请输入重定向地址"></el-input>
      </el-form-item>
      <!--备注-->
      <el-form-item label="备注" prop="sort" :label-width="formLabelWidth">
        <el-input v-model="formData.remark" placeholder="请输入备注" type="textarea"></el-input>
      </el-form-item>
      <!--排序-->
      <el-form-item label="排序" prop="sort" :label-width="formLabelWidth"><el-input v-model="formData.sort" placeholder="请输入排序" type="number"></el-input></el-form-item>
    </el-form>
    <!--操作按钮-->
    <div slot="footer" class="dialog-footer">
      <el-button @click="dialogFormVisible">取 消</el-button>
      <el-button type="primary" @click="onSubmit()" :disabled="loading">确 定</el-button>
    </div>
  </el-dialog>
</template>
<script>
import PlusApi from '@/api/plus/region.js';
import { deepClone } from '@/utils/base.js';
export default {
  data() {
    return {
      /*是否加载中*/
      loading: false,
      /*form表单数据对象*/
      formData: {
        /*菜单名称*/
        name: '',
        /*路由地址*/
        path:'',
        /*组件名*/
        views:'',
        /*别名*/
        alias:'',
        /*图标*/
        icon:'',
        /*是否是菜单*/
        is_menu: 1,
        /*是否是路由*/
        is_route: 1,
        /*是否显示*/
        is_show: 0,
        /*排序*/
        sort: 1,
        /*父集ID*/
        parent_id: 0
      },
      /*验证规则*/
      formRules: {
        name: [{ required: true, message: '请输入菜单名称', trigger: 'blur' }],
        path: [{ required: true, message: '请输入路径', trigger: 'blur' }],
        views: [{ required: true, message: '请输入组件名称', trigger: 'blur' }],
        alias: [{ required: true, message: '请输入别名', trigger: 'blur' }]
      },
      /*当前父集ID*/
      parentsVal: [],
      /*菜单列表*/
      accessList: [],
      /*排序*/
      srot: '1',
      /*左边长度*/
      formLabelWidth: '120px',
      /*是否显示*/
      dialogVisible: false,
      /*展示数据*/
      propsParam: {
        label: 'name',
        value: 'access_id',
        checkStrictly: true
      }
    };
  },
  props: {
    open_edit:Boolean,
    add_type:String,
    rawData:Array,
    selectModel:Object
  },
  created() {
    this.dialogVisible = this.open_edit;
    this.accessList = deepClone(this.rawData);
    this.accessList.unshift({name:'顶级菜单',access_id:0})
    this.formData=deepClone(this.selectModel);
    this.findParentsID(this.accessList);
  },
  methods: {
    /*选择菜单*/
    handleChange(e) {
    },
    /*查找父集id*/
    findParentsID(list){
      let flag=false;
      for(let i=0;i<list.length;i++){
        let item=list[i];
        if(item.access_id==this.formData.parent_id){
          this.parentsVal.unshift(item.access_id);
          flag=true;
          break;
        }else{
          let children=item.children;
          if(typeof children!='undefined'&&children.length>0){
              if(this.findParentsID(children)){
                this.parentsVal.unshift(item.access_id);
                flag=true;
                break;
              }
          }
        }
      }
      return flag;
    },
    /*修改菜单*/
    onSubmit() {
      let self = this;
      let params = self.formData;
      if(self.parentsVal.length>0){
        params.parent_id=self.parentsVal[self.parentsVal.length-1];
      }
      self.$refs.form.validate(valid => {
        if (valid) {
          self.loading = true;
          PlusApi.regionAccessEdit(params, true)
            .then(res => {
              if (res.code == 1) {
                self.$message({
                  message: res.msg,
                  type: 'success',
                });
                self.$emit('closeDialog', {
                  type: 'success',
                  openDialog: false,
                  data:params
                });
                self.loading = false;
              }
            })
            .catch(error => {
              self.loading = false;
            });
        }
      });
    },
    /*关闭弹窗*/
    dialogFormVisible(e) {
      this.$emit('closeDialog', {
        type: 'error',
        openDialog: false
      });
    }
  }
};
</script>
<style></style>
operations_vue/src/views/plus/operations/auth/index.vue
New file
@@ -0,0 +1,35 @@
<template>
  <div>
    <el-tabs size="small" v-model="activeName" type="card" @tab-click="handleClick">
      <el-tab-pane label="管理员" name="user"></el-tab-pane>
      <el-tab-pane label="角色" name="role"></el-tab-pane>
    </el-tabs>
    <!--角色管理-->
    <Role v-if="activeName == 'role'"></Role>
    <!--管理员列表-->
    <User v-if="activeName == 'user'"></User>
  </div>
</template>
<script>
import Role from './role/Index';
import User from './user/Admin';
export default {
  components: {
    Role,
    User
  },
  data() {
    return {
      /*当前选中*/
      activeName: 'user',
    };
  },
  created() {},
  methods: {
    handleClick(e) {
      this.activeName = e.name;
    }
  }
};
</script>
operations_vue/src/views/plus/operations/auth/role/Index.vue
New file
@@ -0,0 +1,142 @@
<template>
  <!--
        作者:参考 auth/role
        时间:2026-01-20
        描述:区域代理商-角色管理
    -->
  <div class="user">
    <div class="common-level-rail">
      <el-button size="small" type="primary" icon="el-icon-plus" v-auth="'/plus/operations/auth/role/add'" @click="addClick">添加角色</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="role_id" label="角色ID"></el-table-column>
          <el-table-column prop="role_name" label="角色名称"></el-table-column>
          <el-table-column prop="sort" label="排序"></el-table-column>
          <el-table-column prop="create_time" label="添加时间"></el-table-column>
          <el-table-column fixed="right" label="操作" width="150">
            <template slot-scope="scope">
              <el-button @click="editClick(scope.row)" v-auth="'/plus/operations/auth/role/edit'" type="text" size="small">编辑</el-button>
              <el-button @click="deleteClick(scope.row)" v-if="scope.row.region_level == 0" v-auth="'/plus/operations/auth/role/delete'" type="text" size="small">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
    </div>
  </div>
</template>
<script>
import PlusApi from '@/api/plus/operations.js';
export default {
  data() {
    return {
      /*是否加载完成*/
      loading: true,
      /*列表数据*/
      tableData: [],
      /*是否打开添加弹窗*/
      open_add: false,
      /*是否打开编辑弹窗*/
      open_edit: false,
      /*当前编辑的对象*/
      curModel: {}
    };
  },
  created() {
    /*获取列表*/
    this.getTableList();
  },
  methods: {
    /*获取列表*/
    getTableList() {
      let self = this;
      let Params = {};
      PlusApi.operationsRoleList(Params, true)
        .then(data => {
          self.loading = false;
          self.tableData = data.data.list;
        })
        .catch(error => {
          self.loading = false;
        });
    },
    /*打开添加*/
    addClick() {
      this.$router.push('/plus/operations/auth/role/add');
    },
    /*关闭添加*/
    closeAdd(e){
      this.open_add = false;
      if(e.type=='success'){
        this.getTableList();
      }
    },
    /*打开编辑*/
    editClick(row) {
      this.curModel = row;
      this.$router.push({
        path: '/plus/region/auth/role/edit',
        query: {
          role_id: row.role_id,
          scene: 'edit'
        }
      });
      //this.open_edit = true;
    },
    /*关闭编辑*/
    closeEdit(e){
      this.open_edit = false;
      if(e.type=='success'){
        this.getTableList();
      }
    },
    /*删除*/
    deleteClick(row) {
      let self = this;
      self
        .$confirm('此操作将永久删除该记录, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
        .then(() => {
          self.loading = true;
          PlusApi.regionRoleDelete(
            {
              role_id: row.role_id
            },
            true
          )
            .then(data => {
              self.loading = false;
              if (data.code == 1) {
                self.$message({
                  message: '恭喜你,该角色删除成功',
                  type: 'success'
                });
                self.getTableList();
              } else {
                self.loading = false;
              }
            })
            .catch(error => {
              self.loading = false;
            });
        })
        .catch(() => {});
    }
  }
};
</script>
<style></style>
operations_vue/src/views/plus/operations/auth/role/add.vue
New file
@@ -0,0 +1,179 @@
<template>
  <!--
        作者:参考 auth/role/add
        时间:2026-01-21
        描述:区域代理商-角色管理-添加角色
    -->
  <div v-loading="loading">
    <!--form表单-->
    <el-form size="small" ref="form" :model="form" :rules="formRules" label-width="180px">
      <!--添加门店-->
      <div class="common-form">添加角色</div>
      <el-form-item label="角色名称:" prop="role_name">
        <el-input v-model="form.role_name" placeholder="请输入角色名称" class="max-w460"></el-input>
      </el-form-item>
      <el-form-item label="权限列表:" v-model="form.access_id">
        <el-tree :data="treeData" show-checkbox node-key="access_id" :default-expand-all="true" :default-checked-keys="[]" :props="defaultProps" @check="handleCheckChange"></el-tree>
      </el-form-item>
      <el-form-item label="排序:"><el-input type="number" v-model="form.sort" placeholder="请输入排序数字,数字越小越靠前" class="max-w460"></el-input></el-form-item>
      <!--提交-->
      <div class="common-button-wrapper">
        <el-button size="small" type="info" @click="cancelFunc">取消</el-button>
        <el-button type="primary" size="small" @click="onSubmit" :loading="loading">提交</el-button>
      </div>
    </el-form>
  </div>
</template>
<script>
import PlusApi from '@/api/plus/region.js';
export default {
  data() {
    return {
      /*是否正在加载*/
      loading:true,
      /*form表单数据对象*/
      form: {
        access_id: [],
        sort: 100
      },
      data: [], // 原始数据
      treeData: [], // 树形结构数据
      roleList: [],
      defaultProps: {
        children: 'children',
        label: 'name'
      },
      /*form验证*/
      formRules: {
        role_name: [
          {
            required: true,
            message: '请输入角色名称',
            trigger: 'blur'
          }
        ],
        sort: [
          {
            required: true,
            message: '请输入排序',
            trigger: 'blur'
          }
        ]
      },
    };
  },
  created() {
    /*获取数据*/
    this.getData();
  },
  methods: {
    /*添加角色*/
    onSubmit() {
      let self = this;
      let form = self.form;
      self.$refs.form.validate(valid => {
        if (valid) {
          self.loading = true;
          PlusApi.regionRoleAdd({
            params: JSON.stringify(form)
          }, true)
            .then(data => {
              self.loading = false;
              self.$message({
                message: '添加成功',
                type: 'success'
              });
              self.$router.push('/plus/region/auth/role/index');
            })
            .catch(error => {
              self.loading = false;
            });
        }
      });
    },
    /*获取数据*/
    getData() {
      let self = this;
      PlusApi.regionRoleAddInfo()
        .then(data => {
          self.data = data.data.menu;
          self.treeData = self.buildTree(self.data); // 构建树形结构
          self.roleList = data.data.roleList;
          self.loading = false;
        })
        .catch(error => {
          self.loading = false;
        });
    },
    // 将扁平化数据转换为树形结构
    buildTree(data) {
      if (!data || !Array.isArray(data)) {
        return [];
      }
      // 创建映射表
      const map = {};
      const roots = [];
      // 首先创建映射
      for (let i = 0; i < data.length; i++) {
        map[data[i].access_id] = i;
        // 初始化children数组
        data[i].children = [];
      }
      // 然后建立父子关系
      for (let i = 0; i < data.length; i++) {
        const node = data[i];
        if (node.parent_id === 0 || node.parent_id === '0') {
          // 如果parent_id为0,则为根节点
          roots.push(node);
        } else {
          // 查找父节点
          const parentId = node.parent_id;
          if (map.hasOwnProperty(parentId)) {
            // 将当前节点添加到其父节点的children数组中
            data[map[parentId]].children.push(node);
          } else {
            // 如果找不到父节点,也作为根节点处理
            roots.push(node);
          }
        }
      }
      return roots;
    },
    //监听选中
    handleCheckChange(data, checked) {
      this.form.access_id = checked.checkedKeys.concat(checked.halfCheckedKeys);
    },
    /*取消*/
    cancelFunc() {
      this.$router.back(-1);
    }
  }
};
</script>
<style lang="scss" scoped>
.basic-setting-content {
}
.product-add {
  padding-bottom: 50px;
}
.img {
  margin-top: 10px;
}
</style>
operations_vue/src/views/plus/operations/auth/role/edit.vue
New file
@@ -0,0 +1,228 @@
<template>
  <!--
        作者:参考 auth/role/edit
        时间:2026-01-21
        描述:区域代理商-角色管理-编辑角色
    -->
  <div v-loading="loading">
    <!--form表单-->
    <el-form size="small" ref="form" :model="form" :rules="formRules" label-width="180px">
      <!--编辑角色-->
      <div class="common-form">编辑角色</div>
      <el-form-item label="角色名称:" prop="role_name">
        <el-input v-model="form.role_name" placeholder="请输入角色名称" class="max-w460"></el-input>
      </el-form-item>
      <el-form-item label="权限列表:" v-model="form.access_id">
        <el-tree
          :data="treeData"
          show-checkbox
          node-key="access_id"
          :default-expand-all="true"
          :default-checked-keys="select_menu"
          :props="defaultProps"
          @check="handleCheckChange"
        ></el-tree>
      </el-form-item>
      <el-form-item label="排序:"><el-input type="number" v-model="form.sort" placeholder="请输入排序数字,数字越小越靠前" class="max-w460"></el-input></el-form-item>
      <!--提交-->
      <div class="common-button-wrapper">
        <el-button size="small" type="info" @click="cancelFunc">取消</el-button>
        <el-button type="primary" size="small" @click="onSubmit" :loading="loading">提交</el-button>
      </div>
    </el-form>
  </div>
</template>
<script>
import PlusApi from '@/api/plus/region.js';
export default {
  data() {
    return {
      /*是否正在加载*/
      loading:true,
      /*表单数据对象*/
      form: {
        access_id: [],
      },
      data: [], // 原始数据
      treeData: [], // 树形结构数据
      /*角色列表*/
      roleList: [],
      /*权限选中*/
      select_menu: [],
      /*权限树菜单重新自定义字段*/
      defaultProps: {
        children: 'children',
        label: 'name'
      },
      role_id: 0,
      /*form验证*/
      formRules: {
        role_name: [
          {
            required: true,
            message: '请输入角色名称',
            trigger: 'blur'
          }
        ],
        sort: [
          {
            required: true,
            message: '请输入排序',
            trigger: 'blur'
          }
        ]
      },
    };
  },
  created() {
    this.role_id = this.$route.query.role_id;
    /*获取数据*/
    this.getData();
  },
  methods: {
    /*修改角色*/
    onSubmit() {
      let self = this;
      let form = self.form;
      self.$refs.form.validate(valid => {
        if (valid) {
          self.loading = true;
          PlusApi.regionRoleEdit({
            role_id: self.role_id,
            params: JSON.stringify(form)
          }, true)
            .then(data => {
              self.loading = false;
              self.$message({
                message: '修改成功',
                type: 'success'
              });
              self.$router.push('/plus/region/auth/role/index');
            })
            .catch(error => {
              self.loading = false;
            });
        }
      });
    },
    /*获取所有的数据*/
    getData() {
      let self = this;
      PlusApi.regionRoleEditInfo({
        role_id: self.role_id
      })
        .then(data => {
          self.treeData = data.data.accessList;
          //self.treeData = self.buildTree(self.data); // 构建树形结构
          self.select_menu = data.data.select_menu;
          self.form = data.data.model;
          self.roleList = data.data.roleList;
          if (self.form.parent_id == 0) {
            self.form.parent_id = 0 + '';
          }
          self.loading = false;
        })
        .catch(error => {
          self.loading = false;
        });
    },
    // 将扁平化数据转换为树形结构
    buildTree(data) {
      if (!data || !Array.isArray(data)) {
        return [];
      }
      // 创建映射表
      const map = {};
      const roots = [];
      // 首先创建映射
      for (let i = 0; i < data.length; i++) {
        map[data[i].access_id] = i;
        // 初始化children数组
        data[i].children = [];
      }
      // 然后建立父子关系
      for (let i = 0; i < data.length; i++) {
        const node = data[i];
        if (node.parent_id === 0 || node.parent_id === '0') {
          // 如果parent_id为0,则为根节点
          roots.push(node);
        } else {
          // 查找父节点
          const parentId = node.parent_id;
          if (map.hasOwnProperty(parentId)) {
            // 将当前节点添加到其父节点的children数组中
            data[map[parentId]].children.push(node);
          } else {
            // 如果找不到父节点,也作为根节点处理
            roots.push(node);
          }
        }
      }
      return roots;
    },
    /*清除数据*/
    clearData(list, authlist) {
      let total = 0;
      let leng = list.length;
      for (let i = 0; i < leng; i++) {
        let item = list[i];
        if (item.children != null && item.children.length > 0) {
          let flag = this.clearData(item.children, authlist);
          if (!flag) {
            let _index = authlist.indexOf(item.access_id);
            if (_index >= 0) {
              authlist.splice(_index, 1);
            }
          }
        }
        if (authlist.indexOf(item.access_id) != -1) {
          total++;
        }
      }
      if (total < leng) {
        return false;
      } else {
        return true;
      }
    },
    /*监听选中*/
    handleCheckChange(data, checked) {
      this.form.access_id = checked.checkedKeys.concat(checked.halfCheckedKeys);
    },
    /*取消*/
    cancelFunc() {
      this.$router.back(-1);
    }
  }
};
</script>
<style lang="scss" scoped>
.basic-setting-content {
}
.product-add {
  padding-bottom: 50px;
}
.img {
  margin-top: 10px;
}
</style>
operations_vue/src/views/plus/operations/auth/user/Admin.vue
New file
@@ -0,0 +1,203 @@
<template>
  <!--
        作者:参考 auth/user
        时间:2026-01-20
        描述:区域代理商-管理员列表
    -->
  <div class="user">
    <!--添加管理员-->
    <div class="common-level-rail">
      <el-button size="small" type="primary" icon="el-icon-plus" @click="addClick" v-auth="'/plus/region/user/admin/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="region_user_id" label="管理员ID"></el-table-column>
          <el-table-column prop="user_name" label="用户名"></el-table-column>
          <el-table-column prop="role.role_name" label="所属角色">
            <template slot-scope="scope">
              <div>
                <span class="mr10 green" v-for="(item, index) in scope.row.roles" :key="index">{{ item.role.role_name }}</span>
              </div>
            </template>
          </el-table-column>
          <el-table-column prop="real_name" label="姓名"></el-table-column>
          <el-table-column prop="create_time" label="添加时间"></el-table-column>
          <el-table-column fixed="right" label="操作" width="90">
            <template slot-scope="scope">
              <el-button v-if="scope.row.is_super < 1" @click="editClick(scope.row)" type="text" size="small" v-auth="'/plus/region/user/admin/edit'">编辑</el-button>
              <el-button v-if="scope.row.is_super < 1" @click="deleteClick(scope.row)" type="text" size="small" v-auth="'/plus/region/user/admin/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>
    <Add :open="open_add" :roleList="roleList" @close="closeAdd"></Add>
    <Edit :open="open_edit" :roleList="roleList" :region_user_id="curModel.region_user_id"  @close="closeEdit"></Edit>
  </div>
</template>
<script>
import PlusApi from '@/api/plus/operations.js';
import Add from './dialog/Add.vue';
import Edit from './dialog/Edit.vue';
export default {
  components: {
    Add,
    Edit
  },
  inject: ['reload'],
  data() {
    return {
      /*是否加载完成*/
      loading: true,
      /*角色是否加载完成*/
      role_loading:true,
      /*列表数据*/
      tableData: [],
      /*一页多少条*/
      pageSize: 20,
      /*一共多少条数据*/
      totalDataNumber: 0,
      /*当前是第几页*/
      curPage: 1,
      /*横向表单数据模型*/
      formInline: {
        user: '',
        region: ''
      },
      /*是否打开添加弹窗*/
      open_add: false,
      /*是否打开编辑弹窗*/
      open_edit: false,
      /*当前编辑的对象*/
      curModel: {},
      /*角色列表*/
      roleList:[]
    };
  },
  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;
      PlusApi.operationsAdminList(Params, true)
        .then(data => {
          self.loading = false;
          self.role_loading = false;
          self.roleList = data.data.roleList;
          self.tableData = data.data.list.data;
          self.totalDataNumber = data.data.list.total;
        })
        .catch(error => {});
    },
    /*打开添加*/
    addClick() {
      if(!this.role_loading){
         this.open_add=true;
      }
    },
    /*关闭添加*/
    closeAdd(e){
      this.open_add=false;
      if(e.type=='success'){
        this.getTableList();
      }
    },
    /*打开编辑*/
    editClick(row) {
      this.curModel=row;
      this.open_edit=true;
    },
    /*关闭添加*/
    closeEdit(e){
      this.open_edit=false;
      if(e.type=='success'){
        this.getTableList();
      }
    },
    /*删除*/
    deleteClick(row) {
      let self = this;
      self
        .$confirm('此操作将永久删除该记录, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
        .then(() => {
          self.loading = true;
          PlusApi.regionAdminDelete(
            {
              shop_user_id: row.shop_user_id
            },
            true
          )
            .then(data => {
              self.loading = false;
              if (data.code == 1) {
                self.$message({
                  message: '恭喜你,该管理员删除成功',
                  type: 'success'
                });
                //刷新页面
                self.getTableList();
              } else {
                self.loading = false;
              }
            })
            .catch(error => {
              self.loading = false;
            });
        })
        .catch(() => {});
    }
  }
};
</script>
<style></style>
operations_vue/src/views/plus/operations/auth/user/dialog/Add.vue
New file
@@ -0,0 +1,130 @@
<template>
  <!--
        作者:参考 auth/user/dialog/Add.vue
        时间:2026-01-20
        描述:区域代理商-管理员列表-添加管理员
    -->
  <el-dialog title="添加管理员" :visible.sync="dialogVisible" @close="dialogFormVisible" :close-on-click-modal="false" :close-on-press-escape="false">
    <!--form表单-->
    <el-form size="small" ref="form" :model="form" :rules="formRules" :label-width="formLabelWidth">
      <el-form-item label="用户名" prop="user_name"><el-input v-model="form.user_name" placeholder="请输入用户名"></el-input></el-form-item>
      <el-form-item label="所属角色" prop="role_id">
        <el-select v-model="form.role_id" :multiple="true">
          <el-option v-for="item in roleList" :value="item.role_id" :key="item.role_id" :label="item.role_name"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="登录密码" prop="password"><el-input v-model="form.password" placeholder="请输入登录密码" type="password"></el-input></el-form-item>
      <el-form-item label="确认密码" prop="confirm_password"><el-input v-model="form.confirm_password" placeholder="请输入确认密码" type="password"></el-input></el-form-item>
      <el-form-item label="姓名" prop="real_name"><el-input v-model="form.real_name"></el-input></el-form-item>
    </el-form>
    <div slot="footer" class="dialog-footer">
      <el-button @click="dialogVisible = false">取 消</el-button>
      <el-button type="primary" @click="onSubmit" :loading="loading">确 定</el-button>
    </div>
  </el-dialog>
</template>
<script>
import PlusApi from '@/api/plus/region.js';
export default {
  data() {
    return {
      /*左边长度*/
      formLabelWidth: '120px',
      /*是否显示*/
      loading: false,
      /*是否显示*/
      dialogVisible: false,
      /*form表单对象*/
      form: {
        user_name: '',
        access_id: []
      },
      /*form验证*/
      formRules: {
        user_name: [
          {
            required: true,
            message: ' ',
            trigger: 'blur'
          }
        ],
        role_id: [
          {
            required: true,
            message: ' ',
            trigger: 'blur'
          }
        ],
        password: [
          {
            required: true,
            message: ' ',
            trigger: 'blur'
          }
        ],
        confirm_password: [
          {
            required: true,
            message: ' ',
            trigger: 'blur'
          }
        ],
        real_name: [
          {
            required: true,
            message: ' ',
            trigger: 'blur'
          }
        ]
      }
    };
  },
  props: ['open', 'roleList'],
  watch: {
    open: function(n, o) {
      if (n != o) {
        this.dialogVisible = this.open;
      }
    }
  },
  created() {},
  methods: {
    /*添加*/
    onSubmit() {
      let self = this;
      self.loading = true;
      let params = self.form;
      PlusApi.regionAdminAdd(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('close', {
          type: 'success',
          openDialog: false
        });
      } else {
        this.$emit('close', {
          type: 'error',
          openDialog: false
        });
      }
    }
  }
};
</script>
<style></style>
operations_vue/src/views/plus/operations/auth/user/dialog/Edit.vue
New file
@@ -0,0 +1,154 @@
<template>
  <!--
        作者:参考 auth/user/dialog/Edit.vue
        时间:2026-01-20
        描述:区域代理商-管理员列表-修改管理员
    -->
  <el-dialog title="修改管理员" :visible.sync="dialogVisible" @close="dialogFormVisible" :close-on-click-modal="false" :close-on-press-escape="false">
    <!--form表单-->
    <el-form size="small" ref="form" :model="form" :rules="formRules" :label-width="formLabelWidth" v-loading="loading">
      <el-form-item label="用户名" prop="user_name"><el-input v-model="form.user_name" placeholder="请输入用户名"></el-input></el-form-item>
      <el-form-item label="所属角色" prop="access_id">
        <el-select v-model="form.access_id" :multiple="true">
          <el-option v-for="item in roleList" :value="item.role_id" :key="item.role_id" :label="item.role_name_h1"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="登录密码" prop="password"><el-input v-model="form.password" placeholder="请输入登录密码" type="password"></el-input></el-form-item>
      <el-form-item label="确认密码" prop="confirm_password"><el-input v-model="form.confirm_password" placeholder="请输入确认密码" type="password"></el-input></el-form-item>
      <el-form-item label="姓名" prop="real_name"><el-input v-model="form.real_name"></el-input></el-form-item>
    </el-form>
    <div slot="footer" class="dialog-footer">
      <el-button @click="dialogVisible = false">取 消</el-button>
      <el-button type="primary" @click="onSubmit" :loading="loading">确 定</el-button>
    </div>
  </el-dialog>
</template>
<script>
import PlusApi from '@/api/plus/region.js';
export default {
  data() {
    return {
      /*左边长度*/
      formLabelWidth: '120px',
      /*是否显示*/
      loading: false,
      /*是否显示*/
      dialogVisible: false,
      /*form表单对象*/
      form: {
        confirm_password:'',
        access_id:[]
      },
      /*当前角色*/
      access_id: [],
      /*角色对象*/
      roleList: [],
      /*form验证*/
      formRules: {
        user_name: [
          {
            required: true,
            message: ' ',
            trigger: 'blur'
          }
        ],
        access_id: [
          {
            required: true,
            message: ' ',
            trigger: 'blur'
          }
        ],
        password: [
          {
            required: true,
            message: ' ',
            trigger: 'blur'
          }
        ],
        confirm_password: [
          {
            required: true,
            message: ' ',
            trigger: 'blur'
          }
        ],
        real_name: [
          {
            required: true,
            message: ' ',
            trigger: 'blur'
          }
        ]
      }
    };
  },
  props: ['open','region_user_id'],
  watch: {
    open: function(n, o) {
      if (n != o) {
        this.dialogVisible = this.open;
        this.getData();
      }
    }
  },
  created() {},
  methods: {
    /*获取数据*/
    getData() {
      let self = this;
      PlusApi.regionAdminEditInfo({
        region_user_id: this.region_user_id
        }).then(res => {
          self.loading = false;
          self.roleList = res.data.roleList;
          let obj=res.data.info;
          obj.access_id = res.data.role_arr;
          obj.password = '';
          self.form=obj;
        })
        .catch(error => {
          self.loading = false;
        });
    },
    /*修改*/
    onSubmit() {
      let self = this;
      self.loading = true;
      let params = self.form;
      PlusApi.regionAdminEdit(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('close', {
          type: 'success',
          openDialog: false
        });
      } else {
        this.$emit('close', {
          type: 'error',
          openDialog: false
        });
      }
    }
  }
};
</script>
<style></style>
operations_vue/src/views/plus/operations/cash/Cash.vue
New file
@@ -0,0 +1,331 @@
<template>
  <!--
          作者:luoyiming
          时间:2020-06-01
          描述:插件中心-分销-提现申请
      -->
  <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-select v-model="formInline.apply_status" placeholder="请选择状态">
            <el-option label="全部" value="-1"></el-option>
            <el-option label="待审核" value="10"></el-option>
            <el-option label="审核通过" value="20"></el-option>
            <el-option label="已打款" value="40"></el-option>
            <el-option label="驳回" value="30"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="提现方式">
          <el-select v-model="formInline.pay_type" placeholder="请选择提现方式">
            <el-option label="全部" value="-1"></el-option>
            <el-option label="微信" value="10"></el-option>
            <el-option label="支付宝" value="20"></el-option>
            <el-option label="银行卡" value="30"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="用户id">
          <el-input v-model="formInline.user_id" placeholder="请输入用户ID"></el-input>
        </el-form-item>
        <el-form-item label=""><el-input v-model="formInline.search" placeholder="请输入昵称/姓名/手机号"></el-input></el-form-item>
        <el-form-item><el-button type="primary" @click="onSubmit">查询</el-button></el-form-item>
      </el-form>
    </div>
    <!--内容-->
    <div class="product-content">
      <div class="table-wrap">
        <el-table :data="tableData" border style="width: 100%" v-loading="loading">
          <el-table-column prop="user_id" label="用户ID" width="60"></el-table-column>
          <el-table-column prop="nickName" label="微信头像" width="70">
            <template slot-scope="scope">
              <img class="radius" v-img-url="scope.row.avatarUrl" width="30" height="30" />
            </template>
          </el-table-column>
          <el-table-column prop="nickName" label="微信昵称" width="120"></el-table-column>
          <el-table-column prop="real_name" label="姓名"></el-table-column>
          <el-table-column prop="mobile" label="手机号">
            <template slot-scope="scope">
              <p class="text-ellipsis" :title="scope.row.mobile">{{ scope.row.mobile }}</p>
            </template>
          </el-table-column>
          <el-table-column prop="money" label="提现金额">
            <template slot-scope="scope">
              <span class="orange">{{ scope.row.money }}</span>
            </template>
          </el-table-column>
          <el-table-column prop="fee_money" label="手续费">
            <template slot-scope="scope">
              <span class="black">{{ scope.row.fee_money || 0 }}</span>
            </template>
          </el-table-column>
          <el-table-column prop="real_money" label="实际到账">
            <template slot-scope="scope">
              <span class="green">{{ scope.row.real_money || scope.row.money }}</span>
            </template>
          </el-table-column>
          <el-table-column prop="pay_type.text" label="提现方式"></el-table-column>
          <el-table-column prop="pay_type" label="提现信息    ">
            <template slot-scope="scope">
              <div v-if="scope.row.pay_type.value == 20">
                <p>
                  <span>{{ scope.row.alipay_name }}</span>
                </p>
                <p>
                  <span>{{ scope.row.alipay_account }}</span>
                </p>
              </div>
              <div v-else-if="scope.row.pay_type.value == 30">
                <p>
                  <span>{{ scope.row.bank_name }}</span>
                </p>
                <p>
                  <span>{{ scope.row.bank_account }}</span>
                </p>
                <p>
                  <span>{{ scope.row.bank_card }}</span>
                </p>
              </div>
              <div v-else>
                <p><span>--</span></p>
              </div>
            </template>
          </el-table-column>
          <el-table-column prop="apply_status.text" label="审核状态"></el-table-column>
          <el-table-column prop="create_time" label="申请时间" width="135"></el-table-column>
          <el-table-column prop="audit_time" label="审核时间" width="135"></el-table-column>
          <el-table-column fixed="right" label="操作" width="180">
            <template slot-scope="scope">
              <div v-if="scope.row.apply_status.value == 10 || scope.row.apply_status.value == 20">
                <el-button @click="editClick(scope.row)" type="text" size="small" v-auth="'/plus/operations/cash/submit'">审核</el-button>
                <template v-if="scope.row.apply_status.value == 20">
                  <el-button @click="makeMoney(scope.row)" type="text" size="small" v-auth="'/plus/operations/cash/money'">确认打款</el-button>
                </template>
                <template v-if="scope.row.apply_status.value == 20 && scope.row.pay_type.value == 10">
                  <el-button @click="WxPay(scope.row.id)" type="text" size="small" v-auth="'/plus/operations/cash/money'">微信付款</el-button>
                </template>
              </div>
              <div v-if="scope.row.apply_status.value == 30">
                <el-button @click="editClick(scope.row)" type="text" size="small">查看详情</el-button>
               </div>
            </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>
    <Edit v-if="open_edit" :open_edit="open_edit" :form="userModel" @closeDialog="closeDialogFunc($event, 'edit')"></Edit>
  </div>
</template>
<script>
import OperationsApi from '@/api/plus/operations.js';
import Edit from './dialog/Edit.vue';
export default {
  components: {
    /*编辑组件*/
    Edit
  },
  data() {
    return {
      /*是否加载完成*/
      loading: true,
      /*列表数据*/
      tableData: [],
      /*一页多少条*/
      pageSize: 20,
      /*一共多少条数据*/
      totalDataNumber: 0,
      /*当前是第几页*/
      curPage: 1,
      formInline: {
        apply_status: '-1',
        pay_type: '-1',
        search: '',
        /*用户ID*/
        user_id: ''
      },
      /*是否打开编辑弹窗*/
      open_edit: false,
      /*当前编辑的对象*/
      userModel: {}
    };
  },
  props: {},
  watch:{
    $route(to, from) {
      if (to.query.user_id != null) {
        this.formInline.user_id = to.query.user_id;
      }else{
        this.formInline.user_id ='';
      }
      this.curPage = 1;
      this.getData();
    }
  },
  created() {
    if (this.$route.query.user_id != null) {
      this.formInline.user_id = this.$route.query.user_id;
    }
    /*获取列表*/
    this.getData();
  },
  methods: {
    /*获取数据*/
    getData() {
      let self = this;
      let Params = self.formInline;
      Params.page = self.curPage;
      Params.list_rows = self.pageSize;
      OperationsApi.cash(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;
      let Params = self.formInline;
      OperationsApi.cash(Params, true)
        .then(data => {
          self.loading = false;
          self.tableData = data.data.list.data;
          self.totalDataNumber = data.data.list.total;
        })
        .catch(error => {
          self.loading = false;
        });
    },
    /*每页多少条*/
    handleSizeChange(val) {
      this.curPage = 1;
      this.pageSize = val;
      this.getData();
    },
    /*选择第几页*/
    handleCurrentChange(val) {
      let self = this;
      self.curPage = val;
      self.getData();
    },
    /*打开弹出层编辑*/
    editClick(item) {
      this.userModel = item;
      this.open_edit = true;
    },
    /*关闭弹窗*/
    closeDialogFunc(e, f) {
      if (f == 'add') {
        this.open_add = e.openDialog;
        if (e.type == 'success') {
          this.getData();
        }
      }
      if (f == 'edit') {
        this.open_edit = e.openDialog;
        if (e.type == 'success') {
          this.getData();
        }
      }
    },
    /*确认打款*/
    makeMoney(e) {
      let self = this;
      self
        .$confirm('确认要打款吗?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
        .then(() => {
          self.loading = true;
          OperationsApi.money(
            {
              id: e.id
            },
            true
          )
            .then(data => {
              self.loading = false;
              if (data.code == 1) {
                self.$message({
                  message: '恭喜你,操作成功',
                  type: 'success'
                });
                this.getData();
              } else {
                self.loading = false;
              }
            })
            .catch(error => {
              self.loading = false;
            });
        })
        .catch(() => {});
    },
    /*微信打款*/
    WxPay(e) {
      let self = this;
      self
        .$confirm('该操作 将使用微信支付企业付款到零钱功能,确定打款吗?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
        .then(() => {
          self.loading = true;
          OperationsApi.WxPay(
            {
              id: e
            },
            true
          )
            .then(data => {
              self.loading = false;
              if (data.code == 1) {
                self.$message({
                  message: '恭喜你,操作成功',
                  type: 'success'
                });
                this.getData();
              } else {
                self.loading = false;
              }
            })
            .catch(error => {
              self.loading = false;
            });
        })
        .catch(() => {});
    }
  }
};
</script>
<style></style>
operations_vue/src/views/plus/operations/cash/dialog/Edit.vue
New file
@@ -0,0 +1,94 @@
<template>
  <!--
          作者:luoyiming
          时间:2020-06-01
          描述:插件中心-分销-提现申请-弹窗
      -->
  <div v-if="status != 30">
    <el-dialog title="提现审核" :visible.sync="dialogVisible" @close="dialogFormVisible" :close-on-click-modal="false" :close-on-press-escape="false">
      <el-form :model="form">
        <el-form-item label="审核状态" :label-width="formLabelWidth">
          <div>
            <el-radio v-model="form.apply_status" label="20">审核通过</el-radio>
            <el-radio v-model="form.apply_status" label="30">驳回</el-radio>
          </div>
        </el-form-item>
        <div v-if="form.apply_status == 30">
          <el-form-item label="驳回原因" :label-width="formLabelWidth"><el-input v-model="form.reject_reason" autocomplete="off"></el-input></el-form-item>
        </div>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible">取 消</el-button>
        <el-button type="primary" @click="editApplyStatus">确 定</el-button>
      </div>
    </el-dialog>
  </div>
  <div v-else>
    <el-dialog title="驳回原因" :visible.sync="dialogVisible" @close="dialogFormVisible" :close-on-click-modal="false" :close-on-press-escape="false">
      <p>{{ reject_reason }}</p>
      <!-- <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible">取 消</el-button>
        <el-button type="primary" @click="dialogFormVisible">确 定</el-button>
      </div> -->
    </el-dialog>
  </div>
</template>
<script>
import OperationsApi from '@/api/plus/operations.js';
export default {
  data() {
    return {
      status: '',
      reject_reason: '',
      /*左边长度*/
      formLabelWidth: '120px',
      /*是否显示*/
      dialogVisible: false
    };
  },
  props: ['open_edit', 'form'],
  created() {
    this.dialogVisible = this.open_edit;
    this.status = this.form.apply_status.value;
    if (this.status == 30) {
      this.reject_reason = this.form.reject_reason;
    }
  },
  methods: {
    /*修改*/
    editApplyStatus() {
      let self = this;
      let params = this.form;
      OperationsApi.cashSubmit(params, true)
        .then(data => {
          self.$message({
            message: '恭喜你,修改成功',
            type: 'success'
          });
          self.dialogFormVisible(true);
        })
        .catch(error => {});
    },
    /*关闭弹窗*/
    dialogFormVisible(e) {
      if (e) {
        this.$emit('closeDialog', {
          type: 'success',
          openDialog: false
        });
      } else {
        this.$emit('closeDialog', {
          type: 'error',
          openDialog: false
        });
      }
    }
  }
};
</script>
<style></style>
operations_vue/src/views/plus/operations/grade/index.vue
New file
@@ -0,0 +1,36 @@
<template>
  <div>
    <el-tabs size="small" v-model="activeName" type="card" @tab-click="handleClick">
      <el-tab-pane label="等级列表" name="list"></el-tab-pane>
      <el-tab-pane label="升级日志" name="log"></el-tab-pane>
    </el-tabs>
    <!--等级列表-->
    <List v-if="activeName == 'list'"></List>
    <!--升级日志-->
    <Log v-if="activeName == 'log'"></Log>
  </div>
</template>
<script>
import List from './part/list';
import Log from './part/log';
export default {
  components: {
    /*编辑组件*/
    List,
    Log
  },
  data() {
    return {
      /*当前选中*/
      activeName: 'list',
    };
  },
  created() {},
  methods: {
    handleClick(e) {
      this.activeName = e.name;
    }
  }
};
</script>
operations_vue/src/views/plus/operations/grade/part/Add.vue
operations_vue/src/views/plus/operations/grade/part/Edit.vue
operations_vue/src/views/plus/operations/grade/part/list.vue
operations_vue/src/views/plus/operations/grade/part/log.vue
operations_vue/src/views/plus/operations/index.vue
New file
@@ -0,0 +1,162 @@
<template>
  <!--
          作者:luoyiming
          时间:2019-06-04
          描述:插件中心-运营中心
      -->
  <div>
    <!--入驻申请-->
    <Apply v-if="activeName == 'apply'"></Apply>
    <!--代理用户-->
    <User v-if="activeName == 'user'"></User>
    <!--提现申请-->
    <Cash v-if="activeName == 'cash'"></Cash>
    <!--运营中心订单-->
    <Order v-if="activeName == 'order'"></Order>
    <!--分销设置-->
    <Setting v-if="activeName == 'setting'"></Setting>
    <Auth v-if="activeName == 'auth'"></Auth>
    <!--分销海报-->
    <Grade v-if="activeName == 'grade'"></Grade>
  </div>
</template>
<script>
import bus from '@/utils/eventBus.js';
import OperationsApi from '@/api/plus/operations.js';
import Apply from './apply/apply';
import User from './user/user.vue';
import Cash from './cash/Cash';
import Order from './order/order.vue';
import Setting from './setting/Setting';
import Grade from './grade/index';
import Auth from './auth/index';
export default {
  components: {
    Apply,
    User,
    Cash,
    Order,
    Setting,
    Grade,
    Auth
  },
  data() {
    return {
      formInline: {
        nick_name: ''
      },
      /*参数*/
      param: {},
      /*当前选中*/
      activeName: 'apply',
      /*切换数组*/
      sourceList: [
        {
          key: 'apply',
          value: '入驻申请',
          path:'/plus/operations/apply/index'
        },
        {
          key: 'user',
          value: '运营中心管理',
          path:'/plus/operations/user/index'
        },
        {
          key: 'cash',
          value: '提现申请',
          path:'/plus/operations/cash/index'
        },
        {
          key: 'order',
          value: '运营订单',
          path:'/plus/operations/order/index'
        },
        // {
        //   key: 'grade',
        //   value: '等级管理',
        //   path:'/plus/operations/grade/index'
        // },
        {
          key: 'auth',
          value: '权限设置',
          path:'/plus/operations/auth/index'
        },
        {
          key: 'setting',
          value: '运营中心设置',
          path:'/plus/operations/setting/index'
        },
      ],
      /*权限筛选后的数据*/
      tabList:[],
      /*判断third是否有参数*/
      is_third_param: false
    };
  },
  watch:{
    //监听路由
    $route(to, from) {
      this.init();
    }
  },
  created() {
    this.init();
  },
  beforeDestroy() {
    //发送类别切换
    bus.$emit('tabData', { active: null, tab_type:'operations',list: [] });
    bus.$off('activeValue');
  },
  methods: {
    /*初始化方法*/
    init(){
      this.tabList=this.authFilter();
      if(this.tabList.length>0){
        this.activeName=this.tabList[0].key;
      }
      if (this.$route.query.type != null) {
        this.activeName = this.$route.query.type;
      }
      /*监听传插件的值*/
      bus.$on('activeValue', res => {
        if (this.is_third_param) {
          this.param.user_id = '';
          this.is_third_param = false;
        }
        this.activeName = res;
      });
      //发送类别切换
      let params = {
        active: this.activeName,
        list: this.tabList,
        tab_type:'operations'
      };
      bus.$emit('tabData', params);
    },
    /*权限过滤*/
    authFilter(){
      let list=[];
      for(let i=0;i<this.sourceList.length;i++){
        let item=this.sourceList[i];
        if(this.$filter.isAuth(item.path)){
          list.push(item);
        }
      }
      return list;
    }
  }
};
</script>
operations_vue/src/views/plus/operations/order/order.vue
New file
@@ -0,0 +1,272 @@
<template>
  <!--
          作者:luoyiming
          时间:2020-06-01
          描述:插件中心-运营中心-运营中心订单
      -->
  <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-select v-model="formInline.is_settled" placeholder="是否结算佣金">
            <el-option label="全部" value="-1"></el-option>
            <el-option label="已结算" value="1"></el-option>
            <el-option label="未结算" value="0"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="用户id">
          <el-input v-model="formInline.user_id" placeholder="请输入用户ID"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="onSubmit">查询</el-button>
        </el-form-item>
        <el-form-item>
          <el-button size="small" type="success" @click="onExport" v-auth="'/plus/operations/order/export'">导出</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!--内容-->
    <div class="product-content">
      <div class="table-wrap">
        <el-table :data="tableData" size="small" border style="width: 100%" v-loading="loading">
          <el-table-column prop="order_master.create_time" label="商品信息">
            <template slot-scope="scope">
              <div class="product-info p-10-0" v-for="(item, index) in scope.row.order_master.product" :key="index">
                <div class="pic"><img v-img-url="item.image.file_path" alt="" /></div>
                <div class="info">
                  <div class="name gray3">{{ item.product_name }}</div>
                </div>
              </div>
            </template>
          </el-table-column>
          <el-table-column prop="referee.value" label="运营中心" width="400">
            <template slot-scope="scope">
              <div class="d-s-s d-c">
                <div class="d-s-c ww100 border-b-d" v-if="scope.row.first_user_id > 0">
                  <p class="referee-name text-ellipsis">
                    <span class="gray9">省级运营中心:</span>
                    <span class="blue">{{ scope.row.agent_first.nickName }}</span>
                  </p>
                  <p class="referee-name text-ellipsis">
                    <span class="gray9">用户ID:</span>
                    <span class="gray6">{{ scope.row.agent_first.user_id }}</span>
                  </p>
                  <p class="referee-name text-ellipsis">
                    <span class="gray9">运营佣金:</span>
                    <span class="orange">¥{{ scope.row.first_money }}</span>
                  </p>
                </div>
                <div class="d-s-c ww100 border-b-d" v-if="scope.row.second_user_id > 0">
                  <p class="referee-name text-ellipsis">
                    <span class="gray9">市级运营中心:</span>
                    <span class="blue">{{ scope.row.agent_second.nickName }}</span>
                  </p>
                  <p class="referee-name text-ellipsis">
                    <span class="gray9">用户ID:</span>
                    <span class="gray6">{{ scope.row.agent_second.user_id }}</span>
                  </p>
                  <p class="referee-name text-ellipsis">
                    <span class="gray9">运营佣金:</span>
                    <span class="orange">¥{{ scope.row.second_money }}</span>
                  </p>
                </div>
                <div class="d-s-c ww100 border-b-d" v-if="scope.row.third_user_id > 0">
                  <p class="referee-name text-ellipsis">
                    <span class="gray9">区级运营中心:</span>
                    <span class="blue">{{ scope.row.agent_third.nickName }}</span>
                  </p>
                  <p class="referee-name text-ellipsis">
                    <span class="gray9">用户ID:</span>
                    <span class="gray6">{{ scope.row.agent_third.user_id }}</span>
                  </p>
                  <p class="referee-name text-ellipsis">
                    <span class="gray9">运营佣金:</span>
                    <span class="orange">¥{{ scope.row.third_money }}</span>
                  </p>
                </div>
              </div>
            </template>
          </el-table-column>
          <el-table-column prop="nickName" label="单价/数量" width="150">
            <template slot-scope="scope">
              <div v-for="(item, index) in scope.row.order_master.product" :key="index">
                <span class="orange">¥{{ item.product_price }}</span>
                ×{{ item.total_num }}
              </div>
            </template>
          </el-table-column>
          <el-table-column prop="order_master.pay_price" label="实付款" width="100">
            <template slot-scope="scope">
              <span class="fb orange">{{ scope.row.order_master.pay_price }}</span>
            </template>
          </el-table-column>
          <el-table-column prop="order_master.user.nickName" label="买家" width="100"></el-table-column>
          <el-table-column prop="mobile" label="交易状态" width="130">
            <template slot-scope="scope">
              <p>
                <span class="gray9">付款状态:</span>
                {{ scope.row.order_master.pay_status.text }}
              </p>
              <p>
                <span class="gray9">发货状态:</span>
                {{ scope.row.order_master.delivery_status.text }}
              </p>
              <p>
                <span class="gray9">收货状态:</span>
                {{ scope.row.order_master.receipt_status.text }}
              </p>
            </template>
          </el-table-column>
          <el-table-column prop="referee.value" label="佣金结算" width="70">
            <template slot-scope="scope">
              <span class="green" v-if="scope.row.is_settled == 1">已结算</span>
              <span class="red" v-if="scope.row.is_settled == 0">未结算</span>
            </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 OperationsApi from '@/api/plus/operations.js';
  import qs from 'qs';
export default {
  components: {
    /*编辑组件*/
  },
  data() {
    return {
      /*是否加载完成*/
      loading: true,
      /*列表数据*/
      tableData: [],
      /*一页多少条*/
      pageSize: 20,
      /*一共多少条数据*/
      totalDataNumber: 0,
      /*当前是第几页*/
      curPage: 1,
      formInline: {
        is_settled: '-1',
        /*用户ID*/
        user_id: ''
      },
      /*是否打开编辑弹窗*/
      open_edit: false,
      /*当前编辑的对象*/
      userModel: {}
    };
  },
  props: {},
  watch: {
    $route(to, from) {
      if (to.query.user_id != null) {
        this.formInline.user_id = to.query.user_id;
      } else {
        this.formInline.user_id = '';
      }
      this.curPage = 1;
      this.getData();
    }
  },
  created() {
    if (this.$route.query.user_id != null) {
      this.formInline.user_id = this.$route.query.user_id;
    }
    /*获取列表*/
    this.getData();
  },
  methods: {
    /*选择第几页*/
    handleCurrentChange(val) {
      let self = this;
      self.curPage = val;
      self.loading = true;
      self.getData();
    },
    /*获取数据*/
    getData(user_id) {
      let self = this;
      let Params = {
        user_id: self.formInline.user_id,
        page: self.curPage,
        list_rows: self.pageSize,
        is_settled: self.is_settled
      };
      OperationsApi.operationsOrder(Params, true)
        .then(data => {
          self.loading = false;
          self.tableData = data.data.list.data;
          self.totalDataNumber = data.data.list.total;
        })
        .catch(error => {
          self.loading = false;
        });
    },
    //搜索
    onSubmit() {
      let self = this;
      self.loading = true;
      self.is_settled = self.formInline.is_settled;
      self.getData();
    },
      onExport: function() {
        let baseUrl = window.location.protocol + '//' + window.location.host;
        window.location.href = baseUrl + '/index.php/operations/plus.operations.order/export?' + qs.stringify(this.formInline);
      },
    /*每页多少条*/
    handleSizeChange(val) {
      this.curPage = 1;
      this.pageSize = val;
      this.getData();
    },
    /*打开弹出层编辑*/
    editClick(item) {
      this.userModel = item;
      this.open_edit = true;
    },
    /*关闭弹窗*/
    closeDialogFunc(e, f) {
      if (f == 'add') {
        this.open_add = e.openDialog;
        if (e.type == 'success') {
          this.getData();
        }
      }
      if (f == 'edit') {
        this.open_edit = e.openDialog;
        if (e.type == 'success') {
          this.getData();
        }
      }
    }
  }
};
</script>
<style scoped="">
  .referee-name {
    width: 33.333333%;
  }
</style>
operations_vue/src/views/plus/operations/role/add.vue
New file
@@ -0,0 +1,121 @@
<template>
  <!--
        作者:参考 auth/role
        时间:2026-01-20
        描述:区域代理商-角色管理-添加角色
    -->
  <div v-loading="loading">
    <!--form表单-->
    <el-form size="small" ref="form" :model="form" label-width="180px">
      <!--添加门店-->
      <div class="common-form">添加角色</div>
      <el-form-item label="角色名称:" prop="role_name" :rules="[{ required: true, message: ' ' }]">
        <el-input v-model="form.role_name" placeholder="请输入角色名称" class="max-w460"></el-input>
      </el-form-item>
      <el-form-item label="权限列表:" v-model="form.access_id">
        <el-tree :data="data" show-checkbox node-key="access_id" :default-expand-all="true" :default-checked-keys="[]" :props="defaultProps" @check="handleCheckChange"></el-tree>
      </el-form-item>
      <el-form-item label="排序:"><el-input type="number" v-model="form.sort" placeholder="请输入排序" class="max-w460"></el-input></el-form-item>
      <!--提交-->
      <div class="common-button-wrapper">
        <el-button size="small" type="info" @click="cancelFunc">取消</el-button>
        <el-button type="primary" size="small" @click="onSubmit" :loading="loading">提交</el-button>
      </div>
    </el-form>
  </div>
</template>
<script>
import OperationsApi from '@/api/plus/operations.js';
export default {
  data() {
    return {
      /*是否正在加载*/
      loading:true,
      /*表单数据对象*/
      form: {
        access_id: [],
        sort: 1
      },
      data: [],
      roleList: [],
      defaultProps: {
        children: 'children',
        label: 'name'
      }
    };
  },
  created() {
    /*获取列表*/
    this.getData();
  },
  methods: {
    /*添加角色*/
    onSubmit() {
      let self = this;
      let form = self.form;
      self.$refs.form.validate(valid => {
        if (valid) {
          self.loading = true;
          OperationsApi.operationsRoleAdd({
            params: JSON.stringify(form)
          }, true)
            .then(data => {
              self.loading = false;
              self.$message({
                message: '添加成功',
                type: 'success'
              });
              self.$router.push('/plus/operations/role/index');
            })
            .catch(error => {
              self.loading = false;
            });
        }
      });
    },
    /*获取数据*/
    getData() {
      let self = this;
      OperationsApi.operationsRoleAddInfo()
        .then(data => {
          self.data = data.data.menu;
          self.roleList = data.data.roleList;
           self.loading = false;
        })
        .catch(error => {
          self.loading = false;
        });
    },
    //监听选中
    handleCheckChange(data, checked) {
      this.form.access_id = checked.checkedKeys.concat(checked.halfCheckedKeys);
    },
    /*取消*/
    cancelFunc() {
      this.$router.back(-1);
    }
  }
};
</script>
<style lang="scss" scoped>
.basic-setting-content {
}
.product-add {
  padding-bottom: 50px;
}
.img {
  margin-top: 10px;
}
</style>
operations_vue/src/views/plus/operations/role/edit.vue
New file
@@ -0,0 +1,170 @@
<template>
  <!--
        作者:参考 auth/role
        时间:2026-01-20
        描述:区域代理商-角色管理-编辑角色
    -->
  <div v-loading="loading">
    <!--form表单-->
    <el-form size="small" ref="form" :model="form" label-width="180px">
      <!--编辑角色-->
      <div class="common-form">编辑角色</div>
      <el-form-item label="角色名称:" prop="role_name" :rules="[{ required: true, message: ' ' }]">
        <el-input v-model="form.role_name" placeholder="请输入角色名称" class="max-w460"></el-input>
      </el-form-item>
      <el-form-item label="权限列表:" v-model="form.access_id">
        <el-tree
          :data="data"
          show-checkbox
          node-key="access_id"
          :default-expand-all="true"
          :default-checked-keys="select_menu"
          :props="defaultProps"
          @check="handleCheckChange"
        ></el-tree>
      </el-form-item>
      <el-form-item label="排序:"><el-input type="number" v-model="form.sort" placeholder="请输入排序" class="max-w460"></el-input></el-form-item>
      <!--提交-->
      <div class="common-button-wrapper">
        <el-button size="small" type="info" @click="cancelFunc">取消</el-button>
        <el-button type="primary" size="small" @click="onSubmit" :loading="loading">提交</el-button>
      </div>
    </el-form>
  </div>
</template>
<script>
import OperationsApi from '@/api/plus/operations.js';
export default {
  data() {
    return {
      /*是否正在加载*/
      loading:true,
      /*表单数据对象*/
      form: {
        access_id: [],
      },
      data: [],
      /*角色列表*/
      roleList: [],
      /*权限选中*/
      select_menu: [],
      /*权限树菜单重新自定义字段*/
      defaultProps: {
        children: 'children',
        label: 'name'
      },
      role_id: 0
    };
  },
  created() {
    this.role_id = this.$route.query.role_id;
    /*获取列表*/
    this.getData();
  },
  methods: {
    /*修改角色*/
    onSubmit() {
      let self = this;
      let form = self.form;
      self.$refs.form.validate(valid => {
        if (valid) {
          self.loading = true;
          OperationsApi.operationsRoleEdit({
            role_id: self.role_id,
            params: JSON.stringify(form)
          }, true)
            .then(data => {
              self.loading = false;
              self.$message({
                message: '修改成功',
                type: 'success'
              });
              self.$router.push('/plus/operations/role/index');
            })
            .catch(error => {
              self.loading = false;
            });
        }
      });
    },
    /*获取所有的数据*/
    getData() {
      let self = this;
      OperationsApi.operationsRoleEditInfo({
        role_id: self.role_id
      })
        .then(data => {
          let obj = self.clearData(data.data.menu, data.data.select_menu);
          self.select_menu = data.data.select_menu;
          self.form = data.data.model;
          self.roleList = data.data.roleList;
          self.data = data.data.menu;
          if (self.form.parent_id == 0) {
            self.form.parent_id = 0 + '';
          }
          self.loading = false;
        })
        .catch(error => {
          self.loading = false;
        });
    },
    /*清除数据*/
    clearData(list, authlist) {
      let total = 0;
      let leng = list.length;
      for (let i = 0; i < leng; i++) {
        let item = list[i];
        if (item.children != null) {
          let flag = this.clearData(item.children, authlist);
          if (!flag) {
            let _index = authlist.indexOf(item.access_id);
            if (_index >= 0) {
              authlist.splice(_index, 1);
            }
          }
        }
        if (authlist.indexOf(item.access_id) != -1) {
          total++;
        }
      }
      if (total < leng) {
        return false;
      } else {
        return true;
      }
    },
    /*监听选中*/
    handleCheckChange(data, checked) {
      this.form.access_id = checked.checkedKeys.concat(checked.halfCheckedKeys);
    },
    /*取消*/
    cancelFunc() {
      this.$router.back(-1);
    }
  }
};
</script>
<style lang="scss" scoped>
.basic-setting-content {
}
.product-add {
  padding-bottom: 50px;
}
.img {
  margin-top: 10px;
}
</style>
operations_vue/src/views/plus/operations/role/index.vue
New file
@@ -0,0 +1,135 @@
<template>
  <!--
        作者:参考 auth/role
        时间:2026-01-20
        描述:区域代理商-角色管理
    -->
  <div class="user">
    <div class="common-level-rail">
      <el-button size="small" type="primary" icon="el-icon-plus" @click="addClick" v-auth="'/plus/operations/role/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="role_id" label="角色ID"></el-table-column>
          <el-table-column prop="role_name_h1" label="角色名称"></el-table-column>
          <el-table-column prop="sort" label="排序"></el-table-column>
          <el-table-column prop="create_time" label="添加时间"></el-table-column>
          <el-table-column fixed="right" label="操作" width="90">
            <template slot-scope="scope">
              <el-button @click="editClick(scope.row)" type="text" size="small" v-auth="'/plus/operations/role/edit'">编辑</el-button>
              <el-button @click="deleteClick(scope.row)" type="text" size="small" v-auth="'/plus/operations/role/delete'">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
    </div>
  </div>
</template>
<script>
import OperationsApi from '@/api/plus/operations.js';
export default {
  components: {},
  inject: ['reload'],
  data() {
    return {
      /*是否加载完成*/
      loading: true,
      /*列表数据*/
      tableData: [],
      /*横向表单数据模型*/
      formInline: {
        user: '',
        region: ''
      },
      /*是否打开添加弹窗*/
      open_add: false,
      /*是否打开编辑弹窗*/
      open_edit: false,
      /*当前编辑的对象*/
      userModel: {}
    };
  },
  created() {
    /*获取列表*/
    this.getTableList();
  },
  methods: {
    /*获取列表*/
    getTableList() {
      let self = this;
      let Params = {};
      OperationsApi.operationsRoleList(Params, true)
        .then(data => {
          self.loading = false;
          self.tableData = data.data.list;
        })
        .catch(error => {
          self.loading = false;
        });
    },
    /*打开添加*/
    addClick() {
      this.$router.push('/plus/operations/role/add');
    },
    /*打开编辑*/
    editClick(row) {
      let self = this;
      this.$router.push({
        path: '/plus/operations/role/edit',
        query: {
          role_id: row.role_id
        }
      });
    },
    /*刷新页面*/
    refresh() {
      this.reload();
    },
    /*删除*/
    deleteClick(row) {
      let self = this;
      self
        .$confirm('此操作将永久删除该记录, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
        .then(() => {
          self.loading = true;
          OperationsApi.operationsRoleDelete(
            {
              role_id: row.role_id
            },
            true
          )
            .then(data => {
              self.loading = false;
              if (data.code == 1) {
                self.$message({
                  message: '恭喜你,该角色删除成功',
                  type: 'success'
                });
                self.getTableList();
              } else {
                self.loading = false;
              }
            })
            .catch(error => {
              self.loading = false;
            });
        })
        .catch(() => {});
    }
  }
};
</script>
<style></style>
operations_vue/src/views/plus/operations/setting/Setting.vue
New file
@@ -0,0 +1,99 @@
<template>
  <!--
          作者:luoyiming
          时间:2019-06-04
          描述:插件中心-分销-分销设置
      -->
  <div v-loading="loading">
    <el-tabs size="small" v-model="activeName" type="card" @tab-click="handleClick">
      <el-tab-pane label="基础设置" name="basic"></el-tab-pane>
    <!--  <el-tab-pane label="代理条件" name="condition"></el-tab-pane> -->
     <el-tab-pane label="分红设置" name="bonus"></el-tab-pane>
      <el-tab-pane label="结算" name="settlement"></el-tab-pane>
      <el-tab-pane label="自定义文字" name="words"></el-tab-pane>
      <el-tab-pane label="代理协议" name="license"></el-tab-pane>
      <el-tab-pane label="页面背景图" name="background"></el-tab-pane>
    </el-tabs>
    <!--基础设置-->
    <Basic v-if="activeName == 'basic'" :settingData="settingData"></Basic>
    <!--代理条件-->
   <Condition v-if="activeName == 'condition'" :settingData="settingData"></Condition>
    <!--佣金设置,只有B2B2C在这里设置-->
    <Bonus v-if="activeName == 'bonus'" :settingData="settingData"></Bonus>
    <!--结算-->
    <Settlement v-if="activeName == 'settlement'" :settingData="settingData"></Settlement>
    <!--自定义文字-->
    <Words v-if="activeName == 'words'" :settingData="settingData"></Words>
    <!--申请协议-->
    <License v-if="activeName == 'license'" :settingData="settingData"></License>
    <!--页面背景图-->
    <Background v-if="activeName == 'background'" :settingData="settingData"></Background>
  </div>
</template>
<script>
import PlusApi from '@/api/plus/operations.js';
import Basic from './part/Basic';
import Condition from './part/Condition';
import Bonus from './part/Bonus';
import Settlement from './part/Settlement';
import Words from './part/Words';
import License from './part/License';
import Background from './part/Background';
export default {
  components: {
    /*编辑组件*/
    Basic,
    Condition,
    Bonus,
    Settlement,
    Words,
    License,
    Background
  },
  data() {
    return {
      /*是否正在加载*/
      loading:true,
      /*当前选中*/
      activeName: '',
      /*数据对象*/
      settingData:{}
    };
  },
  created() {
    if (this.$route.query.type != null) {
      this.activeName = this.$route.query.type;
    }
    this.getData();
  },
  methods: {
    /*获取数据*/
    getData() {
      let self = this;
      PlusApi.operationsSet({}, true)
        .then(res => {
          self.settingData = res.data;
          self.loading=false;
          self.activeName='basic';
        })
        .catch(error => {});
    },
    handleClick(e) {
      this.activeName = e.name;
    }
  }
};
</script>
operations_vue/src/views/plus/operations/setting/part/Background.vue
New file
@@ -0,0 +1,128 @@
<template>
  <!--
          作者:luoyiming
          时间:2019-06-04
          描述:插件中心-分销-分销设置-页面背景图
      -->
  <div class="test-wrap mt30">
    <el-form size="small" ref="form" :model="form" label-width="200px">
      <el-form-item label="代理分红首页">
        <el-button type="primary" plain icon="el-icon-upload" @click="openUpload(1)">上传图片</el-button>
        <div v-if="form.index != ''" class="img"><img :src="form.index" width="750" /></div>
        <div class="tips">建议尺寸:宽750像素 高度357像素</div>
      </el-form-item>
      <el-form-item label="申请成为代理页">
        <el-button type="primary" plain icon="el-icon-upload" @click="openUpload(2)">上传图片</el-button>
        <div v-if="form.apply != ''" class="img"><img :src="form.apply" width="750" /></div>
        <div class="tips">建议尺寸:宽750像素 高度357像素</div>
      </el-form-item>
      <el-form-item label="申请提现页">
        <el-button type="primary" plain icon="el-icon-upload" @click="openUpload(3)">上传图片</el-button>
        <div v-if="form.cash_apply != ''" class="img"><img :src="form.cash_apply" width="750" /></div>
        <div class="tips">建议尺寸:宽750像素 高度357像素</div>
      </el-form-item>
      <el-form-item label="代理权益说明">
        <el-button type="primary" plain icon="el-icon-upload" @click="openUpload(4)">上传图片</el-button>
        <div v-if="form.description != ''" class="img"><img :src="form.description" width="750" /></div>
        <div class="tips">建议尺寸:宽750像素 高度不限</div>
      </el-form-item>
      <!--提交-->
      <div class="common-button-wrapper">
        <el-button size="small" type="primary" @click="onSubmit" :loading="loading">提交</el-button>
      </div>
    </el-form>
    <!--上传图片组件-->
    <Upload v-if="isupload" :isupload="isupload" :type="type" @returnImgs="returnImgsFunc">上传图片</Upload>
  </div>
</template>
<script>
import Upload from '@/components/file/Upload';
import PlusApi from '@/api/plus/operations.js';
export default {
  components: {
    Upload: Upload
  },
  data() {
    return {
      form: {
        index: '',
        apply: '',
        cash_apply: ''
      },
      /*是否上传图片*/
      isupload: false,
       /*是否正在加载*/
      loading: false,
       /*图片类别*/
      type: ''
    };
  },
  props:{
    settingData:Object
  },
  created() {
    this.form=this.settingData.data.background.values;
  },
  methods: {
    /*上传*/
    openUpload(e) {
      this.type = e;
      this.isupload = true;
    },
    /*获取图片*/
    returnImgsFunc(e) {
      if (e != null) {
        if (this.type == 1) {
          this.form.index = e[0].file_path;
        }
        if (this.type == 2) {
          this.form.apply = e[0].file_path;
        }
        if (this.type == 3) {
          this.form.cash_apply = e[0].file_path;
        }
        if (this.type == 4) {
          this.form.description = e[0].file_path;
        }
      }
      this.isupload = false;
    },
    /*提交表单*/
    onSubmit() {
      let self = this;
      self.loading = true;
      let params = self.form;
      PlusApi.background(params, true)
        .then(data => {
          self.loading = false;
          self.$message({
            message: '恭喜你,设置成功',
            type: 'success'
          });
        })
        .catch(error => {
          self.loading = false;
        });
    }
  }
};
</script>
<style lang="scss">
.test-wrap {
  padding: 30px;
}
.img {
  margin-top: 10px;
}
.tips {
  color: #ccc;
}
</style>
operations_vue/src/views/plus/operations/setting/part/Basic.vue
New file
@@ -0,0 +1,190 @@
<template>
  <!--
          作者:luoyiming
          时间:2019-06-04
          描述:插件中心-分销-分销设置-基础设置
      -->
  <div class="product-add mt30">
    <!--form表单-->
    <el-form size="small" ref="form" :model="form" label-width="200px">
      <el-form-item label="是否开启代理收益功能">
        <div>
          <el-radio v-model="form.is_open" label="1">开启</el-radio>
          <el-radio v-model="form.is_open" label="0">关闭</el-radio>
        </div>
      </el-form-item>
      <el-form-item label="可申请成为代理条件">
        <div>
          <el-radio-group @change="chooseBecomeType" v-model="form.become">
            <el-radio :label="10">无条件</el-radio>
            <el-radio :label="40">下级分销商总数</el-radio>
            <el-radio :label="50">累计佣金总数</el-radio>
            <el-radio :label="90">单次消费</el-radio>
            <el-radio :label="100">购买指定商品</el-radio>
          </el-radio-group>
        </div>
      </el-form-item>
      <el-form-item :label="label_name" v-if="form.become!=10&&form.become!=100">
        <div>
          <el-input v-model="form.province_condition" type="number" class="max-w460">
            <template slot="prepend">省运营中心满</template>
            <template slot="append">{{unit}}</template>
          </el-input>
        </div>
        <div>
          <el-input v-model="form.city_condition" type="number" class="max-w460 mt10">
            <template slot="prepend">市运营中心满</template>
            <template slot="append">{{unit}}</template>
          </el-input>
        </div>
        <div>
          <el-input v-model="form.area_condition" type="number" class="max-w460 mt10">
            <template slot="prepend">区/县运营中心满</template>
            <template slot="append">{{unit}}</template>
          </el-input>
        </div>
      </el-form-item>
      <el-form-item label="" v-if="form.become == 100">
        <div>
          <el-row>
            <el-button type="primary" @click="openProduct">选择商品</el-button>
            <div v-if="form.product_image && form.product_image.length > 0" class="d-s-c f-w">
              <div v-for="(item, index) in form.product_image" :key="index" class="img pr">
                <a href="javascript:void(0)" class="delete-btn" @click="deleteFunc(index)"><i class="el-icon-error"></i></a>
                <img :src="item.image" width="100" height="100" />
                <p class="text-ellipsis">{{ item.product_name }}</p>
              </div>
            </div>
          </el-row>
        </div>
      </el-form-item>
      <!--提交-->
      <div class="common-button-wrapper">
        <el-button size="small" type="primary" @click="onSubmit" :loading="loading">提交</el-button>
      </div>
    </el-form>
    <!--产品列表弹出层组件-->
    <Product :isproduct="isproduct" @closeDialog="closeDialogFunc($event)">产品列表弹出层</Product>
  </div>
</template>
<script>
import PlusApi from '@/api/plus/operations.js';
import Product from '@/components/product/Product';
export default {
  components: {
    /*产品列表组件*/
    Product: Product
  },
  data() {
    return {
      /*form表单数据*/
      form: {
        is_open: '',
        level: '',
        self_buy: '',
        self_buy_money: '',
        become: 10
      },
      /*是否打开产品弹出层*/
      isproduct: false,
      /*是否正在加载*/
      loading: false,
      label_name: '',
      unit: ''
    };
  },
  props:{
    settingData:Object
  },
  created() {
    this.form = this.settingData.data.basic.values;
    this.form.become = parseInt(this.form.become);
    this.chooseBecomeType(this.form.become);
    if (!this.form.product_image) {
      this.form.product_image = [];
    }
  },
  methods: {
    /*提交表单*/
    onSubmit() {
      let self = this;
      self.loading = true;
      let params = this.form;
      PlusApi.basic(params, true)
        .then(data => {
          self.loading = false;
          self.$message({
            message: '恭喜你,设置成功',
            type: 'success'
          });
        })
        .catch(error => {
          self.loading = false;
        });
    },
    chooseBecomeType(e) {
      switch(e) {
        case 40:
          this.label_name = '下级分销商总数'
          break;
        case 50:
          this.label_name = '累计佣金总数'
          break;
        case 70:
          this.label_name = '累计团队业绩'
          break;
        case 80:
          this.label_name = '团队总人数'
          break;
        case 90:
          this.label_name = '单次消费'
          break;
      }
      if (e == 40 || e == 80) {
        this.form.province_condition = parseInt(this.form.province_condition);
        this.form.city_condition = parseInt(this.form.city_condition);
        this.form.area_condition = parseInt(this.form.area_condition);
        this.unit = '人';
      } else {
        this.unit = '元';
      }
    },
    /*删除商品*/
    deleteFunc(i) {
      this.form.become__buy_product_ids.splice(i, 1);
      this.form.product_image.splice(i, 1);
    },
    /*产品列表弹出层*/
    openProduct() {
      this.isproduct = true;
    },
    /*关闭弹窗*/
    closeDialogFunc(e) {
      this.isproduct = e.openDialog;
      if (e.type == 'success') {
        if (this.form.become__buy_product_ids.indexOf(e.params.product_id) == -1) {
          this.form.become__buy_product_ids.push(e.params.product_id);
          this.form.product_image.push({ product_id: e.params.product_id, image: e.params.image,product_name: e.params.product_name });
        } else {
          this.$message({
            message: '已选择该商品',
            type: 'warning'
          });
        }
      }
    }
  }
};
</script>
<style>
.tips {
  color: #ccc;
}
</style>
operations_vue/src/views/plus/operations/setting/part/Bonus.vue
New file
@@ -0,0 +1,89 @@
<template>
  <!--
          作者:luoyiming
          时间:2019-06-04
          描述:插件中心-分销-分销设置-佣金设置
      -->
  <div class="product-add mt30">
    <!--form表单-->
    <el-form size="small" ref="form" :model="form" label-width="200px">
      <el-form-item label="省代理收益比例 ">
        <el-input v-model="form.province_ratio" type="number" class="max-w460">
          <template slot="append">%</template>
        </el-input>
        <div class="tips">收益比例范围 0% - 100%</div>
      </el-form-item>
      <el-form-item label="市代理分红比例">
        <el-input v-model="form.city_ratio" type="number" class="max-w460">
          <template slot="append">%</template>
        </el-input>
        <div class="tips">收益比例范围 0% - 100%</div>
      </el-form-item>
      <el-form-item label="区/县代理收益比例  ">
        <el-input v-model="form.area_ratio" type="number" class="max-w460">
          <template slot="append">%</template>
        </el-input>
        <div class="tips">收益比例范围 0% - 100%</div>
      </el-form-item>
      <!--提交-->
      <div class="common-button-wrapper">
        <el-button size="small" type="primary" @click="onSubmit" :loading="loading">提交</el-button>
      </div>
    </el-form>
  </div>
</template>
<script>
  import PlusApi from '@/api/plus/operations.js';
  export default {
    data() {
      return {
        /*form表单数据*/
        form: {},
        /*加载完成*/
        loading: false,
      };
    },
    props: {
      settingData: Object
    },
    created() {
      this.form=this.settingData.data.bonus.values;
    },
    methods: {
      /*提交表单*/
      onSubmit() {
        let self = this;
        self.loading = true;
        let params = this.form;
        PlusApi.bonus(params, true)
          .then(data => {
            self.loading = false;
            self.$message({
              message: '恭喜你,设置成功',
              type: 'success'
            });
          })
          .catch(error => {
            self.loading = false;
          });
      },
    }
  };
</script>
<style>
  .tips {
    color: #ccc;
  }
</style>
operations_vue/src/views/plus/operations/setting/part/Condition.vue
New file
@@ -0,0 +1,153 @@
<template>
  <!--
          作者:luoyiming
          时间:2019-06-04
          描述:插件中心-分销-分销设置-代理条件
      -->
  <div class="product-add mt30">
    <!--form表单-->
    <el-form size="small" ref="form" :model="form" label-width="200px">
      <el-form-item label="成为代理条件">
        <div>
          <el-radio v-model="form.become" label="10">需后台审核</el-radio>
          <el-radio v-model="form.become" label="20">无需审核</el-radio>
        </div>
      </el-form-item>
      <el-form-item label="购买指定商品成为代理">
        <div>
          <el-radio v-model="form.become__buy_product" label="0">关闭</el-radio>
          <el-radio v-model="form.become__buy_product" label="1">开启</el-radio>
          <div class="tips">购买指定商品付款后自动成为代理,无需后台审核</div>
          <div v-if="form.become__buy_product == 1">
            <el-row>
              <el-button type="primary" @click="openProduct">选择商品</el-button>
              <div v-if="form.product_image && form.product_image.length > 0" class="d-s-c f-w">
                <div v-for="(item, index) in form.product_image" :key="index" class="img pr">
                  <a href="javascript:void(0)" class="delete-btn" @click="deleteFunc(index)"><i class="el-icon-error"></i></a>
                  <img :src="item.image" width="100" height="100" />
                  <p class="text-ellipsis">{{ item.product_name }}</p>
                </div>
              </div>
            </el-row>
          </div>
        </div>
      </el-form-item>
      <el-form-item label="成为下线条件">
        <div><el-radio v-model="form.downline" label="10">首次点击分享链接</el-radio></div>
      </el-form-item>
      <!--提交-->
      <div class="common-button-wrapper"><el-button size="small" type="primary" @click="onSubmit" :loading="loading">提交</el-button></div>
    </el-form>
    <!--产品列表弹出层组件-->
    <Product :isproduct="isproduct" @closeDialog="closeDialogFunc($event)">产品列表弹出层</Product>
  </div>
</template>
<script>
import PlusApi from '@/api/plus/operations.js';
import Product from '@/components/product/Product';
export default {
  components: {
    /*产品列表组件*/
    Product: Product
  },
  data() {
    return {
      /*切换菜单*/
      // activeIndex: '1',
      /*form表单数据*/
      form: {},
      /*是否打开产品弹出层*/
      isproduct: false,
      loading: false
    };
  },
  props: {
    settingData: Object
  },
  created() {
    this.form = this.settingData.data.condition.values;
    if (!this.form.product_image) {
      this.form.product_image = [];
    }
  },
  methods: {
    /*提交表单*/
    onSubmit() {
      let self = this;
      self.loading = true;
      let params = this.form;
      PlusApi.condition(params, true)
        .then(data => {
          self.loading = false;
          self.$message({
            message: '恭喜你,设置成功',
            type: 'success'
          });
        })
        .catch(error => {
          self.loading = false;
        });
    },
    /*删除商品*/
    deleteFunc(i) {
      this.form.become__buy_product_ids.splice(i, 1);
      this.form.product_image.splice(i, 1);
    },
    /*产品列表弹出层*/
    openProduct() {
      this.isproduct = true;
    },
    /*关闭弹窗*/
    closeDialogFunc(e) {
      this.isproduct = e.openDialog;
      if (e.type == 'success') {
        if (this.form.become__buy_product_ids.indexOf(e.params.product_id) == -1) {
          this.form.become__buy_product_ids.push(e.params.product_id);
          this.form.product_image.push({ product_id: e.params.product_id, image: e.params.image,product_name: e.params.product_name });
        } else {
          this.$message({
            message: '已选择该商品',
            type: 'warning'
          });
        }
      }
    }
  }
};
</script>
<style scoped="scoped">
.tips {
  color: #ccc;
}
.img {
  width: 100px;
  margin-top: 10px;
  height: 130px;
  margin-right: 10px;
}
.img img {
  border: 1px solid #eeeeee;
}
.delete-btn {
  position: absolute;
  display: block;
  width: 20px;
  height: 20px;
  line-height: 20px;
  right: -8px;
  top: -8px;
  color: red;
}
</style>
operations_vue/src/views/plus/operations/setting/part/License.vue
New file
@@ -0,0 +1,69 @@
<template>
  <!--
          作者:luoyiming
          时间:2019-06-04
          描述:插件中心-分销-分销设置-申请协议
      -->
  <div class="product-add mt30">
    <!--form表单-->
    <el-form size="small" ref="form" :model="form" label-width="200px">
      <el-form-item label="代理申请协议  ">
        <el-input v-model="form.license" type="textarea" rows="5" class="max-w460"></el-input>
      </el-form-item>
      <!--提交-->
      <div class="common-button-wrapper">
        <el-button size="small" type="primary" @click="onSubmit" :loading="loading">提交</el-button>
      </div>
    </el-form>
  </div>
</template>
<script>
  import PlusApi from '@/api/plus/operations.js';
  export default {
    data() {
      return {
        /*form表单数据*/
        form: {},
         /*是否正在加载*/
        loading: false,
      };
    },
    props:{
      settingData:Object
    },
    created() {
      this.form=this.settingData.data.license.values;
    },
    methods: {
       /*提交表单*/
      onSubmit() {
        let self = this;
        self.loading = true;
        let params = self.form;
        PlusApi.license(params, true)
          .then(data => {
            self.loading = false;
            self.$message({
              message: '恭喜你,设置成功',
              type: 'success'
            });
          })
          .catch(error => {
            self.loading = false;
          });
      },
    }
  };
</script>
<style>
</style>
operations_vue/src/views/plus/operations/setting/part/Settlement.vue
New file
@@ -0,0 +1,110 @@
<template>
  <!--
          作者:luoyiming
          时间:2019-06-04
          描述:插件中心-分销-分销设置-结算
      -->
  <div class="mt30">
    <!--form表单-->
    <el-form size="small" ref="form" :model="form" label-width="200px">
      <el-form-item label="提现方式">
        <el-checkbox-group v-model="form.pay_type">
          <el-checkbox v-for="(item,index) in list" :label="item.id" :key="index">{{item.name}}</el-checkbox>
        </el-checkbox-group>
        <div class="tips">注:如使用微信支付,则需申请微信支付企业付款到零钱功能</div>
      </el-form-item>
      <el-form-item label="分红提现手续费" prop="fee_rate" :rules="[{required: true,message: ' '}]">
        <el-input v-model="form.fee_rate" type="number" class="max-w460">
           <template slot="append">%</template>
        </el-input>
      </el-form-item>
      <el-form-item label="最低提现额度" prop="min_money" :rules="[{required: true,message: ' '}]">
        <el-input v-model="form.min_money" type="number" class="max-w460"></el-input>
      </el-form-item>
      <el-form-item label="分红结算天数" prop="settle_days" :rules="[{required: true,message: ' '}]">
        <el-input v-model="form.settle_days" type="number" class="max-w460"></el-input>
        <div class="tips">
          <p>当订单完成n天后,该订单的分红才会进行结算,0为不限制</p>
          <p class="red">注:建议分红结算天数大于允许发起售后申请天数,如果用户申请退款退货 则不结算分红</p>
        </div>
      </el-form-item>
      <el-form-item label="提现说明">
        <el-input v-model="form.explain" type="textarea" rows="5" class="max-w460"></el-input>
      </el-form-item>
      <!--提交-->
      <div class="common-button-wrapper">
        <el-button size="small" type="primary" @click="onSubmit" :loading="loading">提交</el-button>
      </div>
    </el-form>
  </div>
</template>
<script>
  import PlusApi from '@/api/plus/operations.js';
  export default {
    data() {
      return {
        /*form表单数据*/
        form: {
          pay_type: [
            10
          ],
          explain:'',
        },
        list: [],
        selectlist: [
          10
        ],
        loading: false,
      };
    },
    props: {
      settingData: Object
    },
    created() {
      this.form=this.settingData.data.settlement.values;
      this.list = this.settingData.pay_type;
    },
    methods: {
      /*提交表单*/
      onSubmit() {
        let self = this;
        let params = self.form;
        self.$refs.form.validate((valid) => {
          if (valid) {
            self.loading = true;
            PlusApi.settlement({
                form: params
              }, true)
              .then(data => {
                self.loading = false;
                self.$message({
                  message: '恭喜你,设置成功',
                  type: 'success'
                });
              })
              .catch(error => {
                self.loading = false;
              });
          }
        });
      },
    }
  };
</script>
<style>
</style>
operations_vue/src/views/plus/operations/setting/part/Words.vue
New file
@@ -0,0 +1,139 @@
<template>
  <!--
          作者:luoyiming
          时间:2019-06-04
          描述:插件中心-分销-分销设置-自定义文字
      -->
  <div class="product-add mt30">
    <!--form表单-->
    <el-form size="small" ref="form" :model="form" label-width="200px">
      <div class="common-form">代理分红页面</div>
      <el-form-item label="页面标题 ">
        <el-input v-model="form.index.title.value" placeholder="代理分红" class="max-w460"></el-input>
        <div class="tips">默认:代理分红</div>
      </el-form-item>
      <el-form-item label="代理 ">
        <el-input v-model="form.index.words.region.value" placeholder="代理" class="max-w460"></el-input>
      </el-form-item>
      <el-form-item label="非代理提示 ">
        <el-input v-model="form.index.words.region.value" placeholder="您还不是代理,请先提交申请" class="max-w460"></el-input>
      </el-form-item>
      <el-form-item label="申请运营中心 "><el-input v-model="form.index.words.apply_now.value" placeholder="立即加入" class="max-w460"></el-input></el-form-item>
     <!-- <el-form-item label="推荐人 "><el-input v-model="form.index.words.referee.value" placeholder="推荐人" class="max-w460"></el-input></el-form-item> -->
      <el-form-item label="可提现分红 "><el-input v-model="form.index.words.money.value" placeholder="可提现" class="max-w460"></el-input></el-form-item>
      <el-form-item label="待提现分红  "><el-input v-model="form.index.words.freeze_money.value" placeholder="待提现" class="max-w460"></el-input></el-form-item>
      <el-form-item label="已提现金额"><el-input v-model="form.index.words.total_money.value" placeholder="已提现金额" class="max-w460"></el-input></el-form-item>
      <el-form-item label="去提现"><el-input v-model="form.index.words.cash.value" placeholder="去提现" class="max-w460"></el-input></el-form-item>
      <div class="common-form">申请运营中心页面</div>
      <el-form-item label="页面标题">
        <el-input v-model="form.apply.title.value" placeholder="申请运营中心" class="max-w460"></el-input>
        <div class="tips">默认:申请运营中心</div>
      </el-form-item>
      <el-form-item label="请填写申请信息"><el-input v-model="form.apply.words.title.value" placeholder="请填写申请信息" class="max-w460"></el-input></el-form-item>
      <el-form-item label="代理申请协议"><el-input v-model="form.apply.words.license.value" placeholder="代理申请协议" class="max-w460"></el-input></el-form-item>
      <el-form-item label="申请运营中心"><el-input v-model="form.apply.words.submit.value" placeholder="申请运营中心" class="max-w460"></el-input></el-form-item>
      <el-form-item label="审核中提示信息">
        <el-input v-model="form.apply.words.wait_audit.value" placeholder="您的申请已受理,正在进行信息核验,请耐心等待。" class="max-w460"></el-input>
      </el-form-item>
      <el-form-item label="未达到申请条件提示信息">
        <el-input v-model="form.apply.words.not_pass.value" placeholder="很抱歉,您未达到申请条件" class="max-w460"></el-input>
      </el-form-item>
      <el-form-item label="去商城逛逛"><el-input v-model="form.apply.words.goto_mall.value" placeholder="去商城逛逛" class="max-w460"></el-input></el-form-item>
      <div class="common-form">运营中心订单页面</div>
      <el-form-item label="页面标题">
        <el-input v-model="form.order.title.value" placeholder="运营中心订单" class="max-w460"></el-input>
        <div class="tips">默认:运营中心订单</div>
      </el-form-item>
      <el-form-item label="全部"><el-input v-model="form.order.words.all.value" placeholder="全部" class="max-w460"></el-input></el-form-item>
      <el-form-item label="未结算"><el-input v-model="form.order.words.unsettled.value" placeholder="未结算" class="max-w460"></el-input></el-form-item>
      <el-form-item label="已结算"><el-input v-model="form.order.words.settled.value" placeholder="已结算" class="max-w460"></el-input></el-form-item>
      <div class="common-form">结算明细页面</div>
      <el-form-item label="页面标题">
        <el-input v-model="form.bonus_list.title.value" placeholder="结算明细" class="max-w460"></el-input>
        <div class="tips">默认:结算明细</div>
      </el-form-item>
      <div class="common-form">提现明细页面</div>
      <el-form-item label="页面标题">
        <el-input v-model="form.cash_list.title.value" placeholder="提现明细" class="max-w460"></el-input>
        <div class="tips">默认:提现明细</div>
      </el-form-item>
      <el-form-item label="全部"><el-input v-model="form.cash_list.words.all.value" placeholder="全部" class="max-w460"></el-input></el-form-item>
      <el-form-item label="审核中"><el-input v-model="form.cash_list.words.apply_10.value" placeholder="审核中" class="max-w460"></el-input></el-form-item>
      <el-form-item label="审核通过"><el-input v-model="form.cash_list.words.apply_20.value" placeholder="审核通过" class="max-w460"></el-input></el-form-item>
      <el-form-item label="已打款"><el-input v-model="form.cash_list.words.apply_40.value" placeholder="已打款" class="max-w460"></el-input></el-form-item>
      <el-form-item label="驳回"><el-input v-model="form.cash_list.words.apply_30.value" placeholder="驳回" class="max-w460"></el-input></el-form-item>
      <div class="common-form">申请提现页面</div>
      <el-form-item label="页面标题">
        <el-input v-model="form.cash_apply.title.value" placeholder="申请提现" class="max-w460"></el-input>
        <div class="tips">默认:申请提现</div>
      </el-form-item>
      <el-form-item label="可提现分红"><el-input v-model="form.cash_apply.words.capital.value" placeholder="可提现分红" class="max-w460"></el-input></el-form-item>
      <el-form-item label="提现金额"><el-input v-model="form.cash_apply.words.money.value" placeholder="提现金额" class="max-w460"></el-input></el-form-item>
      <el-form-item label="请输入要提取的金额">
        <el-input v-model="form.cash_apply.words.money_placeholder.value" placeholder="请输入要提取的金额" class="max-w460"></el-input>
      </el-form-item>
      <el-form-item label="最低提现分红"><el-input v-model="form.cash_apply.words.min_money.value" placeholder="最低提现分红" class="max-w460"></el-input></el-form-item>
      <el-form-item label="提交申请"><el-input v-model="form.cash_apply.words.submit.value" placeholder="提交申请" class="max-w460"></el-input></el-form-item>
      <!--提交-->
      <div class="common-button-wrapper">
        <el-button size="small" type="primary" @click="onSubmit" :loading="loading">提交</el-button>
      </div>
    </el-form>
  </div>
</template>
<script>
import PlusApi from '@/api/plus/operations.js';
export default {
  data() {
    return {
      /*form表单数据*/
      form: {},
      /*是否正在加载*/
      loading: false,
    };
  },
  props: {
    settingData: Object
  },
  created() {
    this.form = this.settingData.data.words.values;
  },
  methods: {
    /*提交表单*/
    onSubmit() {
      let self = this;
      let params = self.form;
      self.loading = true;
      PlusApi.words(params, true)
        .then(data => {
          self.loading = false;
          self.$message({
            message: '恭喜你,设置成功',
            type: 'success'
          });
        })
        .catch(error => {
          self.loading = false;
        });
    }
  }
};
</script>
<style>
.tips {
  color: #ccc;
}
</style>
operations_vue/src/views/plus/operations/user/dialog/Add.vue
New file
@@ -0,0 +1,305 @@
<template>
  <!--
          作者:luoyiming
          时间:2020-06-01
          描述:插件中心-区域代理-添加区域代理
      -->
  <el-dialog title="添加区域代理" :visible.sync="dialogVisible" @close="cancelFunc" :close-on-click-modal="false" :close-on-press-escape="false" width="500px">
    <el-form :model="formData" :rules="rules" ref="formData" label-width="100px">
      <el-form-item label="绑定用户" prop="user_id" :rules="[{required: true,message: '请选择用户'}]">
        <el-row>
          <el-button icon="el-icon-picture-outline" @click="userClick()">选择用户</el-button>
          <div v-if="formData.user_id!=0" class="img">
            <img :src="user_info.avatarUrl" width="100" height="100" />
            <div style="margin-top: 5px;">{{ user_info.nickName }}</div>
          </div>
        </el-row>
      </el-form-item>
      <el-form-item label="姓名" prop="real_name">
        <el-input type="text" v-model="formData.real_name" autocomplete="off" placeholder="请输入真实姓名"></el-input>
      </el-form-item>
      <el-form-item label="手机号" prop="mobile">
        <el-input type="text" v-model="formData.mobile" autocomplete="off" placeholder="请输入手机号"></el-input>
      </el-form-item>
      <el-form-item label="代理级别" prop="region_level">
        <el-select v-model="formData.region_level" placeholder="请选择代理级别" @change="handleLevelChange">
<!--          <el-option label="省级代理"  :value="1"></el-option>-->
          <el-option label="市级代理"  :value="2"></el-option>
          <el-option label="区/县级代理" :value="3"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="省份" prop="province_id">
        <el-select v-model="formData.province_id" placeholder="请选择省份" @change="handleProvinceChange">
          <el-option v-for="item in provinceList" :key="item.id" :label="item.name" :value="item.id"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="城市" prop="city_id" v-if="formData.region_level >= 2">
        <el-select v-model="formData.city_id" placeholder="请选择城市" @change="handleCityChange" :disabled="!formData.province_id">
          <el-option v-for="item in cityList" :key="item.id" :label="item.name" :value="item.id"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="区/县" prop="area_id" v-if="formData.region_level == 3">
        <el-select v-model="formData.area_id" placeholder="请选择区/县" :disabled="!formData.city_id">
          <el-option v-for="item in areaList" :key="item.id" :label="item.name" :value="item.id"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="代理等级" prop="grade_id">
        <el-select v-model="formData.grade_id" placeholder="请选择代理等级">
          <el-option label="默认等级" :value="0"></el-option>
          <el-option v-for="(item,index) in gradeList" :key="index" :label="item.name" :value="item.grade_id"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="登录账号" prop="user_name">
        <el-input type="text" v-model="formData.user_name" autocomplete="off" placeholder="请输入登录账号"></el-input>
      </el-form-item>
      <el-form-item label="登录密码" prop="password">
        <el-input type="password" v-model="formData.password" autocomplete="off" placeholder="请输入登录密码"></el-input>
      </el-form-item>
    </el-form>
    <div slot="footer" class="dialog-footer">
      <el-button @click="cancelFunc">取 消</el-button>
      <el-button type="primary" @click="confirmFunc" :loading="loading">确 定</el-button>
    </div>
    <!--选择用户组件-->
    <GetUser :is_open="open_user" :is_radio="true" @close="closeDialogFunc"></GetUser>
  </el-dialog>
</template>
<script>
import OperationsApi from '@/api/plus/operations.js';
import DataApi from '@/api/data.js';
import GetUser from '@/components/user/GetUser.vue';
export default {
  components: {
    GetUser
  },
  data() {
    return {
      /*是否显示*/
      dialogVisible: false,
      /*表单数据模型*/
      formData: {
        user_id: 0,
        real_name: '',
        mobile: '',
        region_level: 1,
        province_id: '',
        city_id: '',
        area_id: '',
        grade_id: 0,
        user_name: '',
        password: ''
      },
      /*表单验证规则*/
      rules: {
        user_id: [
          { required: true, message: '请选择用户', trigger: 'change' }
        ],
        real_name: [
          { required: true, message: '请输入真实姓名', trigger: 'blur' }
        ],
        mobile: [
          { required: true, message: '请输入手机号', trigger: 'blur' },
          { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
        ],
        region_level: [
          { required: true, message: '请选择代理级别', trigger: 'change' }
        ],
        province_id: [
          { required: true, message: '请选择省份', trigger: 'change' }
        ],
        city_id: [
          { required: true, message: '请选择城市', trigger: 'change' }
        ],
        area_id: [
          { required: true, message: '请选择区/县', trigger: 'change' }
        ],
        user_name: [
          { required: true, message: '请输入登录账号', trigger: 'blur' }
        ],
        password: [
          { required: true, message: '请输入登录密码', trigger: 'blur' },
          { min: 6, message: '密码长度不能少于6位', trigger: 'blur' }
        ]
      },
      /*地区数据*/
      regionData: [],
      /*等级列表*/
      gradeList: [],
      /*加载状态*/
      loading: false,
      /*是否打开选择用户弹窗*/
      open_user: false,
      /*选中的用户信息*/
      user_info: {}
    };
  },
  props: {
    open_add: Boolean
  },
  watch: {
    open_add: function(n, o) {
      if (n != o) {
        this.dialogVisible = this.open_add;
        if (n) {
          this.resetForm();
          this.getGradeList();
          this.getRegionData();
        }
      }
    }
  },
  created() {
  },
  computed: {
    /*获取省份列表*/
    provinceList() {
      return Object.values(this.regionData).filter(item => item.level === 1);
    },
    /*获取城市列表*/
    cityList() {
      if (this.formData.province_id && this.regionData[this.formData.province_id]) {
        const provinceData = this.regionData[this.formData.province_id];
        if (provinceData.city) {
          return Object.values(provinceData.city);
        }
      }
      return [];
    },
    /*获取区/县列表*/
    areaList() {
      if (this.formData.city_id && this.formData.province_id && this.regionData[this.formData.province_id]) {
        const provinceData = this.regionData[this.formData.province_id];
        if (provinceData.city && provinceData.city[this.formData.city_id]) {
          const cityData = provinceData.city[this.formData.city_id];
          if (cityData.region) {
            return Object.values(cityData.region);
          }
        }
      }
      return [];
    }
  },
  methods: {
    /*获取等级列表*/
    getGradeList(){
      let self = this;
      OperationsApi.toOperationsEdit({}, true)
        .then(res => {
          self.gradeList = res.data.gradeList;
        })
        .catch(() => {});
    },
    /*获取地区数据*/
    getRegionData(){
      let self = this;
      DataApi.getRegion({}, true)
        .then(res => {
          self.regionData = res.data.regionData;
        })
        .catch(() => {});
    },
    /*省份改变*/
    handleProvinceChange(){
      this.formData.city_id = '';
      this.formData.area_id = '';
    },
    /*城市改变*/
    handleCityChange(){
      this.formData.area_id = '';
    },
    /*代理级别改变*/
    handleLevelChange(val){
      if(val == 1){
        this.formData.city_id = '';
        this.formData.area_id = '';
        this.$refs.formData.clearValidate(['city_id', 'area_id']);
      }else if(val == 2){
        this.formData.area_id = '';
        this.$refs.formData.clearValidate(['area_id']);
      }
    },
    /*确认添加*/
    confirmFunc() {
      let self = this;
      this.$refs.formData.validate((valid) => {
        if (valid) {
          self.loading = true;
          OperationsApi.addOperationsUser(self.formData, true)
            .then(data => {
              self.loading = false;
              self.$message({
                message: '添加成功',
                type: 'success'
              });
              self.cancelFunc(true);
            })
            .catch(() => {
              self.loading = false;
            });
        } else {
          return false;
        }
      });
    },
    /*重置表单*/
    resetForm(){
      this.formData = {
        user_id: 0,
        real_name: '',
        mobile: '',
        region_level: 1,
        province_id: '',
        city_id: '',
        area_id: '',
        grade_id: 0,
        user_name: '',
        password: ''
      };
      this.user_info = {};
      if(this.$refs.formData){
        this.$refs.formData.resetFields();
      }
    },
    /*打开选择用户弹窗*/
    userClick() {
      this.open_user = true;
    },
    /*关闭获取用户弹窗*/
    closeDialogFunc(e) {
      if (e.type != 'error') {
        // e.params可能是单个对象(单选模式)或数组(多选模式)
        const user = Array.isArray(e.params) ? e.params[0] : e.params;
        this.user_info = user;
        this.formData.user_id = user.user_id;
      }
      this.open_user = false;
    },
    /*关闭弹窗*/
    cancelFunc(e) {
      let type = 'cancel';
      if(e){
        type = 'success';
      }
      this.$emit('close', {
        type: type
      });
    }
  }
};
</script>
<style>
.img {
  margin-top: 10px;
}
</style>
operations_vue/src/views/plus/operations/user/dialog/Edit.vue
New file
@@ -0,0 +1,122 @@
<template>
  <!--
          作者:luoyiming
          时间:2020-06-01
          描述:插件中心-分销-分销商用户-编辑
      -->
  <el-dialog title="编辑" :visible.sync="dialogVisible" @close="cancelFunc" :close-on-click-modal="false" :close-on-press-escape="false" width="30%">
    <el-form :model="formData">
      <el-form-item label="微信昵称" :label-width="formLabelWidth">
        <el-input type="text" v-model="formData.nickName" autocomplete="off" :disabled="true"></el-input>
      </el-form-item>
      <el-form-item label="微信头像" :label-width="formLabelWidth">
        <img v-img-url="formData.avatarUrl" width="50" height="50" />
      </el-form-item>
      <el-form-item label="姓名" :label-width="formLabelWidth">
        <el-input type="text" v-model="formData.real_name" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="手机号" :label-width="formLabelWidth">
        <el-input type="text" v-model="formData.mobile" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="登录账号" :label-width="formLabelWidth">
        <el-input type="text" v-model="formData.user_name" autocomplete="off" placeholder="如需修改请输入新账号"></el-input>
      </el-form-item>
      <el-form-item label="登录密码" :label-width="formLabelWidth">
        <el-input type="password" v-model="formData.password" autocomplete="off" placeholder="如需修改请输入新密码"></el-input>
      </el-form-item>
      <el-form-item label="管理员账号" :label-width="formLabelWidth">
        <el-tag v-if="formData.has_login" type="success">已创建</el-tag>
        <el-tag v-else type="warning">未创建</el-tag>
      </el-form-item>
    </el-form>
    <div slot="footer" class="dialog-footer">
      <el-button @click="cancelFunc">取 消</el-button>
      <el-button type="primary" @click="confirmFunc">确 定</el-button>
    </div>
  </el-dialog>
</template>
<script>
import OperationsApi from '@/api/plus/operations.js';
export default {
  data() {
    return {
      /*左边长度*/
      formLabelWidth: '100px',
      /*是否显示*/
      dialogVisible: false,
      /*表单数据模型*/
      formData: {},
      gradeList: []
    };
  },
  props: {
    open_edit: Boolean,
    userModel: Object
  },
  watch: {
    open_edit: function(n, o) {
      if (n != o) {
        this.dialogVisible = this.open_edit;
        if (n) {
          this.formData = this.userModel;
        }
      }
    }
  },
  created() {
    this.getData();
  },
  methods: {
    getData(){
      let self = this;
      OperationsApi.toOperationsEdit({}, true)
        .then(res => {
          self.gradeList = res.data.gradeList;
        })
        .catch(error => {});
    },
    /*修改用户*/
    confirmFunc() {
      let self = this;
      let params ={};
      params.user_id= this.formData.user_id;
      params.real_name=this.formData.real_name;
      params.mobile=this.formData.mobile;
      // 只有在输入了用户名时才传递
      if (this.formData.user_name && this.formData.user_name.trim() !== '') {
        params.user_name = this.formData.user_name;
      }
      // 只有在输入了密码时才传递
      if (this.formData.password && this.formData.password.trim() !== '') {
        params.password = this.formData.password;
      }
      //params.grade_id=this.formData.grade_id;
      OperationsApi.operationsEdit(params, true)
        .then(data => {
          self.$message({
            message: '恭喜你,修改成功',
            type: 'success'
          });
          self.cancelFunc(true);
        })
        .catch(error => {});
    },
    /*关闭弹窗*/
    cancelFunc(e) {
      let type='cancel';
      if(e){
        type='success';
      }
      this.$emit('close', {
        type:type
      });
    }
  }
};
</script>
<style></style>
operations_vue/src/views/plus/operations/user/dialog/SubUser.vue
New file
@@ -0,0 +1,135 @@
<template>
  <!--
          作者:luoyiming
          时间:2020-06-01
          描述:插件中心-分销-代理用户-查看下级用户
      -->
  <div>
    <el-dialog title="下级用户" :visible.sync="dialogVisible" @close="dialogFormVisible" :close-on-click-modal="true" :close-on-press-escape="false">
      <el-radio-group v-model="level" size="small" @change="changFunc">
        <el-radio-button label="1">一级</el-radio-button>
        <el-radio-button label="2">二级</el-radio-button>
        <el-radio-button label="3">三级</el-radio-button>
      </el-radio-group>
      <!--table-->
      <div class="mt16">
        <el-table size="small" :data="tableData" border style="width: 100%" v-loading="loading">
          <el-table-column prop="user_id" label="用户ID"></el-table-column>
          <el-table-column prop="nickName" label="微信头像">
            <template slot-scope="scope">
              <img class="radius" v-img-url="scope.row.user.avatarUrl" width="30" height="30" />
            </template>
          </el-table-column>
          <el-table-column prop="user.nickName" label="    微信昵称"></el-table-column>
          <el-table-column prop="user.mobile" label="手机号"></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>
    </el-dialog>
  </div>
</template>
<script>
import OperationsApi from '@/api/plus/operations.js';
export default {
  data() {
    return {
      /*是否显示*/
      dialogVisible: false,
      /*是否正在加载*/
      loading:true,
      /*当前第几级*/
      level: '1',
      /*列表数据*/
      tableData: [],
      /*一页多少条*/
      pageSize: 20,
      /*一共多少条数据*/
      totalDataNumber: 0,
      /*当前是第几页*/
      curPage: 1
    };
  },
  props: {
    open_dialog: Boolean,
    userModel:Object
  },
  watch: {
    open_dialog: function(n, o) {
      if (n != o) {
        this.dialogVisible = this.open_dialog;
        if(n){
          this.getData();
        }
      }
    }
  },
  created() {
  },
  methods: {
    /*切换等级*/
    changFunc(e){
      this.getData();
    },
    /*选择第几页*/
    handleCurrentChange(val) {
      let self = this;
      self.curPage = val;
      self.loading = true;
      self.getData();
    },
    /*获取数据*/
    getData() {
      let self = this;
      let Params = {};
      Params.page = self.curPage;
      Params.list_rows = self.pageSize;
      Params.user_id=self.userModel.user_id;
      Params.level=self.level;
      OperationsApi.operationsUserFans(Params, true)
        .then(data => {
          self.loading = false;
          self.tableData = data.data.list.data;
        })
        .catch(error => {});
    },
    /*每页多少条*/
    handleSizeChange(val) {
      this.curPage = 1;
      this.pageSize = val;
      this.getData();
    },
    /*关闭弹窗*/
    dialogFormVisible(e) {
      this.$emit('close', {});
    }
  }
};
</script>
<style scoped>
.el-dialog__body {
  padding: 10px 20px;
}
</style>
operations_vue/src/views/plus/operations/user/user.vue
New file
@@ -0,0 +1,286 @@
<template>
  <!--
          作者:luoyiming
          时间:2020-06-01
          描述:插件中心-分销-代理用户
      -->
  <div class="user">
      <div class="common-seach-wrap flex-1">
        <el-form size="small" :inline="true" :model="formInline" class="demo-form-inline">
          <el-form-item label=""><el-input v-model="formInline.nick_name" placeholder="请输入昵称/姓名/手机号"></el-input></el-form-item>
          <el-form-item><el-button type="primary" @click="onSubmit">查询</el-button></el-form-item>
          <el-form-item><el-button type="primary" @click="addClick" v-auth="'/plus/operations/user/add'">添加运营中心</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="user_id" label="用户ID" width="70"></el-table-column>
          <el-table-column prop="nickName" label="微信头像" width="70">
            <template slot-scope="scope">
              <img class="radius" v-img-url="scope.row.avatarUrl" width="30" height="30" />
            </template>
          </el-table-column>
          <el-table-column prop="nickName" label="    微信昵称"></el-table-column>
          <el-table-column prop="real_name" label="姓名"></el-table-column>
          <el-table-column prop="mobile" label="手机号"></el-table-column>
          <el-table-column prop="has_login" label="管理员账号" width="100">
            <template slot-scope="scope">
              <el-tag v-if="scope.row.has_login" type="success" size="small">已创建</el-tag>
              <el-tag v-else type="warning" size="small">未创建</el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="money" label="累计分红">
            <template slot-scope="scope">
              <span class="orange">{{ scope.row.money }}</span>
            </template>
          </el-table-column>
          <el-table-column prop="total_money" label="可提现分红">
            <template slot-scope="scope">
              <span class="orange">{{ scope.row.total_money }}</span>
            </template>
          </el-table-column>
          <!-- <el-table-column prop="referee.nickName" label="推荐人"></el-table-column> -->
         <el-table-column prop="" label="代理级别/区域">
           <template slot-scope="scope">
             <div>{{scope.row.operations_level.text}}</div>
             <div>
               <span>{{scope.row.region.province}}</span>
               <span v-if="scope.row.operations_level.value>1">{{scope.row.region.city}}</span>
               <span v-if="scope.row.operations_level.value>2">{{scope.row.region.area}}</span>
             </div>
           </template>
         </el-table-column>
          <el-table-column prop="create_time" label="成为时间" width="140"></el-table-column>
          <el-table-column fixed="right" label="操作" width="160">
            <template slot-scope="scope">
              <div>
                <el-button @click="saleClick(scope.row)" type="text" size="small" v-auth="'/plus/operations/order/index'">分红订单</el-button>
                <el-button @click="detailedClick(scope.row)" type="text" size="small" v-auth="'/plus/operations/cash/index'">提现明细</el-button>
               <!-- <el-button @click="openSubUser(scope.row)" type="text" size="small" v-auth="'/plus/operations/user/fans'">下级用户</el-button> -->
                <el-button @click="EditClick(scope.row)" type="text" size="small" v-auth="'/plus/operations/operations/edit'">修改</el-button>
                <el-button @click="delClick(scope.row)" type="text" size="small" v-auth="'/plus/operations/operations/delete'">删除</el-button>
              </div>
            </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>
    <!--查看下级用户-->
    <SubUser :open_dialog="open_dialog" :userModel="userModel" @close="closeFunc"></SubUser>
    <!--编辑-->
    <Edit :open_edit="open_edit" :userModel="userModel" @close="closeEditFunc"></Edit>
    <!--添加区域代理-->
    <Add :open_add="open_add" @close="closeAddFunc"></Add>
  </div>
</template>
<script>
import { deepClone } from '@/utils/base.js'
import OperationsApi from '@/api/plus/operations.js';
import SubUser from './dialog/SubUser.vue';
import Edit from './dialog/Edit.vue';
import Add from './dialog/Add.vue';
export default {
  components: {
    SubUser,
    Edit,
    Add
  },
  data() {
    return {
      /*是否加载完成*/
      loading: true,
      /*列表数据*/
      tableData: [],
      /*一页多少条*/
      pageSize: 20,
      /*一共多少条数据*/
      totalDataNumber: 0,
      /*当前是第几页*/
      curPage: 1,
      /*搜索对象*/
      formInline: {
        nick_name: ''
      },
      /*是否打开弹窗*/
      open_dialog: false,
      /*基础设置当前用户的信息*/
      basicSetting: [],
      /*选中的用户*/
      userModel:{},
      /*是否打开修改*/
      open_edit:false,
      /*是否打开添加*/
      open_add:false
    };
  },
  created() {
    /*获取列表*/
    this.getData();
  },
  methods: {
    /*选择第几页*/
    handleCurrentChange(val) {
      let self = this;
      self.curPage = val;
      self.loading = true;
      self.getData();
    },
    /*获取数据*/
    getData() {
      let self = this;
      let Params = {};
      Params.page = self.curPage;
      Params.list_rows = self.pageSize;
      if(self.formInline.nick_name!=''){
        Params.nick_name=self.formInline.nick_name;
      }
      OperationsApi.operationsList(Params, true)
        .then(data => {
          self.loading = false;
          self.tableData = data.data.list.data;
          self.totalDataNumber = data.data.list.total;
          self.basicSetting = data.data.basicSetting;
        })
        .catch(error => {
          self.loading = false;
        });
    },
    //搜索
    onSubmit() {
      this.curPage = 1;
      this.getData();
    },
    /*每页多少条*/
    handleSizeChange(val) {
      this.curPage = 1;
      this.pageSize = val;
      this.getData();
    },
    /*分红订单*/
    saleClick(item) {
      this.$router.push({
        path:'/plus/operations/index',
        query:{
          type:'order',
          user_id:item.user_id
        }
      })
    },
    /*提现明细*/
    detailedClick(item) {
      this.$router.push({
        path:'/plus/operations/index',
        query:{
          type:'cash',
          user_id:item.user_id
        }
      })
    },
    /*删除代理*/
    delClick(row) {
      let self = this;
      self
        .$confirm('此操作将永久删除该记录, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
        .then(() => {
          self.loading = true;
          OperationsApi.deleteOperations(
            {
              user_id: row.user_id
            },
            true
          )
            .then(data => {
              self.loading = false;
              self.$message({
                message: data.msg,
                type: 'success'
              });
              self.getData();
            })
            .catch(error => {
              self.loading = false;
            });
        })
        .catch(() => {
          self.loading = false;
        });
    },
    /*打开下级用户弹窗*/
    openSubUser(e){
      this.userModel=e;
      this.open_dialog=true;
    },
    /*关闭下级用户弹窗*/
    closeFunc(){
      this.open_dialog=false;
    },
     /*打开编辑用户弹窗*/
    EditClick(e){
      this.userModel=deepClone(e);
      this.open_edit=true;
    },
    /*关闭编辑用户弹窗*/
    closeEditFunc(e){
      this.open_edit=false;
      if(e.type=='success'){
        this.getData();
      }
    },
    /*打开添加代理弹窗*/
    addClick(){
      this.open_add=true;
    },
    /*关闭添加代理弹窗*/
    closeAddFunc(e){
      this.open_add=false;
      if(e.type=='success'){
        this.getData();
      }
    }
  }
};
</script>
<style scoped="scoped">
  .el-button{margin-left: 0; margin-right: 10px;}
</style>
shop_vue/src/api/branch.js
@@ -100,6 +100,10 @@
  deleteActivity(data, errorback) {
    return request._post('/shop/branch.activity/delete', data, errorback);
  },
  /*审核活动*/
  auditActivity(data, errorback) {
    return request._post('/shop/branch.activity/audit', data, errorback);
  },
  activityStatus(data, errorback) {
    return request._post('/shop/branch.activity/status', data, errorback);
  },
shop_vue/src/views/branch/activity/add.vue
@@ -15,7 +15,7 @@
        <el-input v-model="form.name" placeholder="请输入活动标题" class="max-w460"></el-input>
      </el-form-item>
      <el-form-item label="活动分类" prop="category_id">
        <el-select v-model="form.category_id" placeholder="请选择">
        <el-select v-model="form.category_id" placeholder="请选择" @change="handleCategoryChange">
          <el-option v-for="(item, index) in category" :key="index" :label="item.name" :value="item.category_id"></el-option>
        </el-select>
      </el-form-item>
@@ -46,12 +46,16 @@
          <el-radio :label="0">否</el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item v-if="form.is_visit" label="被走访企业名称" prop="visit_supplier_name">
        <el-input v-model="form.visit_supplier_name" placeholder="商户没有入驻时,请输入被走访企业名称" class="max-w460"></el-input>
      </el-form-item>
      <el-form-item label="被走访企业" prop="visit_supplier_id" v-if="form.is_visit">
        <el-row>
          <el-button @click="selectSupplier('visit')" icon="el-icon-plus">选择企业</el-button>
          <div v-if="form.visit_supplier_id!=''" class="mt10">
            <el-tag>{{ visit_supplier_name }}</el-tag>
          </div>
          <div class="gray9" v-if="form.visit_supplier_id==''">如没有可不选</div>
        </el-row>
      </el-form-item>
      <el-form-item label="提供场地企业" prop="space_supplier_id" v-if="!form.is_visit">
@@ -73,7 +77,7 @@
        <el-input v-model="form.limit_num" placeholder="请输入活动名额" class="max-w460">
          <template slot="append">人</template>
        </el-input>
        <div class="gray9">0为不限制人数</div>
        <div class="gray9">0为不限制人数{{selectedCategory.limit_num?(',该分类最多'+selectedCategory.limit_num+'人'):''}}</div>
      </el-form-item>
      <el-form-item label="联系电话" prop="phone">
        <el-input v-model="form.phone" placeholder="请输入联系电话" class="max-w460"></el-input>
@@ -224,6 +228,8 @@
      },
      /*活动类别*/
      category: [],
      /*选中的分类信息*/
      selectedCategory: null,
      loading: false,
      upload_type: 'image', // 封面image 分享海报pic
      open_branch: false,
@@ -280,7 +286,9 @@
        .then(res => {
          self.category = res.data.category;
          if(self.category.length > 0){
            self.form.category_id = self.catgory[0].category_id;
            self.form.category_id = self.category[0].category_id;
            // 设置默认选中的分类信息
            self.selectedCategory = self.category[0];
          }
        })
        .catch(error => {
@@ -288,6 +296,16 @@
        });
    },
    /*处理分类选择变化*/
    handleCategoryChange(value) {
      // 根据选中的category_id找到对应的分类对象
      const selected = this.category.find(item => item.category_id === value);
      this.selectedCategory = selected || null;
      // 可以在这里添加其他业务逻辑,比如根据分类显示不同的表单字段等
      console.log('选中的分类信息:', this.selectedCategory);
    },
    /*添加活动*/
    onSubmit() {
      let self = this;
shop_vue/src/views/branch/activity/drawer/part/edit.vue
@@ -13,9 +13,10 @@
      </el-form-item>
      <el-form-item label="活动标题" prop="name"><el-input v-model="form.name" placeholder="请输入活动标题" class="max-w460"></el-input></el-form-item>
      <el-form-item label="活动分类" prop="category_id">
        <el-select v-model="form.category_id" placeholder="请选择">
        <el-select v-model="form.category_id" placeholder="请选择" @change="handleCategoryChange">
          <el-option v-for="(item, index) in category" :key="index" :label="item.name" :value="item.category_id"></el-option>
        </el-select>
        <div class="gray9" v-if="selectedCategory">该分类最多{{ selectedCategory.limit_num }}人</div>
      </el-form-item>
      <el-form-item label="活动简介" prop="describe"><el-input type="textarea" v-model="form.describe" rows="4" maxlength="200" show-word-limit placeholder="请输入活动简介" class="max-w460"></el-input></el-form-item>
      <el-form-item label="封面图">
@@ -44,12 +45,16 @@
          <el-radio :label="0">否</el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item v-if="form.is_visit" label="被走访企业名称" prop="visit_supplier_name">
        <el-input v-model="form.visit_supplier_name" placeholder="商户没有入驻时,请输入被走访企业名称" class="max-w460"></el-input>
      </el-form-item>
      <el-form-item label="被走访企业" prop="visit_supplier_id" key="visit_supplier_id" v-if="form.is_visit">
        <el-row>
          <el-button @click="selectSupplier('visit')" icon="el-icon-plus">选择企业</el-button>
          <div v-if="form.visit_supplier_id!=''" class="mt10">
            <el-tag>{{ visit_supplier_name }}</el-tag>
          </div>
          <div class="gray9" v-if="form.visit_supplier_id==''">如没有可不选</div>
        </el-row>
      </el-form-item>
      <el-form-item label="提供场地企业" prop="space_supplier_id" key="space_supplier_id" v-if="!form.is_visit">
@@ -71,7 +76,7 @@
        <el-input v-model="form.limit_num" placeholder="请输入活动名额" class="max-w460">
          <template slot="append">人</template>
        </el-input>
        <div class="gray9">0为不限制人数</div>
        <div class="gray9">0为不限制人数{{selectedCategory&&selectedCategory.limit_num?(',该分类最多'+selectedCategory.limit_num+'人'):''}}</div>
      </el-form-item>
      <el-form-item label="联系电话" prop="phone">
        <el-input v-model="form.phone" placeholder="请输入联系电话" class="max-w460"></el-input>
@@ -213,6 +218,20 @@
      rules: {
        name: [{ required: true, message: '请输入活动标题', trigger: 'blur' }],
        category_id: [{ required: true, message: '请选择活动分类', trigger: 'blur' }],
        visit_supplier_name: [
          {
            required: true,
            message: '请输入被走访企业名称',
            trigger: 'blur',
            validator: (rule, value, callback) => {
              if (this.form.is_visit && (!value || value.trim() === '')) {
                callback(new Error('请输入被走访企业名称'));
              } else {
                callback();
              }
            }
          }
        ],
        visit_supplier_id: [{ required: true, trigger: 'blur', validator: validateVisit }],
        reg_date: [{ required: true, message: '请选择报名起止时间', trigger: 'blur' }],
        act_date: [{ required: true, message: '请选择活动起止时间', trigger: 'blur' }],
@@ -263,6 +282,16 @@
        .catch(error => {});
    },
    /*处理分类选择变化*/
    handleCategoryChange(value) {
      // 根据选中的category_id找到对应的分类对象
      const selected = this.category.find(item => item.category_id === value);
      this.selectedCategory = selected || null;
      // 可以在这里添加其他业务逻辑,比如根据分类显示不同的表单字段等
      console.log('选中的分类信息:', this.selectedCategory);
    },
    formatData() {
      this.ueditor.text = this.form.content;
      this.branch_name = this.form.branch.name;
@@ -273,6 +302,12 @@
      this.visit_supplier_name = this.form.visitSupplier ? this.form.visitSupplier.name : '';
      this.space_supplier_name = this.form.spaceSupplier ? this.form.spaceSupplier.name : '';
      this.select_list = this.form.verify_user;
      // 初始化选中的分类信息
      if (this.category && this.form.category_id) {
        this.selectedCategory = this.category.find(item => item.category_id === this.form.category_id) || null;
      }
      this.loading = false;
    },
shop_vue/src/views/branch/activity/index.vue
@@ -1,6 +1,13 @@
<template>
  <div>
    <div class="common-level-rail"><el-button size="small" type="primary" icon="el-icon-plus" @click="add">添加活动</el-button></div>
    <div class="common-level-rail">
      <el-button size="small" type="primary" icon="el-icon-plus" @click="add">添加活动</el-button>
      <el-select v-model="searchForm.audit_status" placeholder="审核状态" clearable @change="handleSearch">
        <el-option label="待审核" :value="0"></el-option>
        <el-option label="已通过" :value="10"></el-option>
        <el-option label="已驳回" :value="20"></el-option>
      </el-select>
    </div>
    <div class="table-wrap">
      <el-table :data="tableData" style="width: 100%" v-loading="loading">
        <el-table-column prop="activity_id" label="活动ID" width="60"></el-table-column>
@@ -32,16 +39,24 @@
            <el-tag :type="tagType(row.status_text.status)">{{ row.status_text.status_text }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="audit_status" label="审核状态" width="100">
          <template slot-scope="{ row }">
            <el-tag :type="auditStatusType(row.audit_status_text.status)">
              {{ row.audit_status_text.text }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="create_time" label="创建时间" width="140"></el-table-column>
        <el-table-column prop="status" label="是否显示" width="100">
            <template slot-scope="scope">
                <el-switch v-model="scope.row.status" :active-value="1" :inactive-value="0" active-text="显示" inactive-text="隐藏" :width="55" @change="statusSet($event, scope.row)"></el-switch>
            </template>
        </el-table-column>
        <el-table-column prop="name" label="操作" width="180">
        <el-table-column prop="name" label="操作" width="220">
          <template slot-scope="scope">
            <el-button @click="onDetail(scope.row.activity_id, false)" type="text" size="small">查看</el-button>
            <el-button @click="qrcode(scope.row)" type="text" size="small">核销码</el-button>
            <el-button @click="showAuditDialog(scope.row)" type="text" size="small" v-if="scope.row.audit_status === 0">审核</el-button>
            <el-button @click="onDetail(scope.row.activity_id, true)" type="text" size="small">编辑</el-button>
            <el-button @click="onDelete(scope.row)" type="text" size="small">删除</el-button>
          </template>
@@ -65,6 +80,29 @@
    <Detail ref="activityDetail" :open="open_detail" @getList="getTableList" @close="closeDrawerDetail"></Detail>
    <!-- 核销码 -->
    <Qrcode :open='isQrcode' :code_id='code_id' @close="closeQrcode"></Qrcode>
    <!-- 审核对话框 -->
    <el-dialog title="审核活动" :visible.sync="auditDialogVisible" width="500px">
      <el-form :model="auditForm" label-width="80px">
        <el-form-item label="审核结果">
          <el-radio-group v-model="auditForm.audit_status">
            <el-radio :label="10">通过</el-radio>
            <el-radio :label="20">驳回</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="审核备注" v-if="auditForm.audit_status === 20">
          <el-input
            type="textarea"
            :rows="4"
            v-model="auditForm.audit_remark"
            placeholder="请输入驳回原因"
          ></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer">
        <el-button @click="auditDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="submitAudit">确定</el-button>
      </span>
    </el-dialog>
  </div>
</template>
@@ -101,6 +139,17 @@
      open_detail: false,
      isQrcode: false,
      code_id: '',
      /*审核相关*/
      auditDialogVisible: false,
      auditForm: {
        activity_id: 0,
        audit_status: 10,
        audit_remark: ''
      },
      /*搜索条件*/
      searchForm: {
        audit_status: ''
      },
    };
  },
  created() {
@@ -114,6 +163,10 @@
      let Params = {};
      Params.page = self.curPage;
      Params.list_rows = self.pageSize;
      // 添加审核状态筛选
      if (self.searchForm.audit_status !== '') {
        Params.audit_status = self.searchForm.audit_status;
      }
      BranchApi.activityList(Params, true)
        .then(data => {
          self.loading = false;
@@ -209,6 +262,11 @@
      return this.tagTypeData[e];
    },
    auditStatusType(e) {
      const typeMap = { 0: 'warning', 10: 'success', 20: 'danger' };
      return typeMap[e] || 'info';
    },
    qrcode(row){
      this.code_id = row.activity_id;
      this.isQrcode = true;
@@ -216,6 +274,37 @@
    closeQrcode(){
      this.isQrcode = false;
    },
    /*显示审核对话框*/
    showAuditDialog(row) {
      this.auditForm = {
        activity_id: row.activity_id,
        audit_status: 10,
        audit_remark: ''
      };
      this.auditDialogVisible = true;
    },
    /*提交审核*/
    submitAudit() {
      if (this.auditForm.audit_status === 20 && !this.auditForm.audit_remark) {
        this.$message.warning('请输入驳回原因');
        return;
      }
      BranchApi.auditActivity(this.auditForm, true)
        .then(data => {
          this.$message.success(data.msg);
          this.auditDialogVisible = false;
          this.getTableList();
        })
        .catch(error => {});
    },
    /*搜索*/
    handleSearch() {
      this.curPage = 1;
      this.getTableList();
    },
  }
};
</script>
shop_vue/src/views/branch/category/part/Add.vue
@@ -10,6 +10,12 @@
      <el-form-item label="分类名称" :label-width="formLabelWidth" prop="name">
        <el-input v-model="form.name" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="名额" :label-width="formLabelWidth"  prop="limit_num">
        <el-input v-model="form.limit_num" placeholder="请输入名额" autocomplete="off">
          <template slot="append">人</template>
        </el-input>
        <div class="gray9">0为不限制人数</div>
      </el-form-item>
      <el-form-item label="分类排序" prop="sort" :label-width="formLabelWidth">
        <el-input v-model.number="form.sort" autocomplete="off"></el-input>
      </el-form-item>
@@ -37,6 +43,8 @@
          name: '',
          status: 1,
          sort: 100,
          /*名额*/
          limit_num: 0,
        },
        formRules: {
          name: [{
shop_vue/src/views/branch/category/part/Edit.vue
@@ -8,6 +8,12 @@
      <el-form-item label="保证金(元)" :label-width="formLabelWidth" prop="deposit_money">
        <el-input v-model="form.deposit_money" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="名额" prop="limit_num" :label-width="formLabelWidth">
        <el-input v-model="form.limit_num" placeholder="请输入名额" autocomplete="off">
          <template slot="append">人</template>
        </el-input>
        <div class="gray9">0为不限制人数</div>
      </el-form-item>
    </el-form>
    <div slot="footer" class="dialog-footer">
      <el-button @click="dialogFormVisible">取 消</el-button>
shop_vue/src/views/plus/operations/apply/dialog/Edit.vue
@@ -5,21 +5,77 @@
          描述:插件中心-分销-代理审核
      -->
  <div v-if="status != 30">
    <el-dialog title="代理审核" :visible.sync="dialogVisible" @close="dialogFormVisible" :close-on-click-modal="false" :close-on-press-escape="false">
      <el-form :model="form">
        <el-form-item label="审核状态" :label-width="formLabelWidth">
          <div>
            <el-radio v-model="form.apply_status" label="20">审核通过</el-radio>
            <el-radio v-model="form.apply_status" label="30">驳回</el-radio>
          </div>
    <el-dialog title="代理审核" :visible.sync="dialogVisible" @close="dialogFormVisible" :close-on-click-modal="false" :close-on-press-escape="false" width="600px">
      <el-form :model="form" ref="formRef" label-width="120px">
        <el-form-item label="审核状态">
          <el-radio-group v-model="form.apply_status" @change="handleStatusChange">
            <el-radio label="20">审核通过</el-radio>
            <el-radio label="30">驳回</el-radio>
          </el-radio-group>
        </el-form-item>
        <!-- 审核通过时显示区域和级别选择 -->
        <div v-if="form.apply_status == 20">
          <el-form-item label="运营中心级别">
            <el-select v-model="form.region_level" placeholder="请选择级别" @change="handleLevelChange">
              <el-option label="省级" :value="1"></el-option>
              <el-option label="市级" :value="2"></el-option>
              <el-option label="区县级" :value="3"></el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="省/直辖市">
            <el-select v-model="form.province_id" placeholder="请选择省份" @change="handleProvinceChange">
              <el-option
                v-for="item in provinceList"
                :key="item.id"
                :label="item.name"
                :value="item.id">
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="城市" v-if="form.region_level >= 2">
            <el-select v-model="form.city_id" placeholder="请选择城市" @change="handleCityChange" :disabled="!form.province_id">
              <el-option
                v-for="item in cityList"
                :key="item.id"
                :label="item.name"
                :value="item.id">
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="区县" v-if="form.region_level == 3">
            <el-select v-model="form.area_id" placeholder="请选择区县" :disabled="!form.city_id">
              <el-option
                v-for="item in areaList"
                :key="item.id"
                :label="item.name"
                :value="item.id">
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="登录账号" prop="user_name">
            <el-input type="text" v-model="form.user_name" autocomplete="off" placeholder="请输入登录账号"></el-input>
          </el-form-item>
          <el-form-item label="登录密码" prop="password">
            <el-input type="password" v-model="form.password" autocomplete="off" placeholder="请输入登录密码"></el-input>
          </el-form-item>
        </div>
        <!-- 驳回时显示驳回原因 -->
        <div v-if="form.apply_status == 30">
          <el-form-item label="驳回原因" :label-width="formLabelWidth"><el-input v-model="form.reject_reason" autocomplete="off"></el-input></el-form-item>
          <el-form-item label="驳回原因">
            <el-input v-model="form.reject_reason" type="textarea" :rows="3" placeholder="请输入驳回原因"></el-input>
          </el-form-item>
        </div>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible">取 消</el-button>
        <el-button type="primary" @click="editApplyStatus">确 定</el-button>
        <el-button type="primary" @click="editApplyStatus" :loading="loading">确 定</el-button>
      </div>
    </el-dialog>
  </div>
@@ -27,25 +83,22 @@
  <div v-else>
    <el-dialog title="驳回原因" :visible.sync="dialogVisible" @close="dialogFormVisible" :close-on-click-modal="false" :close-on-press-escape="false">
      <p>{{ reject_reason }}</p>
      <!-- <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible">取 消</el-button>
        <el-button type="primary" @click="dialogFormVisible">确 定</el-button>
      </div> -->
    </el-dialog>
  </div>
</template>
<script>
import OperationsApi from '@/api/plus/operations.js';
import DataApi from '@/api/data.js';
export default {
  data() {
    return {
      status: '',
      reject_reason: '',
      /*左边长度*/
      formLabelWidth: '120px',
      /*是否显示*/
      dialogVisible: false
      loading: false,
      /*地区数据*/
      regionData: []
    };
  },
  props: ['open_edit', 'form'],
@@ -54,13 +107,149 @@
    this.status = this.form.apply_status.value;
    if (this.status == 30) {
      this.reject_reason = this.form.reject_reason;
    } else {
      // 如果是待审核状态,默认设置为省级
      if (!this.form.region_level) {
        this.form.region_level = 1;
      }
      // 加载地区数据
      this.getRegionData();
    }
  },
  computed: {
    /*获取省份列表*/
    provinceList() {
      return Object.values(this.regionData).filter(item => item.level === 1);
    },
    /*获取城市列表*/
    cityList() {
      if (this.form.province_id && this.regionData[this.form.province_id]) {
        const provinceData = this.regionData[this.form.province_id];
        if (provinceData.city) {
          return Object.values(provinceData.city);
        }
      }
      return [];
    },
    /*获取区/县列表*/
    areaList() {
      if (this.form.city_id && this.form.province_id && this.regionData[this.form.province_id]) {
        const provinceData = this.regionData[this.form.province_id];
        if (provinceData.city && provinceData.city[this.form.city_id]) {
          const cityData = provinceData.city[this.form.city_id];
          if (cityData.region) {
            return Object.values(cityData.region);
          }
        }
      }
      return [];
    }
  },
  methods: {
    /*获取地区数据*/
    getRegionData() {
      let self = this;
      DataApi.getRegion({}, true)
        .then(res => {
          self.regionData = res.data.regionData;
        })
        .catch(() => {});
    },
    /*省份改变*/
    handleProvinceChange(val) {
      this.form.city_id = 0;
      this.form.area_id = 0;
    },
    /*城市改变*/
    handleCityChange(val) {
      this.form.area_id = 0;
    },
    /*级别改变*/
    handleLevelChange(val) {
      // 切换级别时清空下级区域
      if (val < 2) {
        this.form.city_id = 0;
        this.form.area_id = 0;
      }
      if (val < 3) {
        this.form.area_id = 0;
      }
    },
    /*审核状态改变*/
    handleStatusChange(val) {
      // 切换到审核通过时,加载数据
      if (val == 20) {
        if (this.regionData.length === 0) {
          this.getRegionData();
        }
      }
    },
    /*修改用户*/
    editApplyStatus() {
      // 验证审核通过时的必填项
      if (this.form.apply_status == 20) {
        if (!this.form.region_level) {
          this.$message.error('请选择运营中心级别');
          return;
        }
        if (!this.form.province_id) {
          this.$message.error('请选择省份');
          return;
        }
        if (this.form.region_level >= 2 && !this.form.city_id) {
          this.$message.error('请选择城市');
          return;
        }
        if (this.form.region_level == 3 && !this.form.area_id) {
          this.$message.error('请选择区县');
          return;
        }
        if (!this.form.user_name) {
          this.$message.error('请输入登录账号');
          return;
        }
        if (!this.form.password) {
          this.$message.error('请输入登录密码');
          return;
        }
        if (this.form.password.length < 6) {
          this.$message.error('密码长度不能少于6位');
          return;
        }
      } else {
        // 驳回时必须填写原因
        if (!this.form.reject_reason) {
          this.$message.error('请输入驳回原因');
          return;
        }
      }
      this.loading = true;
      let self = this;
      let params = this.form;
      let params = {
        apply_id: this.form.apply_id,
        apply_status: this.form.apply_status,
        real_name: this.form.real_name,
        mobile: this.form.mobile,
        user_id: this.form.user_id,
        referee_id: this.form.referee_id,
        region_level: {
          value: this.form.region_level,
          text: this.form.region_level == 1 ? '省级' : (this.form.region_level == 2 ? '市级' : '区县级')
        },
        province_id: this.form.province_id,
        city_id: this.form.city_id || 0,
        area_id: this.form.area_id || 0,
        user_name: this.form.user_name || '',
        password: this.form.password || '',
        reject_reason: this.form.reject_reason || ''
      };
      OperationsApi.editApplyStatus(params, true)
        .then(data => {
          self.$message({
@@ -69,7 +258,9 @@
          });
          self.dialogFormVisible(true);
        })
        .catch(error => {});
        .catch(error => {
          this.loading = false;
        });
    },
    /*关闭弹窗*/
shop_vue/src/views/plus/operations/auth/role/Index.vue
@@ -83,7 +83,7 @@
    editClick(row) {
      this.curModel = row;
      this.$router.push({
        path: '/plus/region/auth/role/edit',
        path: '/plus/operations/auth/role/edit',
        query: {
          role_id: row.role_id,
          scene: 'edit'
shop_vue/src/views/plus/operations/auth/role/add.vue
@@ -30,7 +30,7 @@
</template>
<script>
import PlusApi from '@/api/plus/region.js';
import PlusApi from '@/api/plus/operations.js';
export default {
  data() {
@@ -80,7 +80,7 @@
      self.$refs.form.validate(valid => {
        if (valid) {
          self.loading = true;
          PlusApi.regionRoleAdd({
          PlusApi.operationsRoleAdd({
            params: JSON.stringify(form)
          }, true)
            .then(data => {
@@ -89,7 +89,7 @@
                message: '添加成功',
                type: 'success'
              });
              self.$router.push('/plus/region/auth/role/index');
              self.$router.push('/plus/operations/auth/role/index');
            })
            .catch(error => {
              self.loading = false;
@@ -101,7 +101,7 @@
    /*获取数据*/
    getData() {
      let self = this;
      PlusApi.regionRoleAddInfo()
      PlusApi.operationsRoleAddInfo()
        .then(data => {
          self.data = data.data.menu;
          self.treeData = self.buildTree(self.data); // 构建树形结构
shop_vue/src/views/plus/operations/auth/role/edit.vue
@@ -38,7 +38,7 @@
</template>
<script>
import PlusApi from '@/api/plus/region.js';
import PlusApi from '@/api/plus/operations.js';
export default {
  data() {
@@ -93,7 +93,7 @@
      self.$refs.form.validate(valid => {
        if (valid) {
          self.loading = true;
          PlusApi.regionRoleEdit({
          PlusApi.operationsRoleEdit({
            role_id: self.role_id,
            params: JSON.stringify(form)
          }, true)
@@ -103,7 +103,7 @@
                message: '修改成功',
                type: 'success'
              });
              self.$router.push('/plus/region/auth/role/index');
              self.$router.push('/plus/operations/auth/role/index');
            })
            .catch(error => {
              self.loading = false;
@@ -115,7 +115,7 @@
    /*获取所有的数据*/
    getData() {
      let self = this;
      PlusApi.regionRoleEditInfo({
      PlusApi.operationsRoleEditInfo({
        role_id: self.role_id
      })
        .then(data => {
shop_vue/src/views/plus/operations/auth/user/Admin.vue
@@ -14,7 +14,7 @@
    <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="region_user_id" label="管理员ID"></el-table-column>
          <el-table-column prop="operations_user_id" label="管理员ID"></el-table-column>
          <el-table-column prop="user_name" label="用户名"></el-table-column>
          <el-table-column prop="role.role_name" label="所属角色">
            <template slot-scope="scope">
@@ -50,7 +50,7 @@
    <Add :open="open_add" :roleList="roleList" @close="closeAdd"></Add>
    <Edit :open="open_edit" :roleList="roleList" :region_user_id="curModel.region_user_id"  @close="closeEdit"></Edit>
    <Edit :open="open_edit" :roleList="roleList" :operations_user_id="curModel.operations_user_id"  @close="closeEdit"></Edit>
  </div>
</template>
shop_vue/src/views/plus/operations/auth/user/dialog/Add.vue
@@ -25,7 +25,7 @@
</template>
<script>
import PlusApi from '@/api/plus/region.js';
import PlusApi from '@/api/plus/operations.js';
export default {
  data() {
    return {
@@ -95,7 +95,7 @@
      let self = this;
      self.loading = true;
      let params = self.form;
      PlusApi.regionAdminAdd(params, true)
      PlusApi.operationsAdminAdd(params, true)
        .then(data => {
          self.loading = false;
          self.$message({
shop_vue/src/views/plus/operations/auth/user/dialog/Edit.vue
@@ -25,7 +25,7 @@
</template>
<script>
import PlusApi from '@/api/plus/region.js';
import PlusApi from '@/api/plus/operations.js';
export default {
  data() {
    return {
@@ -84,7 +84,7 @@
      }
    };
  },
  props: ['open','region_user_id'],
  props: ['open','operations_user_id'],
  watch: {
    open: function(n, o) {
      if (n != o) {
@@ -99,8 +99,8 @@
    /*获取数据*/
    getData() {
      let self = this;
      PlusApi.regionAdminEditInfo({
        region_user_id: this.region_user_id
      PlusApi.operationsAdminEditInfo({
        operations_user_id: this.operations_user_id
        }).then(res => {
          self.loading = false;
          self.roleList = res.data.roleList;
@@ -119,7 +119,7 @@
      let self = this;
      self.loading = true;
      let params = self.form;
      PlusApi.regionAdminEdit(params, true)
      PlusApi.operationsAdminEdit(params, true)
        .then(data => {
          self.loading = false;
          self.$message({
shop_vue/src/views/product/product/edit.vue
@@ -187,7 +187,9 @@
          /*最大抵扣消费券数量*/
          max_consumption_discount: 0,
          service_content:'',
          shop_supplier_id: 0
          shop_supplier_id: 0,
          /*是否价格面议,默认0为否,1为是*/
          is_price_negotiable: 0
      }
    };
  },
shop_vue/src/views/product/product/part/Spec.vue
@@ -24,6 +24,11 @@
      <div v-if="form.isSpecLocked" class="red">此商品正在参加活动,不能修改规格</div>
    </el-form-item>
    <el-form-item label="价格面议:">
      <el-switch v-model="form.model.is_price_negotiable" active-text="是" inactive-text="否"></el-switch>
      <div class="tips">开启后,移动端将显示"价格面议"而非具体价格</div>
    </el-form-item>
    <!--单规格-->
    <template v-if="form.model.spec_type == 10">
      <Single></Single>
supplier_vue/src/views/product/product/part/Spec.vue
@@ -24,6 +24,11 @@
      <div v-if="form.isSpecLocked" class="red">此商品正在参加活动,不能修改规格</div>
    </el-form-item>
    <el-form-item label="价格面议">
      <el-switch v-model="form.model.is_price_negotiable" active-text="是" inactive-text="否"></el-switch>
      <div class="tips">开启后,移动端将显示"价格面议"而非具体价格</div>
    </el-form-item>
    <!--单规格-->
    <template v-if="form.model.spec_type == 10">
      <Single></Single>