quanwei
2 days ago 73b874c72ad55eb9eef21c36160ac0de58f0189e
优化名片
8 files added
31 files modified
2273 ■■■■ changed files
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/model/plus/operations/Operations.php 40 ●●●●● patch | view | raw | blame | history
admin/app/api/model/plus/operations/Order.php 39 ●●●●● patch | view | raw | blame | history
admin/app/api/model/plus/operations/Setting.php 11 ●●●●● patch | view | raw | blame | history
admin/app/api/service/order/paysuccess/type/MasterPaySuccessService.php 4 ●●● 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/service/business/Poster.php 371 ●●●● 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/JobScheduler.php 2 ●●●●● patch | view | raw | blame | history
admin/app/job/event/OperationsOrder.php 88 ●●●●● 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/service/order/ExportService.php 74 ●●●●● 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/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 32 ●●●●● patch | view | raw | blame | history
mobile/pages/plus/business/list.vue 1 ●●●● patch | view | raw | blame | history
operations_vue/static/css/common.css 4 ●●●● patch | view | raw | blame | history
shop_vue/src/api/plus/operations.js 186 ●●●●● 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/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 32 ●●●●● 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 2 ●●● patch | view | raw | blame | history
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/model/plus/operations/Operations.php
New file
@@ -0,0 +1,40 @@
<?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;
    }
}
admin/app/api/model/plus/operations/Order.php
New file
@@ -0,0 +1,39 @@
<?php
namespace app\api\model\plus\operations;
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);
    }
}
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/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);
            // 记录VIP专区订单
            OperationsOrderModel::createOrder($detail);
            
            event('PaySuccess', $detail);
        }
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('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' => '',    // 提现状态通知                 ]             ],         ];     } }
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,200 @@
     * @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转换系数:1px ≈ 0.75pt (GD库使用磅pt作为字体单位)
        // 使用更精确的转换系数
        $fontSizePt = $fontSize * 0.75;
        // 调整top位置,使文字基线对齐
        // imagettftext的y坐标是文字基线位置,不是文字顶部
        // 需要加上字体大小来使文字显示在期望的位置
        $data[0] = $fontSizePt;  // 字体大小(pt)
        $data[1]  = (float)$left;  // 左边距(px)
        $data[2]  = (float)$top + $fontSize;  // 顶部位置(px),加字体大小以校正基线
        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/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/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/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)
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/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
@@ -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,
@@ -143,6 +145,9 @@
        },
        onLoad() {
            this.screenWidth = uni.getSystemInfoSync().windowWidth * 2 - 70;
        },
        onShow() {
            this.getbusinessList();
            this.getVisitorList();
        },
@@ -156,9 +161,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 +241,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 +266,13 @@
            },
            shareCard() {
                // 分享名片逻辑
            },
            viewAllVisitors() {
                // 查看全部访客
                this.gotoPage('/pages/plus/business/visitors');
            },
            // 跳转到聊天记录页面
            gotoChatList() {
                uni.navigateTo({
@@ -354,7 +359,7 @@
                    this.showToast('默认名片不能删除');
                    return;
                }
                uni.showModal({
                    title: '提示',
                    content: '确定要删除这个名片吗?',
@@ -368,12 +373,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
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 {
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;
}
}
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/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/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,42 +13,12 @@
          <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-group>
        </div>
@@ -82,7 +52,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/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
@@ -80,7 +80,7 @@
</template>
<script>
import PlusApi from '@/api/plus/region.js';
import PlusApi from '@/api/plus/operations.js';
export default {
  data() {