c441dea81bd86bdfb12dff35821fed51f4cc91c2..04102f7237efefa744090ed7c25f7b5d0807b679
2 days ago quanwei
完成运营中心提现和运营中心权限管理
04102f diff | tree
2 days ago quanwei
优化名片
73b874 diff | tree
17 files added
65 files modified
4255 ■■■■ changed files
admin/app/admin/controller/AgentAccess.php 80 ●●●●● patch | view | raw | blame | history
admin/app/admin/model/AgentAccess.php 183 ●●●●● patch | view | raw | blame | history
admin/app/api/controller/plus/business/Business.php 17 ●●●●● patch | view | raw | blame | history
admin/app/api/controller/plus/business/Template.php 86 ●●●●● patch | view | raw | blame | history
admin/app/api/controller/plus/operations/Cash.php 62 ●●●●● patch | view | raw | blame | history
admin/app/api/controller/plus/vip/User.php 2 ●●●●● patch | view | raw | blame | history
admin/app/api/controller/product/Category.php 1 ●●●● patch | view | raw | blame | history
admin/app/api/controller/product/Product.php 2 ●●● patch | view | raw | blame | history
admin/app/api/controller/user/Bonus.php 2 ●●●●● patch | view | raw | blame | history
admin/app/api/controller/user/Team.php 2 ●●● patch | view | raw | blame | history
admin/app/api/model/branch/ActivityUser.php 10 ●●●● patch | view | raw | blame | history
admin/app/api/model/page/Page.php 1 ●●●● patch | view | raw | blame | history
admin/app/api/model/plus/operations/Cash.php 100 ●●●●● patch | view | raw | blame | history
admin/app/api/model/plus/operations/Operations.php 50 ●●●●● patch | view | raw | blame | history
admin/app/api/model/plus/operations/Order.php 79 ●●●●● patch | view | raw | blame | history
admin/app/api/model/plus/operations/Setting.php 11 ●●●●● patch | view | raw | blame | history
admin/app/api/model/plus/operations/User.php 32 ●●●●● patch | view | raw | blame | history
admin/app/api/model/supplier/Supplier.php 1 ●●●● 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/type/MasterPaySuccessService.php 4 ●●● patch | view | raw | blame | history
admin/app/common/enum/supplier/SupplierType.php 3 ●●●●● patch | view | raw | blame | history
admin/app/common/model/plus/operations/Order.php 178 ●●●●● patch | view | raw | blame | history
admin/app/common/model/plus/operations/Setting.php 2 ●●● patch | view | raw | blame | history
admin/app/common/model/product/Product.php 5 ●●●● patch | view | raw | blame | history
admin/app/common/service/business/Poster.php 372 ●●●● patch | view | raw | blame | history
admin/app/common/service/order/OrderCompleteService.php 4 ●●● patch | view | raw | blame | history
admin/app/event.php 4 ●●●● patch | view | raw | blame | history
admin/app/job/event/AgentUserGrade.php 3 ●●●●● patch | view | raw | blame | history
admin/app/job/event/JobScheduler.php 2 ●●●●● patch | view | raw | blame | history
admin/app/job/event/OperationsOrder.php 88 ●●●●● patch | view | raw | blame | history
admin/app/job/event/VipOrder.php 4 ●●●● patch | view | raw | blame | history
admin/app/job/model/plus/operations/Order.php 38 ●●●●● patch | view | raw | blame | history
admin/app/shop/controller/plus/operations/Operations.php 2 ●●● patch | view | raw | blame | history
admin/app/shop/controller/plus/operations/Order.php 33 ●●●●● patch | view | raw | blame | history
admin/app/shop/controller/supplier/Category.php 4 ●●● patch | view | raw | blame | history
admin/app/shop/model/plus/operations/Cash.php 10 ●●●● patch | view | raw | blame | history
admin/app/shop/service/order/ExportService.php 74 ●●●●● patch | view | raw | blame | history
admin/app/supplier/model/product/Category.php 4 ●●●● patch | view | raw | blame | history
agent_vue/src/api/statistics.js 32 ●●●● patch | view | raw | blame | history
agent_vue/src/filters/index.js 30 ●●●● patch | view | raw | blame | history
agent_vue/src/permission.js 2 ●●● patch | view | raw | blame | history
agent_vue/src/router/index.js 4 ●●●● patch | view | raw | blame | history
agent_vue/src/store/index.js 2 ●●● patch | view | raw | blame | history
agent_vue/src/utils/base.js 12 ●●●● patch | view | raw | blame | history
agent_vue/src/utils/request.js 14 ●●●● patch | view | raw | blame | history
mobile/pages.json 41 ●●●●● patch | view | raw | blame | history
mobile/pages/plus/business/add.vue 893 ●●●● patch | view | raw | blame | history
mobile/pages/plus/business/detail.vue 11 ●●●● patch | view | raw | blame | history
mobile/pages/plus/business/index.vue 53 ●●●● patch | view | raw | blame | history
mobile/pages/plus/business/list.vue 1 ●●●● patch | view | raw | blame | history
mobile/pages/plus/vip/index.vue 5 ●●●● patch | view | raw | blame | history
mobile/pages2/bonus/index/index.vue 5 ●●●● patch | view | raw | blame | history
mobile/pages2/shareholder/index/index.vue 102 ●●●●● patch | view | raw | blame | history
mobile/pages2/team/index/index.vue 105 ●●●●● patch | view | raw | blame | history
operations_vue/static/css/common.css 4 ●●●● patch | view | raw | blame | history
saas_vue/src/views/agentaccess/Index.vue 288 ●●●●● patch | view | raw | blame | history
saas_vue/src/views/agentaccess/part/Add.vue 218 ●●●●● patch | view | raw | blame | history
saas_vue/src/views/agentaccess/part/Edit.vue 210 ●●●●● patch | view | raw | blame | history
shop_vue/src/api/plus/operations.js 186 ●●●●● patch | view | raw | blame | history
shop_vue/src/components/setlink/part/Menu.vue 5 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/operations/index.vue 9 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/operations/order/Order.vue 272 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/operations/setting/Setting.vue 4 ●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/operations/setting/part/Background.vue 2 ●●● patch | view | raw | blame | history
shop_vue/src/views/plus/operations/setting/part/Basic.vue 87 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/plus/operations/setting/part/Bonus.vue 2 ●●● patch | view | raw | blame | history
shop_vue/src/views/plus/operations/setting/part/Condition.vue 2 ●●● patch | view | raw | blame | history
shop_vue/src/views/plus/operations/setting/part/License.vue 2 ●●● patch | view | raw | blame | history
shop_vue/src/views/plus/operations/setting/part/Settlement.vue 2 ●●● patch | view | raw | blame | history
shop_vue/src/views/plus/operations/setting/part/Words.vue 21 ●●●● patch | view | raw | blame | history
shop_vue/src/views/product/category/index.vue 8 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/product/product/edit.vue 2 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/product/product/part/spec/Single.vue 3 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/product/product/part/spec/many/Table.vue 18 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/supplier/category/index.vue 12 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/supplier/category/part/Add.vue 5 ●●●●● patch | view | raw | blame | history
shop_vue/src/views/supplier/category/part/Edit.vue 5 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/product/category/index.vue 8 ●●●●● patch | view | raw | blame | history
supplier_vue/src/views/product/product/add.vue 1 ●●●● patch | view | raw | blame | history
supplier_vue/src/views/product/product/part/Basic.vue 6 ●●●● patch | view | raw | blame | history
supplier_vue/src/views/statistics/index.vue 2 ●●● patch | view | raw | blame | history
admin/app/admin/controller/AgentAccess.php
New file
@@ -0,0 +1,80 @@
<?php
namespace app\admin\controller;
use app\admin\model\AgentAccess as AccesscModel;
/**
 * 代理商用户权限控制器
 */
class AgentAccess extends Controller
{
    /**
     * 权限列表
     */
    public function index()
    {
        $model = new AccesscModel;
        $list = $model->getList();
        return $this->renderSuccess('', $list);
    }
    /**
     * 添加权限
     */
    public function add()
    {
        $model = new AccesscModel;
        $data = $this->postData();
        if ($model->add($data)) {
            return $this->renderSuccess('添加成功', compact('model'));
        }
        return $this->renderError($model->getError() ?:'添加失败');
    }
    /**
     * 更新权限
     */
    public function edit()
    {
        $data = $this->postData();
        // 权限详情
        $model = AccesscModel::detail($data['access_id']);
        // 更新记录
        if ($model->edit($data)) {
            return $this->renderSuccess('更新成功');
        }
        return $this->renderError($model->getError() ?:'更新失败');
    }
    /**
     * 删除权限
     */
    public function delete($access_id)
    {
        $model = new  AccesscModel();
        $num = $model->getChildCount(['parent_id' => $access_id]);
        if ($num > 0) {
            return $this->renderError('当前菜单下存在子权限,请先删除');
        }
        if ($model->remove($access_id)) {
            return $this->renderSuccess('删除成功');
        }
        return $this->renderError($model->getError() ?:'删除失败');
    }
    /**
     * 权限状态
     */
    public function status($access_id, $status)
    {
        $model = AccesscModel::detail($access_id);
        if ($model->status($status)) {
            return $this->renderSuccess('修改成功');
        }
        return $this->renderError($model->getError() ?:'修改失败');
    }
}
admin/app/admin/model/AgentAccess.php
New file
@@ -0,0 +1,183 @@
<?php
namespace app\admin\model;
use app\common\model\plus\operations\Access as AccessModel;
/**
 * Class AgentAccess
 *  代理商用户权限模型
 * @package app\admin\model
 */
class AgentAccess extends AccessModel
{
    /**
     * 获取权限列表
     */
    public function getList()
    {
        $all = static::getAll(-1);
        $res = $this->recursiveMenuArray($all, 0);
        return array_values($this->foo($res));
    }
    /**
     * 新增记录
     */
    public function add($data)
    {
        // 校验路径
        if(!$this->validate($data)){
            return false;
        }
        $data['access_id'] = time();
        $data['app_id'] = self::$app_id;
        return $this->save($data);
    }
    /**
     * 更新记录
     */
    public function edit($data)
    {
        if ($data['access_id'] == $data['parent_id']) {
            $this->error = '上级菜单不允许设置为当前菜单';
            return false;
        }
        // 判断上级角色是否为当前子级
        if ($data['parent_id'] > 0) {
            // 获取所有上级id集
            $parentIds = $this->getTopAccessIds($data['parent_id']);
            if (in_array($data['access_id'], $parentIds)) {
                $this->error = '上级菜单不允许设置为当前子菜单';
                return false;
            }
        }
        // 校验路径,不限制大小写
        if(strtolower($data['path']) !== strtolower($this['path'])){
            if(!$this->validate($data)){
                return false;
            }
        }
        $data['redirect_name'] = ($data['is_route'] == 1) ? $data['redirect_name'] : '';
        $data['icon'] = ($data['parent_id'] == 0) ? $data['icon'] : '';
        return $this->save($data);
    }
    /**
     * 验证
     */
    private function validate($data){
         $count = $this->where(['path' => $data['path']])->count();
         if($count > 0){
             $this->error = '路径已存在,请重新更改';
             return false;
         }
         return true;
    }
    public function getChildCount($where)
    {
        return $this->where($where)->count();
    }
    /**
     * 删除权限
     */
    public function remove($access_id)
    {
        return $this->where('access_id', '=', $access_id)->delete();
    }
    /**
     * 删除插件
     */
    public function removePlus()
    {
        return $this->save([
            'plus_category_id' => 0
        ]);
    }
    /**
     * 获取所有上级id集
     */
    public function getTopAccessIds($access_id, &$all = null)
    {
        static $ids = [];
        is_null($all) && $all = $this->getAll();
        foreach ($all as $item) {
            if ($item['access_id'] == $access_id && $item['parent_id'] > 0) {
                $ids[] = $item['parent_id'];
                $this->getTopAccessIds($item['parent_id'], $all);
            }
        }
        return $ids;
    }
    /**
     * 递归获取获取分类
     */
    public function recursiveMenuArray($data, $pid)
    {
        $re_data = [];
        foreach ($data as $key => $value) {
            if ($value['parent_id'] == $pid) {
                $re_data[$value['access_id']] = $value;
                $re_data[$value['access_id']]['children'] = $this->recursiveMenuArray($data, $value['access_id']);
            } else {
                continue;
            }
        }
        return $re_data;
    }
    /**
     * 格式化递归数组下标
     */
    public function foo(&$ar)
    {
        if (!is_array($ar)) return;
        foreach ($ar as $k => &$v) {
            if (is_array($v)) $this->foo($v);
            if ($k == 'children') $v = array_values($v);
        }
        return $ar;
    }
    /**
     * 更改显示状态
     */
    public function status($status){
        return $this->save([
            'is_show' => $status
        ]);
    }
    /**
     * 获取所有插件
     */
    public static function getAllPlus(){
        $model = new static();
        $plus = $model->where('path', '=', '/plus/plus/index')->find();
        return $model->where('parent_id', '=', $plus['access_id'])
            ->where('plus_category_id', '=', 0)
            ->select();
    }
    /**
     * 保存插件分类
     * @param $data
     */
    public function addPlus($data){
        $model = new self();
        return $model->where('access_id', '=', $data['access_id'])->save([
            'plus_category_id' => $data['plus_category_id']
        ]);
    }
}
admin/app/api/controller/plus/business/Business.php
@@ -116,6 +116,12 @@
        if(!(new BusinessModel())->where(['user_id'=>$user['user_id'],'is_default'=>1])->find()){
            $param['is_default'] = 1;
        }
        if (empty($param['name'])){
            return $this->renderError('请输入姓名');
        }
        if (empty($param['mobile'])){
            return $this->renderError('输入手机号');
        }
        if ((new BusinessModel())->add($param)) {
            return $this->renderSuccess('添加成功');
        }
@@ -257,12 +263,21 @@
            $user = $this->getUser();
            $param['user_id'] = $user['user_id'];
        }
        if (empty($param['name'])){
            return $this->renderError('请填写姓名');
        }
        if (empty($param['mobile'])){
            return $this->renderError('请填写手机号');
        }
        if (empty($param['unit'][0])){
            return $this->renderError('请至少填写填写公司');
        }
        $param['unit'] = json_encode($param['unit'], JSON_UNESCAPED_UNICODE);
        $param['duties'] = json_encode($param['duties'], JSON_UNESCAPED_UNICODE);
        $param['address'] = json_encode($param['address'], JSON_UNESCAPED_UNICODE);
        !empty($param['position'])?$param['position'] = json_encode($param['position'], JSON_UNESCAPED_UNICODE):'';
        $param['position'] = $param['duties'];
        if ($model->add($param)) {
            return $this->renderSuccess('编辑成功');
        }
admin/app/api/controller/plus/business/Template.php
@@ -12,40 +12,64 @@
    public function getList()
    {
        $model = new TemplateModel();
        $param=$this->request->param();
        $list=$model->lists($param);
        foreach($list as $l=>$v ){
            $list[$l]['style']= json_decode($v['style'],true);
            $width=round($param['screenWidth']/$v['style']['backdrop']['width'],2);
            $v['width']=$width;
            foreach ($v['style'] as $key=>$item){
                if(is_array($item)){
                    foreach ($item as $i=>$y){
                        if($i!='color'&&$i!='src'&&$i!='style'&&$i!='display'&&$i!='type'||is_array($y)){
                            if(is_array($y)&&count($y)){
                                foreach ($y as $u=>$n){
                                    if($u!='color'&&$u!='src'&&$u!='style'&&$n!=0){
                                        $data[$l]['style'][$key][$i][$u]= round($n*$width,2);
                                    }else{
                                        $data[$l]['style'][$key][$i][$u]=$n;
                                    }
                                }
                            }else{
                                $data[$l]['style'][$key][$i]= round($y*$width,2);
                            }
                        }else{
                            $data[$l]['style'][$key][$i]=$y;
                        }
                    }
                }else{
                    $data[$l]['style'][$key]=$item;
        $param = $this->request->param();
        $list = $model->lists($param);
        // 获取屏幕宽度
        $screenWidth = isset($param['screenWidth']) ? floatval($param['screenWidth']) : 375;
        foreach($list as $index => $item) {
            // 解析style JSON
            $style = json_decode($item['style'], true);
            if (!$style) {
                $list[$index]['style'] = [];
                continue;
            }
            // 计算缩放比例 (基于背景图宽度)
            $backdropWidth = isset($style['backdrop']['width']) && $style['backdrop']['width'] > 0
                ? floatval($style['backdrop']['width'])
                : 375;
            $scale = round($screenWidth / $backdropWidth, 4);
            // 需要缩放的数值字段(排除这些字段名)
            $excludeKeys = ['color', 'src', 'style', 'display', 'type', 'src'];
            // 递归处理style数组,对所有数值字段进行缩放
            $this->scaleStyleValues($style, $scale, $excludeKeys);
            $list[$index]['style'] = $style;
        }
        return $this->renderSuccess('', $list);
    }
    /**
     * 递归缩放style中的数值字段
     * @param array &$data 数据数组(引用传递)
     * @param float $scale 缩放比例
     * @param array $excludeKeys 不需要缩放的键名
     */
    private function scaleStyleValues(&$data, $scale, $excludeKeys = [])
    {
        if (!is_array($data)) {
            return;
        }
        foreach ($data as $key => &$value) {
            if (is_array($value)) {
                // 递归处理子数组
                $this->scaleStyleValues($value, $scale, $excludeKeys);
            } elseif (is_numeric($value) && !in_array($key, $excludeKeys)) {
                // 对数值进行缩放(非0值)
                if ($value != 0) {
                    $value = round($value * $scale, 2);
                }
            }
            // 其他类型(字符串等)保持不变
        }
        foreach ($data as $l=>$v ){
            $list[$l]['style']=$v['style'];
        }
        return $this->renderSuccess('',$list);
    }
    
    /**
admin/app/api/controller/plus/operations/Cash.php
New file
@@ -0,0 +1,62 @@
<?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\Operations as operationsUserModel;
use app\api\model\plus\operations\Cash as CashModel;
/**
 * 队长提现
 */
class Cash 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 submit($data)
    {
        $formData = json_decode(htmlspecialchars_decode($data), true);
        $model = new CashModel;
        if ($model->submit($this->operations, $formData)) {
            return $this->renderSuccess('申请提现成功');
        }
        return $this->renderError($model->getError() ?: '提交失败');
    }
    /**
     * 队长提现明细
     */
    public function lists($status = -1)
    {
        $model = new CashModel;
        return $this->renderSuccess('', [
            // 提现明细列表
            'list' => $model->getList($this->user['user_id'], (int)$status,$this->postData()),
            // 页面文字
            'words' => $this->setting['words']['values'],
        ]);
    }
}
admin/app/api/controller/plus/vip/User.php
@@ -50,6 +50,8 @@
            'user' => $this->user,
            // VIP用户信息
            'vip' => $this->vip,
            // VIP专区url
            'vip_url'=>'pages/shop/shop?shop_supplier_id=1',
            // 背景图
            'background' => $this->setting['background']['values']['index'],
            // 页面文字
admin/app/api/controller/product/Category.php
@@ -36,6 +36,7 @@
        ]);
        $param['shop_supplier_id'] = empty($postData["shop_supplier_id"]) ? 0 : $postData["shop_supplier_id"];
        $param['is_gift_pack'] = 0;
        // 获取列表数据
        $model = new ProductModel;
        $productList = $model->getList($param, $this->getUser(false));
admin/app/api/controller/product/Product.php
@@ -39,7 +39,7 @@
                $param['category_id']=197;
            }
        }
        $param['is_gift_pack'] = 0;
        // 获取列表数据
        $model = new ProductModel;
        $list = $model->getList($param, $this->getUser(false));
admin/app/api/controller/user/Bonus.php
@@ -53,6 +53,8 @@
            'bonus' => $this->bonus,
            // 背景图
            'background' => $this->setting['background']['values']['index'],
            // VIP专区url
            'vip_url'=>'pages/shop/shop?shop_supplier_id=1',
            // 页面文字
            'words' => $this->setting['words']['values'],
            // 排位过期时间 by lyzflash 2023.01.26
