8 files added
31 files modified
| | |
| | | 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('添加成功'); |
| | | } |
| | |
| | | $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('编辑成功'); |
| | | } |
| | |
| | | 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); |
| | | } |
| | | |
| | | /** |
| New file |
| | |
| | | <?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; |
| | | } |
| | | } |
| New file |
| | |
| | | <?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); |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | <?php |
| | | |
| | | namespace app\api\model\plus\operations; |
| | | use app\common\model\plus\operations\Setting as SettingModel; |
| | | /** |
| | | * 运营中心设置模型 |
| | | */ |
| | | class Setting extends SettingModel |
| | | { |
| | | |
| | | } |
| | |
| | | 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; |
| | | /** |
| | | * 订单支付成功服务类 |
| | | */ |
| | |
| | | TeamOrderModel::createOrder($detail); |
| | | // 记录VIP专区订单 |
| | | VipOrderModel::createOrder($detail); |
| | | // 记录VIP专区订单 |
| | | OperationsOrderModel::createOrder($detail); |
| | | |
| | | event('PaySuccess', $detail); |
| | | } |
| New file |
| | |
| | | <?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; |
| | | } |
| | | } |
| | |
| | | <?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' => '', // 提现状态通知
]
],
];
}
} |
| | |
| | | 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); |
| | |
| | | } |
| | | // 脱敏处理 |
| | | if($this->businessName=='desensitization'){ |
| | | // 保存原始数据以便后续可能需要使用 |
| | | $originalDealer = $this->dealer; |
| | | |
| | | // 手机号脱敏:保留前3位和后4位 |
| | | if(!empty($this->dealer['mobile'])){ |
| | | $this->dealer['mobile'] = $this->maskPhoneNumber($this->dealer['mobile']); |
| | |
| | | $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) { |
| | |
| | | $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); |
| | | } |
| | | |
| | |
| | | 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使用最高质量 |
| | | } |
| | | |
| | | // 清理内存 |
| | |
| | | * @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]; |
| | |
| | | } 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); |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | |
| | | $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); |
| | | |
| | |
| | | * @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); |
| | | } |
| | | |
| | | } |
| | |
| | | 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; |
| | | /** |
| | | * 已完成订单结算服务类 |
| | | */ |
| | |
| | | } |
| | | } |
| | | AgentOrderModel::grantMoney($order, $this->orderType); |
| | | // 发放运营中心佣金 |
| | | OperationsOrderModel::grantMoney($order, $this->orderType); |
| | | // 发放团队分红 by yj |
| | | TeamOrderModel::grantMoney($order, $this->orderType); |
| | | // 发放会员分红 |
| | |
| | | 'VipUserGrade' => [ |
| | | \app\job\event\VipUserGrade::class |
| | | ], |
| | | /*运营中心订单*/ |
| | | 'OperationsOrder' => [ |
| | | \app\job\event\OperationsOrder::class |
| | | ], |
| | | ], |
| | | |
| | | 'subscribe' => [ |
| | |
| | | event('LiveRoom'); |
| | | // 分会 |
| | | event('Branch'); |
| | | // 运营中心订单 |
| | | event('OperationsOrder'); |
| | | return true; |
| | | } |
| | | |
| New file |
| | |
| | | <?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'); |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | <?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]); |
| | | } |
| | | |
| | | } |
| | |
| | | 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; |
| | | |
| | | /** |
| | | * 分销控制器 |
| New file |
| | |
| | | <?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); |
| | | } |
| | | |
| | | } |
| | |
| | | } |
| | | |
| | | /** |
| | | * 运营中心订单导出 |
| | | */ |
| | | 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) |
| | |
| | | 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); |
| | | }, |
| | | } |
| | | |
| | |
| | | return 'vip'+val; |
| | | }, |
| | | |
| | | /*夿忮µæ¯å¦ä¸ºç©ºï¼ä¸ºç©ºçè¯å
�*/ |
| | | /*判断字段是否为空,为空的话先说-*/ |
| | | isNull:function(val){ |
| | | |
| | | if(val==null||val==undefined||val===""||val==="null"||val=='undefined'){ |
| | |
| | | } |
| | | }, |
| | | |
| | | /*ç¾åæ¯?/ |
| | | /*百分比*/ |
| | | returnPercentage:function(val){ |
| | | if(val!==null&&val!==''&&val!==undefined){ |
| | | let num=(val*100).toFixed(2); |
| | |
| | | } |
| | | }, |
| | | |
| | | /*å°æ°ç¹åé¢ä¿ç使?/ |
| | | /*小数点后面保留位数*/ |
| | | returnToFixed:function(val,num){ |
| | | if(val!=null){ |
| | | let nums=val.toFixed(num); |
| | |
| | | } |
| | | }, |
| | | |
| | | /*åä¸å
?/ |
| | | /*取万元*/ |
| | | tenThousand:function(val){ |
| | | if(val!=null&&val!=''){ |
| | | var x=(val/10000).toFixed(2); |
| | |
| | | } |
| | | }, |
| | | |
| | | /*æ°åæ¢æå?/ |
| | | /*数字换成周*/ |
| | | numTabWeek: function(val) { |
| | | |
| | | let ch = ''; |
| | |
| | | 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; |
| | |
| | | let sex = ''; |
| | | switch(num) { |
| | | case 0: |
| | | sex = '�; |
| | | sex = '女'; |
| | | break; |
| | | case 1: |
| | | sex= 'ç?; |
| | | sex= '男'; |
| | | break; |
| | | default: |
| | | sex = '其他'; |
| | |
| | | } |
| | | }, |
| | | |
| | | /*å¤æææ²¡æç©ºæ ?/ |
| | | /*判断有没有空格*/ |
| | | hasSpace:function(val){ |
| | | if(val!=undefined){ |
| | | let patt=/\s/g; |
| | |
| | | } |
| | | }, |
| | | |
| | | /*夿å符串æ¯å¦å
¨æ¯ç©ºæ ?/ |
| | | /*判断字符串是否全是空格*/ |
| | | isAllSpace(val){ |
| | | if(val.match(/^[ ]*$/)){ |
| | | return true; |
| | |
| | | } from '@/utils/base' |
| | | |
| | | const whiteList = ['/login', '/test', '/fonticon'] |
| | | // 卿¯ä¸ªè·¯ç±çæä¹åï¼å
è¿è¡ä¸äºå¤çï¼è¯·åè?vue-router宿¹ææ¡£-导èªé©å |
| | | // 在每个路由生效之前,先进行一些处理,请参考 vue-router官方文档-导航钩子 |
| | | router.beforeEach((to, from, next) => { |
| | | |
| | | const isLogin = getCookie('isLogin'); |
| | |
| | | } |
| | | ] |
| | | }, |
| | | /*----代çååè¡?---*/ |
| | | /*----代理商列表----*/ |
| | | { |
| | | path: '/agent', |
| | | redirect: { name: 'agent_Index' }, |
| | |
| | | path: 'Index', |
| | | name: 'agent_Index', |
| | | meta: { |
| | | title: '代çå管ç? |
| | | title: '代理商管理' |
| | | }, |
| | | component: () => |
| | | import('@/views/agent/Index') |
| | |
| | | generateRoutes: async function(context, str) { |
| | | /*返回理由*/ |
| | | return new Promise((resolve, reject) => { |
| | | /*夿æ¬å°ç¼åæ¯å¦æèåæ°æ?/ |
| | | /*判断本地缓存是否有菜单数据*/ |
| | | if(res.status&&res.data){ |
| | | let temps=null; |
| | | let accessRoutes=temps.concat(menu); |
| | |
| | | } |
| | | |
| | | /* |
| | | * éè¿åæ°è·åsessionStorageçæ°æ? |
| | | * 通过参数获取sessionStorage的数据 |
| | | */ |
| | | export const getSessionStorage = (name) => { |
| | | if(sessionStorage.hasOwnProperty(name)) { |
| | |
| | | } |
| | | |
| | | /* |
| | | * éå sessionStorage, type==true 忝æ´ä¸ªä¿®æ¹ï¼? |
| | | * 附加sessionStorage, type==true 则是整个修改, |
| | | */ |
| | | export const addSessionStorage = (name, val) => { |
| | | if(sessionStorage.hasOwnProperty(name)) { |
| | |
| | | } |
| | | |
| | | /* |
| | | * éè¿åæ°è·ålocalStorageçæ°æ? |
| | | * 通过参数获取localStorage的数据 |
| | | */ |
| | | export const getLocalStorage = (name) => { |
| | | if(localStorage.hasOwnProperty(name)) { |
| | |
| | | } |
| | | |
| | | /* |
| | | * éå localStorage, type==true 忝æ´ä¸ªä¿®æ¹ï¼? |
| | | * 附加localStorage, type==true 则是整个修改, |
| | | */ |
| | | export const addLocalStorage = (name, val) => { |
| | | if(localStorage.hasOwnProperty(name)) { |
| | |
| | | } |
| | | |
| | | /* |
| | | *æ·±æ·è´? |
| | | *深拷贝 |
| | | */ |
| | | export const deepClone = (obj) => { |
| | | var objClone = Array.isArray(obj) ? [] : {}; |
| | |
| | | |
| | | |
| | | /* |
| | | *æ·±åå¹? |
| | | *深合并 |
| | | */ |
| | | export const deepMerger = (obj1, obj2) => { |
| | | for (var key in obj2) { |
| | |
| | | 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, |
| | |
| | | <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> |
| | |
| | | logo_height: 0, // Logo高度 |
| | | logo_width: 0, // Logo宽度 |
| | | avatar_width: 0, // 头像宽度 |
| | | // 公司职位列表 |
| | | companyList: [], // 公司职位列表 |
| | | // 显示控制 |
| | | avatar_display: 1, // 头像显示状态 |
| | | logo_display: 1, // Logo显示状态 |
| | |
| | | }) |
| | | this.business_card_id = e.business_card_id |
| | | this.getBusiness(e.business_card_id) |
| | | } else { |
| | | // 新增时默认添加一个公司职位 |
| | | this.addCompany(); |
| | | } |
| | | this.getTemplate(); |
| | | this.getIndustryList(); |
| | |
| | | // 初始化区域选择器数据 |
| | | 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; |
| | |
| | | }, |
| | | 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 |
| | |
| | | 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) { |
| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | 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> |
| | |
| | | } else { |
| | | this.showError('暂未填写微信'); |
| | | } |
| | | }, |
| | | },/* |
| | | // 通过聊天联系 |
| | | contactWithChat() { |
| | | console.log(this.businessInfo); |
| | |
| | | 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 |
| | |
| | | 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; |
| | | } |
| | | } |
| | | } |
| | |
| | | <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> |
| | |
| | | |
| | | <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, |
| | |
| | | }, |
| | | onLoad() { |
| | | this.screenWidth = uni.getSystemInfoSync().windowWidth * 2 - 70; |
| | | |
| | | }, |
| | | onShow() { |
| | | this.getbusinessList(); |
| | | this.getVisitorList(); |
| | | }, |
| | |
| | | }, 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) |
| | |
| | | this.gotoPage( |
| | | `/pages/plus/business/add?business_card_id=${this.businessList[this.current].business_card_id}` |
| | | ); |
| | | }else{ |
| | | } else { |
| | | this.gotoPage( |
| | | `/pages/plus/business/add` |
| | | ); |
| | |
| | | }, |
| | | shareCard() { |
| | | // 分享名片逻辑 |
| | | |
| | | |
| | | }, |
| | | viewAllVisitors() { |
| | | // 查看全部访客 |
| | | this.gotoPage('/pages/plus/business/visitors'); |
| | | }, |
| | | |
| | | |
| | | // 跳转到聊天记录页面 |
| | | gotoChatList() { |
| | | uni.navigateTo({ |
| | |
| | | this.showToast('默认名片不能删除'); |
| | | return; |
| | | } |
| | | |
| | | |
| | | uni.showModal({ |
| | | title: '提示', |
| | | content: '确定要删除这个名片吗?', |
| | |
| | | // 删除成功,更新列表 |
| | | 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 |
| | |
| | | |
| | | .card-list { |
| | | width: calc(100% - 40rpx); |
| | | height: calc(100vh - 94rpx - 80rpx); |
| | | padding: 0 20rpx 20rpx; |
| | | |
| | | .card-item { |
| | |
| | | input, |
| | | select, |
| | | figure, |
| | | figcaption, |
| | | figcaption |
| | | { |
| | | padding: 0; |
| | | margin: 0; |
| | |
| | | |
| | | .sel-width { |
| | | width: 280px !important; |
| | | } |
| | | } |
| New file |
| | |
| | | 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; |
| | |
| | | <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> |
| | |
| | | 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'; |
| | |
| | | Apply, |
| | | User, |
| | | Cash, |
| | | Order, |
| | | Setting, |
| | | Grade, |
| | | Auth |
| | |
| | | value: '提现申请', |
| | | path:'/plus/operations/cash/index' |
| | | }, |
| | | { |
| | | key: 'order', |
| | | value: '运营订单', |
| | | path:'/plus/operations/order/index' |
| | | }, |
| | | // { |
| | | // key: 'grade', |
| | | // value: '等级管理', |
| | |
| | | </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'; |
| | |
| | | /*获取数据*/ |
| | | getData() { |
| | | let self = this; |
| | | PlusApi.regionSet({}, true) |
| | | PlusApi.operationsSet({}, true) |
| | | .then(res => { |
| | | self.settingData = res.data; |
| | | self.loading=false; |
| | |
| | | |
| | | <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 |
| | |
| | | <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> |
| | |
| | | </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: { |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import PlusApi from '@/api/plus/region.js'; |
| | | import PlusApi from '@/api/plus/operations.js'; |
| | | |
| | | export default { |
| | | data() { |
| | |
| | | </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: { |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import PlusApi from '@/api/plus/region.js'; |
| | | import PlusApi from '@/api/plus/operations.js'; |
| | | |
| | | export default { |
| | | data() { |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import PlusApi from '@/api/plus/region.js'; |
| | | import PlusApi from '@/api/plus/operations.js'; |
| | | |
| | | export default { |
| | | data() { |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import PlusApi from '@/api/plus/region.js'; |
| | | import PlusApi from '@/api/plus/operations.js'; |
| | | |
| | | export default { |
| | | data() { |