admin/app/api/controller/user/Team.php
@@ -1 +1 @@
<?php namespace app\api\controller\user; use app\api\controller\Controller; use app\api\model\plus\team\Referee; use app\api\model\plus\team\Setting; use app\api\model\plus\team\User as TeamUserModel; use app\api\model\plus\team\Apply as TeamApplyModel; use app\api\model\settings\Message as MessageModel; use app\common\model\plus\team\Referee as TeamRefereeModel; use app\api\model\plus\agent\User as AgentUserModel; /**  * 分销中心  */ class Team extends Controller {     // 用户     private $user;     // 队长     private $team;     // 分销设置     private $setting;     /**      * 构造方法      */     public function initialize()     {         // 用户信息         $this->user = $this->getUser();         // 队长用户信息         $this->team = TeamUserModel::detail($this->user['user_id'],['user', 'referee','grade']);         // 队长设置         $this->setting = Setting::getAll();         // 分销商用户信息         $this->agent = AgentUserModel::detail($this->user['user_id']);     }     /**      * 队长中心      */     public function center()     {         //如果不是队长,列出条件 by lyzflash         $is_team = $this->isTeamUser();         $setting = $this->setting['basic']['values'];         $agent_total = $agent_money = 0;         //统计下级分销商总数         if ($setting['become'] == '40' && $this->agent) {             $agent_total = $this->agent['first_num'] + $this->agent['second_num']+ $this->agent['third_num'];         }         // 累计佣金         if ($setting['become'] == '50' && $this->agent) {             $agent_money = $this->agent['total_money'];         }         return $this->renderSuccess('', [             // 当前是否为分销商             'is_agent' => $this->isAgentUser(),             // 当前是否为队长             'is_team' => $is_team,             // 当前是否在申请中             'is_applying' => TeamApplyModel::isApplying($this->user['user_id']),             // 当前用户信息             'user' => $this->user,             // 队长用户信息             'team' => $this->team,             // 背景图             'background' => $this->setting['background']['values']['index'],             // 页面文字             'words' => $this->setting['words']['values'],             //'teamnum'=>count($user_ids),             // 下级分销商总数             'agent_total' => $agent_total,             // 累计佣金             'agent_money' => $agent_money,             'setting' => $setting         ]);     }     /**      * 队长申请状态      */     public function apply($referee_id = null, $platform= '')     {         return $this->renderSuccess('', [             // 当前是否为队长             'is_team' => $this->isTeamUser(),             // 当前是否在申请中             'is_applying' => TeamApplyModel::isApplying($this->user['user_id']),             // 背景图             'background' => $this->setting['background']['values']['apply'],             // 页面文字             'words' => $this->setting['words']['values'],             // 申请协议             'license' => $this->setting['license']['values']['license'],             // 如果来源是小程序, 则获取小程序订阅消息id.获取售后通知.             'template_arr' => MessageModel::getMessageByNameArr($platform, ['team_apply_user']),         ]);     }     /**      * 队长提现信息      */     public function cash($platform = '')     {         // 如果来源是小程序, 则获取小程序订阅消息id.获取售后通知.         $template_arr = MessageModel::getMessageByNameArr($platform, ['team_cash_user']);         return $this->renderSuccess('', [             // 队长用户信息             'team' => $this->team,             // 结算设置             'settlement' => $this->setting['settlement']['values'],             // 背景图             'background' => $this->setting['background']['values']['cash_apply'],             // 页面文字             'words' => $this->setting['words']['values'],             // 小程序消息             'template_arr' => $template_arr         ]);     }     /**      * 当前用户是否为队长      */     private function isTeamUser()     {         return !!$this->team && !$this->team['is_delete'];     }     /**      * 当前用户是否为分销商      */     private function isAgentUser()     {         return !!$this->agent && !$this->agent['is_delete'];     } }
<?php namespace app\api\controller\user; use app\api\controller\Controller; use app\api\model\plus\team\Referee; use app\api\model\plus\team\Setting; use app\api\model\plus\team\User as TeamUserModel; use app\api\model\plus\team\Apply as TeamApplyModel; use app\api\model\settings\Message as MessageModel; use app\common\model\plus\team\Referee as TeamRefereeModel; use app\api\model\plus\agent\User as AgentUserModel; use app\common\model\product\Product as ProductModel; use app\common\model\user\Grade as GradeModel; /**  * 分销中心  */ class Team extends Controller {     // 用户     private $user;     // 队长     private $team;     // 分销设置     private $setting;     /**      * 构造方法      */     public function initialize()     {         // 用户信息         $this->user = $this->getUser();         // 队长用户信息         $this->team = TeamUserModel::detail($this->user['user_id'],['user', 'referee','grade']);         // 队长设置         $this->setting = Setting::getAll();         // 分销商用户信息         $this->agent = AgentUserModel::detail($this->user['user_id']);     }     /**      * 队长中心      */     public function center()     {         //如果不是队长,列出条件 by lyzflash         $is_team = $this->isTeamUser();         $setting = $this->setting['basic']['values'];         $agent_total = $agent_money = 0;         //统计下级分销商总数         if ($setting['become'] == '40' && $this->agent) {             $agent_total = $this->agent['first_num'] + $this->agent['second_num']+ $this->agent['third_num'];         }         // 累计佣金         if ($setting['become'] == '50' && $this->agent) {             $agent_money = $this->agent['total_money'];         }         // 购买商品         $productList = [];         if ($setting['become'] == '70') {             if ($setting['team_buy_product_ids']) {                 $productList = (new ProductModel)->getListByIds($setting['team_buy_product_ids']);             }         }         $gradeList=[];         if ($setting['become'] == '70') {             if ($setting['referee_grade_ids']) {                 $gradeList = (new GradeModel)->getListByIds($setting['referee_grade_ids']);             }         }         return $this->renderSuccess('', [             // 当前是否为分销商             'is_agent' => $this->isAgentUser(),             // 当前是否为队长             'is_team' => $is_team,             // 当前是否在申请中             'is_applying' => TeamApplyModel::isApplying($this->user['user_id']),             // 当前用户信息             'user' => $this->user,             // 队长用户信息             'team' => $this->team,             // 背景图             'background' => $this->setting['background']['values']['index'],             // 页面文字             'words' => $this->setting['words']['values'],             //'teamnum'=>count($user_ids),             // 下级分销商总数             'agent_total' => $agent_total,             // 累计佣金             'agent_money' => $agent_money,             // 购买商品             'productList' => $productList,             // 购买等级             'gradeList' => $gradeList,             'setting' => $setting         ]);     }     /**      * 队长申请状态      */     public function apply($referee_id = null, $platform= '')     {         return $this->renderSuccess('', [             // 当前是否为队长             'is_team' => $this->isTeamUser(),             // 当前是否在申请中             'is_applying' => TeamApplyModel::isApplying($this->user['user_id']),             // 背景图             'background' => $this->setting['background']['values']['apply'],             // 页面文字             'words' => $this->setting['words']['values'],             // 申请协议             'license' => $this->setting['license']['values']['license'],             // 如果来源是小程序, 则获取小程序订阅消息id.获取售后通知.             'template_arr' => MessageModel::getMessageByNameArr($platform, ['team_apply_user']),         ]);     }     /**      * 队长提现信息      */     public function cash($platform = '')     {         // 如果来源是小程序, 则获取小程序订阅消息id.获取售后通知.         $template_arr = MessageModel::getMessageByNameArr($platform, ['team_cash_user']);         return $this->renderSuccess('', [             // 队长用户信息             'team' => $this->team,             // 结算设置             'settlement' => $this->setting['settlement']['values'],             // 背景图             'background' => $this->setting['background']['values']['cash_apply'],             // 页面文字             'words' => $this->setting['words']['values'],             // 小程序消息             'template_arr' => $template_arr         ]);     }     /**      * 当前用户是否为队长      */     private function isTeamUser()     {         return !!$this->team && !$this->team['is_delete'];     }     /**      * 当前用户是否为分销商      */     private function isAgentUser()     {         return !!$this->agent && !$this->agent['is_delete'];     } }
admin/app/api/model/branch/ActivityUser.php
@@ -131,7 +131,11 @@
            'branch_id' => $params['branch_id']?:0,
            'app_id' => self::$app_id,
        ];
        $refereeUser=(new UserModel())->where(['real_name'=>$params['recommend_name'],'mobile'=>$params['recommend_mobile']])->find();
        $refereeUser=[];
        if (!empty($params['recommend_name'])&&!empty($params['recommend_mobile'])){
            $refereeUser=(new UserModel())->where(['real_name'=>$params['recommend_name'],'mobile'=>$params['recommend_mobile']])->find();
        }
        if ($refereeUser){
            $data['referee_id']=$refereeUser['user_id'];
        }
@@ -263,10 +267,10 @@
            $this->error = '请输入姓名和手机号';
            return false;
        }
        /*if(empty($params['recommend_name']) || empty($params['recommend_mobile'])){
        if(empty($params['recommend_name']) || empty($params['recommend_mobile'])){
            $this->error = '请输入推荐人姓名和手机号';
            return false;
        }*/
        }
        if ($activity["status_text"]["reg_status"] == 2){
            $this->error = '报名已结束';
            return false;
admin/app/api/model/page/Page.php
@@ -121,6 +121,7 @@
                'list_rows' => $item['params']['auto']['showNum'],
                'audit_status' => 10,
                'city_supplier_ids' => $city_supplier_ids,
                'is_gift_pack' => 0,
            ], $user);
        }
        if ($productList->isEmpty()) return [];
admin/app/api/model/plus/operations/Cash.php
New file
@@ -0,0 +1,100 @@
<?php
namespace app\api\model\plus\operations;
use app\common\exception\BaseException;
use app\common\model\plus\operations\Cash as CashModel;
use app\api\model\user\UserAuth;
/**
 * 队长提现明细模型
 */
class Cash extends CashModel
{
    /**
     * 隐藏字段
     */
    protected $hidden = [
        'update_time',
    ];
    /**
     * 获取队长提现明细
     */
    public function getList($user_id, $apply_status = -1,$limit=15)
    {
        $model = $this;
        $apply_status > -1 && $model = $model->where('apply_status', '=', $apply_status);
        return $model->where('user_id', '=', $user_id)->order(['create_time' => 'desc'])
            ->paginate($limit);
    }
    /**
     * 提交申请
     */
    public function submit($shareholder, $data)
    {
        // 数据验证
        $this->validation($shareholder, $data);
        // 新增申请记录
        $this->save(array_merge($data, [
            'user_id' => $shareholder['user_id'],
            'apply_status' => 10,
            'app_id' => self::$app_id,
        ]));
        // 冻结用户资金
        $shareholder->freezeMoney($data['money']);
        return true;
    }
    /**
     * 数据验证
     */
    private function validation($shareholder, &$data)
    {
        // 结算设置
        $settlement = Setting::getItem('settlement');
        // 最低提现佣金
        if ($data['money'] <= 0) {
            throw new BaseException(['msg' => '提现金额不正确']);
        }
        if ($shareholder['money'] <= 0) {
            throw new BaseException(['msg' => '当前用户没有可提现佣金']);
        }
        if ($data['money'] > $shareholder['money']) {
            throw new BaseException(['msg' => '提现金额不能大于可提现佣金']);
        }
        if ($data['money'] < $settlement['min_money']) {
            throw new BaseException(['msg' => '最低提现金额为' . $settlement['min_money']]);
        }
        if (!in_array($data['pay_type'], $settlement['pay_type'])) {
            throw new BaseException(['msg' => '提现方式不正确']);
        }
        if ($data['pay_type'] == '20') {
            if (empty($data['alipay_name']) || empty($data['alipay_account'])) {
                throw new BaseException(['msg' => '请补全提现信息']);
            }
        } elseif ($data['pay_type'] == '30') {
            if (empty($data['bank_name']) || empty($data['bank_account']) || empty($data['bank_card'])) {
                throw new BaseException(['msg' => '请补全提现信息']);
            }
        } elseif ($data['pay_type'] == '10') {
            //微信支付需要实名认证
            $auth = UserAuth::detail($shareholder['user_id']);
            if(empty($auth)){
                throw new BaseException(['msg' => '请先到个人中心->设置->实名认证']);
            }elseif(!empty($auth) && $auth["auth_status"] != 1){
                throw new BaseException(['msg' => '您的实名认证还未审核通过']);
            }
        }
        // 处理手续费
        $data['fee_rate'] = $settlement['fee_rate'];
        if ($settlement['fee_rate']) {
            $data['fee_money'] = round($data['money'] * $settlement['fee_rate'] / 100, 2);
            $data['real_money'] = $data['money'] - $data['fee_money'];
        } else {
            $data['real_money'] = $data['money'];
        }
    }
}
admin/app/api/model/plus/operations/Operations.php
New file
@@ -0,0 +1,50 @@
<?php
namespace app\api\model\plus\operations;
use app\common\model\plus\operations\Operations as OperationsModel;
/**
 * 运营中心用户模型
 */
class Operations extends OperationsModel
{
    public static function getOrderOperations($order)
    {
        $model = new self;
        $province_id=0;
        $city_id=0;
        $area_id=0;
        if ($order['delivery_type']['value'] == 10){
            $province_id=$order['address']['province_id'];
            $city_id=$order['address']['city_id'];
            $area_id=$order['address']['region_id'];
        }else if($order['delivery_type']['value'] == 20||$order['delivery_type']['value'] == 40){
            $province_id=$order['extractStore']['province_id'];
            $city_id=$order['extractStore']['city_id'];
            $area_id=$order['extractStore']['region_id'];
        }
        $province=$model->where('province_id', $province_id)->where(['operations_level'=>1])->find();
        $city=$model->where('city_id', $city_id)->where(['operations_level'=>2])->find();
        $area=$model->where('area_id', $area_id)->where(['operations_level'=>3])->find();
        $data=['province_user_id'=>0,'city_user_id'=>0,'area_user_id'=>0];
        if ($province){
            $data['province_user_id']=$province['user_id'];
        }
        if($city){
            $data['city_user_id']=$city['user_id'];
        }
        if($area){
            $data['area_user_id']=$area['user_id'];
        }
        return $data;
    }
    /**
     * 资金冻结
     */
    public function freezeMoney($money)
    {
        return $this->save([
            'money' => $this['money'] - $money,
            'freeze_money' => $this['freeze_money'] + $money,
        ]);
    }
}
admin/app/api/model/plus/operations/Order.php
New file
@@ -0,0 +1,79 @@
<?php
namespace app\api\model\plus\operations;
use app\api\model\plus\operations\Operations as OperationsModel;
use app\common\enum\order\OrderTypeEnum;
use app\common\model\plus\operations\Order as OrderModel;
use app\common\service\order\OrderService;
/**
 * 运营中心订单模型
 */
class Order extends OrderModel
{
    /**
     * 隐藏字段
     */
    protected $hidden = [
        'update_time',
    ];
    /**
     * 获取运营中心订单列表
     */
    public function getList($user_id, $is_settled = -1)
    {
        $model = $this;
        $is_settled > -1 && $model = $model->where('is_settled', '=', !!$is_settled);
        $data = $model->with(['user'])
            ->where('first_user_id|second_user_id|third_user_id', '=', $user_id)
            ->order(['create_time' => 'desc'])
            ->paginate(15);
        if ($data->isEmpty()) {
            return $data;
        }
        // 整理订单信息
        $with = ['product' => ['image', 'refund'], 'address', 'user'];
        return OrderService::getOrderList($data, 'order_master', $with);
    }
    /**
     * 创建运营中心订单
     */
    public static function createOrder( $order, $order_type = OrderTypeEnum::MASTER)
    {
        $model = new self;
        $setting = Setting::getItem('basic', $order['app_id']);
        if (!$setting['is_open']) {
            return false;
        }
        $operations=OperationsModel::getOrderOperations($order);
        if ($operations['province_user_id']==0 && $operations['city_user_id']==0 && $operations['area_user_id']==0){
            return false;
        }
        // 计算订单分销佣金
        $capital = $model->getCapitalByOrder($order, 'create',$operations);
        // 如果没有佣金,则不写入订单
        if(!$capital['is_record']){
            return false;
        }
        // 保存分销订单记录
        return $model->save([
            'user_id' => $order['user_id'],
            'order_id' => $order['order_id'],
            'order_type' => $order_type,
            'order_price' => $capital['orderPrice'],
            'first_money' => $operations['province_user_id'] > 0?max($capital['first_money'], 0):0,
            'second_money' => $operations['city_user_id'] > 0?max($capital['second_money'], 0):0,
            'third_money' => $operations['area_user_id'] > 0?max($capital['third_money'], 0):0,
            'first_user_id' => $capital['first_money']>0?$operations['province_user_id']:0,
            'second_user_id' => $capital['second_money']>0?$operations['city_user_id']:0,
            'third_user_id' => $capital['third_money']>0?$operations['area_user_id']:0,
            'is_settled' => 0,
            'shop_supplier_id' => $order['shop_supplier_id'],
            'app_id' => $order['app_id']
        ]);
    }
}
admin/app/api/model/plus/operations/Setting.php
New file
@@ -0,0 +1,11 @@
<?php
namespace app\api\model\plus\operations;
use app\common\model\plus\operations\Setting as SettingModel;
/**
 * 运营中心设置模型
 */
class Setting extends SettingModel
{
}
admin/app/api/model/plus/operations/User.php
New file
@@ -0,0 +1,32 @@
<?php
namespace app\api\model\plus\operations;
use app\common\model\plus\operations\User as UserModel;
/**
 * 运营中心后台管理用户模型
 */
class User extends UserModel
{
    /**
     * 隐藏字段
     */
    protected $hidden = [
        'create_time',
        'update_time',
    ];
    /**
     * 资金冻结
     */
    public function freezeMoney($money)
    {
        return $this->save([
            'money' => $this['money'] - $money,
            'freeze_money' => $this['freeze_money'] + $money,
        ]);
    }
}
admin/app/api/model/supplier/Supplier.php
@@ -117,6 +117,7 @@
        $product_model = new ProductModel();
        foreach ($list as &$v) {
            $productList = $product_model->with(['image.file'])
                ->where('is_gift_pack', '=', 0)
                ->where([
                    'shop_supplier_id' => $v['shop_supplier_id'],
                    'product_status' => 10,
admin/app/api/model/supplier/page/Page.php
@@ -129,6 +129,7 @@
                'list_rows' => $item['params']['auto']['showNum'],
                'audit_status' => 10,
                'city_supplier_ids' => $city_supplier_ids,
                'is_gift_pack' => 0,
            ], $user);
        }
        if ($productList->isEmpty()) return [];
admin/app/api/model/user/User.php
@@ -46,6 +46,9 @@
    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/type/MasterPaySuccessService.php
@@ -20,7 +20,7 @@
use app\api\model\settings\Setting as SettingModel;
use app\common\model\supplier\Supplier as SupplierModel;
use app\common\model\plus\vip\Order as VipOrderModel;
use app\api\model\plus\operations\Order as OperationsOrderModel;
/**
 * 订单支付成功服务类
 */
@@ -107,6 +107,8 @@
            TeamOrderModel::createOrder($detail);
            // 记录VIP专区订单
            VipOrderModel::createOrder($detail);
            // 记录运营中心订单
            OperationsOrderModel::createOrder($detail);
            
            event('PaySuccess', $detail);
        }
admin/app/common/enum/supplier/SupplierType.php
@@ -6,6 +6,8 @@
{
    const PHYSICAL = 10; //实物
    const GROUPBUYING = 20; //团购
    //服务
    const SERVICE = 30; //服务
    /**
     * 供应商类型数据
     */
@@ -14,6 +16,7 @@
        return [
            self::PHYSICAL => ['name' => '实物','value' => self::PHYSICAL],
            self::GROUPBUYING => ['name' => '团购','value' => self::GROUPBUYING],
            self::SERVICE => ['name' => '服务','value' => self::SERVICE],
        ];
    }
    /**
admin/app/common/model/plus/operations/Order.php
New file
@@ -0,0 +1,178 @@
<?php
namespace app\common\model\plus\operations;
use app\common\enum\order\OrderTypeEnum;
use app\common\model\BaseModel;
use app\common\model\settings\Setting as SettingModel;
use app\common\model\plus\operations\Operations as OperationsModel;
/**
 * 运营中心订单管理
 */
class Order extends BaseModel
{
    protected $name="operations_order";
    /**
     * 订单所属用户
     * @return \think\model\relation\BelongsTo
     */
    public function user()
    {
        return $this->belongsTo('app\common\model\user\User');
    }
    /**
     * 一级分销商用户
     * @return \think\model\relation\BelongsTo
     */
    public function agentFirst()
    {
        return $this->belongsTo('app\common\model\user\User', 'first_user_id');
    }
    /**
     * 二级分销商用户
     * @return \think\model\relation\BelongsTo
     */
    public function agentSecond()
    {
        return $this->belongsTo('app\common\model\user\User', 'second_user_id');
    }
    /**
     * 三级分销商用户
     * @return \think\model\relation\BelongsTo
     */
    public function agentThird()
    {
        return $this->belongsTo('app\common\model\user\User', 'third_user_id');
    }
    /**
     * 订单类型
     * @param $value
     * @return array
     */
    public function getOrderTypeAttr($value)
    {
        $types = OrderTypeEnum::getTypeName();
        return ['text' => $types[$value], 'value' => $value];
    }
    /**
     * 订单详情
     */
    public static function getDetailByOrderId($orderId, $orderType)
    {
        return (new static())->where('order_id', '=', $orderId)
            ->where('order_type', '=', $orderType)
            ->find();
    }
    public static function grantMoney($order, $orderType = OrderTypeEnum::MASTER)
    {
        // 订单是否已完成
        if ($order['order_status']['value'] != 30) {
            return false;
        }
        // 分销订单详情
        $model = self::getDetailByOrderId($order['order_id'], $orderType);
        if (!$model || $model['is_settled'] == 1) {
            return false;
        }
        // 佣金结算天数
        $settleDays = Setting::getItem('settlement', $order['app_id'])['settle_days'];
        // 写入结算时间
        $deadlineTime = $model['settle_end_time'];
        if($deadlineTime == 0){
            $deadlineTime = $order['receipt_time'] + $settleDays  * 86400;
            $model->save([
                'settle_end_time' => $deadlineTime
            ]);
        }
        if ($deadlineTime > time()) {
            return false;
        }
        // 重新计算分销佣金
        $capital = $model->getCapitalByOrder($order);
        // 发放一级分销商佣金
        $model['first_user_id'] > 0 && OperationsModel::grantMoney($model['first_user_id'], $capital['first_money']);
        // 发放二级分销商佣金
        $model['second_user_id'] > 0 && OperationsModel::grantMoney($model['second_user_id'], $capital['second_money']);
        // 发放三级分销商佣金
        $model['third_user_id'] > 0 && OperationsModel::grantMoney($model['third_user_id'], $capital['third_money']);
        // 更新分销订单记录
        $model->save([
            'order_price' => $capital['orderPrice'],
            'first_money' => $model['first_user_id'] > 0? $capital['first_money']:0,
            'second_money' => $model['second_user_id'] > 0? $capital['second_money']:0,
            'third_money' => $model['third_user_id'] > 0? $capital['third_money']:0,
            'is_settled' => 1,
            'settle_time' => time()
        ]);
        event('AgentUserGrade', $model['first_user_id']);
        event('AgentUserGrade', $model['second_user_id']);
        event('AgentUserGrade', $model['third_user_id']);
        // 更新队长等级 by lyzflash
        event('TeamUserGrade', $model['first_user_id']);
        event('TeamUserGrade', $model['second_user_id']);
        event('TeamUserGrade', $model['third_user_id']);
        // 更新股东等级 by lyzflash
        event('ShareholderUserGrade', $model['first_user_id']);
        event('ShareholderUserGrade', $model['second_user_id']);
        event('ShareholderUserGrade', $model['third_user_id']);
        return true;
    }
    /**
     * 获取订单分销佣金数据
     * @param $order
     * @param string $source
     * @param array $operations
     * @return array
     */
    protected function getCapitalByOrder($order, $source = 'create',$operations=[])
    {
        $setting = Setting::getItem('bonus', $order['app_id']);
        // 分销订单佣金数据
        $capital = [
            // 订单总金额(不含运费)
            'orderPrice' => bcsub($order['pay_price'], $order['express_price'], 2),
            // 一级分销佣金
            'first_money' => 0.00,
            // 二级分销佣金
            'second_money' => 0.00,
            // 三级分销佣金
            'third_money' => 0.00,
            // 是否记录
            'is_record' => true
        ];
        $total_count = count($order['product']);
        // 计算分销佣金
        foreach ($order['product'] as $product) {
            // 商品实付款金额
            $productPrice = min($capital['orderPrice'], $product['total_pay_price']);
            // 计算商品实际佣金
            $productCapital = $this->calculateProductCapital($setting, $productPrice,$product);
            // 累积分销佣金
            $capital['first_money'] += $productCapital['first_money'];
            $capital['second_money'] += $productCapital['second_money'];
            $capital['third_money'] += $productCapital['third_money'];
        }
        return $capital;
    }
    /**
     * 计算商品实际佣金 by yj
     * @param $setting
     * @param $productPrice
     * @return float[]|int[]
     */
    private function calculateProductCapital($setting, $productPrice,$product)
    {
        $storeSetting=SettingModel::getItem('store', $product['app_id']);
        $productMoney=bcmul($productPrice, bcdiv($storeSetting['commission_rate'],100,2), 2);
        $capital['first_money'] = bcmul($productMoney, bcdiv($setting['province_ratio'],100,2), 2);
        $capital['second_money'] = bcmul($productMoney, bcdiv($setting['city_ratio'],100,2), 2);
        $capital['third_money'] = bcmul($productMoney, bcdiv($setting['area_ratio'],100,2), 2);
        return $capital;
    }
}
admin/app/common/model/plus/operations/Setting.php
@@ -1 +1 @@
<?php namespace app\common\model\plus\operations; use app\common\model\BaseModel; use think\facade\Cache; /**  * 区域代理设置模型  */ class Setting extends BaseModel {     protected $name = 'region_setting';     protected $createTime = false;     /**      * 转义数组格式      * @param $value      * @return mixed      */     public function getValuesAttr($value)     {         return json_decode($value, true);     }     /**      * 转义成json格式      * @param $value      * @return false|string      */     public function setValuesAttr($value)     {         return json_encode($value);     }     /**      * 获取指定项设置      * @param $key      * @param null $app_id      * @return array|mixed      */     public static function getItem($key, $app_id = null)     {         $data = static::getAll($app_id);         return isset($data[$key]) ? $data[$key]['values'] : [];     }     /**      * 获取区域代理设置      */     public static function getAll($app_id = null)     {         $self = new static;         is_null($app_id) && $app_id = $self::$app_id;         if (!$data = Cache::get('region_setting_' . $app_id)) {             $data = array_column($self->select()->toArray(), null, 'key');             Cache::tag('cache')->set('region_setting_' . $app_id, $data);         }         return array_merge_multiple($self->defaultData(), $data);     }     /**      * 获取设置项信息      */     public static function detail($key)     {         return (new static())->find(compact('key'));     }     /**      * 是否开启分销功能      */     public static function isOpen($app_id = null)     {         return static::getItem('basic', $app_id)['is_open'];     }     /**      * 分销中心页面名称      */     public static function getregionTitle($app_id = null)     {         return static::getItem('words', $app_id)['index']['title']['value'];     }     /**      * 默认配置      */     public function defaultData()     {         return [             'basic' => [                 'key' => 'basic',                 'describe' => '基础设置',                 'values' => [                     // 是否开启分红功能                     'is_open' => '0',   // 参数值:1开启 0关闭                     //'jcaward' => '0',   //级差奖                     'pjaward' => '0',   //平级奖                     'pjaward_level' => '1',   //平级奖奖励层级,默认往上1级                     'become' => '10',                     'total_rate' => '0',                     // 分红结算方式                     'bonus_type' => '20', // 10按周 20按月 30按年                     'total_team_user' => 0, // 团队总人数                     'self_buy_money' => 0, // 累计团队业绩是是否计算个人业绩                     'one_expend_money' => 0, // 个人一次性消费                     // 购买指定商品成为分销商 0关闭 1开启                     'become__buy_product' => '0',                     // 购买指定商品的id集                     'become__buy_product_ids' => [],                     'province_condition' => 0,                     'city_condition' => 0,                     'area_condition' => 0                 ],             ],             'condition' => [                 'key' => 'condition',                 'describe' => '区域代理条件',                 'values' => [                     // 成为区域代理条件                     'become' => '10',   // 参数值:10填写申请信息(需后台审核) 20填写申请信息(无需审核)                     // 购买指定商品成为区域代理 0关闭 1开启                     'become__buy_product' => '0',                     // 购买指定商品的id集                     'become__buy_product_ids' => [],                 ]             ],             'bonus' => [                 'key' => 'bonus',                 'describe' => '分红设置',                 'values' => [                     // 一级佣金                     'province_ratio' => '0',                     // 一级佣金                     'city_ratio' => '0',                     // 一级佣金                     'area_ratio' => '0',                 ]             ],             'settlement' => [                 'key' => 'settlement',                 'describe' => '结算',                 'values' => [                     // 提现方式                     'pay_type' => [],   // 参数值:10微信支付 20支付宝支付 30银行卡支付                     // 微信支付自动打款                     'wechat_pay_auto' => '0',       // 微信支付自动打款:1开启 0关闭                     'fee_rate' => 0, //手续费                     // 最低提现额度                     'min_money' => '10.00',                     // 分红结算天数                     'settle_days' => '10',                 ]             ],             'words' => [                 'key' => 'words',                 'describe' => '自定义文字',                 'values' => [                     'index' => [                         'title' => [                             'default' => '区域代理',                             'value' => '区域代理'                         ],                         'words' => [                             'region' => [                                 'default' => '区域代理',                                 'value' => '区域代理'                             ],                             'not_region' => [                                 'default' => '很抱歉,您还不是区域代理',                                 'value' => '很抱歉,您还不是区域代理'                             ],                             'apply_now' => [                                 'default' => '立即加入',                                 'value' => '立即加入'                             ],                             'referee' => [                                 'default' => '推荐人',                                 'value' => '推荐人'                             ],                             'money' => [                                 'default' => '可提现分红',                                 'value' => '可提现'                             ],                             'freeze_money' => [                                 'default' => '待提现分红',                                 'value' => '待提现'                             ],                             'total_money' => [                                 'default' => '已提现金额',                                 'value' => '已提现金额'                             ],                             'cash' => [                                 'default' => '去提现',                                 'value' => '去提现'                             ],                         ]                     ],                     'apply' => [                         'title' => [                             'default' => '申请成为区域代理',                             'value' => '申请成为区域代理'                         ],                         'words' => [                             'title' => [                                 'default' => '请填写申请信息',                                 'value' => '请填写申请信息'                             ],                             'license' => [                                 'default' => '区域代理申请协议',                                 'value' => '区域代理申请协议'                             ],                             'submit' => [                                 'default' => '申请成为区域代理',                                 'value' => '申请成为区域代理'                             ],                             'wait_audit' => [                                 'default' => '您的申请已受理,正在进行信息核验,请耐心等待。',                                 'value' => '您的申请已受理,正在进行信息核验,请耐心等待。'                             ],                             'goto_mall' => [                                 'default' => '去商城逛逛',                                 'value' => '去商城逛逛'                             ],                             'not_pass' => [                                 'default' => '很抱歉,您未达到申请条件',                                 'value' => '很抱歉,您未达到申请条件'                             ],                         ]                     ],                     'bonus_list' => [                         'title' => [                             'default' => '结算明细',                             'value' => '结算明细'                         ],                         'words' => [                                                      ]                     ],                     'cash_list' => [                         'title' => [                             'default' => '提现明细',                             'value' => '提现明细'                         ],                         'words' => [                             'all' => [                                 'default' => '全部',                                 'value' => '全部'                             ],                             'apply_10' => [                                 'default' => '审核中',                                 'value' => '审核中'                             ],                             'apply_20' => [                                 'default' => '审核通过',                                 'value' => '审核通过'                             ],                             'apply_40' => [                                 'default' => '已打款',                                 'value' => '已打款'                             ],                             'apply_30' => [                                 'default' => '驳回',                                 'value' => '驳回'                             ],                         ]                     ],                     'cash_apply' => [                         'title' => [                             'default' => '申请提现',                             'value' => '申请提现'                         ],                         'words' => [                             'capital' => [                                 'default' => '可提现分红',                                 'value' => '可提现分红'                             ],                             'money' => [                                 'default' => '提现金额',                                 'value' => '提现金额'                             ],                             'money_placeholder' => [                                 'default' => '请输入要提取的金额',                                 'value' => '请输入要提取的金额'                             ],                             'min_money' => [                                 'default' => '最低提现分红',                                 'value' => '最低提现分红'                             ],                             'submit' => [                                 'default' => '提交申请',                                 'value' => '提交申请'                             ],                         ]                     ],                 ]             ],             'license' => [                 'key' => 'license',                 'describe' => '申请协议',                 'values' => [                     'license' => ''                 ]             ],             'background' => [                 'key' => 'background',                 'describe' => '页面背景图',                 'values' => [                     // 分销中心首页                     'index' => self::$base_url . 'image/region/region-bg.jpg',                     // 申请成为区域代理页                     'apply' => self::$base_url . 'image/region/region-bg.jpg',                     // 申请提现页                     'cash_apply' => self::$base_url . 'image/region/region-bg.jpg',                     // 权益说明                     'description' => self::$base_url . 'image/region/description.png',                 ],             ],             'template_msg' => [                 'key' => 'template_msg',                 'describe' => '模板消息',                 'values' => [                     'apply_tpl' => '',    // 区域代理审核通知                     'cash_tpl' => '',    // 提现状态通知                 ]             ],         ];     } }
<?php namespace app\common\model\plus\operations; use app\common\model\BaseModel; use think\facade\Cache; /**  * 区域代理设置模型  */ class Setting extends BaseModel {     protected $name = 'operations_setting';     protected $createTime = false;     /**      * 转义数组格式      * @param $value      * @return mixed      */     public function getValuesAttr($value)     {         return json_decode($value, true);     }     /**      * 转义成json格式      * @param $value      * @return false|string      */     public function setValuesAttr($value)     {         return json_encode($value);     }     /**      * 获取指定项设置      * @param $key      * @param null $app_id      * @return array|mixed      */     public static function getItem($key, $app_id = null)     {         $data = static::getAll($app_id);         return isset($data[$key]) ? $data[$key]['values'] : [];     }     /**      * 获取区域代理设置      */     public static function getAll($app_id = null)     {         $self = new static;         is_null($app_id) && $app_id = $self::$app_id;         if (!$data = Cache::get('operations_setting_' . $app_id)) {             $data = array_column($self->select()->toArray(), null, 'key');             Cache::tag('cache')->set('operations_setting_' . $app_id, $data);         }         return array_merge_multiple($self->defaultData(), $data);     }     /**      * 获取设置项信息      */     public static function detail($key)     {         return (new static())->find(compact('key'));     }     /**      * 是否开启分销功能      */     public static function isOpen($app_id = null)     {         return static::getItem('basic', $app_id)['is_open'];     }     /**      * 分销中心页面名称      */     public static function getregionTitle($app_id = null)     {         return static::getItem('words', $app_id)['index']['title']['value'];     }     /**      * 默认配置      */     public function defaultData()     {         return [             'basic' => [                 'key' => 'basic',                 'describe' => '基础设置',                 'values' => [                     // 是否开启分红功能                     'is_open' => '0',   // 参数值:1开启 0关闭                     //'jcaward' => '0',   //级差奖                     'pjaward' => '0',   //平级奖                     'pjaward_level' => '1',   //平级奖奖励层级,默认往上1级                     'become' => '10',                     'total_rate' => '0',                     // 分红结算方式                     'bonus_type' => '20', // 10按周 20按月 30按年                     'total_team_user' => 0, // 团队总人数                     'self_buy_money' => 0, // 累计团队业绩是是否计算个人业绩                     'one_expend_money' => 0, // 个人一次性消费                     // 购买指定商品成为分销商 0关闭 1开启                     'become__buy_product' => '0',                     // 购买指定商品的id集                     'become__buy_product_ids' => [],                     'province_condition' => 0,                     'city_condition' => 0,                     'area_condition' => 0                 ],             ],             'condition' => [                 'key' => 'condition',                 'describe' => '运营中心条件',                 'values' => [                     // 成为区域代理条件                     'become' => '10',   // 参数值:10填写申请信息(需后台审核) 20填写申请信息(无需审核)                     // 购买指定商品成为区域代理 0关闭 1开启                     'become__buy_product' => '0',                     // 购买指定商品的id集                     'become__buy_product_ids' => [],                 ]             ],             'bonus' => [                 'key' => 'bonus',                 'describe' => '抽成设置',                 'values' => [                     // 一级佣金                     'province_ratio' => '0',                     // 一级佣金                     'city_ratio' => '0',                     // 一级佣金                     'area_ratio' => '0',                 ]             ],             'settlement' => [                 'key' => 'settlement',                 'describe' => '结算',                 'values' => [                     // 提现方式                     'pay_type' => [],   // 参数值:10微信支付 20支付宝支付 30银行卡支付                     // 微信支付自动打款                     'wechat_pay_auto' => '0',       // 微信支付自动打款:1开启 0关闭                     'fee_rate' => 0, //手续费                     // 最低提现额度                     'min_money' => '10.00',                     // 分红结算天数                     'settle_days' => '10',                 ]             ],             'words' => [                 'key' => 'words',                 'describe' => '自定义文字',                 'values' => [                     'index' => [                         'title' => [                             'default' => '运营中心',                             'value' => '运营中心'                         ],                         'words' => [                             'region' => [                                 'default' => '运营中心',                                 'value' => '运营中心'                             ],                             'not_region' => [                                 'default' => '很抱歉,您还不是运营中心',                                 'value' => '很抱歉,您还不是运营中心'                             ],                             'apply_now' => [                                 'default' => '立即加入',                                 'value' => '立即加入'                             ],                             'referee' => [                                 'default' => '推荐人',                                 'value' => '推荐人'                             ],                             'money' => [                                 'default' => '可提现分红',                                 'value' => '可提现'                             ],                             'freeze_money' => [                                 'default' => '待提现分红',                                 'value' => '待提现'                             ],                             'total_money' => [                                 'default' => '已提现金额',                                 'value' => '已提现金额'                             ],                             'cash' => [                                 'default' => '去提现',                                 'value' => '去提现'                             ],                         ]                     ],                     'apply' => [                         'title' => [                             'default' => '申请成为运营中心',                             'value' => '申请成为运营中心'                         ],                         'words' => [                             'title' => [                                 'default' => '请填写申请信息',                                 'value' => '请填写申请信息'                             ],                             'license' => [                                 'default' => '运营中心申请协议',                                 'value' => '运营中心申请协议'                             ],                             'submit' => [                                 'default' => '申请成为运营中心',                                 'value' => '申请成为运营中心'                             ],                             'wait_audit' => [                                 'default' => '您的申请已受理,正在进行信息核验,请耐心等待。',                                 'value' => '您的申请已受理,正在进行信息核验,请耐心等待。'                             ],                             'goto_mall' => [                                 'default' => '去商城逛逛',                                 'value' => '去商城逛逛'                             ],                             'not_pass' => [                                 'default' => '很抱歉,您未达到申请条件',                                 'value' => '很抱歉,您未达到申请条件'                             ],                         ]                     ],                     'order' => [                         'title' => [                             'default' => '运营中心订单',                             'value' => '运营中心订单'                         ],                         'words' => [                             'all' => [                                 'default' => '全部',                                 'value' => '全部'                             ],                             'unsettled' => [                                 'default' => '未结算',                                 'value' => '未结算'                             ],                             'settled' => [                                 'default' => '已结算',                                 'value' => '已结算'                             ],                         ]                     ],                     'bonus_list' => [                         'title' => [                             'default' => '结算明细',                             'value' => '结算明细'                         ],                         'words' => [                                                      ]                     ],                     'cash_list' => [                         'title' => [                             'default' => '提现明细',                             'value' => '提现明细'                         ],                         'words' => [                             'all' => [                                 'default' => '全部',                                 'value' => '全部'                             ],                             'apply_10' => [                                 'default' => '审核中',                                 'value' => '审核中'                             ],                             'apply_20' => [                                 'default' => '审核通过',                                 'value' => '审核通过'                             ],                             'apply_40' => [                                 'default' => '已打款',                                 'value' => '已打款'                             ],                             'apply_30' => [                                 'default' => '驳回',                                 'value' => '驳回'                             ],                         ]                     ],                     'cash_apply' => [                         'title' => [                             'default' => '申请提现',                             'value' => '申请提现'                         ],                         'words' => [                             'capital' => [                                 'default' => '可提现分红',                                 'value' => '可提现分红'                             ],                             'money' => [                                 'default' => '提现金额',                                 'value' => '提现金额'                             ],                             'money_placeholder' => [                                 'default' => '请输入要提取的金额',                                 'value' => '请输入要提取的金额'                             ],                             'min_money' => [                                 'default' => '最低提现分红',                                 'value' => '最低提现分红'                             ],                             'submit' => [                                 'default' => '提交申请',                                 'value' => '提交申请'                             ],                         ]                     ],                 ]             ],             'license' => [                 'key' => 'license',                 'describe' => '申请协议',                 'values' => [                     'license' => ''                 ]             ],             'background' => [                 'key' => 'background',                 'describe' => '页面背景图',                 'values' => [                     // 分销中心首页                     'index' => self::$base_url . 'image/region/region-bg.jpg',                     // 申请成为区域代理页                     'apply' => self::$base_url . 'image/region/region-bg.jpg',                     // 申请提现页                     'cash_apply' => self::$base_url . 'image/region/region-bg.jpg',                     // 权益说明                     'description' => self::$base_url . 'image/region/description.png',                 ],             ],             'template_msg' => [                 'key' => 'template_msg',                 'describe' => '模板消息',                 'values' => [                     'apply_tpl' => '',    // 区域代理审核通知                     'cash_tpl' => '',    // 提现状态通知                 ]             ],         ];     } }
admin/app/common/model/product/Product.php
@@ -211,8 +211,8 @@
            'audit_status' => -1,    //审核状态
            'is_virtual' => -1,    //商品类型
            'is_good' => -1,    //商品类型
            'is_gift_pack' => -1,    //是否是升级礼包
        ], $param);
        // 筛选条件
        $filter = [];
        $model = $this;
@@ -228,6 +228,9 @@
        if (!empty($params['product_name'])) {
            $model = $model->where('product_name', 'like', '%' . trim($params['product_name']) . '%');
        }
        if ($params['is_gift_pack']>-1) {
            $model = $model->where('is_gift_pack',  $params['is_gift_pack']);
        }
        if (!empty($params['search'])) {
            $model = $model->where('product_name', 'like', '%' . trim($params['search']) . '%');
        }
admin/app/common/service/business/Poster.php
@@ -113,13 +113,31 @@
    private function savePoster($backdrop, $avatarUrl, $imageUrl, $logo)
    {
        // 创建画布
        list($width, $height) = getimagesize($backdrop);
        // 获取背景图信息,判断图片类型
        $backdropInfo = getimagesize($backdrop);
        $width = $backdropInfo[0];
        $height = $backdropInfo[1];
        // 根据原图类型创建对应类型的画布,提高质量
        $imageType = $backdropInfo[2];
        // 创建真彩色画布,确保足够的色彩深度
        $newImage = imagecreatetruecolor($width, $height);
        $backdropIm = $this->imagEcr($backdrop);
        // 启用抗锯齿
        imageantialias($newImage, true);
        // 将第一张图片覆盖在新图像上
        imagecopy($newImage, $backdropIm, 0, 0, 0, 0, $width, $height);
        // 启用alpha混合模式,确保透明度正常
        imagealphablending($newImage, true);
        // 保存透明度
        imagesavealpha($newImage, true);
        // 加载背景图
        $backdropIm = $this->imagEcr($backdrop);
        // 将背景图复制到画布(使用更好的插值方法)
        imagecopyresampled($newImage, $backdropIm, 0, 0, 0, 0, $width, $height, $width, $height);
        if (!empty($this->config['icon'])) {
            foreach ($this->config['icon'] as $key => $value) {
                $this->addImagecopy($newImage, $value);
@@ -127,9 +145,6 @@
        }
        // 脱敏处理
        if($this->businessName=='desensitization'){
            // 保存原始数据以便后续可能需要使用
            $originalDealer = $this->dealer;
            // 手机号脱敏:保留前3位和后4位
            if(!empty($this->dealer['mobile'])){
                $this->dealer['mobile'] = $this->maskPhoneNumber($this->dealer['mobile']);
@@ -167,6 +182,7 @@
            $avatarY = $this->config['avatar']['top'];
            // 打开用户头像
            $avatarIm = $this->imagEcr($avatarUrl);
            // 使用更好的插值方法复制头像(使用imagecopy保持原有质量)
            imagecopy($newImage, $avatarIm, $avatarX, $avatarY, 0, 0, $avatarWidth, $avatarWidth);
        }
        if (is_file($logo) && $this->config['logo']['display'] == 1) {
@@ -182,43 +198,109 @@
            $logoY = $this->config['logo']['top'];
            // 打开用户logo
            $logoImage = $this->imagEcr($logo);
            // 使用更好的插值方法复制logo(使用imagecopy保持原有质量)
            imagecopy($newImage, $logoImage, $logoX, $logoY, 0, 0, $logoWidth, $logoHeight);
        }
        // 写入用户昵称
        $this->addText($newImage, 'name');
        $this->addText($newImage, 'name', '', 0, false, $width);
        // 写入公司列表
        $unitBaseTop = 0;
        $unitFontSize = $this->config['unit'][0]['fontSize'];
        foreach ($this->dealer['unit'] as $key => $value) {
            // 写入公司
            $this->addText($newImage, 'unit', '', $key, true);
            if($key > 0){
                $this->config['unit'][$key] = $this->config['unit'][0];
                // 计算偏移量:每个公司增加基于前一个公司实际行数的距离
                $this->config['unit'][$key]['top'] = $this->config['unit'][0]['top'] + $unitBaseTop;
            }
            // 写入公司,获取实际占用的行数
            $lineCount = $this->addText($newImage, 'unit', '', $key, true, $width);
            // 计算下一个公司的偏移量:(行数 - 1) * 行高 + 行间距
            $unitLineHeight = $this->getLineHeight($unitFontSize);
            $unitLineSpacing = $this->getLineSpacing($unitFontSize);
            if ($key > 0) {
                $unitBaseTop += ($lineCount * $unitLineHeight) + $unitLineSpacing;
            } else {
                $unitBaseTop = ($lineCount * $unitLineHeight) + $unitLineSpacing;
            }
        }
        // 写入职位列表
        if (!empty($this->dealer['duties']) && !empty($this->config['duties'])) {
           // 写入职位
            $this->addText($newImage, 'duties');
            $dutiesBaseTop = 0;
            $dutiesFontSize = $this->config['duties'][0]['fontSize'];
            foreach ($this->dealer['duties'] as $key => $value) {
                if($key > 0){
                    $this->config['duties'][$key] = $this->config['duties'][0];
                    // 计算偏移量:每个职位增加基于前一个职位实际行数的距离
                    $this->config['duties'][$key]['top'] = $this->config['duties'][0]['top'] + $dutiesBaseTop;
                }
                // 写入职位,获取实际占用的行数
                $lineCount = $this->addText($newImage, 'duties','', $key, true, $width);
                // 计算下一个职位的偏移量:(行数 - 1) * 行高 + 行间距
                $dutiesLineHeight = $this->getLineHeight($dutiesFontSize);
                $dutiesLineSpacing = $this->getLineSpacing($dutiesFontSize);
                if ($key > 0) {
                    $dutiesBaseTop += ($lineCount * $dutiesLineHeight) + $dutiesLineSpacing;
                } else {
                    $dutiesBaseTop = ($lineCount * $dutiesLineHeight) + $dutiesLineSpacing;
                }
            }
        }
        // 写入position列表(备用字段)
        if (!empty($this->dealer['position']) && !empty($this->config['position'])) {
            $positionBaseTop = 0;
            $positionFontSize = $this->config['position'][0]['fontSize'];
            foreach ($this->dealer['position'] as $key => $value) {
                // 写入公司
                $this->addText($newImage, 'position', '', $key, true);
                if($key > 0){
                    $this->config['position'][$key] = $this->config['position'][0];
                    // 计算偏移量:每个position增加基于前一个实际行数的距离
                    $this->config['position'][$key]['top'] = $this->config['position'][0]['top'] + $positionBaseTop;
                }
                // 写入position,获取实际占用的行数
                $lineCount = $this->addText($newImage, 'position', '', $key, true, $width);
                // 计算下一个position的偏移量:(行数 - 1) * 行高 + 行间距
                $positionLineHeight = $this->getLineHeight($positionFontSize);
                $positionLineSpacing = $this->getLineSpacing($positionFontSize);
                if ($key > 0) {
                    $positionBaseTop += ($lineCount * $positionLineHeight) + $positionLineSpacing;
                } else {
                    $positionBaseTop = ($lineCount * $positionLineHeight) + $positionLineSpacing;
                }
            }
        }
        // 写入手机号
        $this->addText($newImage, 'mobile', '手机:');
        $this->addText($newImage, 'mobile', '手机:', 0, false, $width);
        if (!empty($this->dealer['wechat']) && !empty($this->config['wechat'])) {
            // 写入微信
            $this->addText($newImage, 'wechat', '微信:');
            $this->addText($newImage, 'wechat', '微信:', 0, false, $width);
        }
        // 写入邮箱
        if ($this->dealer['mailbox']) {
            // 写入邮箱
            $this->addText($newImage, 'mailbox', '邮箱:');
            $this->addText($newImage, 'mailbox', '邮箱:', 0, false, $width);
        }
        if ($this->dealer['phone']) {
            $this->addText($newImage, 'phone', '电话:');
            $this->addText($newImage, 'phone', '电话:', 0, false, $width);
        }
        // 保存图片
        imagejpeg($newImage, $this->getPosterPath($imageUrl),100); // 根据需要选择合适的函数(如imagepng、imagegif等)
        // 根据背景图类型选择保存格式
        $imageType = $backdropInfo[2];
        $savePath = $this->getPosterPath($imageUrl);
        if ($imageType == IMAGETYPE_PNG) {
            // PNG格式,使用最高质量(9)
            imagepng($newImage, $savePath, 9);
        } elseif ($imageType == IMAGETYPE_GIF) {
            // GIF格式
            imagegif($newImage, $savePath);
        } else {
            // JPEG格式,使用最高质量(100)
            imagejpeg($newImage, $savePath, 100);
        }
        // 清理内存
        imagedestroy($newImage);
        imagedestroy($backdropIm);
        return $this->getPosterUrl($imageUrl);
    }
@@ -256,9 +338,9 @@
        imagecopyresampled($targetImage, $image, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height); // 保存时使用最高质量
        $ext = pathinfo($imageUrl, PATHINFO_EXTENSION);
        if ($ext == 'png'){
            imagepng($targetImage, $imageUrl,0); // 根据需要选择合适的函数(如imagepng、imagegif等)
            imagepng($targetImage, $imageUrl, 9); // PNG使用最高质量(9)
        }else{
            imagejpeg($targetImage, $imageUrl,100);
            imagejpeg($targetImage, $imageUrl, 100); // JPEG使用最高质量
        }
        // 清理内存
@@ -289,35 +371,42 @@
     * @param $key
     * @param $type
     * @param $width
     * @return array|bool
     * @return array|bool|int 返回实际占用的行数(仅对type=true时有效)
     */
    public function addText($editor, $name, $text = '', $key = 0, $type = false, $width = 0)
    {
        $fontPath = $_SERVER['DOCUMENT_ROOT']. '/fonts/MSYH.TTC';
        if ($type) {
            list($fontSize, $fontX,$fontY)  = self::SizeLeftTop($this->config[$name][$key]['fontSize'], $this->config[$name][$key]['left'],$this->config[$name][$key]['top']);
            $colorResource=self::colorResource($this->config[$name][$key]['color'],$editor);
            return imagettftext($editor, $fontSize, 0, $fontX, $fontY, $colorResource, $fontPath, $text . $this->dealer[$name][$key]);
            // 确保配置数组存在该索引,不存在则使用索引0
            $configKey = isset($this->config[$name][$key]) ? $key : 0;
            list($fontSize, $fontX,$fontY)  = self::SizeLeftTop($this->config[$name][$configKey]['fontSize'], $this->config[$name][$configKey]['left'],$this->config[$name][$configKey]['top']);
            $colorResource=self::colorResource($this->config[$name][$configKey]['color'],$editor);
            // 智能计算最大宽度
            $maxWidth = $this->calculateFieldMaxWidth($this->config[$name][$configKey]['left'], $this->config[$name][$configKey]['top'], $width);
            // 写入支持换行的文本
            return $this->writeTextWithWrap($editor, $text . $this->dealer[$name][$key], $fontX, $fontY, $fontSize, $colorResource, $fontPath, $maxWidth);
        } else if ($name == 'mobile') {
            list($fontSize, $fontX,$fontY)  = self::SizeLeftTop($this->config[$name]['fontSize'], $this->config[$name]['left'],$this->config[$name]['top']);
            $text = $text . $this->dealer['mobile'];
            if (!empty($this->dealer['mobile_phone'])) {
                $text = $text . ' / ' . $this->dealer['mobile_phone'];
            }
            $colorResource=self::colorResource($this->config[$name]['color'],$editor);
            return imagettftext($editor, $fontSize, 0, $fontX, $fontY, $colorResource, $fontPath, $text);
            // 智能计算最大宽度
            $maxWidth = $this->calculateFieldMaxWidth($this->config[$name]['left'], $this->config[$name]['top'], $width);
            // 写入支持换行的文本
            $this->writeTextWithWrap($editor, $text, $fontX, $fontY, $fontSize, $colorResource, $fontPath, $maxWidth);
        } else if ($name == 'duties') {
            list($fontSize, $fontX,$fontY)  = self::SizeLeftTop($this->config[$name][$key]['fontSize'], $this->config[$name][$key]['left'],$this->config[$name][$key]['top']);
            // 确保配置数组存在该索引,不存在则使用索引0
            $configKey = isset($this->config[$name][$key]) ? $key : 0;
            list($fontSize, $fontX,$fontY)  = self::SizeLeftTop($this->config[$name][$configKey]['fontSize'], $this->config[$name][$configKey]['left'],$this->config[$name][$configKey]['top']);
            $duties = $this->dealer['duties'][$key];
            if (!empty($this->dealer['duties'][1])) {
                $duties = $duties . ' / ' . $this->dealer['duties'][1];
            }
            if (!empty($this->dealer['duties'][2])) {
                $duties = $duties . ' / ' . $this->dealer['duties'][2];
            }
            $colorResource=self::colorResource($this->config['duties'][0]['color'],$editor);
            return imagettftext($editor, $fontSize, 0, $fontX, $fontY, $colorResource, $fontPath, $text . $duties);
            // 智能计算最大宽度
            $maxWidth = $this->calculateFieldMaxWidth($this->config[$name][$configKey]['left'], $this->config[$name][$configKey]['top'], $width);
            // 写入支持换行的文本
            return $this->writeTextWithWrap($editor, $text . $duties, $fontX, $fontY, $fontSize, $colorResource, $fontPath, $maxWidth);
        } else if ($name == 'address') {
            list($fontSize, $fontX,$fontY)  = self::SizeLeftTop($this->config[$name][$key]['fontSize'], $this->config[$name][$key]['left'],$this->config[$name][$key]['top']);
            $title = $this->dealer['address'][0];
@@ -353,9 +442,11 @@
        } else {
            list($fontSize, $fontX,$fontY)  = self::SizeLeftTop($this->config[$name]['fontSize'], $this->config[$name]['left'],$this->config[$name]['top']);
            $colorResource=self::colorResource($this->config[$name]['color'],$editor);
            return imagettftext($editor, $fontSize, 0, $fontX, $fontY, $colorResource, $fontPath, $text . $this->dealer[$name]); // path/to/font.ttf为自定义字体路径
            // 智能计算最大宽度
            $maxWidth = $this->calculateFieldMaxWidth($this->config[$name]['left'], $this->config[$name]['top'], $width);
            // 写入支持换行的文本
            $this->writeTextWithWrap($editor, $text . $this->dealer[$name], $fontX, $fontY, $fontSize, $colorResource, $fontPath, $maxWidth);
        }
    }
    /**
@@ -451,11 +542,10 @@
                $areaCode = $parts[0]; // 区号
                $number = end($parts); // 号码部分
                $separator = strpos($phone, '-') !== false ? '-' : ' '; // 保持原始分隔符
                $numLen = strlen($number);
                if($numLen <= 4) return $phone; // 号码太短不脱敏
                $numPrefix = substr($number, 0, 0); // 号码部分前半段不显示
                $numSuffix = substr($number, -4); // 保留号码后4位
                $stars = str_repeat('*', $numLen - 4);
                
@@ -533,15 +623,201 @@
     * @param $fontSize
     * @param $left
     * @param $top
     * @return array
     * @return array [fontSizePt, left, top]
     */
    private function SizeLeftTop($fontSize,$left,$top){
        // 正确的px到pt转换系数:1px = 0.75pt
        // 使用0.75而不是0.76以确保字体大小显示准确
        $data[0] = $fontSize * 0.75;
        $data[1]  = (float)$left;
        $data[2]  = (float)$top + $fontSize;
        // px到pt转换系数:GD库使用磅(pt)作为字体单位
        // 使用标准转换: 1pt = 4/3 px, 所以 1px = 3/4 pt = 0.75pt
        // 但为了更清晰的文字,调整为 1px = 0.8pt
        $fontSizePt = $fontSize * 0.8;
        // 调整top位置,使文字基线对齐
        // imagettftext的y坐标是文字基线位置,不是文字顶部
        // 微软雅黑字体的基线大约在字体高度的85%位置
        $data[0] = $fontSizePt;  // 字体大小(pt)
        $data[1]  = (float)$left;  // 左边距(px)
        $data[2]  = (float)$top + ($fontSize * 0.85);  // 顶部位置(px),加字体大小的85%以校正基线
        return $data;
    }
    /**
     * 获取文本实际高度
     * @param $fontSizePx 字体大小(px)
     * @return float 行高(px)
     */
    private function getLineHeight($fontSizePx) {
        // 行高 = 字体大小 * 1.5 (更舒适的行间距)
        return $fontSizePx * 1.5;
    }
    /**
     * 获取行间距
     * @param $fontSizePx 字体大小(px)
     * @return float 行间距(px)
     */
    private function getLineSpacing($fontSizePx) {
        // 行间距 = 字体大小 * 0.5 (50%的字体大小作为间距)
        return $fontSizePx * 0.5;
    }
    /**
     * 智能计算字段的最大宽度
     * 根据右边是否有其他字段来动态计算maxWidth
     * @param $left
     * @param $top
     * @param $backdropWidth
     * @return float
     */
    private function calculateFieldMaxWidth($left, $top, $backdropWidth = 375)
    {
        $rightFields = [];
        $tolerance = 20; // 容差:判断是否在同一行的像素范围
        // 收集所有可能的字段
        $fields = [];
        // 公司
        if (!empty($this->config['unit'][0])) {
            $fields[] = [
                'name' => 'unit',
                'left' => $this->config['unit'][0]['left'],
                'top' => $this->config['unit'][0]['top']
            ];
        }
        // 职位
        if (!empty($this->config['duties'][0])) {
            $fields[] = [
                'name' => 'duties',
                'left' => $this->config['duties'][0]['left'],
                'top' => $this->config['duties'][0]['top']
            ];
        }
        // 姓名
        if (!empty($this->config['name'])) {
            $fields[] = [
                'name' => 'name',
                'left' => $this->config['name']['left'],
                'top' => $this->config['name']['top']
            ];
        }
        // 地址
        if (!empty($this->config['address'][0])) {
            $fields[] = [
                'name' => 'address',
                'left' => $this->config['address'][0]['left'],
                'top' => $this->config['address'][0]['top']
            ];
        }
        // 邮箱
        if (!empty($this->config['mailbox'])) {
            $fields[] = [
                'name' => 'mailbox',
                'left' => $this->config['mailbox']['left'],
                'top' => $this->config['mailbox']['top']
            ];
        }
        // 手机
        if (!empty($this->config['mobile'])) {
            $fields[] = [
                'name' => 'mobile',
                'left' => $this->config['mobile']['left'],
                'top' => $this->config['mobile']['top']
            ];
        }
        // 微信
        if (!empty($this->config['wechat'])) {
            $fields[] = [
                'name' => 'wechat',
                'left' => $this->config['wechat']['left'],
                'top' => $this->config['wechat']['top']
            ];
        }
        // 电话
        if (!empty($this->config['phone'])) {
            $fields[] = [
                'name' => 'phone',
                'left' => $this->config['phone']['left'],
                'top' => $this->config['phone']['top']
            ];
        }
        // 找出右边最近的字段
        // 判断标准: left > 当前left, 且top在合理范围内(±20px)
        foreach ($fields as $field) {
            if ($field['left'] > $left && abs($field['top'] - $top) <= $tolerance) {
                $rightFields[] = $field;
            }
        }
        // 如果右边有字段,取最近的一个的左边距
        if (count($rightFields) > 0) {
            // 按left排序
            usort($rightFields, function($a, $b) {
                return $a['left'] - $b['left'];
            });
            return max($rightFields[0]['left'] - $left - 10, 50);
        }
        // 如果右边没有字段,使用名片边缘
        return max($backdropWidth - $left - 10, 100);
    }
    /**
     * 写入支持换行的文本
     * @param $editor
     * @param $text
     * @param $x
     * @param $y
     * @param $fontSize
     * @param $color
     * @param $fontPath
     * @param $maxWidth
     * @return int 返回实际使用的行数
     */
    private function writeTextWithWrap($editor, $text, $x, $y, $fontSize, $color, $fontPath, $maxWidth)
    {
        $fontSizePt = $fontSize * 0.75; // px转pt
        $lineHeight = $this->getLineHeight($fontSize); // 获取精确的行高
        $lines = [];
        $currentLine = '';
        // 按字符分割文本
        $chars = preg_split('//u', $text, -1, PREG_SPLIT_NO_EMPTY);
        foreach ($chars as $char) {
            $testLine = $currentLine . $char;
            $bbox = imagettfbbox($fontSizePt, 0, $fontPath, $testLine);
            $lineWidth = $bbox[2] - $bbox[0];
            // 使用maxWidth减去一点边距,确保不超出边界
            if ($lineWidth > $maxWidth - 2 && $currentLine !== '') {
                $lines[] = $currentLine;
                $currentLine = $char;
            } else {
                $currentLine = $testLine;
            }
        }
        if ($currentLine !== '') {
            $lines[] = $currentLine;
        }
        // 写入每一行
        foreach ($lines as $index => $line) {
            // 第一行使用原始y坐标,后续行加上行高偏移
            $lineY = $y + ($index * $lineHeight);
            imagettftext($editor, $fontSizePt, 0, $x, $lineY, $color, $fontPath, $line);
        }
        // 返回实际占用的行数
        return count($lines);
    }
}
admin/app/common/service/order/OrderCompleteService.php
@@ -26,7 +26,7 @@
use app\common\model\plus\shareholder\Setting as ShareholderSettingModel;
use app\common\model\plus\shareholder\Bonus as ShareholderBonusModel;
use app\common\model\plus\vip\Order as VipOrderModel;
use app\common\model\plus\operations\Order as OperationsOrderModel;
/**
 * 已完成订单结算服务类
 */
@@ -110,6 +110,8 @@
                }
            }
            AgentOrderModel::grantMoney($order, $this->orderType);
            // 发放运营中心佣金
            OperationsOrderModel::grantMoney($order, $this->orderType);
            // 发放团队分红 by yj
            TeamOrderModel::grantMoney($order, $this->orderType);
            // 发放会员分红
admin/app/event.php
@@ -83,6 +83,10 @@
        'VipUserGrade' => [
            \app\job\event\VipUserGrade::class
        ],
        /*运营中心订单*/
        'OperationsOrder' => [
            \app\job\event\OperationsOrder::class
        ],
    ],
    'subscribe' => [
admin/app/job/event/AgentUserGrade.php
@@ -30,6 +30,9 @@
        log_write('分销商升级$user_id='.$userId);
        // 用户模型
        $user = UserModel::detail($userId);
        if (empty($user)){
            return false;
        }
        // 获取所有等级
        $list = GradeModel::getUsableList($user['app_id']);
        if ($list->isEmpty()) {
admin/app/job/event/JobScheduler.php
@@ -41,6 +41,8 @@
        event('LiveRoom');
        // 分会
        event('Branch');
        // 运营中心订单
        event('OperationsOrder');
        return true;
    }
admin/app/job/event/OperationsOrder.php
New file
@@ -0,0 +1,88 @@
<?php
namespace app\job\event;
use think\facade\Cache;
use app\job\model\plus\operations\Order as OperationsOrderModel;
/**
 * 运营中心订单事件管理
 */
class OperationsOrder
{
    // 模型
    private $model;
    /**
     * 执行函数
     */
    public function handle()
    {
        try {
            $this->model = new OperationsOrderModel();
            $cacheKey = "task_space_OperationsOrder";
            if (!Cache::has($cacheKey)) {
                 $this->model->startTrans();
                try {
                    // 发放运营中心订单佣金
                    $this->grantMoney();
                    $this->model->commit();
                } catch (\Exception $e) {
                    $this->model->rollback();
                }
                Cache::set($cacheKey, time(), 60);
            }
        } catch (\Throwable $e) {
            echo 'ERROR OperationsOrder: ' . $e->getMessage() . PHP_EOL;
            log_write('OperationsOrder TASK : ' . '__ ' . $e->getMessage(), 'task');
        }
        return true;
    }
    /**
     * 发放运营中心订单佣金
     */
    private function grantMoney()
    {
        // 获取未结算佣金的订单列表
        $list = $this->model->getUnSettledList();
        if ($list->isEmpty()) return false;
        // 整理id集
        $invalidIds = [];
        $grantIds = [];
        // 发放运营中心订单佣金
        foreach ($list->toArray() as $item) {
            // 已失效的订单
            if ($item['order_master']['order_status']['value'] == 20) {
                $invalidIds[] = $item['id'];
            }
            // 已完成的订单
            if ($item['order_master']['order_status']['value'] == 30) {
                $grantIds[] = $item['id'];
                OperationsOrderModel::grantMoney($item['order_master'], $item['order_type']['value']);
            }
        }
        // 标记已失效的订单
        $this->model->setInvalid($invalidIds);
        // 记录日志
        $this->dologs('invalidIds', ['Ids' => $invalidIds]);
        $this->dologs('grantMoney', ['Ids' => $grantIds]);
        return true;
    }
    /**
     * 记录日志
     */
    private function dologs($method, $params = [])
    {
        $value = 'behavior OperationsOrder --' . $method;
        foreach ($params as $key => $val) {
            $value .= ' --' . $key . ' ' . (is_array($val) ? json_encode($val) : $val);
        }
        return log_write($value, 'task');
    }
}
admin/app/job/event/VipOrder.php
@@ -22,7 +22,7 @@
        try {
            $this->model = new VipOrderModel();
            $cacheKey = "task_space_VipOrder";
            //if (!Cache::has($cacheKey)) {
            if (!Cache::has($cacheKey)) {
                $this->model->startTrans();
                try {
                    // 发放VIP订单佣金
@@ -33,7 +33,7 @@
                    $this->model->rollback();
                }
                Cache::set($cacheKey, time(), 60);
            //}
            }
        } catch (\Throwable $e) {
            echo 'ERROR VipOrder: ' . $e->getMessage() . PHP_EOL;
            log_write('VipOrder TASK : ' . '__ ' . $e->getMessage(), 'task');
admin/app/job/model/plus/operations/Order.php
New file
@@ -0,0 +1,38 @@
<?php
namespace app\job\model\plus\operations;
use app\common\model\plus\operations\Order as OrderModel;
use app\common\service\order\OrderService;
/**
 * 运营中心订单模型
 */
class Order extends OrderModel
{
    /**
     * 获取未结算的运营中心订单
     */
    public function getUnSettledList()
    {
        $list = $this->where('is_invalid', '=', 0)
            ->where('is_settled', '=', 0)
            ->select();
        if ($list->isEmpty()) {
            return $list;
        }
        // 整理订单信息
        $with = ['product' => ['refund']];
        return OrderService::getOrderList($list, 'order_master', $with);
    }
    /**
     * 标记订单已失效(批量)
     */
    public function setInvalid($ids)
    {
        return $this->where('id', 'in', $ids)
            ->save(['is_invalid' => 1]);
    }
}
admin/app/shop/controller/plus/operations/Operations.php
@@ -7,7 +7,7 @@
use app\shop\model\plus\operations\Grade as GradeModel;
use app\shop\model\plus\agent\Referee as RefereeModel;
use app\shop\model\plus\operations\Setting as SettingModel;
use app\shop\model\plus\operations\User as UserModel;
use app\shop\model\plus\operations\operations as UserModel;
/**
 * 分销控制器
admin/app/shop/controller/plus/operations/Order.php
New file
@@ -0,0 +1,33 @@
<?php
namespace app\shop\controller\plus\operations;
use app\shop\controller\Controller;
use app\shop\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/shop/controller/supplier/Category.php
@@ -2,6 +2,7 @@
namespace app\shop\controller\supplier;
use app\common\enum\supplier\SupplierType;
use app\shop\controller\Controller;
use app\shop\model\supplier\Category as CategoryModel;
@@ -15,11 +16,12 @@
     */
    public function index()
    {
        $typeList = SupplierType::getTypeName();// 获取请求的供应商类型参数
        // 广告分类
        $model = new CategoryModel;
        $params = $this->request->param();
        $category = $model->getAll($params);
        return $this->renderSuccess('', compact('category'));
        return $this->renderSuccess('', compact('category','typeList'));
    }
    /**
admin/app/shop/model/plus/operations/Cash.php
@@ -16,10 +16,10 @@
use app\common\library\easywechat\WxPay;
use app\common\model\plus\region\Cash as CashModel;
use app\common\model\plus\operations\Cash as CashModel;
use app\shop\model\plus\region\Capital;
use app\shop\model\plus\region\User;
use app\shop\model\plus\operations\Capital;
use app\shop\model\plus\operations\Operations;
use app\shop\model\user\User as UserModel;
/**
@@ -152,7 +152,7 @@
        if ($param['apply_status'] == 30) {
            User::backFreezeMoney($param['user_id'], $param['money']);
            Operations::backFreezeMoney($param['user_id'], $param['money']);
        }
@@ -192,7 +192,7 @@
            // 更新队长累积提现佣金
            User::totalMoney($this['user_id'], $this['money']);
            Operations::totalMoney($this['user_id'], $this['money']);
admin/app/shop/service/order/ExportService.php
@@ -181,6 +181,80 @@
    }
    /**
     * 运营中心订单导出
     */
    public function operationsOrderList($list)
    {
        $spreadsheet = new Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();
        //列宽
        $sheet->getColumnDimension('B')->setWidth(30);
        //设置工作表标题名称
        $sheet->setTitle('运营中心订单明细');
        $sheet->setCellValue('A1', '订单号');
        $sheet->setCellValue('B1', '商品信息');
        $sheet->setCellValue('C1', '订单总额');
        $sheet->setCellValue('D1', '实付款金额');
        $sheet->setCellValue('E1', '支付方式');
        $sheet->setCellValue('F1', '下单时间');
        $sheet->setCellValue('G1', '省级运营中心');
        $sheet->setCellValue('H1', '省级佣金');
        $sheet->setCellValue('I1', '市级运营中心');
        $sheet->setCellValue('J1', '市级佣金');
        $sheet->setCellValue('K1', '区级运营中心');
        $sheet->setCellValue('L1', '区级佣金');
        $sheet->setCellValue('M1', '买家');
        $sheet->setCellValue('N1', '付款状态');
        $sheet->setCellValue('O1', '付款时间');
        $sheet->setCellValue('P1', '发货状态');
        $sheet->setCellValue('Q1', '发货时间');
        $sheet->setCellValue('R1', '收货状态');
        $sheet->setCellValue('S1', '收货时间');
        $sheet->setCellValue('T1', '订单状态');
        $sheet->setCellValue('U1', '佣金结算');
        $sheet->setCellValue('V1', '结算时间');
        //填充数据
        $index = 0;
        foreach ($list as $operations) {
            $order = $operations['order_master'];
            $sheet->setCellValue('A' . ($index + 2), "\t" . $order['order_no'] . "\t");
            $sheet->setCellValue('B' . ($index + 2), $this->filterProductInfo($order));
            $sheet->setCellValue('C' . ($index + 2), $order['total_price']);
            $sheet->setCellValue('D' . ($index + 2), $order['pay_price']);
            $sheet->setCellValue('E' . ($index + 2), $order['pay_type']['text']);
            $sheet->setCellValue('F' . ($index + 2), $order['create_time']);
            $sheet->setCellValue('G' . ($index + 2), isset($operations['agent_first'])?$operations['agent_first']['nickName']:'');
            $sheet->setCellValue('H' . ($index + 2), $operations['first_money']);
            $sheet->setCellValue('I' . ($index + 2), isset($operations['agent_second'])?$operations['agent_second']['nickName']:'');
            $sheet->setCellValue('J' . ($index + 2), $operations['second_money']);
            $sheet->setCellValue('K' . ($index + 2), isset($operations['agent_third'])?$operations['agent_third']['nickName']:'');
            $sheet->setCellValue('L' . ($index + 2), $operations['third_money']);
            $sheet->setCellValue('M' . ($index + 2), $order['user']['nickName']);
            $sheet->setCellValue('N' . ($index + 2), $order['pay_status']['text']);
            $sheet->setCellValue('O' . ($index + 2), $this->filterTime($order['pay_time']));
            $sheet->setCellValue('P' . ($index + 2), $order['delivery_status']['text']);
            $sheet->setCellValue('Q' . ($index + 2), $this->filterTime($order['delivery_time']));
            $sheet->setCellValue('R' . ($index + 2), $order['receipt_status']['text']);
            $sheet->setCellValue('S' . ($index + 2), $this->filterTime($order['receipt_time']));
            $sheet->setCellValue('T' . ($index + 2), $order['order_status']['text']);
            $sheet->setCellValue('U' . ($index + 2), $operations['is_settled'] == 1 ? '已结算' : '未结算');
            $sheet->setCellValue('V' . ($index + 2), $this->filterTime($operations['settle_time']));
            $index++;
        }
        //保存文件
        $filename = iconv("UTF-8", "GB2312//IGNORE", '运营中心订单') . '-' . date('YmdHis') . '.xlsx';
        header('Content-Type: application/vnd.ms-excel');
        header('Content-Disposition: attachment;filename="' . $filename . '"');
        header('Cache-Control: max-age=0');
        $writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
        $writer->save('php://output');
    }
    /**
     * 提现订单导出
     */
    public function cashList($list)
admin/app/supplier/model/product/Category.php
@@ -18,9 +18,9 @@
        $model = new static;
        if (!Cache::get('category_supplier_' . $shop_supplier_id)) {
            $supplier=(new SupplierModel)->detail($shop_supplier_id);
            $where=[$shop_supplier_id]
            $where=[$shop_supplier_id];
            if($supplier['is_newcomer']||$supplier['is_repurchase']||$supplier['is_vip']){
                $where=[0,$shop_supplier_id]
                $where=[0,$shop_supplier_id];
            }
            $data = $model->with(['images'])
                ->where('shop_supplier_id','in',$where)
agent_vue/src/api/statistics.js
@@ -3,47 +3,47 @@
let StatisticsApi = {
  /*订单数据统计*/
  getOrderTotal(data, errorback) {
    return request._post('/region/statistics.sales/index', data, errorback);
    return request._post('/shop/statistics.sales/index', data, errorback);
  },
  /*订单时间段统è®?/
  /*订单时间段统计*/
  getOrderByDate(data, errorback) {
    return request._post('/region/statistics.sales/order', data, errorback);
    return request._post('/shop/statistics.sales/order', data, errorback);
  },
  /*商品时间段统è®?/
  /*商品时间段统计*/
  getProductByDate(data, errorback) {
    return request._post('/region/statistics.sales/product', data, errorback);
    return request._post('/shop/statistics.sales/product', data, errorback);
  },
  /*会员数据统计*/
  getUserTotal(data, errorback) {
    return request._post('/region/statistics.user/index', data, errorback);
    return request._post('/shop/statistics.user/index', data, errorback);
  },
  /*成交占比*/
  getUserScale(data, errorback) {
    return request._post('/region/statistics.user/scale', data, errorback);
    return request._post('/shop/statistics.user/scale', data, errorback);
  },
  /*新增会员*/
  getNewUser(data, errorback) {
    return request._post('/region/statistics.user/new_user', data, errorback);
    return request._post('/shop/statistics.user/new_user', data, errorback);
  },
  /*成交会员æ•?/
  /*成交会员数*/
  getPayUser(data, errorback) {
    return request._post('/region/statistics.user/pay_user', data, errorback);
    return request._post('/shop/statistics.user/pay_user', data, errorback);
  },
  /*供应商统è®?/
  /*供应商统计*/
  getSupplierTotal(data, errorback) {
    return request._post('/region/statistics.supplier/index', data, errorback);
    return request._post('/shop/statistics.supplier/index', data, errorback);
  },
  /*供应商时间段统计*/
  getSupplierByDate(data, errorback) {
    return request._post('/region/statistics.supplier/data', data, errorback);
    return request._post('/shop/statistics.supplier/data', data, errorback);
  },
  /*访问统计*/
  getAccessTotal(data, errorback) {
    return request._post('/region/statistics.access/index', data, errorback);
    return request._post('/shop/statistics.access/index', data, errorback);
  },
  /*访问时间段统è®?/
  /*访问时间段统计*/
  getAccessByDate(data, errorback) {
    return request._post('/region/statistics.access/data', data, errorback);
    return request._post('/shop/statistics.access/data', data, errorback);
  },
}
agent_vue/src/filters/index.js
@@ -5,7 +5,7 @@
    return 'vip'+val;
  },
    /*判断字段是否为空,为空的话先è¯?*/
    /*判断字段是否为空,为空的话先说-*/
    isNull:function(val){
        if(val==null||val==undefined||val===""||val==="null"||val=='undefined'){
@@ -18,7 +18,7 @@
        }
    },
    /*百分æ¯?/
    /*百分比*/
    returnPercentage:function(val){
        if(val!==null&&val!==''&&val!==undefined){
            let num=(val*100).toFixed(2);
@@ -28,7 +28,7 @@
        }
    },
    /*小数点后面保留位æ•?/
    /*小数点后面保留位数*/
    returnToFixed:function(val,num){
        if(val!=null){
            let nums=val.toFixed(num);
@@ -42,7 +42,7 @@
        }
    },
    /*取万å…?/
    /*取万元*/
    tenThousand:function(val){
        if(val!=null&&val!=''){
            var x=(val/10000).toFixed(2);
@@ -54,7 +54,7 @@
        }
    },
    /*数字换成å‘?/
    /*数字换成周*/
    numTabWeek: function(val) {
        let ch = '';
@@ -63,22 +63,22 @@
                ch = '一';
                break;
            case 2:
                ch = 'äº?;
                ch = '二';
                break;
            case 3:
                ch = 'ä¸?;
                ch = '三';
                break;
            case 4:
                ch = 'å›?;
                ch = '四';
                break;
            case 5:
                ch = 'äº?;
                ch = '五';
                break;
            case 6:
                ch = 'å…?;
                ch = '六';
                break;
            case 7:
                ch = 'æ—?;
                ch = '日';
                break;
        }
        return ch;
@@ -90,10 +90,10 @@
        let sex = '';
        switch(num) {
            case 0:
                sex = 'å¥?;
                sex = '女';
                break;
            case 1:
                sex= 'ç”?;
                sex= '男';
                break;
            default:
                sex = '其他';
@@ -110,7 +110,7 @@
      }
  },
  
  /*判断有没有空æ ?/
  /*判断有没有空格*/
  hasSpace:function(val){
      if(val!=undefined){
          let patt=/\s/g;
@@ -130,7 +130,7 @@
      }
  },
  
  /*判断字符串是否全是空æ ?/
  /*判断字符串是否全是空格*/
  isAllSpace(val){
      if(val.match(/^[ ]*$/)){
          return true;
agent_vue/src/permission.js
@@ -14,7 +14,7 @@
} from '@/utils/base'
 const whiteList = ['/login', '/test', '/fonticon']
// åœ¨æ¯ä¸ªè·¯ç”±ç”Ÿæ•ˆä¹‹å‰ï¼Œå…ˆè¿›è¡Œä¸€äº›å¤„理,请参è€?vue-router官方文档-导航钩子
// 在每个路由生效之前,先进行一些处理,请参考 vue-router官方文档-导航钩子
router.beforeEach((to, from, next) => {
  const isLogin = getCookie('isLogin');
agent_vue/src/router/index.js
@@ -151,7 +151,7 @@
      }
    ]
  },
  /*----代理商列è¡?---*/
  /*----代理商列表----*/
  {
    path: '/agent',
    redirect: { name: 'agent_Index' },
@@ -166,7 +166,7 @@
        path: 'Index',
        name: 'agent_Index',
        meta: {
          title: '代理商管ç?
          title: '代理商管理'
        },
        component: () =>
          import('@/views/agent/Index')
agent_vue/src/store/index.js
@@ -67,7 +67,7 @@
  generateRoutes: async function(context, str) {
    /*返回理由*/
    return new Promise((resolve, reject) => {
      /*判断本地缓存是否有菜单数æ?/
      /*判断本地缓存是否有菜单数据*/
        if(res.status&&res.data){
            let temps=null;
            let accessRoutes=temps.concat(menu);
agent_vue/src/utils/base.js
@@ -38,7 +38,7 @@
}
/*
 * é€šè¿‡å‚数获取sessionStorage的数æ?
 * 通过参数获取sessionStorage的数据
 */
export const getSessionStorage = (name) => {
    if(sessionStorage.hasOwnProperty(name)) {
@@ -49,7 +49,7 @@
}
/*
 * é™„加sessionStorage, type==true åˆ™æ˜¯æ•´ä¸ªä¿®æ”¹ï¼?
 * 附加sessionStorage, type==true 则是整个修改,
 */
export const addSessionStorage = (name, val) => {
    if(sessionStorage.hasOwnProperty(name)) {
@@ -80,7 +80,7 @@
}
/*
 * é€šè¿‡å‚数获取localStorage的数æ?
 * 通过参数获取localStorage的数据
 */
export const getLocalStorage = (name) => {
    if(localStorage.hasOwnProperty(name)) {
@@ -91,7 +91,7 @@
}
/*
 * é™„加localStorage, type==true åˆ™æ˜¯æ•´ä¸ªä¿®æ”¹ï¼?
 * 附加localStorage, type==true 则是整个修改,
 */
export const addLocalStorage = (name, val) => {
    if(localStorage.hasOwnProperty(name)) {
@@ -115,7 +115,7 @@
}
/*
 *深拷è´?
 *深拷贝
 */
export const deepClone = (obj) => {
  var objClone = Array.isArray(obj) ? [] : {};
@@ -135,7 +135,7 @@
/*
 *深合å¹?
 *深合并
 */
export const deepMerger = (obj1, obj2) => {
  for (var key in obj2) {
agent_vue/src/utils/request.js
@@ -8,29 +8,29 @@
import { delCookie } from '@/utils/base.js';
//axios.defaults.timeout = 5000;                        //响应时间
axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'; //配置请求å¤?
axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'; //配置请求头
//axios.defaults.baseURL = 'http://www.jjj-shop.com/';   //配置接口地址
axios.defaults.baseURL = '/index.php'; //配置接口地址
axios.defaults.withCredentials = true;
axios.defaults.responseType = 'json';
//POST传参序列åŒ?添加请求拦截å™?
//POST传参序列化(添加请求拦截器)
axios.interceptors.request.use((config) => {
  //在发送请求之前做某件äº?
  //在发送请求之前做某件事
  if (config.method === 'post') {
    config.data = qs.stringify(config.data);
  }
  return config;
}, (error) => {
  console.log('错误的传å?)
  console.log('错误的传参')
  return Promise.reject(error);
});
//返回状态判æ–?添加响应拦截å™?
//返回状态判断(添加响应拦截器)
axios.interceptors.response.use((res) => {
  //未登é™?
  //未登陆
  if (res.data.code !== 1) {
    console.log('未登录状æ€?)
    console.log('未登录状态')
    if(res.data.code===0){
      Message({
        showClose: true,
mobile/pages.json
@@ -1606,6 +1606,47 @@
                            //#endif
                        }
                    }
                },{
                    "path": "operations/index",
                    "style": {
                        "navigationStyle": "custom",
                        "navigationBarTitleText": "运营中心",
                        "app-plus": {
                            //#ifdef H5
                            "titleNView": false
                            //#endif
                        }
                    }
                }, {
                    "path": "operations/cash/apply",
                    "style": {
                        "navigationBarTitleText": "提现申请",
                        "app-plus": {
                            //#ifdef H5
                            "titleNView": false
                            //#endif
                        }
                    }
                }, {
                    "path": "operations/cash/list",
                    "style": {
                        "navigationBarTitleText": "提现明细",
                        "app-plus": {
                            //#ifdef H5
                            "titleNView": false
                            //#endif
                        }
                    }
                }, {
                    "path": "operations/order",
                    "style": {
                        "navigationBarTitleText": "运营中心订单",
                        "app-plus": {
                            //#ifdef H5
                            "titleNView": false
                            //#endif
                        }
                    }
                }
            ]
        },
mobile/pages/plus/business/add.vue
@@ -1,244 +1,293 @@
<template>
    <view>
    <template>
        <view>
        <form @submit="add">
            <view
                style="display: flex;justify-content: center;position: relative;overflow: hidden;border-radius: 30rpx;"
                v-for="(item,index) in templateList" v-if="item.template_id==template_id" :key="index">
                <view v-for="(item,index) in item.style.icon" :key="index"
                    :style="'position:absolute;display: flex;left:'+item.left+'px;top:'+item.top+'px;width:'+item.width+'px;height:'+item.height+'px;'">
                    <image :src="item.src" :style="'width:'+item.width+'px;height:'+item.height+'px;'"></image>
                </view>
                <view v-for="(item,index) in item.style.address" :key="index"
                    :style="'position:absolute;left:'+item.left+'px;top:'+item.top+'px;color:'+item.color+';font-size:'+item.fontSize+'px;'">
                    地址:{{(business.address[index]||selectCity!='选择省 市 区')?(selectCity!='选择省 市 区'?selectCity:'')+business.address[index]:'未填写地址'}}
                </view>
                <view v-for="(item,index) in item.style.unit" :key="index"
                    :style="'position:absolute;left:'+item.left+'px;top:'+item.top+'px;color:'+item.color+';font-size:'+item.fontSize+'px;'">
                    {{business.unit[index]?business.unit[index]:'未填写公司'}}
                </view>
                <!-- <view v-for="(item,index) in item.style.position" :key="index"
                    :style="'position:absolute;left:'+item.left+'px;top:'+item.top+'px;color:'+item.color+';font-size:'+item.fontSize+'px;'">
                    {{business.position[index]?business.position[index]:'未填职位'}}
                </view> -->
                <view
                    :style="'position:absolute;left:'+item.style.duties[0].left+'px;top:'+item.style.duties[0].top+'px;color:'+item.style.duties[0].color+';font-size:'+item.style.duties[0].fontSize+'px;'">
                    {{business.duties[0]?business.duties[0]:'未填写职位'}}
                </view>
                <view v-if="business.mailbox"
                    :style="'position:absolute;left:'+item.style.mailbox.left+'px;top:'+item.style.mailbox.top+'px;color:'+item.style.mailbox.color+';font-size:'+item.style.mailbox.fontSize+'px;'">
                    邮箱:{{business.mailbox?business.mailbox:'未填写邮箱'}}
                </view>
                <view
                    :style="'position:absolute;left:'+item.style.mobile.left+'px;top:'+item.style.mobile.top+'px;color:'+item.style.mobile.color+';font-size:'+item.style.mobile.fontSize+'px;'">
                    手机:{{business.mobile?business.mobile:'未填写手机'}}{{business.mobile_phone?' / '+business.mobile_phone:''}}
                </view>
                <view
                    :style="'position:absolute;left:'+item.style.wechat.left+'px;top:'+item.style.wechat.top+'px;color:'+item.style.wechat.color+';font-size:'+item.style.wechat.fontSize+'px;'">
                    微信:{{business.wechat?business.wechat:'未填写微信'}}
                </view>
                <view
                    :style="'position:absolute;left:'+item.style.name.left+'px;top:'+item.style.name.top+'px;color:'+item.style.name.color+';font-size:'+item.style.name.fontSize+'px;'">
                    {{business.name?business.name:'未填写姓名'}}
                </view>
                <view v-if="business.phone"
                    :style="'position:absolute;left:'+item.style.phone.left+'px;top:'+item.style.phone.top+'px;color:'+item.style.phone.color+';font-size:'+item.style.phone.fontSize+'px;'">
                    电话:{{business.phone?business.phone:'未填写电话'}}
                </view>
                <image class="tup"
                    :style="'width:'+item.style.backdrop.width+'px;height:'+item.style.backdrop.height+'px;'"
                    :src="item.style.backdrop.src"></image>
                <view v-if="item.style.avatar.display==1"
                    :style="'position:absolute;left:'+item.style.avatar.left+'px;top:'+item.style.avatar.top+'px;width:'+item.style.avatar.width+'px;height:'+item.style.avatar.width+'px;'+(item.style.avatar.style=='circle'?'border-radius:'+item.style.avatar.width+'px;overflow: hidden;':'overflow: hidden;')">
                    <image :src="file_path?file_path:item.style.avatar.src"
                        :style="'width:'+item.style.avatar.width+'px;height:'+item.style.avatar.width+'px;'">
                    </image>
                </view>
                <view v-if="item.style.logo.display==1" class="logo_h" ref="logo_h"
                    :style="'position:absolute;left:'+item.style.logo.left+'px;top:'+item.style.logo.top+'px;width:'+item.style.logo.width+'px;height:'+item.style.logo.height+'px;'+(item.style.logo.style=='circle'?'border-radius:'+item.style.logo.width+'px;overflow: hidden;':'overflow: hidden;')">
                    <image :src="logo_path?logo_path:item.style.logo.src" class="logo_h" ref="logo_h"></image>
                </view>
            <!-- 名片预览区域 -->
            <view class="business-card-preview"
                v-for="(templateItem,templateIndex) in templateList" v-if="templateItem.template_id==template_id" :key="templateIndex">
            <!-- 图标装饰 -->
            <view v-for="(item,index) in templateItem.style.icon" :key="index"
                class="card-icon"
                :style="{position:'absolute',display:'flex',left:item.left+'px',top:item.top+'px',width:item.width+'px',height:item.height+'px'}">
                <image :src="item.src" :style="{width:item.width+'px',height:item.height+'px'}"></image>
            </view>
            <!-- 预览区域 - 支持多个公司和职位 -->
            <scroll-view scroll-y="true" class="card-scroll-unit"
                :style="{position:'absolute',left:(templateItem.style.unit[0].left||0)+'px',top:(templateItem.style.unit[0].top||0)+'px',width:unitWidth+'px',height:unitHeight+'px'}">
                    <view v-for="(companyItem, idx) in business.unit" :key="idx"
                        class="card-text-item"
                        :style="{color:(templateItem.style.unit[0].color||'#333'),fontSize:(templateItem.style.unit[0].fontSize||14)+'px',marginBottom:((templateItem.style.unit[0].fontSize||14)*0.5)+'px'}">
                        {{companyItem||'未填写公司'}}
                    </view>
                </scroll-view>
            <scroll-view scroll-y="true" class="card-scroll-duties"
                :style="{position:'absolute',left:(templateItem.style.duties[0].left||0)+'px',top:(templateItem.style.duties[0].top||0)+'px',width:dutiesWidth+'px',height:dutiesHeight+'px'}">
                    <view v-for="(dutiesItem, idx) in business.duties" :key="idx"
                        class="card-text-item"
                        :style="{color:(templateItem.style.duties[0].color||'#333'),fontSize:(templateItem.style.duties[0].fontSize||14)+'px',lineHeight:1.5,marginBottom:((templateItem.style.duties[0].fontSize||14)*0.5)+'px'}">
                        {{dutiesItem||'未填写职位'}}
                    </view>
                </scroll-view>
            <!-- 地址 -->
            <view v-for="(item,index) in templateItem.style.address" :key="index"
                class="card-text"
                :style="{position:'absolute',left:item.left+'px',top:item.top+'px',color:item.color,fontSize:item.fontSize+'px',maxWidth:addressMaxWidth+'px'}">
                地址:{{(business.address[index]||selectCity!='选择省 市 区')?(selectCity!='选择省 市 区'?selectCity:'')+business.address[index]:'未填写地址'}}
            </view>
            <!-- 邮箱 -->
            <view v-if="business.mailbox"
                class="card-text"
                :style="{position:'absolute',left:templateItem.style.mailbox.left+'px',top:templateItem.style.mailbox.top+'px',color:templateItem.style.mailbox.color,fontSize:templateItem.style.mailbox.fontSize+'px',maxWidth:mailboxMaxWidth+'px'}">
                邮箱:{{business.mailbox?business.mailbox:'未填写邮箱'}}
            </view>
            <!-- 手机 -->
            <view class="card-text"
                :style="{position:'absolute',left:templateItem.style.mobile.left+'px',top:templateItem.style.mobile.top+'px',color:templateItem.style.mobile.color,fontSize:templateItem.style.mobile.fontSize+'px',maxWidth:mobileMaxWidth+'px'}">
                手机:{{business.mobile?business.mobile:'未填写手机'}}{{business.mobile_phone?' / '+business.mobile_phone:''}}
            </view>
            <!-- 微信 -->
            <view class="card-text"
                :style="{position:'absolute',left:templateItem.style.wechat.left+'px',top:templateItem.style.wechat.top+'px',color:templateItem.style.wechat.color,fontSize:templateItem.style.wechat.fontSize+'px',maxWidth:wechatMaxWidth+'px'}">
                微信:{{business.wechat?business.wechat:'未填写微信'}}
            </view>
            <!-- 姓名 -->
            <view class="card-text"
                :style="{position:'absolute',left:templateItem.style.name.left+'px',top:templateItem.style.name.top+'px',color:templateItem.style.name.color,fontSize:templateItem.style.name.fontSize+'px',maxWidth:nameMaxWidth+'px'}">
                {{business.name?business.name:'未填写姓名'}}
            </view>
            <!-- 电话 -->
            <view v-if="business.phone"
                class="card-text"
                :style="{position:'absolute',left:templateItem.style.phone.left+'px',top:templateItem.style.phone.top+'px',color:templateItem.style.phone.color,fontSize:templateItem.style.phone.fontSize+'px',maxWidth:phoneMaxWidth+'px'}">
                电话:{{business.phone?business.phone:'未填写电话'}}
            </view>
            <!-- 背景图 -->
            <image class="tup card-backdrop"
                :style="{width:templateItem.style.backdrop.width+'px',height:templateItem.style.backdrop.height+'px'}"
                :src="templateItem.style.backdrop.src"></image>
            <!-- 头像 -->
            <view v-if="templateItem.style.avatar.display==1"
                class="card-avatar"
                :class="{'avatar-circle': templateItem.style.avatar.style==='circle'}"
                style="position:absolute"
                :style="{left:templateItem.style.avatar.left+'px',top:templateItem.style.avatar.top+'px',width:templateItem.style.avatar.width+'px',height:templateItem.style.avatar.width+'px'}">
                <image :src="file_path?file_path:templateItem.style.avatar.src"
                    :style="{width:templateItem.style.avatar.width+'px',height:templateItem.style.avatar.width+'px'}">
                </image>
            </view>
            <!-- Logo -->
            <view v-if="templateItem.style.logo.display==1"
                class="card-logo"
                :class="{'logo-circle': templateItem.style.logo.style==='circle'}"
                ref="logo_h"
                style="position:absolute"
                :style="{left:templateItem.style.logo.left+'px',top:templateItem.style.logo.top+'px',width:templateItem.style.logo.width+'px',height:templateItem.style.logo.height+'px'}">
                <image :src="logo_path?logo_path:templateItem.style.logo.src" class="logo_h" ref="logo_h"></image>
            </view>
            </view>
            <view class="fds">
                <view>
                    <scroll-view scroll-x="true">
                        <view style="width: 100%;white-space: nowrap;">
                            <view class="mpxz" v-for="(item,index) in templateList" :key="index"
                                @tap="radioChange(index)">
                                <view class="zjc" v-if="item.template_id==template_id">
                <scroll-view scroll-x="true">
                    <view style="width: 100%;white-space: nowrap;">
                        <view class="mpxz" v-for="(item,index) in templateList" :key="index"
                            @tap="radioChange(index)">
                            <view class="zjc" v-if="item.template_id==template_id">
                            </view>
                            <image class="mpxz-image" :src="item.image" mode="aspectFit"></image>
                        </view>
                    </view>
                </scroll-view>
            </view>
            <view class="lxfx">
                <view class="lxfxbiaoti">名片类型:</view>
                <view class="lxfxnrr">
                    <picker @change="changeIlk" :range="ilkList" :range-key="'name'" class="lxfxneirong"
                        mode="selector">
                        <view class="picker-content">
                            {{selectedIlk.name || '请选择名片类型'}}
                            <text class="icon iconfont icon-jiantou"></text>
                        </view>
                        <input style="display: none;" name='ilk' v-model="business.ilk" type="text">
                    </picker>
                </view>
            </view>
            <view class="grxx" @click="is_avatar=true" v-show="avatar_display==1" style="overflow: hidden;">
                <view class="biaoti">
                    头像
                </view>
                <view class="tx" style="margin-left: 30rpx;">
                    <image class="logo" :src="file_path||'@/static/shop/login/qietu_1054.png'" mode="heightFix"></image>
                    <Upload v-if="is_avatar" @getImgs="handleAvatarUpload" :imageList="[file_path]"></Upload>
                </view>
            </view>
            <view @click="is_logo=true" v-show="logo_display==1">
                <view class="biaoti">
                    logo
                </view>
                <view class="logo" style="overflow: hidden;">
                    <image class="logo" :src="logo_path||'@/static/shop/login/qietu_1054.png'" mode="heightFix"></image>
                    <Upload v-if="is_logo" @getImgs="handleLogoUpload" :imageList="[logo_path]"></Upload>
                </view>
            </view>
            <view>
                <view class="biaoti">
                    联系方式
                </view>
                <view>
                    <view class="lxfx">
                        <view class="lxfxbiaoti"><text style="color: #fa3534;">*</text>姓名:</view>
                        <view class="lxfxnrr">
                            <input placeholder="请输入姓名" name='name' v-model="business.name" class="lxfxneirong"
                                type="text">
                        </view>
                    </view>
                    <view class="lxfx">
                        <view class="lxfxbiaoti"><text style="color: #fa3534;">*</text>手机:</view>
                        <view class="lxfxnrr">
                            <input @input="sjh" placeholder="输入手机号" v-model="mobile" class="lxfxneirong"
                                type="text">
                            <input style="display: none;" name="mobile" v-model="business.mobile"
                                class="lxfxneirong" type="text">
                            <input style="display: none;" name="mobile_phone" v-model="business.mobile_phone"
                                class="lxfxneirong" type="text">
                        </view>
                    </view>
                    <view class="lxfx">
                        <view class="lxfxbiaoti">座机:</view>
                        <view class="lxfxnrr"><input placeholder="请输入电话" v-model="business.phone" name="phone"
                                class="lxfxneirong" type="text">
                        </view>
                    </view>
                    <view class="lxfx">
                        <view class="lxfxbiaoti">微信:</view>
                        <view class="lxfxnrr"><input class="lxfxneirong" name="wechat" v-model="business.wechat"
                                placeholder="请输入微信" type="text">
                        </view>
                    </view>
                    <view class="lxfx">
                        <view class="lxfxbiaoti">邮箱:</view>
                        <view class="lxfxnrr"><input class="lxfxneirong" name="mailbox" v-model="business.mailbox"
                                placeholder="请输入邮箱" type="text">
                        </view>
                    </view>
                </view>
            </view>
            <view style="padding-bottom: 300rpx;">
                <view class="biaoti">
                    详细信息
                </view>
                <view>
                    <view v-for="(item,index) in companyList" :key="index" class="company-item">
                        <view class="company-header">
                            <text class="company-title">公司/职位 {{index+1}}</text>
                            <text class="delete-btn" v-if="companyList.length > 1" @tap="deleteCompany(index)">删除</text>
                        </view>
                        <view class="lxfx">
                            <view class="lxfxbiaoti">公司名称:</view>
                            <view class="lxfxnrr">
                                <input placeholder="请输入公司名称" :name="'unit['+index+']'"
                                    v-model="companyList[index].unit" @input="syncBusinessFromCompanyList"
                                    class="lxfxneirong" type="text">
                            </view>
                        </view>
                        <view class="lxfx">
                            <view class="lxfxbiaoti">职位:</view>
                            <view class="lxfxnrr">
                                <input placeholder="请输入职位" :name="'duties['+index+']'"
                                    v-model="companyList[index].duties" @input="syncBusinessFromCompanyList"
                                    class="lxfxneirong" type="text">
                            </view>
                        </view>
                    </view>
                    <view class="add-company-btn" @tap="addCompany">
                        <text class="icon iconfont icon-add"></text>
                        <text>添加公司/职位</text>
                    </view>
                    <view class="lxfx" @tap="industryClose">
                        <view class="lxfxbiaoti">行业:</view>
                        <view class="lxfxnrr">
                            <input class="lxfxneirong" :value="industryNmae" disabled readonly>
                            <input style="display: none;" type="hidden" name="industry_id"
                                v-model="business.industry_id">
                        </view>
                    </view>
                    <view class="lxfx" >
                        <view class="lxfxbiaoti">所在地区:</view>
                        <view class="lxfxnrr">
                            <input class="lxfxneirong" :value="selectCity" disabled="true"
                                @click="chooseLocation" placeholder="请选择省市区">
                            <input style="display: none;" type="hidden" name="province_id"
                                v-model="business.province_id">
                            <input style="display: none;" type="hidden" name="city_id" v-model="business.city_id">
                            <input style="display: none;" type="hidden" name="region_id"
                                v-model="business.region_id">
                        </view>
                    </view>
                    <view class="lxfx" >
                        <view class="lxfxbiaoti"><text style="color: #fa3534;">*</text>地址:</view>
                        <view class="lxfxnrr">
                            <input placeholder="请输入详细地址" name="address[0]" v-model="business.address[0]"
                                class="lxfxneirong" type="text">
                        </view>
                    </view>
                    <view class="lxfx">
                        <view class="lxfxbiaoti">简介:</view>
                        <view class="lxfxnrr">
                            <textarea placeholder="请输入个人或公司简介" maxlength="-1" name="Introduction" v-model="business.Introduction"
                                class="lxfxneirong" :auto-height="true"></textarea>
                        </view>
                    </view>
                </view>
            </view>
            <view class="anu">
                <button form-type="submit" class="tijiao">保存名片</button>
                <input type="text" style="display: none;" name="file_id" :value="file_id">
                <input type="text" style="display: none;" name="logo" :value="logo_id">
                <input type="text" style="display: none;" name="logo_height" :value="logo_height">
                <input type="text" style="display: none;" name="logo_width" :value="logo_width">
                <input type="text" style="display: none;" name="longitude" :value="business.longitude">
                <input type="text" style="display: none;" name="latitude" :value="business.latitude">
            </view>
            <Popup :show="industryShow" :width="screenWidth" type="bottom" :closeable="true" @close="industryClose">
                <view class="industry-popup">
                    <view class="industry-title">选择行业</view>
                    <scroll-view scroll-y="true" style="height: 600rpx;">
                        <!-- 递归展示行业树形结构 -->
                        <view v-for="item in industryList" :key="item.industry_id">
                            <view class="industry-item" @tap="selectIndustry" :data-id="item.industry_id"
                                :class="{ 'selected': business.industry_id == item.industry_id }">
                                {{ item.name }}
                            </view>
                            <!-- 显示子行业 -->
                            <view v-if="item.child && item.child.length > 0" class="industry-child">
                                <view class="industry-item industry-child-item" v-for="child in item.child"
                                    :key="child.industry_id" @tap="selectIndustry" :data-id="child.industry_id"
                                    :class="{ 'selected': business.industry_id == child.industry_id }">
                                    {{ child.name }}
                                </view>
                                <image class="mpxz-image" :src="item.image" mode="aspectFit"></image>
                            </view>
                        </view>
                    </scroll-view>
                </view>
                <view class="lxfx">
                    <view class="lxfxbiaoti">名片类型:</view>
                    <view class="lxfxnrr">
                        <picker @change="changeIlk" :range="ilkList" :range-key="'name'" class="lxfxneirong"
                            mode="selector">
                            <view class="picker-content">
                                {{selectedIlk.name || '请选择名片类型'}}
                                <text class="icon iconfont icon-jiantou"></text>
                            </view>
                            <input style="display: none;" name='ilk' v-model="business.ilk" type="text">
                        </picker>
                    </view>
                </view>
                <view class="grxx" @click="is_avatar=true" v-show="avatar_display==1" style="overflow: hidden;">
                    <view class="biaoti">
                        头像
                    </view>
                    <view class="tx" style="margin-left: 30rpx;">
                        <image class="logo" :src="file_path||'@/static/shop/login/qietu_1054.png'" mode="heightFix"></image>
                        <Upload v-if="is_avatar" @getImgs="handleAvatarUpload" :imageList="[file_path]"></Upload>
                    </view>
                </view>
                <view @click="is_logo=true" v-show="logo_display==1">
                    <view class="biaoti">
                        logo
                    </view>
                    <view class="logo" style="overflow: hidden;">
                        <image class="logo" :src="logo_path||'@/static/shop/login/qietu_1054.png'" mode="heightFix"></image>
                        <Upload v-if="is_logo" @getImgs="handleLogoUpload" :imageList="[logo_path]"></Upload>
                    </view>
                </view>
                <view>
                    <view class="biaoti">
                        联系方式
                    </view>
                    <view>
                        <view class="lxfx">
                            <view class="lxfxbiaoti"><text style="color: #fa3534;">*</text>姓名:</view>
                            <view class="lxfxnrr">
                                <input placeholder="请输入姓名" name='name' v-model="business.name" class="lxfxneirong"
                                    type="text">
                            </view>
                        </view>
                        <view class="lxfx">
                            <view class="lxfxbiaoti"><text style="color: #fa3534;">*</text>手机:</view>
                            <view class="lxfxnrr">
                                <input @input="sjh" placeholder="输入手机号" v-model="mobile" class="lxfxneirong"
                                    type="text">
                                <input style="display: none;" name="mobile" v-model="business.mobile"
                                    class="lxfxneirong" type="text">
                                <input style="display: none;" name="mobile_phone" v-model="business.mobile_phone"
                                    class="lxfxneirong" type="text">
                            </view>
                        </view>
                        <view class="lxfx">
                            <view class="lxfxbiaoti">座机:</view>
                            <view class="lxfxnrr"><input placeholder="请输入电话" v-model="business.phone" name="phone"
                                    class="lxfxneirong" type="text">
                            </view>
                        </view>
                        <view class="lxfx">
                            <view class="lxfxbiaoti">微信:</view>
                            <view class="lxfxnrr"><input class="lxfxneirong" name="wechat" v-model="business.wechat"
                                    placeholder="请输入微信" type="text">
                            </view>
                        </view>
                        <view class="lxfx">
                            <view class="lxfxbiaoti">邮箱:</view>
                            <view class="lxfxnrr"><input class="lxfxneirong" name="mailbox" v-model="business.mailbox"
                                    placeholder="请输入邮箱" type="text">
                            </view>
                        </view>
                    </view>
                </view>
                <view style="padding-bottom: 120rpx;">
                    <view class="biaoti">
                        详细信息
                    </view>
                    <view>
                        <view v-for="(item,index) in unit" :key="index">
                            <view class="lxfx">
                                <view class="lxfxbiaoti">单位名称:</view>
                                <view class="lxfxnrr">
                                    <input placeholder="请输入单位名称" :name="'unit['+index+']'"
                                        v-model="business.unit[index]" class="lxfxneirong" type="text">
                                </view>
                            </view>
                            <view class="lxfx">
                                <view class="lxfxbiaoti">职位:</view>
                                <view class="lxfxnrr">
                                    <input placeholder="请输入职位" :name="'duties['+index+']'"
                                        v-model="business.duties[index]" class="lxfxneirong" type="text">
                                </view>
                            </view>
                        </view>
                        <view class="lxfx" @tap="industryClose">
                            <view class="lxfxbiaoti">行业:</view>
                            <view class="lxfxnrr">
                                <input class="lxfxneirong" :value="industryNmae" disabled readonly>
                                <input style="display: none;" type="hidden" name="industry_id"
                                    v-model="business.industry_id">
                            </view>
                        </view>
                        <view class="lxfx" >
                            <view class="lxfxbiaoti">所在地区:</view>
                            <view class="lxfxnrr">
                                <input class="lxfxneirong" :value="selectCity" disabled="true"
                                    @click="chooseLocation" placeholder="请选择省市区">
                                <input style="display: none;" type="hidden" name="province_id"
                                    v-model="business.province_id">
                                <input style="display: none;" type="hidden" name="city_id" v-model="business.city_id">
                                <input style="display: none;" type="hidden" name="region_id"
                                    v-model="business.region_id">
                            </view>
                        </view>
                        <view class="lxfx" >
                            <view class="lxfxbiaoti"><text style="color: #fa3534;">*</text>地址:</view>
                            <view class="lxfxnrr">
                                <input placeholder="请输入详细地址" name="address[0]" v-model="business.address[0]"
                                    class="lxfxneirong" type="text">
                            </view>
                        </view>
                        <view class="lxfx">
                            <view class="lxfxbiaoti">简介:</view>
                            <view class="lxfxnrr">
                                <textarea placeholder="请输入个人或公司简介" name="Introduction" v-model="business.Introduction"
                                    class="lxfxneirong" :auto-height="true"></textarea>
                            </view>
                        </view>
                    </view>
                </view>
                <view class="anu">
                    <button form-type="submit" class="tijiao">保存名片</button>
                    <input type="text" style="display: none;" name="file_id" :value="file_id">
                    <input type="text" style="display: none;" name="logo" :value="logo_id">
                    <input type="text" style="display: none;" name="logo_height" :value="logo_height">
                    <input type="text" style="display: none;" name="logo_width" :value="logo_width">
                    <input type="text" style="display: none;" name="longitude" :value="business.longitude">
                    <input type="text" style="display: none;" name="latitude" :value="business.latitude">
                </view>
                <Popup :show="industryShow" :width="screenWidth" type="bottom" :closeable="true" @close="industryClose">
                    <view class="industry-popup">
                        <view class="industry-title">选择行业</view>
                        <scroll-view scroll-y="true" style="height: 600rpx;">
                            <!-- 递归展示行业树形结构 -->
                            <view v-for="item in industryList" :key="item.industry_id">
                                <view class="industry-item" @tap="selectIndustry" :data-id="item.industry_id"
                                    :class="{ 'selected': business.industry_id == item.industry_id }">
                                    {{ item.name }}
                                </view>
                                <!-- 显示子行业 -->
                                <view v-if="item.child && item.child.length > 0" class="industry-child">
                                    <view class="industry-item industry-child-item" v-for="child in item.child"
                                        :key="child.industry_id" @tap="selectIndustry" :data-id="child.industry_id"
                                        :class="{ 'selected': business.industry_id == child.industry_id }">
                                        {{ child.name }}
                                    </view>
                                </view>
                            </view>
                        </scroll-view>
                    </view>
                </Popup>
                <mpvue-city-picker v-if="is_load" ref="mpvueCityPicker" :province="province" :city="city" :area="area"
                    :pickerValueDefault="cityPickerValueDefault" @onConfirm="onConfirm"></mpvue-city-picker>
            </view>
        </form>
    </view>
            </Popup>
            <mpvue-city-picker v-if="is_load" ref="mpvueCityPicker" :province="province" :city="city" :area="area"
                :pickerValueDefault="cityPickerValueDefault" @onConfirm="onConfirm"></mpvue-city-picker>
        </view>
    </form>
</view>
</template>
<script>
@@ -296,6 +345,8 @@
                logo_height: 0, // Logo高度
                logo_width: 0, // Logo宽度
                avatar_width: 0, // 头像宽度
                // 公司职位列表
                companyList: [], // 公司职位列表
                // 显示控制
                avatar_display: 1, // 头像显示状态
                logo_display: 1, // Logo显示状态
@@ -327,6 +378,9 @@
                })
                this.business_card_id = e.business_card_id
                this.getBusiness(e.business_card_id)
            } else {
                // 新增时默认添加一个公司职位
                this.addCompany();
            }
            this.getTemplate();
            this.getIndustryList();
@@ -334,7 +388,201 @@
            // 初始化区域选择器数据
            this.initRegionData();
        },
        computed: {
            // 计算公司列表高度
            unitHeight() {
                const fontSize = (this.templateList.find(t => t.template_id === this.template_id)?.style?.unit?.[0]?.fontSize) || 14;
                const lineHeight = fontSize * 1.5; // 行高 = 字体大小 * 1.5
                const lineSpacing = fontSize * 0.5; // 行间距 = 字体大小 * 0.5
                const itemCount = this.business.unit ? this.business.unit.length : 0;
                // 估算高度:每个公司可能占用最多3行,乘以行高,加上行间距,再加上padding
                const estimatedLinesPerItem = 3;
                const height = (lineHeight * estimatedLinesPerItem + lineSpacing) * itemCount + 20;
                return Math.max(height, 80); // 确保最小高度为80px
            },
            // 计算职位列表高度
            dutiesHeight() {
                const fontSize = (this.templateList.find(t => t.template_id === this.template_id)?.style?.duties?.[0]?.fontSize) || 14;
                const lineHeight = fontSize * 1.5; // 行高 = 字体大小 * 1.5
                const lineSpacing = fontSize * 0.5; // 行间距 = 字体大小 * 0.5
                const itemCount = this.business.duties ? this.business.duties.length : 0;
                // 估算高度:每个职位可能占用最多3行,乘以行高,加上行间距,再加上padding
                const estimatedLinesPerItem = 3;
                const height = (lineHeight * estimatedLinesPerItem + lineSpacing) * itemCount + 20;
                return Math.max(height, 80); // 确保最小高度为80px
            },
            // 计算公司容器的合适宽度(智能判断右边是否有其他字段)
            unitWidth() {
                const template = this.templateList.find(t => t.template_id === this.template_id);
                if (!template || !template.style?.unit?.[0]) return 150;
                return this.calculateFieldMaxWidth(template.style.unit[0].left, template.style.unit[0].top);
            },
            // 计算职位容器的合适宽度(智能判断右边是否有其他字段)
            dutiesWidth() {
                const template = this.templateList.find(t => t.template_id === this.template_id);
                if (!template || !template.style?.duties?.[0]) return 150;
                return this.calculateFieldMaxWidth(template.style.duties[0].left, template.style.duties[0].top);
            },
            // 地址字段的最大宽度
            addressMaxWidth() {
                const template = this.templateList.find(t => t.template_id === this.template_id);
                if (!template || !template.style?.address?.[0]) return 200;
                return this.calculateFieldMaxWidth(template.style.address[0].left, template.style.address[0].top);
            },
            // 邮箱字段的最大宽度
            mailboxMaxWidth() {
                const template = this.templateList.find(t => t.template_id === this.template_id);
                if (!template || !template.style?.mailbox) return 200;
                return this.calculateFieldMaxWidth(template.style.mailbox.left, template.style.mailbox.top);
            },
            // 手机字段的最大宽度
            mobileMaxWidth() {
                const template = this.templateList.find(t => t.template_id === this.template_id);
                if (!template || !template.style?.mobile) return 200;
                return this.calculateFieldMaxWidth(template.style.mobile.left, template.style.mobile.top);
            },
            // 微信字段的最大宽度
            wechatMaxWidth() {
                const template = this.templateList.find(t => t.template_id === this.template_id);
                if (!template || !template.style?.wechat) return 200;
                return this.calculateFieldMaxWidth(template.style.wechat.left, template.style.wechat.top);
            },
            // 姓名字段的最大宽度
            nameMaxWidth() {
                const template = this.templateList.find(t => t.template_id === this.template_id);
                if (!template || !template.style?.name) return 200;
                return this.calculateFieldMaxWidth(template.style.name.left, template.style.name.top);
            },
            // 电话字段的最大宽度
            phoneMaxWidth() {
                const template = this.templateList.find(t => t.template_id === this.template_id);
                if (!template || !template.style?.phone) return 200;
                return this.calculateFieldMaxWidth(template.style.phone.left, template.style.phone.top);
            }
        },
        watch: {
            // 监听companyList变化,同步到business对象
            // 不使用deep监听,只在数组引用变化时同步
            // 这样可以避免深度监听导致的多次同步
            companyList: {
                handler(newVal, oldVal) {
                    if (newVal && newVal.length > 0) {
                        this.syncBusinessFromCompanyList();
                    }
                }
            }
        },
        methods: {
            // 智能计算文本字段的最大宽度(供computed调用)
            // 根据右边是否有其他字段来动态计算maxWidth
            calculateFieldMaxWidth(left, top) {
                const template = this.templateList.find(t => t.template_id === this.template_id);
                if (!template || !template.style?.backdrop) return 200;
                const backdropWidth = template.style.backdrop.width || 375;
                const rightFields = [];
                // 收集所有可能的字段
                const fields = [];
                // 公司
                if (template.style.unit && template.style.unit[0]) {
                    fields.push({
                        name: 'unit',
                        left: template.style.unit[0].left,
                        top: template.style.unit[0].top,
                        width: template.style.unit[0].width
                    });
                }
                // 职位
                if (template.style.duties && template.style.duties[0]) {
                    fields.push({
                        name: 'duties',
                        left: template.style.duties[0].left,
                        top: template.style.duties[0].top,
                        width: template.style.duties[0].width
                    });
                }
                // 姓名
                if (template.style.name) {
                    fields.push({
                        name: 'name',
                        left: template.style.name.left,
                        top: template.style.name.top,
                        width: template.style.name.width
                    });
                }
                // 地址
                if (template.style.address && template.style.address[0]) {
                    fields.push({
                        name: 'address',
                        left: template.style.address[0].left,
                        top: template.style.address[0].top,
                        width: template.style.address[0].width
                    });
                }
                // 邮箱
                if (template.style.mailbox) {
                    fields.push({
                        name: 'mailbox',
                        left: template.style.mailbox.left,
                        top: template.style.mailbox.top,
                        width: template.style.mailbox.width
                    });
                }
                // 手机
                if (template.style.mobile) {
                    fields.push({
                        name: 'mobile',
                        left: template.style.mobile.left,
                        top: template.style.mobile.top,
                        width: template.style.mobile.width
                    });
                }
                // 微信
                if (template.style.wechat) {
                    fields.push({
                        name: 'wechat',
                        left: template.style.wechat.left,
                        top: template.style.wechat.top,
                        width: template.style.wechat.width
                    });
                }
                // 电话
                if (template.style.phone) {
                    fields.push({
                        name: 'phone',
                        left: template.style.phone.left,
                        top: template.style.phone.top,
                        width: template.style.phone.width
                    });
                }
                // 找出右边最近的字段
                // 判断标准: left > 当前left, 且top在合理范围内(±20px)
                const TOLERANCE = 20;
                for (let field of fields) {
                    if (field.left > left && Math.abs(field.top - top) <= TOLERANCE) {
                        rightFields.push(field);
                    }
                }
                // 如果右边有字段,取最近的一个的左边距
                if (rightFields.length > 0) {
                    rightFields.sort((a, b) => a.left - b.left);
                    return Math.max(rightFields[0].left - left, 50);
                }
                // 如果右边没有字段,使用名片边缘
                return Math.max(backdropWidth - left - 10, 100);
            },
            // 打开地图选择地址 by lyzflash
            chooseLocation(n) {
                let self=this;
@@ -482,10 +730,13 @@
            },
            getTemplate() {
                let _this = this;
                const systemInfo = uni.getSystemInfoSync()
                this.screenWidth = systemInfo.screenWidth * 2 - 70;
                const systemInfo = uni.getSystemInfoSync();
                // 使用实际屏幕宽度减去左右边距 (20rpx * 2 = 40rpx = 20px)
                const displayWidth = systemInfo.screenWidth - 20;
                this.screenWidth = displayWidth * 2; // 保存为rpx宽度
                this._post('plus.business.template/getList', {
                    screenWidth: systemInfo.screenWidth
                    screenWidth: displayWidth // 传递实际显示宽度(px)
                }, res => {
                    this.templateList = res.data;
                    this.template_id ? '' : this.template_id = this.templateList[0].template_id
@@ -526,6 +777,10 @@
                        this.template_id = res.data.template_id;
                        this.unit = res.data.unit;
                        this.position = res.data.position;
                        // 初始化公司职位列表
                        this.initCompanyList();
                        this.mobile = this.business.mobile + (this.business.mobile_phone ? '/' + this.business
                            .mobile_phone : '');
                        this.business.duties.forEach(function(item, index) {
@@ -623,13 +878,61 @@
                this.is_business = templateList.style.is_business;
            },
            // 初始化公司职位列表
            initCompanyList() {
                let unitLength = Array.isArray(this.business.unit) ? this.business.unit.length : 0;
                if (unitLength > 0) {
                    // 根据现有数据生成公司职位列表
                    this.companyList = [];
                    for (let i = 0; i < unitLength; i++) {
                        this.companyList.push({
                            unit: this.business.unit[i] || '',
                            duties: this.business.duties[i] || ''
                        });
                    }
                } else {
                    // 如果没有数据,至少添加一个
                    this.companyList = [{ unit: '', duties: '' }];
                }
                // 不在这里调用syncBusinessFromCompanyList,因为watch会自动同步
                // 这样可以避免数据被意外重置
            },
            // 添加公司职位
            addCompany() {
                this.companyList.push({
                    unit: '',
                    duties: ''
                });
                // 移除syncBusinessFromCompanyList调用,watch会处理
            },
            // 删除公司职位
            deleteCompany(index) {
                if (this.companyList.length <= 1) {
                    this.showError('至少保留一个公司/职位');
                    return;
                }
                this.companyList.splice(index, 1);
                // 移除syncBusinessFromCompanyList调用,watch会处理
            },
            // 从公司职位列表同步到business对象
            syncBusinessFromCompanyList() {
                if (this.companyList && this.companyList.length > 0) {
                    this.business.unit = this.companyList.map(item => item.unit);
                    this.business.duties = this.companyList.map(item => item.duties);
                }
            }
        }
    }
</script>
<style>
    .lxfx {
        height: 100rpx;
        min-height: 100rpx;
        align-items: center;
        display: flex;
        border-bottom: #dce3ec 1rpx solid;
@@ -749,6 +1052,75 @@
        border-radius: 30rpx;
    }
    /* 名片预览样式优化 */
    .business-card-preview {
        position: sticky;
        top: 0;
        z-index: 99999;
        overflow: visible;
        border-radius: 30rpx;
        margin: 20rpx;
        background-color: #f5f5f5;
        width: calc(100% - 40rpx);
        min-height: 450rpx;
    }
    .card-backdrop {
        border-radius: 30rpx;
    }
    .card-icon {
        z-index: 10;
    }
    .card-text {
        white-space: normal;
        word-break: break-word;
        word-wrap: break-word;
        overflow-wrap: break-word;
        overflow: hidden;
        max-width: 100%;
        line-height: 1.5;
    }
    .card-scroll-unit,
    .card-scroll-duties {
        overflow: hidden;
        overflow-y: auto;
        background-color: transparent;
        box-sizing: border-box;
    }
    .card-text-item {
        word-break: break-word;
        word-wrap: break-word;
        overflow-wrap: break-word;
        white-space: normal;
        padding: 2px 4px;
        line-height: 1.5;
        margin-bottom: 4px; /* 行间距 */
    }
    .card-avatar,
    .card-logo {
        overflow: hidden;
    }
    .card-avatar.avatar-circle {
        border-radius: 50%;
    }
    .card-logo.logo-circle {
        border-radius: 50%;
    }
    .card-avatar image,
    .card-logo image {
        width: 100%;
        height: 100%;
        object-fit: cover;
    }
    .picker-content {
        display: flex;
        justify-content: space-between;
@@ -809,4 +1181,53 @@
        font-size: 30rpx;
        color: #666;
    }
    /* 公司职位样式 */
    .company-item {
        background-color: #f9f9f9;
        border-radius: 12rpx;
        padding: 20rpx;
        margin-bottom: 20rpx;
    }
    .company-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 16rpx;
        padding-bottom: 12rpx;
        border-bottom: 1rpx solid #e5e5e5;
    }
    .company-title {
        font-size: 28rpx;
        font-weight: bold;
        color: #333;
    }
    .delete-btn {
        font-size: 26rpx;
        color: #fa3534;
        padding: 4rpx 12rpx;
        background-color: rgba(250, 53, 52, 0.1);
        border-radius: 4rpx;
    }
    .add-company-btn {
        display: flex;
        align-items: center;
        justify-content: center;
        padding: 24rpx;
        margin-top: 20rpx;
        border: 2rpx dashed #D41003;
        border-radius: 12rpx;
        color: #D41003;
        font-size: 28rpx;
        background-color: rgba(212, 16, 3, 0.05);
    }
    .add-company-btn .icon {
        margin-right: 8rpx;
        font-size: 32rpx;
    }
</style>
mobile/pages/plus/business/detail.vue
@@ -194,7 +194,7 @@
                } else {
                    this.showError('暂未填写微信');
                }
            },
            },/*
            // 通过聊天联系
            contactWithChat() {
                console.log(this.businessInfo);
@@ -203,7 +203,7 @@
                uni.navigateTo({
                    url: `/pages/plus/business/chat/chat?user_id=${this.businessInfo.user_id}&business_card_id=${this.business_card_id}&nickName=${this.businessInfo.name}`
                });
            },
            }, */
            // 打开地图
            openLocation(businessInfo) {
                let address = businessInfo.region.province + ' ' + businessInfo.region.city + ' ' + businessInfo.region
@@ -498,6 +498,13 @@
                font-size: 28rpx;
                color: #666;
                line-height: 1.6;
                white-space: normal;
                word-break: break-word;
                word-wrap: break-word;
                overflow-wrap: break-word;
                overflow: hidden;
                max-width: 100%;
                line-height: 1.4;
            }
        }
    }
mobile/pages/plus/business/index.vue
@@ -3,7 +3,7 @@
        <!-- 名片展示区域 -->
        <view class="content">
            <view class="business-card">
                <image style="width: 100%;" @tap="viewPicture(businessImage)" mode="widthFix" :src="businessImage">
                <image class="card-image" @tap="viewPicture(businessImage)" mode="widthFix" :src="businessImage">
                </image>
            </view>
@@ -65,8 +65,10 @@
                            <uni-swipe-action-item :right-options="rightOptions" @click="handleDel(index, card)">
                                <view @click="selectCard(index)" class="card-item">
                                    <view :class="{active: card.is_default==1}" class="card-preview">
                                        <image style="width: 650rpx;border-radius: 12rpx;" :src="card.mp" mode="widthFix"></image>
                                        <image v-show="card.is_default==1" src="@/static/icon/mrmp.png" class="mrmp"></image>
                                        <image style="width: 650rpx;border-radius: 12rpx;" :src="card.mp"
                                            mode="widthFix"></image>
                                        <image v-show="card.is_default==1" src="@/static/icon/mrmp.png" class="mrmp">
                                        </image>
                                    </view>
                                </view>
                            </uni-swipe-action-item>
@@ -110,8 +112,8 @@
<script>
    import Popup from '@/components/uni-popup.vue';
import uniSwipeAction from '@/uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue';
import uniSwipeActionItem from '@/uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue';
    import uniSwipeAction from '@/uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue';
    import uniSwipeActionItem from '@/uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue';
    export default {
        components: {
            Popup,
@@ -123,6 +125,7 @@
                businessImage: '',
                business_card_id: '',
                height: 0,
                cardWidth: 0, // 名片宽度
                businessList: [],
                current: 0,
                statistics: {},
@@ -143,6 +146,11 @@
        },
        onLoad() {
            this.screenWidth = uni.getSystemInfoSync().windowWidth * 2 - 70;
            // 计算名片宽度:屏幕宽度减去左右padding(40rpx)
            const systemInfo = uni.getSystemInfoSync();
            this.cardWidth = (systemInfo.windowWidth * 2) - 40; // rpx单位
        },
        onShow() {
            this.getbusinessList();
            this.getVisitorList();
        },
@@ -156,9 +164,9 @@
                }, function(res) {
                    _this.businessList = res.data.data;
                    if (_this.businessList.length > 0) {
                        for(let i in _this.businessList){
                            if(_this.businessList[i].is_default==1){
                                _this.current=i;
                        for (let i in _this.businessList) {
                            if (_this.businessList[i].is_default == 1) {
                                _this.current = i;
                            }
                        }
                        _this.getbusiness(_this.businessList[_this.current].user_id)
@@ -236,7 +244,7 @@
                    this.gotoPage(
                        `/pages/plus/business/add?business_card_id=${this.businessList[this.current].business_card_id}`
                    );
                }else{
                } else {
                    this.gotoPage(
                        `/pages/plus/business/add`
                    );
@@ -261,13 +269,13 @@
            },
            shareCard() {
                // 分享名片逻辑
            },
            viewAllVisitors() {
                // 查看全部访客
                this.gotoPage('/pages/plus/business/visitors');
            },
            // 跳转到聊天记录页面
            gotoChatList() {
                uni.navigateTo({
@@ -354,7 +362,7 @@
                    this.showToast('默认名片不能删除');
                    return;
                }
                uni.showModal({
                    title: '提示',
                    content: '确定要删除这个名片吗?',
@@ -368,12 +376,13 @@
                                    // 删除成功,更新列表
                                    this.businessList.splice(index, 1);
                                    this.showToast('删除成功');
                                    // 如果删除的是当前选中的名片,切换到第一个名片
                                    if (index === this.current) {
                                        if (this.businessList.length > 0) {
                                            this.current = 0;
                                            this.getStatistics(this.businessList[this.current].business_card_id);
                                            this.getStatistics(this.businessList[this.current]
                                                .business_card_id);
                                        }
                                    } else if (index < this.current) {
                                        // 如果删除的是当前选中名片之前的,current减1
@@ -432,6 +441,15 @@
        background: #fff;
        border-radius: 20rpx;
        overflow: hidden;
        box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
        .card-image {
            width: 100%;
            display: block;
            // 确保图片清晰度,使用高质量渲染
            image-rendering: -webkit-optimize-contrast;
            image-rendering: crisp-edges;
        }
        .top-image {
            width: 100%;
@@ -634,6 +652,13 @@
                .card-preview {
                    border-radius: 12rpx;
                    position: relative;
                    overflow: hidden;
                    image {
                        // 保持图片原始清晰度
                        display: block;
                        image-rendering: -webkit-optimize-contrast;
                    }
                    .mrmp {
                        height: 50rpx;
mobile/pages/plus/business/list.vue
@@ -739,6 +739,7 @@
        .card-list {
            width: calc(100% - 40rpx);
            height: calc(100vh - 94rpx - 80rpx);
            padding: 0 20rpx 20rpx;
            .card-item {
mobile/pages/plus/vip/index.vue
@@ -124,6 +124,7 @@
                words: {},
                user: {},
                titel: '',
                vip_url:'',
                has_apply: false // 是否已申请
            };
        },
@@ -154,6 +155,7 @@
                    self.top_background = data.data.background;
                    self.vip = data.data.vip;
                    self.user = data.data.user;
                    self.vip_url = data.data.vip_url;
                    self.isData = true;
                    self.loadding = false;
                    uni.hideLoading();
@@ -173,7 +175,8 @@
            /*申请成为VIP*/
            applyVip() {
                this.gotoPage('/pages/plus/vip/apply');
                let vip_url=this.vip_url?this.vip_url:'/pages/plus/vip/apply'
                this.gotoPage(vip_url);
            },
            
            /*查看申请状态*/
mobile/pages2/bonus/index/index.vue
@@ -158,6 +158,7 @@
                // 排位过期时间
                remain_time: '',
                isNotePopup: false,
                vip_url:''
            };
        },
        onLoad(e) {
@@ -194,6 +195,7 @@
                    self.bonus = data.data.bonus;
                    self.user = data.data.user;
                    self.remain_time = data.data.remain_time;
                    self.vip_url = data.data.vip_url;
                    self.isData = true;
                    self.loadding = false;
                    uni.hideLoading();
@@ -202,7 +204,8 @@
            /*申请分销商*/
            applybonus() {
                this.gotoPage('/pages2/bonus/apply/apply');
                let vip_url=this.vip_url?this.vip_url:'/pages2/bonus/apply/apply'
                this.gotoPage(vip_url);
            },
            /*去商城逛逛*/
mobile/pages2/shareholder/index/index.vue
@@ -51,7 +51,8 @@
                    </view>
                </view>
                <view class="d-c-c pt30">
                    <button type="primary" class="btn-gcred flex-1" @click="gotoCash">{{ info_words.index.words.cash.value }}</button>
                    <button type="primary" class="btn-gcred flex-1"
                        @click="gotoCash">{{ info_words.index.words.cash.value }}</button>
                </view>
            </view>
            <!--图标入口-->
@@ -64,7 +65,8 @@
                </view>
                <view class="d-c-c d-c flex-1" @click="gotoPage('pages2/shareholder/bonus/bonus')">
                    <view>
                        <image class="team_index_img" src="../../../static/icon/icon-fenxiaodingdan.png" mode=""></image>
                        <image class="team_index_img" src="../../../static/icon/icon-fenxiaodingdan.png" mode="">
                        </image>
                    </view>
                    <text class="pt10 f26 mt20">{{ info_words.bonus_list.title.value }}</text>
                </view>
@@ -74,13 +76,30 @@
        <template v-if="!is_shareholder && isData">
            <view class="no-team">
                <view class="mt50 p-0-20 pt30 red f34 tc">{{ info_words.index.words.not_shareholder.value }}</view>
                <view class="p30 f28" v-if="setting.become=='40'">您需要下级分销商人数达到<text class="orange">{{setting.totalfxs_down}}</text>人才能成为{{ info_words.index.words.shareholder.value }},您当前的分销商人数为<text class="orange">{{agent_total}}</text>人,继续努力吧!</view>
                <view class="p30 f28" v-if="setting.become=='50'">您需要累计分销佣金达到<text class="orange">{{setting.total_money}}</text>元才能成为{{ info_words.index.words.shareholder.value }},您当前累计分销佣金为<text class="orange">{{agent_money}}</text>元,继续努力吧!</view>
                <view class="p30 f28" v-if="setting.become=='70'">您需要团队累计业绩达到<text class="orange">{{setting.total_team_money}}</text>元才能成为{{ info_words.index.words.shareholder.value }},您当前团队累计业绩为<text class="orange">{{team_money}}</text>元,继续努力吧!</view>
                <view class="p30 f28" v-if="setting.become=='90'">您需要一次性消费达到<text class="orange">{{setting.one_expend_money}}</text>元才能成为{{ info_words.index.words.region.value }},继续努力吧!</view>
                <view class="p30 f28" v-if="setting.become=='40'">您需要下级分销商人数达到<text
                        class="orange">{{setting.totalfxs_down}}</text>人才能成为{{ info_words.index.words.shareholder.value }},您当前的分销商人数为<text
                        class="orange">{{agent_total}}</text>人,继续努力吧!</view>
                <view class="p30 f28" v-if="setting.become=='50'">您需要累计分销佣金达到<text
                        class="orange">{{setting.total_money}}</text>元才能成为{{ info_words.index.words.shareholder.value }},您当前累计分销佣金为<text
                        class="orange">{{agent_money}}</text>元,继续努力吧!</view>
                <view class="p30 f28" v-if="setting.become=='70'">您需要团队累计业绩达到<text
                        class="orange">{{setting.total_team_money}}</text>元才能成为{{ info_words.index.words.shareholder.value }},您当前团队累计业绩为<text
                        class="orange">{{team_money}}</text>元,继续努力吧!</view>
                <view class="p30 f28" v-if="setting.become=='90'">您需要一次性消费达到<text
                        class="orange">{{setting.one_expend_money}}</text>元才能成为{{ info_words.index.words.region.value }},继续努力吧!
                </view>
                <view class="section-product" v-if="setting.become=='110'">
                    <view class="p30 f28">您需要团队推荐商户入驻人数需达到<text class="orange">{{setting.totalsh_down}}</text>人并且团队推荐指定会员等级达到<text class="orange" v-for="(item, index ) in gradeList">{{(index>0?'或':'')+item.name}}</text>满<text class="orange">{{setting.totalvip_down}}</text>人并且至少购买VIP专区商品<text class="orange">{{setting.purchase_count}}</text>次或购买以下任意一款商品才能成为{{ info_words.index.words.shareholder.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">
                    <view class="p30 f28">
                        您需要团队推荐<text class="orange">{{setting.totalsh_down}}</text>家商户入驻
                        并且团队推荐指定会员等级达到<text class="orange"
                            v-for="(item, index ) in gradeList">{{(index>0?'或':'')+item.name}}</text>满<text
                            class="orange">{{setting.totalvip_down}}</text>人
                        并且至少购买VIP专区商品<text class="orange">{{setting.purchase_count}}</text>次
                        或购买以下任意一款商品才能成为{{ info_words.index.words.shareholder.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>
@@ -99,7 +118,9 @@
                </view>
                <view class="section-product" v-if="setting.become=='100'">
                    <view class="p30 f28 d-c-c">您需要购买以下任意一款商品才能申请{{ info_words.index.words.shareholder.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">
                    <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>
@@ -117,7 +138,8 @@
                    </view>
                </view>
                <view class="p30 mt30" v-if="setting.become=='10'">
                    <button type="primary" class="btn-gcred" @click="applyShareholder">{{ info_words.index.words.apply_now.value }}</button>
                    <button type="primary" class="btn-gcred"
                        @click="applyShareholder">{{ info_words.index.words.apply_now.value }}</button>
                </view>
                <view class="p30 mt30" v-else-if="setting.become=='40' || setting.become=='50'">
                    <button type="primary" class="btn-gcred" @click="gotoAgent">马上去招募人员</button>
@@ -126,7 +148,8 @@
                    <button type="primary" class="btn-gcred" @click="gotoTeam">去看看我的团队</button>
                </view>
                <view class="p30">
                    <button type="primary" class="btn-gray" @click="gotoShop">{{ info_words.apply.words.goto_mall.value }}</button>
                    <button type="primary" class="btn-gray"
                        @click="gotoShop">{{ info_words.apply.words.goto_mall.value }}</button>
                </view>
            </view>
            <view class="bottom-banner d-c-c d-c" v-if="description_pic!=''">
@@ -165,7 +188,7 @@
                team_money: 0,
                productList: [],
                shareholder: {},
                gradeList:[]
                gradeList: []
            };
        },
        onLoad(e) {
@@ -187,7 +210,8 @@
                self._get('user.shareholder/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
                        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
@@ -216,12 +240,12 @@
            gotoShop() {
                this.gotoPage('pages/index/index')
            },
            /*去分销中心*/
            gotoAgent() {
                this.gotoPage('pages/agent/index/index')
            },
            /*去分红中心*/
            gotoTeam() {
                this.gotoPage('pages2/shareholder/index/index')
@@ -231,11 +255,11 @@
            gotoCash() {
                this.gotoPage('pages2/shareholder/cash/apply/apply');
            },
            goback() {
                uni.navigateBack();
            },
            /*跳转产品详情*/
            gotoProductDetail(e) {
                let url = 'pages/product/detail/detail?product_id=' + e
@@ -297,7 +321,7 @@
        line-height: 88rpx;
        border-radius: 44rpx;
    }
    .index-team .btn-gray {
        height: 88rpx;
        line-height: 88rpx;
@@ -338,7 +362,7 @@
        width: 90rpx;
        height: 90rpx;
    }
    /* 商品列表样式 */
    .section-product .item {
        margin: 0 26rpx;
@@ -347,20 +371,20 @@
        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;
@@ -369,14 +393,14 @@
        -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;
@@ -386,57 +410,57 @@
        -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;
@@ -448,22 +472,22 @@
        align-items: center;
        min-height: 33rpx;
    }
    .section-product .icon-jiantou {
        color: #999;
    }
    .user-info .photo,
    .user-info .photo image {
        width: 50rpx;
        height: 50rpx;
        border-radius: 50%;
    }
    .user-info .photo {
        padding-right: 10rpx;
    }
    .user-info .grade {
        display: block;
        padding: 6rpx 20rpx;
@@ -475,4 +499,4 @@
        /* color: #ffffff; */
        font-family: PingFang SC;
    }
</style>
</style>
mobile/pages2/team/index/index.vue
@@ -51,7 +51,8 @@
                    </view>
                </view>
                <view class="d-c-c pt30">
                    <button type="primary" class="btn-gcred flex-1" @click="gotoCash">{{ info_words.index.words.cash.value }}</button>
                    <button type="primary" class="btn-gcred flex-1"
                        @click="gotoCash">{{ info_words.index.words.cash.value }}</button>
                </view>
            </view>
            <!--图标入口-->
@@ -64,7 +65,8 @@
                </view>
                <view class="d-c-c d-c flex-1" @click="gotoPage('pages2/team/order/order')">
                    <view>
                        <image class="team_index_img" src="../../../static/icon/icon-fenxiaodingdan.png" mode=""></image>
                        <image class="team_index_img" src="../../../static/icon/icon-fenxiaodingdan.png" mode="">
                        </image>
                    </view>
                    <text class="pt10 f26 mt20">{{ info_words.order.title.value }}</text>
                </view>
@@ -86,16 +88,48 @@
        <template v-if="!is_team && isData">
            <view class="no-team">
                <view class="mt50 p-0-20 pt30 red f34 tc">{{ info_words.index.words.not_team.value }}</view>
                <view class="p30 f28" v-if="setting.become=='40'">您需要下级分销商人数达到<text class="orange">{{setting.totalfxs_down}}</text>人才能成为{{ info_words.index.words.team.value }},您当前的分销商人数为<text class="orange">{{agent_total}}</text>人,继续努力吧!</view>
                <view class="p30 f28" v-if="setting.become=='50'">您需要累计分销佣金达到<text class="orange">{{setting.total_money}}</text>元才能成为{{ info_words.index.words.team.value }},您当前累计分销佣金为<text class="orange">{{agent_money}}</text>元,继续努力吧!</view>
                <view class="p30 f28" v-if="setting.become=='40'">您需要下级分销商人数达到<text
                        class="orange">{{setting.totalfxs_down}}</text>人才能成为{{ info_words.index.words.team.value }},您当前的分销商人数为<text
                        class="orange">{{agent_total}}</text>人,继续努力吧!</view>
                <view class="p30 f28" v-if="setting.become=='50'">您需要累计分销佣金达到<text
                        class="orange">{{setting.total_money}}</text>元才能成为{{ info_words.index.words.team.value }},您当前累计分销佣金为<text
                        class="orange">{{agent_money}}</text>元,继续努力吧!</view>
                <view class="section-product" v-if="setting.become=='70'">
                    <view class="p30 f28">您需要推荐<text
                            class="orange">{{setting.totalsh_down}}</text>家商户入驻并且推荐指定会员等级达到<text class="orange"
                            v-for="(item, index ) in gradeList">{{(index>0?'或':'')+item.name}}</text>满<text
                            class="orange">{{setting.totalvip_down}}</text>人并且至少购买VIP专区商品<text
                            class="orange">{{setting.purchase_count}}</text>次或购买以下任意一款商品才能成为{{ info_words.index.words.team.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 class="p30 mt30" v-if="setting.become=='10'">
                    <button type="primary" class="btn-gcred" @click="applyteam">{{ info_words.index.words.apply_now.value }}</button>
                    <button type="primary" class="btn-gcred"
                        @click="applyteam">{{ info_words.index.words.apply_now.value }}</button>
                </view>
                <view class="p30 mt30" v-else-if="setting.become=='40' || setting.become=='50'">
                    <button type="primary" class="btn-gcred" @click="gotoAgent">马上去招募人员</button>
                </view>
                <view class="p30">
                    <button type="primary" class="btn-gray" @click="gotoShop">{{ info_words.apply.words.goto_mall.value }}</button>
                    <button type="primary" class="btn-gray"
                        @click="gotoShop">{{ info_words.apply.words.goto_mall.value }}</button>
                </view>
            </view>
        </template>
@@ -125,7 +159,9 @@
                titel: '',
                setting: {},
                agent_total: 0,
                agent_money: 0
                agent_money: 0,
                productList: [],
                gradeList: []
            };
        },
        onLoad(e) {
@@ -147,7 +183,8 @@
                self._get('user.team/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
                        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
@@ -156,6 +193,8 @@
                    self.team = data.data.team;
                    self.user = data.data.user;
                    self.setting = data.data.setting;
                    self.productList = data.data.productList;
                    self.gradeList = data.data.gradeList;
                    self.agent_total = data.data.agent_total;
                    self.agent_money = data.data.agent_money;
                    self.isData = true;
@@ -171,9 +210,9 @@
            /*去商城逛逛*/
            gotoShop() {
                this.gotoPage('pages2/index/index')
                this.gotoPage('pages/index/index')
            },
            /*去商城逛逛*/
            gotoAgent() {
                this.gotoPage('pages/agent/index/index')
@@ -183,7 +222,7 @@
            gotoCash() {
                this.gotoPage('pages2/team/cash/apply/apply');
            },
            goback() {
                uni.navigateBack();
            },
@@ -243,7 +282,7 @@
        line-height: 88rpx;
        border-radius: 44rpx;
    }
    .index-team .btn-gray {
        height: 88rpx;
        line-height: 88rpx;
@@ -284,7 +323,7 @@
        width: 90rpx;
        height: 90rpx;
    }
    /* 商品列表样式 */
    .section-product .item {
        margin: 0 26rpx;
@@ -293,20 +332,20 @@
        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;
@@ -315,14 +354,14 @@
        -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;
@@ -332,57 +371,57 @@
        -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;
@@ -394,22 +433,22 @@
        align-items: center;
        min-height: 33rpx;
    }
    .section-product .icon-jiantou {
        color: #999;
    }
    .user-info .photo,
    .user-info .photo image {
        width: 50rpx;
        height: 50rpx;
        border-radius: 50%;
    }
    .user-info .photo {
        padding-right: 10rpx;
    }
    .user-info .grade {
        display: block;
        padding: 6rpx 20rpx;
@@ -421,4 +460,4 @@
        color: #ffffff;
        font-family: PingFang SC;
    }
</style>
</style>
operations_vue/static/css/common.css
@@ -28,7 +28,7 @@
input,
select,
figure,
figcaption,
figcaption
  {
  padding: 0;
  margin: 0;
@@ -873,4 +873,4 @@
.sel-width {
  width: 280px !important;
}
}
saas_vue/src/views/agentaccess/Index.vue
New file
@@ -0,0 +1,288 @@
<template>
  <!--
        作者:系统
        时间:2026-01-23
        描述:权限管理-菜单&权限
    -->
  <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 AccessApi from '@/api/access.js';
import Edit from './part/Edit.vue';
import Add from './part/Add';
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;
      AccessApi.agentstatus({ 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 = {};
      AccessApi.agentaccessList(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;
          AccessApi.agentdelAccess(
            {
              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>
saas_vue/src/views/agentaccess/part/Add.vue
New file
@@ -0,0 +1,218 @@
<template>
  <!--
        作者:系统
        时间:2026-01-23
        描述:代理商权限管理-添加菜单&权限
    -->
  <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 AccessApi from '@/api/access.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;
          AccessApi.agentaddpAccess(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>
saas_vue/src/views/agentaccess/part/Edit.vue
New file
@@ -0,0 +1,210 @@
<template>
  <!--
        作者:系统
        时间:2026-01-23
        描述:代理商权限管理-修改菜单&权限
    -->
  <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 AccessApi from '@/api/access.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;
          AccessApi.agenteditAccess(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>
shop_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('/shop/plus.plus/index', data, errorback);
    },
    /*入驻申请列表*/
    applyList(data, errorback) {
        return request._post('/shop/plus.operations.apply/index', data, errorback);
    },
    /*运营中心审核*/
    editApplyStatus(data, errorback) {
        return request._post('/shop/plus.operations.apply/editApplyStatus', data, errorback);
    },
    /*运营中心列表*/
    operationsList(data, errorback) {
        return request._post('/shop/plus.operations.operations/index', data, errorback);
    },
    /*查看下级用户*/
    operationsUserFans(data, errorback) {
        return request._post('/shop/plus.operations.operations/fans', data, errorback);
    },
    /*修改运营中心*/
    toOperationsEdit(data, errorback) {
        return request._get('/shop/plus.operations.operations/edit', data, errorback);
    },
    /*修改运营中心*/
    operationsEdit(data, errorback) {
        return request._post('/shop/plus.operations.operations/edit', data, errorback);
    },
    /*删除运营中心用户*/
    deleteOperations(data, errorback) {
        return request._post('/shop/plus.operations.operations/delete', data, errorback);
    },
    /*添加运营中心*/
    addOperationsUser(data, errorback) {
        return request._post('/shop/plus.operations.operations/add', data, errorback);
    },
    /*提现申请*/
    cash(data, errorback) {
        return request._post('/shop/plus.operations.cash/index', data, errorback);
    },
    /*运营中心提现审核*/
    cashSubmit(data, errorback) {
        return request._post('/shop/plus.operations.cash/submit', data, errorback);
    },
    /*微信打款*/
    WxPay(data, errorback) {
        return request._post('/shop/plus.operations.cash/wechat_pay', data, errorback);
    },
    /*运营中心确认打款*/
    money(data, errorback) {
        return request._post('/shop/plus.operations.cash/money', data, errorback);
    },
    /*运营中心设置*/
    operationsSet(data, errorback) {
        return request._post('/shop/plus.operations.setting/index', data, errorback);
    },
    /*运营中心设置-基础设置*/
    basic(data, errorback) {
        return request._post('/shop/plus.operations.setting/basic', data, errorback);
    },
    /*运营中心设置-条件*/
    condition(data, errorback) {
        return request._post('/shop/plus.operations.setting/condition', data, errorback);
    },
    /*运营中心设置-分红设置*/
    bonus(data, errorback) {
        return request._post('/shop/plus.operations.setting/bonus', data, errorback);
    },
    /*运营中心设置-结算设置*/
    settlement(data, errorback) {
        return request._post('/shop/plus.operations.setting/settlement', data, errorback);
    },
    /*运营中心设置-自定义文字*/
    words(data, errorback) {
        return request._post('/shop/plus.operations.setting/words', data, errorback);
    },
    /*运营中心设置-申请协议*/
    license(data, errorback) {
        return request._post('/shop/plus.operations.setting/license', data, errorback);
    },
    /*运营中心设置-页面背景*/
    background(data, errorback) {
        return request._post('/shop/plus.operations.setting/background', data, errorback);
    },
    /*运营中心权限管理*/
    /*权限列表*/
    operationsAccessList(data, errorback) {
        return request._post('/shop/plus.operations.access/index', data, errorback);
    },
    /*添加权限*/
    operationsAccessAdd(data, errorback) {
        return request._post('/shop/plus.operations.access/add', data, errorback);
    },
    /*修改权限*/
    operationsAccessEdit(data, errorback) {
        return request._post('/shop/plus.operations.access/edit', data, errorback);
    },
    /*删除权限*/
    operationsAccessDelete(data, errorback) {
        return request._post('/shop/plus.operations.access/delete', data, errorback);
    },
    /*权限状态修改*/
    operationsAccessStatus(data, errorback) {
        return request._post('/shop/plus.operations.access/status', data, errorback);
    },
    /*运营中心角色管理*/
    /*角色列表*/
    operationsRoleList(data, errorback) {
        return request._post('/shop/plus.operations.role/index', data, errorback);
    },
    /*添加角色需要的数据*/
    operationsRoleAddInfo(data, errorback) {
        return request._get('/shop/plus.operations.role/addInfo', data, errorback);
    },
    /*添加角色*/
    operationsRoleAdd(data, errorback) {
        return request._post('/shop/plus.operations.role/add', data, errorback);
    },
    /*修改角色需要的数据*/
    operationsRoleEditInfo(data, errorback) {
        return request._get('/shop/plus.operations.role/editInfo', data, errorback);
    },
    /*修改角色*/
    operationsRoleEdit(data, errorback) {
        return request._post('/shop/plus.operations.role/edit', data, errorback);
    },
    /*删除角色*/
    operationsRoleDelete(data, errorback) {
        return request._post('/shop/plus.operations.role/delete', data, errorback);
    },
    /*运营中心管理员管理*/
    /*管理员列表*/
    operationsAdminList(data, errorback) {
        return request._post('/shop/plus.operations.user/index', data, errorback);
    },
    /*添加管理员*/
    operationsAdminAdd(data, errorback) {
        return request._post('/shop/plus.operations.user/add', data, errorback);
    },
    /*修改管理员需要的数据*/
    operationsAdminEditInfo(data, errorback) {
        return request._get('/shop/plus.operations.user/edit', data, errorback);
    },
    /*修改管理员*/
    operationsAdminEdit(data, errorback) {
        return request._post('/shop/plus.operations.user/edit', data, errorback);
    },
    /*删除管理员*/
    operationsAdminDelete(data, errorback) {
        return request._post('/shop/plus.operations.user/delete', data, errorback);
    },
    /*等级管理*/
    /*等级列表*/
    operationsGradeList(data, errorback) {
        return request._post('/shop/plus.operations.grade/index', data, errorback);
    },
    /*添加等级*/
    operationsGradeAdd(data, errorback) {
        return request._post('/shop/plus.operations.grade/add', data, errorback);
    },
    /*修改等级*/
    operationsGradeEdit(data, errorback) {
        return request._post('/shop/plus.operations.grade/edit', data, errorback);
    },
    /*删除等级*/
    operationsGradeDelete(data, errorback) {
        return request._post('/shop/plus.operations.grade/delete', data, errorback);
    },
    /*运营中心订单*/
    /*订单列表*/
    operationsOrder(data, errorback) {
        return request._post('/shop/plus.operations.order/index', data, errorback);
    },
}
export default OperationsApi;
shop_vue/src/components/setlink/part/Menu.vue
@@ -147,6 +147,11 @@
                      url: 'pages/user/activation/index',
                      name: '激活码',
                      type: '菜单',
                    },
                    {
                      url: 'pages/plus/operations/index',
                      name: '运营中心',
                      type: '菜单',
                    }
                    ],
                /*选中的值*/
shop_vue/src/views/plus/operations/index.vue
@@ -11,6 +11,8 @@
    <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>
@@ -26,6 +28,7 @@
import Apply from './apply/Apply';
import User from './user/User';
import Cash from './cash/Cash';
import Order from './order/Order';
import Setting from './setting/Setting';
import Grade from './grade/index';
import Auth from './auth/index';
@@ -35,6 +38,7 @@
    Apply,
    User,
    Cash,
    Order,
    Setting,
    Grade,
    Auth
@@ -65,6 +69,11 @@
          value: '提现申请',
          path:'/plus/operations/cash/index'
        },
        {
          key: 'order',
          value: '运营订单',
          path:'/plus/operations/order/index'
        },
        // {
        //   key: 'grade',
        //   value: '等级管理',
shop_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/shop/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>
shop_vue/src/views/plus/operations/setting/Setting.vue
@@ -39,7 +39,7 @@
  </div>
</template>
<script>
import PlusApi from '@/api/plus/region.js';
import PlusApi from '@/api/plus/operations.js';
import Basic from './part/Basic';
import Condition from './part/Condition';
import Bonus from './part/Bonus';
@@ -82,7 +82,7 @@
    /*获取数据*/
    getData() {
      let self = this;
      PlusApi.regionSet({}, true)
      PlusApi.operationsSet({}, true)
        .then(res => {
          self.settingData = res.data;
          self.loading=false;
shop_vue/src/views/plus/operations/setting/part/Background.vue
@@ -38,7 +38,7 @@
<script>
import Upload from '@/components/file/Upload';
import PlusApi from '@/api/plus/region.js';
import PlusApi from '@/api/plus/operations.js';
export default {
  components: {
    Upload: Upload
shop_vue/src/views/plus/operations/setting/part/Basic.vue
@@ -13,64 +13,50 @@
          <el-radio v-model="form.is_open" label="0">关闭</el-radio>
        </div>
      </el-form-item>
      <el-form-item label="订单总分收益比例">
          <el-input v-model="form.total_rate" type="number" class="max-w460">
            <template slot="append">%</template>
          </el-input>
          <div class="tips">订单总分红比例 * 订单实付金额 = 可被所有代理瓜分的分红总金额</div>
        </el-form-item>
     <!-- <el-form-item label="是否开启平级分红">
       <div>
         <el-radio v-model="form.pjaward" label="1">开启</el-radio>
         <el-radio v-model="form.pjaward" label="0">关闭</el-radio>
       </div>
     </el-form-item> -->
     <!-- <el-form-item label="平级奖励层级" v-if="form.pjaward==1">
       <div>
         <el-input v-model="form.pjaward_level" type="number" class="max-w460"></el-input>
          <div class="tips">默认1级,即只往上找一个平级(根据分销关系查找)</div>
       </div>
     </el-form-item> -->
      <el-form-item label="分红结算周期">
        <div>
          <el-radio v-model="form.bonus_type" label="10">按周</el-radio>
          <el-radio v-model="form.bonus_type" label="20">按月</el-radio>
          <!-- <el-radio v-model="form.bonus_type" label="30">按年</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 v-model="form.become" label="100">购买商品</el-radio> -->
            <!-- <el-radio v-model="form.become" label="20">无需审核</el-radio> -->
            <!-- <el-radio v-model="form.become" label="30">下线人数</el-radio> -->
            <el-radio :label="40">下级分销商总数</el-radio>
            <el-radio :label="50">累计佣金总数</el-radio>
            <!-- <el-radio v-model="form.become" label="70">累计团队业绩</el-radio>
            <el-radio v-model="form.become" label="80">团队总人数</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">
      <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="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="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="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>
      <!--提交-->
@@ -78,11 +64,13 @@
        <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/region.js';
import PlusApi from '@/api/plus/operations.js';
import Product from '@/components/product/Product';
export default {
  components: {
@@ -114,6 +102,9 @@
    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: {
@@ -162,6 +153,32 @@
        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>
shop_vue/src/views/plus/operations/setting/part/Bonus.vue
@@ -36,7 +36,7 @@
</template>
<script>
  import PlusApi from '@/api/plus/region.js';
  import PlusApi from '@/api/plus/operations.js';
  export default {
    data() {
shop_vue/src/views/plus/operations/setting/part/Condition.vue
@@ -47,7 +47,7 @@
</template>
<script>
import PlusApi from '@/api/plus/region.js';
import PlusApi from '@/api/plus/operations.js';
import Product from '@/components/product/Product';
export default {
  components: {
shop_vue/src/views/plus/operations/setting/part/License.vue
@@ -21,7 +21,7 @@
</template>
<script>
  import PlusApi from '@/api/plus/region.js';
  import PlusApi from '@/api/plus/operations.js';
  export default {
    data() {
shop_vue/src/views/plus/operations/setting/part/Settlement.vue
@@ -43,7 +43,7 @@
</template>
<script>
  import PlusApi from '@/api/plus/region.js';
  import PlusApi from '@/api/plus/operations.js';
  export default {
    data() {
shop_vue/src/views/plus/operations/setting/part/Words.vue
@@ -18,21 +18,21 @@
      <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.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>
      <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-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.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>
@@ -40,6 +40,15 @@
        <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="页面标题">
@@ -80,7 +89,7 @@
</template>
<script>
import PlusApi from '@/api/plus/region.js';
import PlusApi from '@/api/plus/operations.js';
export default {
  data() {
shop_vue/src/views/product/category/index.vue
@@ -26,7 +26,7 @@
          <el-table-column prop="create_time" label="添加时间"></el-table-column>
          <el-table-column prop="status" label="状态">
            <template slot-scope="scope">
              <el-checkbox v-model="scope.row.status" :checked="scope.row.status" @change="checked => statusChange(checked,scope.row)">启用</el-checkbox>
              <el-switch v-model="scope.row.status"  :active-value="1" :inactive-value="0" active-text="启用" inactive-text="禁用" @change="statusChange(scope.row)" :width="55">启用</el-switch>
            </template>
          </el-table-column>
          <el-table-column fixed="right" label="操作" width="100">
@@ -144,7 +144,7 @@
        });
      },
      /*启用*/
      statusChange: function(checked,row) {
      statusChange: function(row) {
        let self = this;
        // if(row.child.length>0){
        //   self.$message({
@@ -154,7 +154,7 @@
        //   row.status = !checked;
        //   return;
        // }
        let status=checked?1:0;
        let status=row.status?1:0;
        self.loading = true;
        let params={
            category_id: row.category_id,
@@ -167,11 +167,9 @@
        )
          .then(data => {
            self.loading = false;
            row.status = checked;
          })
          .catch(error => {
            self.loading = false;
            row.status = checked?0:1;
          });
      },
    }
shop_vue/src/views/product/product/edit.vue
@@ -117,6 +117,8 @@
            /*商品编码*/
            product_no: '',
            settlement_price: 0,
            /*激活码数量*/
            activation_code_num: 0,
          },
          /*多规格类别*/
          spec_many: {
shop_vue/src/views/product/product/part/spec/Single.vue
@@ -23,6 +23,9 @@
    <el-form-item label="商品重量(Kg):" :rules="[{ required: true, message: '请填写商品重量' }]" prop="model.sku.product_weight">
      <el-input type="number" v-model="form.model.sku.product_weight" class="max-w460"></el-input>
    </el-form-item>
    <el-form-item label="激活码数量:" v-if="form.model.is_activation_code==1" :rules="[{ required: true, message: '请填写激活码数量' }]" prop="model.sku.activation_code_num">
      <el-input type="number" v-model="form.model.sku.activation_code_num" class="max-w460"></el-input>
    </el-form-item>
  </div>
</template>
shop_vue/src/views/product/product/part/spec/many/Table.vue
@@ -13,6 +13,8 @@
          <el-input size="small" v-model="batchData.settlement_price" placeholder="结算价" style="width: 160px;padding-left: 4px;"></el-input>
          <el-input size="small" v-model="batchData.stock_num" placeholder="库存" style="width: 160px;padding-left: 4px;"></el-input>
          <el-input size="small" v-model="batchData.product_weight" placeholder="重量" style="width: 160px;padding-left: 4px;"></el-input>
          <el-input size="small" v-model="batchData.activation_code_num" placeholder="激活码数量"
                    style="width: 160px;padding-left: 4px;"></el-input>
          <el-button size="small" @click="onSubmitBatchData">应用</el-button>
        </div>
        <!--多规格表格-->
@@ -79,6 +81,18 @@
                </el-form-item>
              </template>
            </el-table-column>
            <el-table-column label="激活码数量"  v-if="form.model.is_activation_code==1">
              <template slot-scope="scope">
                <el-form-item
                  label=""
                  :rules="[{ required: true, message: ' ' }]"
                  :prop="'model.spec_many.spec_list.' + scope.$index + '.spec_form.activation_code_num'"
                  style="margin-bottom: 0;"
                >
                  <el-input size="small" prop="activation_code_num" v-model="scope.row.spec_form.activation_code_num"></el-input>
                </el-form-item>
              </template>
            </el-table-column>
          </el-table>
        </div>
      </el-form-item>
@@ -101,7 +115,9 @@
          product_price: '',
          line_price: '',
          stock_num: '',
          product_weight: ''
          product_weight: '',
          settlement_price: '',
          activation_code_num: '',
        },
        /*图片是否打开*/
        isupload: false,
shop_vue/src/views/supplier/category/index.vue
@@ -8,9 +8,8 @@
        <div class="common-level-rail">
            <el-button size="small" type="primary" @click="addCategory">添加分类</el-button>
            <el-select v-model="form.category_type" placeholder="选择类型" @change="getTableList" style="width: 150px; margin-left: 10px;">
                <el-option label="全部" :value="0"></el-option>
                <el-option label="实物" :value="10"></el-option>
                <el-option label="团购" :value="20"></el-option>
              <el-option label="全部" :value="0"></el-option>
                <el-option v-for="(item,index) in typeList" :key="index" :label="item" :value="index"></el-option>
            </el-select>
        </div>
        <div class="table-wrap">
@@ -28,10 +27,10 @@
                </el-table-column>
            </el-table>
            <!--添加-->
            <Add v-if="open_add" :open_add="open_add" @closeDialog="closeDialogFunc($event, 'add')"></Add>
            <Add v-if="open_add" :open_add="open_add" @closeDialog="closeDialogFunc($event, 'add')" :typeList="typeList"></Add>
            <!--编辑-->
            <Edit v-if="open_edit" :open_edit="open_edit" :form="userModel"
            <Edit v-if="open_edit" :open_edit="open_edit" :form="userModel" :typeList="typeList"
                  @closeDialog="closeDialogFunc($event, 'edit')"></Edit>
        </div>
@@ -62,6 +61,8 @@
                commentData: [],
                /*是否加载完成*/
                loading: true,
                /*供应商类型列表*/
                typeList: [],
                /*筛选表单*/
                form: {
                    category_type: 0
@@ -85,6 +86,7 @@
                    {
                        self.loading = false;
                        self.categoryData = data.data.category;
                        self.typeList = data.data.typeList;
                    })
                    .catch(error =>
                    {
shop_vue/src/views/supplier/category/part/Add.vue
@@ -12,8 +12,7 @@
      </el-form-item>
      <el-form-item label="分类类型" :label-width="formLabelWidth">
        <el-radio-group v-model="form.category_type">
          <el-radio :label="10">实物</el-radio>
          <el-radio :label="20">团购</el-radio>
          <el-radio v-for="(item,index) in typeList" :key="index" :label="index">{{item}}</el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="保证金(元)" :label-width="formLabelWidth" prop="deposit_money">
@@ -57,7 +56,7 @@
        loading: false,
      };
    },
    props: ['open_add'],
    props: ['open_add', 'typeList'],
    created() {
      this.dialogVisible = this.open_add;
    },
shop_vue/src/views/supplier/category/part/Edit.vue
@@ -7,8 +7,7 @@
      </el-form-item>
      <el-form-item label="分类类型" :label-width="formLabelWidth">
        <el-radio-group v-model="form.category_type">
          <el-radio :label="10">实物</el-radio>
          <el-radio :label="20">团购</el-radio>
          <el-radio v-for="(item,index) in typeList" :key="index" :label="index">{{item}}</el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="保证金(元)" :label-width="formLabelWidth" prop="deposit_money">
@@ -46,7 +45,7 @@
        loading: false,
      };
    },
    props: ['open_edit', 'form'],
    props: ['open_edit', 'form', 'typeList'],
    created() {
      this.dialogVisible = this.open_edit;
    },
supplier_vue/src/views/product/category/index.vue
@@ -26,7 +26,7 @@
          <el-table-column prop="create_time" label="添加时间"></el-table-column>
          <el-table-column prop="status" label="状态">
            <template slot-scope="scope">
              <el-checkbox v-model="scope.row.status" :checked="scope.row.status" @change="checked => statusChange(checked,scope.row)">启用</el-checkbox>
              <el-switch v-model="scope.row.status"  :active-value="1" :inactive-value="0" @change="statusChange(scope.row)">启用</el-switch>
            </template>
          </el-table-column>
          <el-table-column fixed="right" label="操作" width="100">
@@ -144,7 +144,7 @@
        });
      },
      /*启用*/
      statusChange: function(checked,row) {
      statusChange: function(row) {
        let self = this;
        // if(row.child.length>0){
        //   self.$message({
@@ -154,7 +154,7 @@
        //   row.status = !checked;
        //   return;
        // }
        let status=checked?1:0;
        let status=row.status?1:0;
        self.loading = true;
        let params={
            category_id: row.category_id,
@@ -167,11 +167,9 @@
        )
          .then(data => {
            self.loading = false;
            row.status = checked;
          })
          .catch(error => {
            self.loading = false;
            row.status = checked?0:1;
          });
      },
    }
supplier_vue/src/views/product/product/add.vue
@@ -153,6 +153,7 @@
            is_gift_pack: 0,
            // 生成几个超级分红订单
            vip_order_num: 0,
            is_vip:0
          },
          /*商品分类*/
          category: [],
supplier_vue/src/views/product/product/part/Basic.vue
@@ -141,19 +141,19 @@
      <el-input type="number" min="0" v-model="form.model.deduction_price" class="max-w460"></el-input>
      <div class="gray9">该券线下核销时,实际抵扣的金额</div>
    </el-form-item>
    <el-form-item v-if="is_vip" label="是否是激活码商品:" >
    <el-form-item v-if="form.is_vip" label="是否是激活码商品:" >
      <el-radio-group v-model="form.model.is_activation_code">
        <el-radio :label="1">是</el-radio>
        <el-radio :label="0">否</el-radio>
      </el-radio-group>
    </el-form-item>
    <el-form-item v-if="is_vip" label="是否可以被激活码兑换:" >
    <el-form-item v-if="form.is_vip" label="是否可以被激活码兑换:" >
      <el-radio-group v-model="form.model.activation_code_exchange">
        <el-radio :label="1">是</el-radio>
        <el-radio :label="0">否</el-radio>
      </el-radio-group>
    </el-form-item>
    <el-form-item v-if="is_vip" label="是否升级礼包:" >
    <el-form-item v-if="form.is_vip" label="是否升级礼包:" >
      <el-radio-group v-model="form.model.is_gift_pack">
        <el-radio :label="1">是</el-radio>
        <el-radio :label="0">否</el-radio>
supplier_vue/src/views/statistics/index.vue
@@ -14,5 +14,5 @@
  }
</script>
<style></style>
<style>
</style>