2 files added
26 files modified
| | |
| | | 'link_name' => $this['user_name'], |
| | | 'business_id' => $this['business_id'], |
| | | 'category_id' => $this['category_id'], |
| | | 'referee_id' => $this['referee_id'], |
| | | 'agent_id' => self::$agent_id |
| | | ]; |
| | | // 供应商状态,如果类目保证金为0,则直接通过,否则需要交纳保证金 |
| | |
| | | $is_vip = $this->isVipUser(); |
| | | if ($is_vip) { |
| | | event('VipUserGrade', $this->user['user_id']); |
| | | $this->vip = VipUserModel::detail($this->user['user_id']); |
| | | } |
| | | return $this->renderSuccess('', [ |
| | | // 当前是否为VIP用户 |
| | |
| | | |
| | | use app\api\controller\Controller; |
| | | use app\api\model\product\Product as ProductModel; |
| | | use app\supplier\service\ProductService; |
| | | |
| | | /** |
| | | * 供应商产品 |
| | |
| | | } |
| | | return $this->renderSuccess('操作成功'); |
| | | } |
| | | |
| | | /** |
| | | * 获取添加商品所需的基础数据 |
| | | */ |
| | | public function getBaseData() |
| | | { |
| | | $data = ProductService::getEditData(null, 'add', $this->supplierUser['shop_supplier_id']); |
| | | return $this->renderSuccess('', $data); |
| | | } |
| | | |
| | | /** |
| | | * 添加商品 |
| | | */ |
| | | public function add() |
| | | { |
| | | $data = $this->postData(); |
| | | $params = json_decode($data['params'], true); |
| | | $params['shop_supplier_id'] = $this->supplierUser['shop_supplier_id']; |
| | | |
| | | $model = new ProductModel; |
| | | if ($model->add($params)) { |
| | | return $this->renderSuccess('添加成功'); |
| | | } |
| | | return $this->renderError($model->getError() ?: '添加失败'); |
| | | } |
| | | |
| | | /** |
| | | * 获取编辑商品所需的数据 |
| | | */ |
| | | public function getEditData() |
| | | { |
| | | $data = $this->postData(); |
| | | $product_id = $data['product_id']; |
| | | // 获取商品数据 |
| | | $model = ProductModel::detail($product_id); |
| | | if($this->supplierUser['shop_supplier_id'] != $model['shop_supplier_id']){ |
| | | return $this->renderError('非法请求'); |
| | | } |
| | | |
| | | $result = ProductService::getEditData($model, 'edit', $this->supplierUser['shop_supplier_id']); |
| | | $result['model'] = $model; |
| | | return $this->renderSuccess('', $result); |
| | | } |
| | | |
| | | /** |
| | | * 编辑商品 |
| | | */ |
| | | public function edit() |
| | | { |
| | | $data = $this->postData(); |
| | | $product_id = $data['product_id']; |
| | | $params = json_decode($data['params'], true); |
| | | |
| | | // 获取商品数据 |
| | | $model = ProductModel::detail($product_id); |
| | | if($this->supplierUser['shop_supplier_id'] != $model['shop_supplier_id']){ |
| | | return $this->renderError('非法请求'); |
| | | } |
| | | |
| | | if ($model->edit($params)) { |
| | | return $this->renderSuccess('编辑成功'); |
| | | } |
| | | return $this->renderError($model->getError() ?: '编辑失败'); |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | use app\api\model\plus\seckill\Active as ActiveModel; |
| | | use app\common\model\product\Product as ProductModel; |
| | | use app\common\model\settings\Setting; |
| | | use app\common\service\product\BaseProductService; |
| | | use app\common\library\helper; |
| | | use app\api\model\supplier\Supplier as SupplierModel; |
| | |
| | | use app\common\model\supplier\User as SupplierUserModel; |
| | | use app\api\model\user\CardRecord as CardRecordModel; // 会员卡 by lyzflash |
| | | use app\common\model\plus\advance\Product as AdvanceProductModel; |
| | | use app\supplier\model\product\ProductSku; |
| | | |
| | | /** |
| | | * 商品模型 |
| | |
| | | { |
| | | return $this->save(['product_status' => $data['product_status']]); |
| | | } |
| | | |
| | | public function add($data) |
| | | { |
| | | if (!isset($data['image']) || empty($data['image'])) { |
| | | $this->error = '请上传商品图片'; |
| | | return false; |
| | | } |
| | | //如果支持核销 by yj |
| | | if ($data['is_virtual'] && $data['is_verify']) { |
| | | if ($data['verify_type'] == 20) { |
| | | if (empty($data['verify_time'])) { |
| | | $this->error = '请选择核销有效时间'; |
| | | return false; |
| | | } |
| | | $data["verify_start_time"] = strtotime(array_shift($data['verify_time'])); |
| | | $data["verify_end_time"] = strtotime(array_pop($data['verify_time'])); |
| | | } |
| | | if ($data['verify_store_ids']) { |
| | | $data['verify_store_ids'] = implode(',', array_unique($data['verify_store_ids'])); |
| | | } |
| | | } |
| | | $data['content'] = isset($data['content']) ? $data['content'] : ''; |
| | | $data['app_id'] = $data['sku']['app_id'] = self::$app_id; |
| | | |
| | | $this->processContent($data); |
| | | // 开启事务 |
| | | $this->startTrans(); |
| | | try { |
| | | // 添加商品 |
| | | $this->save($data); |
| | | // 商品规格 |
| | | $this->addProductSpec($data); |
| | | // 商品图片 |
| | | $this->addProductImages($data['image'], $data['shop_supplier_id']); |
| | | // 商品详情图片 |
| | | if($data['is_picture'] == 1){ |
| | | $this->addProductContentImages($data['contentImage']); |
| | | } |
| | | $this->commit(); |
| | | return true; |
| | | } catch (\Exception $e) { |
| | | $this->error = $e->getMessage(); |
| | | $this->rollback(); |
| | | return false; |
| | | } |
| | | } |
| | | /** |
| | | * 处理内容 |
| | | */ |
| | | private function processContent(&$data) |
| | | { |
| | | $pattern = "/src=[\"\'](.*?)[\"\']/is"; |
| | | preg_match_all($pattern, $data['content'], $match); |
| | | } |
| | | /** |
| | | * 添加商品图片 |
| | | */ |
| | | private function addProductImages($images, $shop_supplier_id) |
| | | { |
| | | $this->image()->delete(); |
| | | $data = array_map(function ($images) use ($shop_supplier_id) { |
| | | isset($images['file_id']) && $image_id = $images['file_id']; |
| | | isset($images['image_id']) && $image_id = $images['image_id']; |
| | | if(!isset($images['file_id']) && !isset($images['image_id'])){ |
| | | $image_id = $images['file_path']; |
| | | } |
| | | return [ |
| | | 'image_id' => $image_id, |
| | | 'app_id' => self::$app_id |
| | | ]; |
| | | }, $images); |
| | | return $this->image()->saveAll($data); |
| | | } |
| | | |
| | | /** |
| | | * 添加商品详情图片 |
| | | */ |
| | | private function addProductContentImages($images) |
| | | { |
| | | $this->contentImage()->delete(); |
| | | $data = array_map(function ($images) { |
| | | return [ |
| | | 'image_id' => isset($images['file_id']) ? $images['file_id'] : $images['image_id'], |
| | | 'image_type' => 1, |
| | | 'app_id' => self::$app_id |
| | | ]; |
| | | }, $images); |
| | | return $this->contentImage()->saveAll($data); |
| | | } |
| | | |
| | | /** |
| | | * 编辑商品 |
| | | */ |
| | | public function edit($data,$shop_supplier_id) |
| | | { |
| | | if (!isset($data['image']) || empty($data['image'])) { |
| | | $this->error = '请上传商品图片'; |
| | | return false; |
| | | } |
| | | //如果支持核销 by yj |
| | | if ($data['is_verify']) { |
| | | if ($data['verify_type'] == 20) { |
| | | if (empty($data['verify_time'])) { |
| | | $this->error = '请选择核销有效时间'; |
| | | return false; |
| | | } |
| | | $data["verify_start_time"] = strtotime(array_shift($data['verify_time'])); |
| | | $data["verify_end_time"] = strtotime(array_pop($data['verify_time'])); |
| | | } |
| | | if ($data['verify_store_ids']) { |
| | | $data['verify_store_ids'] = implode(',', array_unique($data['verify_store_ids'])); |
| | | } |
| | | } |
| | | $data['spec_type'] = isset($data['spec_type']) ? $data['spec_type'] : $this['spec_type']; |
| | | $data['content'] = isset($data['content']) ? $data['content'] : ''; |
| | | $data['app_id'] = $data['sku']['app_id'] = self::$app_id; |
| | | $productSkuIdList = helper::getArrayColumn(($this['sku']), 'product_sku_id'); |
| | | return $this->transaction(function () use ($data, $productSkuIdList) { |
| | | // 商品状态,如果已审核过的,看平台配置是否需要再次审核 |
| | | $edit_audit = Setting::getItem('store')['edit_audit']; |
| | | if($edit_audit && $data['audit_status'] == 0){ |
| | | $data['audit_status'] = 0; |
| | | } |
| | | // 保存商品 |
| | | $this->save($data); |
| | | // 商品规格 |
| | | $this->addProductSpec($data, true, $productSkuIdList); |
| | | // 商品图片 |
| | | $this->addProductImages($data['image'], $this['shop_supplier_id']); |
| | | // 商品详情图片 |
| | | if($data['is_picture'] == 1){ |
| | | $this->addProductContentImages($data['contentImage']); |
| | | } |
| | | return true; |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 添加商品规格 |
| | | */ |
| | | private function addProductSpec($data, $isUpdate = false, $productSkuIdList = []) |
| | | { |
| | | // 更新模式: 先删除所有规格 |
| | | $model = new ProductSku; |
| | | $isUpdate && $model->removeAll($this['product_id']); |
| | | $stock = 0;//总库存 |
| | | $product_price = 0; |
| | | $line_price = 0; |
| | | // 商城设置 |
| | | $settings = Setting::getItem('store'); |
| | | // 添加规格数据 |
| | | if ($data['spec_type'] == '10') { |
| | | // 删除多规格遗留数据 |
| | | $isUpdate && $model->removeSkuBySpec($this['product_id']); |
| | | // 单规格 |
| | | $this->sku()->save($data['sku']); |
| | | $stock = $data['sku']['stock_num']; |
| | | $product_price = $data['sku']['product_price']; |
| | | $line_price = $data['sku']['line_price']; |
| | | } else if ($data['spec_type'] == '20') { |
| | | // 添加商品与规格关系记录 |
| | | $model->addProductSpecRel($this['product_id'], $data['spec_many']['spec_attr']); |
| | | // 添加商品sku |
| | | $model->addSkuList($this['product_id'], $data['spec_many']['spec_list'], $productSkuIdList); |
| | | $product_price = $data['spec_many']['spec_list'][0]['spec_form']['product_price']; |
| | | foreach ($data['spec_many']['spec_list'] as &$item) { |
| | | $stock += $item['spec_form']['stock_num']; |
| | | if($item['spec_form']['product_price'] < $product_price){ |
| | | $product_price = $item['spec_form']['product_price']; |
| | | } |
| | | if($item['spec_form']['line_price'] < $line_price){ |
| | | $line_price = $item['spec_form']['line_price']; |
| | | } |
| | | } |
| | | } |
| | | $save_data = [ |
| | | 'product_stock' => $stock, |
| | | 'product_price' => $product_price, |
| | | 'line_price' => $line_price |
| | | ]; |
| | | // 商品价格 |
| | | $save_data['product_price'] = $product_price; |
| | | $this->save($save_data); |
| | | } |
| | | } |
| | |
| | | use app\common\model\supplier\User as SupplierUserModel; |
| | | use app\api\model\user\Favorite as FavoriteModel; |
| | | use app\api\model\product\Product as ProductModel; |
| | | |
| | | use app\api\model\plus\team\Apply as teamApplyModel; |
| | | /** |
| | | * 供应商模型类 |
| | | */ |
| | |
| | | $data['shop_supplier_id'] = $this['shop_supplier_id']; |
| | | $data['is_super'] = 1; |
| | | $SupplierUserModel->save($data); |
| | | (new teamApplyModel())->becomeTeamByAgent($data['referee_id'],70,$data['app_id']); |
| | | $this->commit(); |
| | | return true; |
| | | } catch (\Exception $e) { |
| | |
| | | const REFERRAL = 20; // 推广复购 |
| | | const VIP_SUBSIDY = 30; // 下级收益补贴 |
| | | const DIRECT_REFEREE = 40; // 平台直推佣金 |
| | | const DIRECT_SUPPLIER = 50; // 直推供应商佣金 |
| | | |
| | | |
| | | |
| | | /** |
| | | * 获取VIP专区订单类型名称 |
| | |
| | | public static function getTypeName() |
| | | { |
| | | return [ |
| | | self::NORMAL => '推广', |
| | | self::REFERRAL => '推广复购', |
| | | self::NORMAL => '推广佣金', |
| | | self::REFERRAL => '推广复购佣金', |
| | | self::VIP_SUBSIDY => '下级收益补贴', |
| | | self::DIRECT_REFEREE => '平台直推佣金', |
| | | self::DIRECT_SUPPLIER => '直推商家佣金', |
| | | ]; |
| | | } |
| | | |
| | |
| | | use app\common\model\plus\agent\User as AgentUserModel; |
| | | use app\common\model\plus\team\User as TeamUserModel; |
| | | use app\common\model\plus\team\Order as TeamOrderModel; |
| | | use app\common\model\plus\vip\User as VipUserModel; |
| | | use app\common\model\plus\vip\Order as VipOrderModel; |
| | | |
| | | /** |
| | | * 股东申请模型 |
| | |
| | | return ['text' => $method[$value], 'value' => $value]; |
| | | } |
| | | |
| | | } |
| | | /** |
| | | * 统计VIP会员直接推荐数量 |
| | | * @param $userId |
| | | * @return int |
| | | */ |
| | | public function countVipRecommendations($userId) |
| | | { |
| | | return VipUserModel::where('referee_id', '=', $userId)->count(); |
| | | } |
| | | |
| | | /** |
| | | * 统计企业商户入驻数量 |
| | | * @param $userId |
| | | * @return int |
| | | */ |
| | | public function countMerchantSettlements($userId) |
| | | { |
| | | // 假设商家入驻与推广团队的关联字段是referee_id |
| | | // 需要根据实际数据库结构调整 |
| | | return \app\common\model\Shop::where('referee_id', '=', $userId)->count(); |
| | | } |
| | | |
| | | /** |
| | | * 统计VIP专区商品购买次数 |
| | | * @param $userId |
| | | * @return int |
| | | */ |
| | | public function countSelfVipPurchases($userId) |
| | | { |
| | | return VipOrderModel::where('user_id', '=', $userId) |
| | | ->where('is_vip', '=', 1) |
| | | ->count(); |
| | | } |
| | | |
| | | /** |
| | | * 检查股东候选人是否满足新的三个条件 |
| | | * @param $userId |
| | | * @param $appId |
| | | * @return bool |
| | | */ |
| | | public function checkNewShareholderConditions($userId, $appId) |
| | | { |
| | | $config = Setting::getItem('basic', $appId); |
| | | |
| | | // 1. 检查VIP会员直接推荐数量 |
| | | $vipRecommendCount = $this->countVipRecommendations($userId); |
| | | if ($vipRecommendCount < $config['vip_recommend_count']) { |
| | | return false; |
| | | } |
| | | |
| | | // 2. 检查企业商户入驻数量 |
| | | $merchantCount = $this->countMerchantSettlements($userId); |
| | | if ($merchantCount < $config['merchant_settle_count']) { |
| | | return false; |
| | | } |
| | | |
| | | // 3. 检查VIP专区商品购买次数 |
| | | $selfVipPurchaseCount = $this->countSelfVipPurchases($userId); |
| | | if ($selfVipPurchaseCount < $config['self_vip_purchase_count']) { |
| | | return false; |
| | | } |
| | | |
| | | // 所有条件都满足 |
| | | return true; |
| | | } |
| | | |
| | | }, |
| | |
| | | <?php
|
| | |
|
| | | namespace app\common\model\plus\team;
|
| | |
|
| | | use app\common\model\BaseModel;
|
| | | use app\common\model\plus\agent\User as AgentUserModel;
|
| | |
|
| | | /**
|
| | | * 队长申请模型
|
| | | */
|
| | | class Apply extends BaseModel
|
| | | {
|
| | | protected $name = 'team_apply';
|
| | | protected $pk = 'apply_id';
|
| | |
|
| | | /**
|
| | | * 申请状态
|
| | | * @var array
|
| | | */
|
| | | public $applyStatus = [
|
| | | 10 => '待审核',
|
| | | 20 => '审核通过',
|
| | | 30 => '驳回',
|
| | | ];
|
| | |
|
| | | /**
|
| | | * 申请时间
|
| | | * @param $value
|
| | | * @return false|string
|
| | | */
|
| | | public function getApplyTimeAttr($value)
|
| | | {
|
| | | return date('Y-m-d H:i:s', $value);
|
| | | }
|
| | |
|
| | | /**
|
| | | * 审核时间
|
| | | * @param $value
|
| | | * @return false|int|string
|
| | | */
|
| | | public function getAuditTimeAttr($value)
|
| | | {
|
| | | return $value > 0 ? date('Y-m-d H:i:s', $value) : 0;
|
| | | }
|
| | |
|
| | | /**
|
| | | * 关联推荐人表
|
| | | * @return \think\model\relation\BelongsTo
|
| | | */
|
| | | public function referee()
|
| | | {
|
| | | return $this->belongsTo('app\common\model\user\User', 'referee_id')
|
| | | ->field(['user_id', 'nickName']);
|
| | | }
|
| | |
|
| | | /**
|
| | | * 销商申请记录详情
|
| | | * @param $where
|
| | | * @return array|\think\Model|null
|
| | | * @throws \think\db\exception\DataNotFoundException
|
| | | * @throws \think\db\exception\DbException
|
| | | * @throws \think\db\exception\ModelNotFoundException
|
| | | */
|
| | | public static function detail($where)
|
| | | {
|
| | | $filter = is_array($where) ? $where : ['apply_id' => $where];
|
| | | return (new static())->where($filter)->find();
|
| | | }
|
| | |
|
| | | /**
|
| | | * 根据分销判断成为队长
|
| | | * @param $userId
|
| | | * @param $appId
|
| | | * @return bool
|
| | | */
|
| | | public function becomeTeamByAgent($userId, $become_type, $appId)
|
| | | {
|
| | | //log_write($become_type);
|
| | | // 验证是否设置
|
| | | $config = Setting::getItem('basic', $appId);
|
| | | if (empty($config['is_open'])) {
|
| | | return false;
|
| | | }
|
| | | if ($config['become'] != $become_type) {
|
| | | return false;
|
| | | }
|
| | | $agent = AgentUserModel::detail($userId);
|
| | | if (!$agent) {
|
| | | return false;
|
| | | }
|
| | | $becomeTeam = false;
|
| | | //分销商总数
|
| | | if ($become_type == '40') {
|
| | | $agent_total = $agent['first_num'] + $agent['second_num'] + $agent['third_num'];
|
| | | if ($agent_total >= $config['totalfxs_down']) {
|
| | | $becomeTeam = true;
|
| | | }
|
| | | }
|
| | | //分销佣金总数
|
| | | if ($become_type == '50') {
|
| | | $agent_money = $agent['total_money'] + $agent['money'] + $agent['freeze_money'];
|
| | | if ($agent_money >= $config['total_money']) {
|
| | | $becomeTeam = true;
|
| | | }
|
| | | }
|
| | | // 新增队长用户
|
| | | if ($becomeTeam) {
|
| | | User::add($userId, [
|
| | | 'referee_id' => $agent['referee_id'], //推荐人id
|
| | | 'app_id' => $appId,
|
| | | ]);
|
| | | }
|
| | | return true;
|
| | | }
|
| | |
|
| | | /**
|
| | | * 审核状态
|
| | | * @param $value
|
| | | * @return array
|
| | | */
|
| | | public function getApplyStatusAttr($value)
|
| | | {
|
| | | $method = [10 => '待审核', 20 => '审核通过', '30' => '驳回'];
|
| | | return ['text' => $method[$value], 'value' => $value];
|
| | | }
|
| | |
|
| | | /**
|
| | | * 审核方式
|
| | | * @param $value
|
| | | * @return array
|
| | | */
|
| | | public function getApplyTypeAttr($value)
|
| | | {
|
| | | $method = [10 => '后台审核', 20 => '无需审核'];
|
| | | return ['text' => $method[$value], 'value' => $value];
|
| | | }
|
| | |
|
| | | } |
| | | <?php
namespace app\common\model\plus\team;
use app\common\model\BaseModel;
use app\common\model\plus\agent\User as AgentUserModel;
/**
* 队长申请模型
*/
class Apply extends BaseModel
{
protected $name = 'team_apply';
protected $pk = 'apply_id';
/**
* 申请状态
* @var array
*/
public $applyStatus = [
10 => '待审核',
20 => '审核通过',
30 => '驳回',
];
/**
* 申请时间
* @param $value
* @return false|string
*/
public function getApplyTimeAttr($value)
{
return date('Y-m-d H:i:s', $value);
}
/**
* 审核时间
* @param $value
* @return false|int|string
*/
public function getAuditTimeAttr($value)
{
return $value > 0 ? date('Y-m-d H:i:s', $value) : 0;
}
/**
* 关联推荐人表
* @return \think\model\relation\BelongsTo
*/
public function referee()
{
return $this->belongsTo('app\common\model\user\User', 'referee_id')
->field(['user_id', 'nickName']);
}
/**
* 销商申请记录详情
* @param $where
* @return array|\think\Model|null
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public static function detail($where)
{
$filter = is_array($where) ? $where : ['apply_id' => $where];
return (new static())->where($filter)->find();
}
/**
* 根据分销判断成为队长
* @param $userId
* @param $appId
* @return bool
*/
public function becomeTeamByAgent($userId, $become_type, $appId)
{
//log_write($become_type);
// 验证是否设置
$config = Setting::getItem('basic', $appId);
if (empty($config['is_open'])) {
return false;
}
if ($config['become'] != $become_type) {
return false;
}
$agent = AgentUserModel::detail($userId);
if (!$agent) {
return false;
}
$becomeTeam = false;
//分销商总数
if ($become_type == '40') {
$agent_total = $agent['first_num'] + $agent['second_num'] + $agent['third_num'];
if ($agent_total >= $config['totalfxs_down']) {
$becomeTeam = true;
}
}
//分销佣金总数
if ($become_type == '50') {
$agent_money = $agent['total_money'] + $agent['money'] + $agent['freeze_money'];
if ($agent_money >= $config['total_money']) {
$becomeTeam = true;
}
}
if($become_type == '70'){
$vipNum=(new \app\common\model\user\User)->where(['referee_id' =>$userId,'grade_id'=>57,'is_delete'=>0])->count();
$supplierNum=(new \app\common\model\user\User)->where(['referee_id' =>$userId,'is_delete'=>0])->count();
if ($vipNum >= $config['totalvip_down'] && $supplierNum >= $config['totalsh_down']) {
$BecomeTeam = true;
}
}
// 新增队长用户
if ($BecomeTeam) {
User::add($userId, [
'referee_id' => $agent['referee_id'], //推荐人id
'app_id' => $appId,
]);
}
return true;
}
/**
* 审核状态
* @param $value
* @return array
*/
public function getApplyStatusAttr($value)
{
$method = [10 => '待审核', 20 => '审核通过', '30' => '驳回'];
return ['text' => $method[$value], 'value' => $value];
}
/**
* 审核方式
* @param $value
* @return array
*/
public function getApplyTypeAttr($value)
{
$method = [10 => '后台审核', 20 => '无需审核'];
return ['text' => $method[$value], 'value' => $value];
}
} |
| | |
| | | <?php
namespace app\common\model\plus\team;
use app\common\enum\user\grade\ChangeTypeEnum;
use app\common\model\BaseModel;
/**
* 队长用户模型
*/
class User extends BaseModel
{
protected $name = 'team_user';
protected $pk = 'user_id';
/**
* 关联会员等级表
*/
public function grade()
{
return $this->belongsTo('app\\common\\model\\plus\\team\\Grade', 'grade_id', 'grade_id');
}
/**
* 关联会员记录表
* @return \think\model\relation\BelongsTo
*/
public function user()
{
return $this->belongsTo('app\\common\\model\\user\\User');
}
/**
* 关联队长关系表
* @return \think\model\relation\BelongsTo
*/
public function referee()
{
return $this->belongsTo('app\\common\\model\\plus\\team\\Referee', 'user_id', 'user_id');
}
/**
* 详情
*/
public static function detail($user_id, $with = ['user', 'referee'])
{
return (new static())->with($with)->find($user_id);
}
/**
* 是否为队长
*/
public static function isteamUser($user_id)
{
$team = self::detail($user_id);
return !!$team && !$team['is_delete'];
}
/**
* 新增队长用户记录
* @param $user_id
* @param $data
* @return bool
*/
public static function add($user_id, $data)
{
$model = static::detail($user_id) ?: new static;
$model->save(array_merge([
'user_id' => $user_id,
'is_delete' => 0,
'app_id' => $model::$app_id
], $data));
//更新队长成员
Referee::createTeam($user_id);
// 更新改用户队长的成员数量
$heads_id = Referee::getHeadsId($user_id);
if ($heads_id) {
User::setMemberInc($heads_id);
}
return true;
}
/**
* 发放队长佣金
* @param $user_id
* @param $money
* @return bool
*/
public static function grantMoney($user_id, $money, $bonus_type)
{
// 队长详情
$model = static::detail($user_id);
if (!$model || $model['is_delete']) {
return false;
}
// 累积队长可提现佣金
$model->where('user_id', '=', $user_id)->inc('money', $money)->update();
// 记录队长资金明细
Capital::add([
'user_id' => $user_id,
'flow_type' => 10,
'money' => $money,
'bonus_type' => $bonus_type['value'],
'describe' => '订单分红结算-' . $bonus_type['text'],
'app_id' => $model['app_id'],
]);
return true;
}
/**
* 批量设置队长等级
*/
public function upgradeGrade($user, $upgradeGrade)
{
// 更新会员等级的数据
$this->where('user_id', '=', $user['user_id'])
->update([
'grade_id' => $upgradeGrade['grade_id']
]);
(new GradeLog)->save([
'old_grade_id' => $user['grade_id'],
'new_grade_id' => $upgradeGrade['grade_id'],
'change_type' => ChangeTypeEnum::AUTO_UPGRADE,
'user_id' => $user['user_id'],
'app_id' => $user['app_id']
]);
return true;
}
/**
* 累计队长成员数量
*/
public static function setMemberInc($user_id)
{
if(empty($user_id)) {
return false;
}
$model = static::detail($user_id);
return $model->save([
'total_num' => Referee::teamCount($user_id)
]);
}
} |
| | | <?php
namespace app\common\model\plus\team;
use app\common\enum\user\grade\ChangeTypeEnum;
use app\common\model\BaseModel;
/**
* 队长用户模型
*/
class User extends BaseModel
{
protected $name = 'team_user';
protected $pk = 'user_id';
/**
* 关联会员等级表
*/
public function grade()
{
return $this->belongsTo('app\\common\\model\\plus\\team\\Grade', 'grade_id', 'grade_id');
}
/**
* 关联会员记录表
* @return \think\model\relation\BelongsTo
*/
public function user()
{
return $this->belongsTo('app\\common\\model\\user\\User');
}
/**
* 关联队长关系表
* @return \think\model\relation\BelongsTo
*/
public function referee()
{
return $this->belongsTo('app\\common\\model\\plus\\team\\Referee', 'user_id', 'user_id');
}
/**
* 详情
*/
public static function detail($user_id, $with = ['user', 'referee'])
{
return (new static())->with($with)->find($user_id);
}
/**
* 是否为队长
*/
public static function isteamUser($user_id)
{
$team = self::detail($user_id);
return !!$team && !$team['is_delete'];
}
/**
* 新增队长用户记录
* @param $user_id
* @param $data
* @return bool
*/
public static function add($user_id, $data)
{
$model = static::detail($user_id) ?: new static;
$model->save(array_merge([
'user_id' => $user_id,
'grade_id' => Grade::getDefaultGradeId(),
'is_delete' => 0,
'app_id' => $model::$app_id
], $data));
//更新队长成员
Referee::createTeam($user_id);
// 更新改用户队长的成员数量
$heads_id = Referee::getHeadsId($user_id);
if ($heads_id) {
User::setMemberInc($heads_id);
}
return true;
}
/**
* 发放队长佣金
* @param $user_id
* @param $money
* @return bool
*/
public static function grantMoney($user_id, $money, $bonus_type)
{
// 队长详情
$model = static::detail($user_id);
if (!$model || $model['is_delete']) {
return false;
}
// 累积队长可提现佣金
$model->where('user_id', '=', $user_id)->inc('money', $money)->update();
// 记录队长资金明细
Capital::add([
'user_id' => $user_id,
'flow_type' => 10,
'money' => $money,
'bonus_type' => $bonus_type['value'],
'describe' => '订单分红结算-' . $bonus_type['text'],
'app_id' => $model['app_id'],
]);
return true;
}
/**
* 批量设置队长等级
*/
public function upgradeGrade($user, $upgradeGrade)
{
// 更新会员等级的数据
$this->where('user_id', '=', $user['user_id'])
->update([
'grade_id' => $upgradeGrade['grade_id']
]);
(new GradeLog)->save([
'old_grade_id' => $user['grade_id'],
'new_grade_id' => $upgradeGrade['grade_id'],
'change_type' => ChangeTypeEnum::AUTO_UPGRADE,
'user_id' => $user['user_id'],
'app_id' => $user['app_id']
]);
return true;
}
/**
* 累计队长成员数量
*/
public static function setMemberInc($user_id)
{
if(empty($user_id)) {
return false;
}
$model = static::detail($user_id);
return $model->save([
'total_num' => Referee::teamCount($user_id)
]);
}
} |
| | |
| | | protected $name = 'vip_area_grade'; |
| | | protected $pk = 'grade_id'; |
| | | |
| | | public function setRefereeGradeIdsAttr($value) |
| | | { |
| | | return json_encode( $value); |
| | | } |
| | | public function getRefereeGradeIdsAttr($value) |
| | | { |
| | | return json_decode($value, true); |
| | | } |
| | | /** |
| | | * 获取详情 |
| | | */ |
| | |
| | | if ($deadlineTime > time()) { |
| | | continue; |
| | | } |
| | | |
| | | // 发放推广佣金(首次购买VIP商品) |
| | | if ($model['vip_area_type'] == 10) { |
| | | $model['vip_area_user_id'] > 0 && User::grantMoney($model['vip_area_user_id'], $model['vip_area_money'], '推广佣金'); |
| | | if ($model['vip_area_user_id'] != 0) { |
| | | User::grantMoney($model['vip_area_user_id'], $model['vip_area_money'], VipAreaTypeEnum::getTypeName()[$model['vip_area_type']]); |
| | | } |
| | | |
| | | // 发放推广复购佣金(非首次购买VIP商品) |
| | | if ($model['vip_area_type'] == 20) { |
| | | $model['vip_area_user_id'] > 0 && User::grantMoney($model['vip_area_user_id'], $model['vip_area_money'], '推广复购佣金'); |
| | | } |
| | | |
| | | // 发放VIP专区补贴给下级用户(当下级获得推广佣金或复购佣金时) |
| | | if ($model['vip_area_type'] == 10 || $model['vip_area_type'] == 20) { |
| | | // 获取下级用户的推荐人(即上级用户) |
| | |
| | | if ($vipUser['grade']['operating_subsidy']>0){ |
| | | // 获取补贴比例设置 |
| | | $subsidyRate = $vipUser['grade']['operating_subsidy']; |
| | | |
| | | // 计算VIP专区补贴 |
| | | $subsidyAmount = bcmul($model['vip_area_money'], bcdiv((string)$subsidyRate, '100', 4), 2); |
| | | User::grantMoney($superiorUser['referee_id'], $subsidyAmount, 'VIP专区补贴'); |
| | | |
| | | // 记录分销订单 |
| | | self::createDistributionOrder($order, $superiorUser['referee_id'], $subsidyAmount, 'vip_subsidy',$model['vip_area_money']); |
| | | } |
| | | |
| | | } |
| | | } |
| | | |
| | |
| | | if (!$setting['is_open']) { |
| | | return false; |
| | | } |
| | | |
| | | // 获取当前买家的推荐人信息 |
| | | $userModel = UserModel::detail($order['user_id']); |
| | | if (!$userModel || !$userModel['referee_id']) { |
| | | return false; |
| | | } |
| | | |
| | | // 检查推荐人是否为VIP专区用户 |
| | | $vipUser = User::detail($userModel['referee_id']); |
| | | if (!$vipUser) { |
| | | return false; |
| | | } |
| | | |
| | | // 获取VIP等级设置 |
| | | $vipGrade = Grade::detail($vipUser['grade_id']); |
| | | if (!$vipGrade) { |
| | | return false; |
| | | } |
| | | // 验证是否设置 |
| | | $config = Setting::getItem('basic', $order['app_id']); |
| | | if (empty($config['become__buy_product_ids'])) { |
| | | return false; |
| | | } |
| | | $data = [ |
| | | 'user_id' => $order['user_id'], |
| | | 'order_id' => $order['order_id'], |
| | | 'order_type' => $order_type, |
| | | 'order_price' => $order['pay_price'], |
| | | 'vip_area_user_id' => $vipUser['user_id'], |
| | | 'referee_id' => $userModel['referee_id'], |
| | | 'vip_area_user_id' => 0, |
| | | 'referee_id' => 0, |
| | | 'vip_area_money' => 0, |
| | | 'vip_area_type' => 0, |
| | | 'is_settled' => 0, |
| | |
| | | $list=[]; |
| | | // 计算佣金金额 |
| | | $orderPrice = bcsub($order['pay_price'], $order['express_price'], 2); |
| | | $purchase_count=(new self())->getPurchaseCount($order['user_id']); |
| | | foreach ($order['product'] as $product){ |
| | | if (in_array($product['product_id'], $config['become__buy_product_ids'])) { |
| | | // 获取商品数量 |
| | | $quantity = $product['total_num']; |
| | | // 为每个商品生成分红订单 |
| | | for ($i = 0; $i < $quantity; $i++) { |
| | | if ($purchase_count==1){ |
| | | $list[]=array_merge($data,['vip_area_type'=>10,'vip_area_money'=>$vipGrade['agent_money'],'is_vip'=>1,'purchase_count'=>$purchase_count]); |
| | | $purchase_count++; |
| | | }else{ |
| | | if ($vipGrade['repurchase_money']>0){ |
| | | $list[]=array_merge($data,['vip_area_type'=>20,'vip_area_money'=>$vipGrade['repurchase_money'],'is_vip'=>1,'purchase_count'=>$purchase_count]); |
| | | $purchase_count++; |
| | | // 获取当前买家的推荐人信息 |
| | | $userModel = UserModel::detail($order['user_id']); |
| | | if (!empty($userModel) && !empty($userModel['referee_id'])) { |
| | | // 检查推荐人是否为VIP专区用户 |
| | | $vipUser = User::detail($userModel['referee_id']); |
| | | if ($vipUser) { |
| | | $data['vip_area_user_id'] = $vipUser['user_id']; |
| | | $data['referee_id'] = $userModel['referee_id']; |
| | | // 获取VIP等级设置 |
| | | $vipGrade = Grade::detail($vipUser['grade_id']); |
| | | if ($vipGrade) { |
| | | $config = Setting::getItem('basic', $order['app_id']); |
| | | if (!empty($config['become__buy_product_ids'])) { |
| | | $purchase_count=(new self())->getPurchaseCount($order['user_id']); |
| | | foreach ($order['product'] as $product){ |
| | | if (in_array($product['product_id'], $config['become__buy_product_ids'])) { |
| | | // 获取商品数量 |
| | | $quantity = $product['total_num']; |
| | | // 为每个商品生成分红订单 |
| | | for ($i = 0; $i < $quantity; $i++) { |
| | | if ($purchase_count==1){ |
| | | $list[]=array_merge($data,['vip_area_type'=>10,'vip_area_money'=>$vipGrade['agent_money'],'is_vip'=>1,'purchase_count'=>$purchase_count]); |
| | | $purchase_count++; |
| | | }else{ |
| | | if ($vipGrade['repurchase_money']>0){ |
| | | $list[]=array_merge($data,['vip_area_type'=>20,'vip_area_money'=>$vipGrade['repurchase_money'],'is_vip'=>1,'purchase_count'=>$purchase_count]); |
| | | $purchase_count++; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | $directReferralsCount=0; |
| | | $user=UserModel::detail($order['user_id']); |
| | | if (!empty($user['referee_id'])){ |
| | | // 检查推荐人是否满足直推条件(直推用户数量) |
| | | $directReferralsCount = UserModel::where('referee_id', '=', $user['referee_id'])->count(); |
| | | } |
| | | $requiredReferralCount = $setting['referee_buy_count'] ?? 0; |
| | | if ($vipGrade['commission']>0 && $directReferralsCount >= $requiredReferralCount){ |
| | | // 计算平台直推佣金金额 |
| | | $commissionAmount = bcmul($orderPrice, bcdiv($vipGrade['commission'], '100', 4), 2); |
| | | $list[]=array_merge($data,['vip_area_type'=>40,'vip_area_money'=>$commissionAmount]); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | $directReferralsCount=0; |
| | | $user=UserModel::detail($order['user_id']); |
| | | if (!empty($user['referee_id'])){ |
| | | // 检查推荐人是否满足直推条件(直推用户数量) |
| | | $directReferralsCount = UserModel::where('referee_id', '=', $user['referee_id'])->count(); |
| | | } |
| | | $requiredReferralCount = $setting['referee_buy_count'] ?? 0; |
| | | if ($vipGrade['commission']>0 && $directReferralsCount >= $requiredReferralCount){ |
| | | // 计算佣金金额 |
| | | $commissionAmount = bcmul($orderPrice, bcdiv($vipGrade['commission'], '100', 4), 2); |
| | | $list[]=array_merge($data,['vip_area_type'=>40,'vip_area_money'=>$commissionAmount]); |
| | | if( $order['supplier']['referee_id']!=0){ |
| | | $supplierReferee=VipUserModel::detail($order['supplier']['referee_id']); |
| | | if ($supplierReferee){ |
| | | $vipGradeSupplier=Grade::detail($supplierReferee['grade_id']); |
| | | if ($vipGradeSupplier['supplier_money']>0){ |
| | | // 计算直推店铺交易额佣金金额 |
| | | $supplier_money = bcmul($orderPrice, bcdiv($vipGrade['supplier_money'], '100', 4), 2); |
| | | $list[]=array_merge($data,['vip_area_type'=>50,'vip_area_money'=>$supplier_money,'vip_area_user_id'=>$supplierReferee['user_id'],'referee_id'=>$supplierReferee['referee_id']]); |
| | | } |
| | | } |
| | | } |
| | | if (empty($list)){ |
| | | return true; |
| | |
| | | { |
| | | $this->save(['money' => $this['money'] - $money,'freeze_money'=>$this['freeze_money']+$money]); |
| | | } |
| | | /** |
| | | * 直推供应商多少人 |
| | | */ |
| | | public function refereeSupplierCount ($referee_id) |
| | | { |
| | | $count = $this->where('referee_id', '=', $referee_id) |
| | | ->where('is_delete', '=', 0) |
| | | ->count(); |
| | | return $count; |
| | | } |
| | | |
| | | } |
| | |
| | | } |
| | | return true; |
| | | } |
| | | /** |
| | | * 获取指定等级推荐人数量 |
| | | */ |
| | | public function getRefereeGradeCount($user_id,$referee_grade_ids) |
| | | { |
| | | return $this->where('referee_id', '=', $user_id)->where('grade_id', 'in', $referee_grade_ids)->count(); |
| | | } |
| | | } |
| | |
| | | namespace app\job\event; |
| | | |
| | | use app\common\model\plus\vip\Grade as GradeModel; |
| | | use app\common\model\plus\vip\User as UserModel; |
| | | use app\common\model\plus\vip\User as vipUserModel; |
| | | use app\common\model\plus\vip\Order as OrderModel; |
| | | |
| | | use app\common\model\supplier\Supplier; |
| | | use app\job\model\user\User as UserModel; |
| | | /** |
| | | * VIP用户等级事件管理 |
| | | */ |
| | |
| | | } |
| | | log_write('VIP用户升级$user_id='.$userId); |
| | | // 用户模型 |
| | | $user = UserModel::detail($userId); |
| | | $user = vipUserModel::detail($userId); |
| | | // 获取所有等级 |
| | | $list = GradeModel::getUsableList($user['app_id']); |
| | | if ($list->isEmpty()) { |
| | |
| | | } |
| | | } |
| | | if($upgradeGrade){ |
| | | if($user['grade_id'] == $upgradeGrade['grade_id']){ |
| | | if($user['grade_id'] == $upgradeGrade['grade_id']||$user['grade']['weight'] >= $upgradeGrade['weight']){ |
| | | return true; |
| | | } |
| | | $this->dologs('setVipUserGrade', [ |
| | |
| | | 'grade_id' => $upgradeGrade['grade_id'], |
| | | ]); |
| | | // 修改会员的等级 |
| | | (new UserModel())->upgradeGrade($user, $upgradeGrade); |
| | | (new vipUserModel())->upgradeGrade($user, $upgradeGrade); |
| | | } |
| | | } |
| | | |
| | |
| | | if($grade['is_purchase_count'] == 1 && $user['user']['purchase_count'] >= $grade['purchase_count']){ |
| | | $purchase_count = true; |
| | | } |
| | | $supplier_count = false; |
| | | $referee_supplier_count = (new Supplier())->where('referee_id', $user['user_id'])->count(); |
| | | // 直推供应商多少人 |
| | | if($grade['is_supplier_count'] == 1 && $referee_supplier_count >= $grade['supplier_count']){ |
| | | $supplier_count = true; |
| | | } |
| | | // 推荐人等级 |
| | | $user_referee_grade_count = (new UserModel())->getRefereeGradeCount($user['user_id'], $grade['referee_grade_ids']); |
| | | $referee_grade_count=false; |
| | | if($grade['is_referee_grade'] == 1 && $user_referee_grade_count >= $grade['referee_grade_count']){ |
| | | $referee_grade_count = true; |
| | | } |
| | | if($grade['condition_type'] == 'and'){ |
| | | $grade['is_purchase_count']!=1 && $purchase_count=true; |
| | | return $purchase_count; |
| | | $grade['is_supplier_count']!=1 && $supplier_count=true; |
| | | $grade['is_referee_grade']!=1 && $referee_grade_count=true; |
| | | return $purchase_count && $supplier_count && $referee_grade_count; |
| | | }else{ |
| | | return $purchase_count; |
| | | return $purchase_count || $supplier_count || $referee_grade_count; |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | use app\common\model\plus\vip\Grade as GradeModel; |
| | | use app\shop\model\plus\vip\User as VipUserModel; |
| | | use app\common\model\user\Grade as UserGradeModel; |
| | | /** |
| | | * VIP专区等级模型 |
| | | */ |
| | |
| | | if($data['is_purchase_count'] == 1){ |
| | | if(!empty($remark)){ |
| | | $remark .= '\r\n'; |
| | | if ($data['condition_type']=='and'){ |
| | | $remark .= "并且"; |
| | | }else{ |
| | | $remark .= "或"; |
| | | } |
| | | } |
| | | $remark .= "购买VIP专区商品次数满{$data['purchase_count']}次"; |
| | | } |
| | | |
| | | if($data['is_supplier_count'] == 1){ |
| | | if(!empty($remark)){ |
| | | $remark .= '\r\n'; |
| | | if ($data['condition_type']=='and'){ |
| | | $remark .= "并且"; |
| | | }else{ |
| | | $remark .= "或"; |
| | | } |
| | | } |
| | | $remark .= "直推商家满{$data['supplier_count']}家"; |
| | | } |
| | | |
| | | if($data['is_referee_grade'] == 1){ |
| | | if(!empty($remark)){ |
| | | $remark .= '\r\n'; |
| | | if ($data['condition_type']=='and'){ |
| | | $remark .= "并且"; |
| | | }else{ |
| | | $remark .= "或"; |
| | | } |
| | | } |
| | | |
| | | |
| | | // 获取用户等级名称 |
| | | $gradeNames = []; |
| | | if (!empty($data['referee_grade_ids']) && is_array($data['referee_grade_ids'])) { |
| | | // 查询用户等级名称 |
| | | $grades = UserGradeModel::where('grade_id', 'in', $data['referee_grade_ids']) |
| | | ->field('name') |
| | | ->select(); |
| | | |
| | | foreach ($grades as $grade) { |
| | | $gradeNames[] = $grade['name']; |
| | | } |
| | | } |
| | | |
| | | $gradeNamesStr = implode('、', $gradeNames); |
| | | $remark .= "直推{$gradeNamesStr}等级会员满{$data['referee_grade_count']}人"; |
| | | } |
| | | |
| | | return $remark; |
| | | } |
| | | } |
| | |
| | | 'link_name' => $this['user_name'], |
| | | 'business_id' => $this['business_id'], |
| | | 'category_id' => $this['category_id'], |
| | | 'referee_id' => $this['referee_id'], |
| | | 'area_id' => $this['area_id'], |
| | | 'app_id' => self::$app_id |
| | | ]; |
| | |
| | | } |
| | | $data['content'] = isset($data['content']) ? $data['content'] : ''; |
| | | $data['app_id'] = $data['sku']['app_id'] = self::$app_id; |
| | | // 设置商品重量默认值 |
| | | $data['product_weight'] = isset($data['product_weight']) ? $data['product_weight'] : 0; |
| | | // 单规格商品,将规格重量赋值给商品重量 |
| | | if (isset($data['spec_type']) && $data['spec_type'] == '10' && isset($data['sku']['weight'])) { |
| | | $data['product_weight'] = $data['sku']['weight']; |
| | | } |
| | | |
| | | $this->processContent($data); |
| | | // 开启事务 |
| | |
| | | $data['spec_type'] = isset($data['spec_type']) ? $data['spec_type'] : $this['spec_type']; |
| | | $data['content'] = isset($data['content']) ? $data['content'] : ''; |
| | | $data['app_id'] = $data['sku']['app_id'] = self::$app_id; |
| | | // 设置商品重量默认值 |
| | | $data['product_weight'] = isset($data['product_weight']) ? $data['product_weight'] : 0; |
| | | // 单规格商品,将规格重量赋值给商品重量 |
| | | if (isset($data['spec_type']) && $data['spec_type'] == '10' && isset($data['sku']['weight'])) { |
| | | $data['product_weight'] = $data['sku']['weight']; |
| | | } |
| | | $productSkuIdList = helper::getArrayColumn(($this['sku']), 'product_sku_id'); |
| | | return $this->transaction(function () use ($data, $productSkuIdList) { |
| | | // 商品状态,如果已审核过的,看平台配置是否需要再次审核 |
| | |
| | | public static function getEditData($model = null, $scene = 'edit', $shop_supplier_id) |
| | | { |
| | | // 商品分类 |
| | | $category = CategoryModel::getCacheTree(); |
| | | $category = CategoryModel::getCacheAll(); |
| | | // 配送模板 |
| | | $delivery = DeliveryModel::getAll($shop_supplier_id); |
| | | // 商品sku数据 |
| | |
| | | created() { |
| | | this.role_id = this.$route.query.role_id; |
| | | /*获取列表*/ |
| | | this.getData(role_id); |
| | | this.getData(this.role_id); |
| | | }, |
| | | methods: { |
| | | /*修改角色*/ |
| | |
| | | //#endif |
| | | } |
| | | } |
| | | }, { |
| | | }, /* { |
| | | "path": "components/upload/upload", |
| | | "style": { |
| | | "app-plus": { |
| | |
| | | //#endif |
| | | } |
| | | } |
| | | }, { |
| | | }, */ { |
| | | "path": "pages/agent/index/index", |
| | | "style": { |
| | | "navigationStyle": "custom", |
| | |
| | | } |
| | | } |
| | | |
| | | }, { |
| | | },{"path": "my_shop/product_add", |
| | | "style": { |
| | | "navigationBarTitleText": "商品添加", |
| | | "enablePullDownRefresh": false, |
| | | "app-plus": { |
| | | //#ifdef H5 |
| | | "titleNView": false |
| | | //#endif |
| | | } |
| | | } |
| | | |
| | | },{"path": "my_shop/product_edit", |
| | | "style": { |
| | | "navigationBarTitleText": "商品编辑", |
| | | "enablePullDownRefresh": false, |
| | | "app-plus": { |
| | | //#ifdef H5 |
| | | "titleNView": false |
| | | //#endif |
| | | } |
| | | } |
| | | |
| | | }, { |
| | | "path": "my_shop/my_shop_data", |
| | | "style": { |
| | | "navigationBarTitleText": "店铺数据", |
| | |
| | | <template> |
| | | <view class="prodcut-list-wrap"> |
| | | <scroll-view scroll-y="true" :style="'height:' + scrollviewHigh + 'px;'" class="scroll-Y" lower-threshold="50" |
| | | <scroll-view scroll-y="true" :style="'height:' + (scrollviewHigh - 120) + 'px;'" class="scroll-Y" lower-threshold="50" |
| | | @scrolltolower="scrolltolowerFunc"> |
| | | <view class="shop"> |
| | | <view class="shop_head"> |
| | |
| | | <view class="shop_body" v-if="!loading"> |
| | | <view class="shop_body_l_item" v-for="(item,index) in product_list" :key="index" > |
| | | <view class="d-s-c mb20"> |
| | | <view class="shop_body_l_item_img"> |
| | | <view class="shop_body_l_item_img" @click="editProduct(item.product_id)"> |
| | | <image class="item_img" :src="item.product_image" mode="aspectFill"></image> |
| | | </view> |
| | | <view class=" flex-1"> |
| | | <view class="shop_body_l_item_info_title h1">{{item.product_name}}</view> |
| | | <view class="shop_body_l_item_info_title h1" @click="editProduct(item.product_id)">{{item.product_name}}</view> |
| | | <view class="shop_body_l_item_info_price h2 red">¥<text class="h1">{{item.product_price}}</text></view> |
| | | <view class="d-b-c"> |
| | | <view>库存:{{item.product_stock}}</view> |
| | | <button class='shop_body_b_btn edit-btn' @click="editProduct(item.product_id)">编辑</button> |
| | | <button v-if="type_active=='sell'" type="warn" class='shop_body_b_btn' @click="operation(item.product_id,20)">下架</button> |
| | | <text v-if="type_active=='audit'" class="audit_txt">审核中</text> |
| | | <button v-if="type_active=='lower'" type="warn" class='shop_body_b_btn' @click="operation(item.product_id,10)">上架</button> |
| | |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view class="d-c-c p30" v-if="product_list.length==0 && !loading"> |
| | | <text class="iconfont icon-wushuju"></text> |
| | | <text class="cont">亲,暂无相关记录哦</text> |
| | | </view> |
| | | <uni-load-more v-else :loadingType="loadingType"></uni-load-more> |
| | | </view> |
| | | <view class="d-c-c p30" v-if="product_list.length==0 && !loading"> |
| | | <text class="iconfont icon-wushuju"></text> |
| | | <text class="cont">亲,暂无相关记录哦</text> |
| | | </view> |
| | | <uni-load-more v-else :loadingType="loadingType"></uni-load-more> |
| | | </scroll-view> |
| | | |
| | | <!-- 添加商品按钮 --> |
| | | <view class="add-product-btn" @click="addProduct"> |
| | | <text class="btn-text">+ 添加商品</text> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | self.getData(self.type_active); |
| | | |
| | | }) |
| | | }, |
| | | |
| | | // 添加商品 |
| | | addProduct() { |
| | | uni.navigateTo({ |
| | | url: '/pages/user/my_shop/product_add?shop_supplier_id=' + this.shop_supplier_id |
| | | }); |
| | | }, |
| | | |
| | | // 编辑商品 |
| | | editProduct(product_id) { |
| | | uni.navigateTo({ |
| | | url: '/pages/user/my_shop/product_edit?product_id=' + product_id + '&shop_supplier_id=' + this.shop_supplier_id |
| | | }); |
| | | } |
| | | } |
| | | } |
| | |
| | | font-size: 23rpx; |
| | | margin-right: 26rpx; |
| | | } |
| | | |
| | | /* 添加商品按钮样式 */ |
| | | .add-product-btn { |
| | | width: 90%; |
| | | height: 70rpx; |
| | | background-color: #e62423; |
| | | color: #fff; |
| | | border-radius: 35rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | margin: 20rpx auto; |
| | | font-size: 28rpx; |
| | | box-shadow: 0 4rpx 10rpx rgba(230, 36, 35, 0.3); |
| | | } |
| | | |
| | | .btn-text { |
| | | color: #fff; |
| | | } |
| | | |
| | | /* 编辑按钮样式 */ |
| | | .edit-btn { |
| | | background-color: #409eff; |
| | | color: #fff; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <view class="product-add"> |
| | | |
| | | <!-- 标签页 --> |
| | | <view class="tab-bar"> |
| | | <scroll-view scroll-x="true" class="tab-scroll"> |
| | | <view class="tab-item" :class="{ active: activeTab === 'basic' }" @click="switchTab('basic')">基础设置 |
| | | </view> |
| | | <view class="tab-item" :class="{ active: activeTab === 'spec' }" @click="switchTab('spec')">规格库存</view> |
| | | <view class="tab-item" :class="{ active: activeTab === 'content' }" @click="switchTab('content')">商品详情 |
| | | </view> |
| | | <view class="tab-item" :class="{ active: activeTab === 'buyset' }" @click="switchTab('buyset')">高级设置 |
| | | </view> |
| | | </scroll-view> |
| | | </view> |
| | | |
| | | <!-- 表单内容 --> |
| | | <scroll-view scroll-y="true" class="form-scroll"> |
| | | <!-- 基础设置 --> |
| | | <view v-show="activeTab === 'basic'" class="form-section"> |
| | | <view class="form-item"> |
| | | <view class="item-label">商品名称</view> |
| | | <input class="item-input" v-model="form.model.product_name" placeholder="请输入商品名称" /> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">商品编码</view> |
| | | <input class="item-input" v-model="form.model.product_no" placeholder="请输入商品编码" /> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">商品分类</view> |
| | | <picker class="item-picker" @change="categoryChange" :range="form.category" :range-key="'name'"> |
| | | <view class="picker-text">{{ selectedCategory || '请选择商品分类' }}</view> |
| | | </picker> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">预告商品</view> |
| | | <view class="radio-group"> |
| | | <view class="radio-item" :class="{ active: form.model.is_preview === 1 }" |
| | | @click="form.model.is_preview = 1">开启</view> |
| | | <view class="radio-item" :class="{ active: form.model.is_preview === 0 }" |
| | | @click="form.model.is_preview = 0">关闭</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="form-item" v-if="form.model.is_preview === 1"> |
| | | <view class="item-label">预告开启购买时间</view> |
| | | <picker mode="datetime" class="item-picker" @change="previewTimeChange" :value="previewTimeArray"> |
| | | <view class="picker-text">{{ previewTimeText || '请选择预告时间' }}</view> |
| | | </picker> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">销售状态</view> |
| | | <view class="radio-group"> |
| | | <view class="radio-item" :class="{ active: form.model.product_status === 10 }" |
| | | @click="form.model.product_status = 10">立即上架</view> |
| | | <view class="radio-item" :class="{ active: form.model.product_status === 20 }" |
| | | @click="form.model.product_status = 20">放入仓库</view> |
| | | </view> |
| | | <view class="form-tips">如果平台开启了商品审核,则商品审核通过后才能销售</view> |
| | | </view> |
| | | |
| | | <view class="form-item" v-if="form.audit_setting.add_audit == 1 && form.model.scene == 'add'"> |
| | | <view class="item-label">是否审核</view> |
| | | <view class="radio-group"> |
| | | <view class="radio-item" :class="{ active: form.model.audit_status === 0 }" |
| | | @click="form.model.audit_status = 0">提交审核</view> |
| | | <view class="radio-item" :class="{ active: form.model.audit_status === 40 }" |
| | | @click="form.model.audit_status = 40">保存草稿</view> |
| | | </view> |
| | | <view class="form-tips">当前平台开启了审核,审核通过后才能上架销售</view> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">商品图片</view> |
| | | <view class="uploader"> |
| | | <view class="uploader-item" v-for="(item, index) in form.model.image" :key="index"> |
| | | <image :src="item.file_path" class="uploader-image"></image> |
| | | <view class="uploader-delete" @click="deleteImage(index)">×</view> |
| | | </view> |
| | | <view class="uploader-add" @click="handleUpload('image')">+</view> |
| | | </view> |
| | | <!-- 上传组件 --> |
| | | <Upload v-if="showUpload && uploadType === 'image'" :isupload="showUpload && uploadType === 'image'" @getImgs="onUploadComplete" type='frontid'>上传图片</Upload> |
| | | </view> |
| | | |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">商品视频</view> |
| | | <view class="uploader"> |
| | | <view v-if="form.model.video_id === 0" class="uploader-add" @click="handleUpload('video')">+ |
| | | </view> |
| | | <view v-else class="uploader-item"> |
| | | <video :src="form.model.video.file_path" class="uploader-video" controls></video> |
| | | <view class="uploader-delete" @click="deleteVideo">×</view> |
| | | </view> |
| | | </view> |
| | | <!-- 上传组件 --> |
| | | <upload v-if="showUpload && uploadType === 'video'" :num="1" file_type="video" |
| | | @getImgs="onUploadComplete"></upload> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">视频封面</view> |
| | | <view class="uploader"> |
| | | <view v-if="form.model.poster_id === 0" class="uploader-add" @click="handleUpload('poster')">+ |
| | | </view> |
| | | <view v-else class="uploader-item"> |
| | | <image :src="form.model.poster.file_path" class="uploader-image"></image> |
| | | <view class="uploader-delete" @click="deletePoster">×</view> |
| | | </view> |
| | | </view> |
| | | <!-- 上传组件 --> |
| | | <uploadOne v-if="showUploadOne && uploadType === 'poster'" @getImgs="onUploadComplete"></uploadOne> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">商品卖点</view> |
| | | <textarea class="item-textarea" v-model="form.model.selling_point" placeholder="请输入商品卖点" |
| | | :auto-height="true"></textarea> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">商品属性</view> |
| | | <view class="radio-group"> |
| | | <view class="radio-item" :class="{ active: form.model.is_virtual === 0 }" |
| | | @click="form.model.is_virtual = 0">实物商品</view> |
| | | <view class="radio-item" :class="{ active: form.model.is_virtual === 1 }" |
| | | @click="form.model.is_virtual = 1">虚拟商品</view> |
| | | <view class="radio-item" :class="{ active: form.model.is_virtual === 2 }" |
| | | @click="form.model.is_virtual = 2">券商品</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="form-item" v-if="form.model.is_virtual === 0"> |
| | | <view class="item-label">运费设置</view> |
| | | <view class="radio-group"> |
| | | <view class="radio-item" :class="{ active: form.model.is_delivery_free === 0 }" |
| | | @click="form.model.is_delivery_free = 0">包邮</view> |
| | | <view class="radio-item" :class="{ active: form.model.is_delivery_free === 1 }" |
| | | @click="form.model.is_delivery_free = 1">运费模板</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="form-item" v-if="form.model.is_delivery_free === 1"> |
| | | <view class="item-label">选择运费模板</view> |
| | | <picker class="item-picker" @change="deliveryChange" :range="form.delivery" range-key="name"> |
| | | <view class="picker-text">{{ selectedDelivery || '请选择运费模板' }}</view> |
| | | </picker> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">商品排序</view> |
| | | <input class="item-input" v-model="form.model.product_sort" placeholder="请输入商品排序" type="number" /> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">限购数量</view> |
| | | <input class="item-input" v-model="form.model.limit_num" placeholder="请输入限购数量,0为不限购" |
| | | type="number" /> |
| | | </view> |
| | | |
| | | <!-- 虚拟商品设置 --> |
| | | <view class="form-item" v-if="form.model.is_virtual === 1"> |
| | | <view class="item-label">发货类型</view> |
| | | <view class="radio-group"> |
| | | <view class="radio-item" :class="{ active: form.model.virtual_auto === 1 }" |
| | | @click="form.model.virtual_auto = 1">自动</view> |
| | | <view class="radio-item" :class="{ active: form.model.virtual_auto === 0 }" |
| | | @click="form.model.virtual_auto = 0">手动</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="form-item" v-if="form.model.is_virtual === 1"> |
| | | <view class="item-label">虚拟内容</view> |
| | | <input class="item-input" v-model="form.model.virtual_content" placeholder="请输入虚拟物品内容" /> |
| | | </view> |
| | | |
| | | <view class="form-item" v-if="form.model.is_virtual === 1 && form.model.virtual_auto === 0"> |
| | | <view class="item-label">支持线下核销</view> |
| | | <view class="radio-group"> |
| | | <view class="radio-item" :class="{ active: form.model.is_verify === 1 }" |
| | | @click="form.model.is_verify = 1">支持</view> |
| | | <view class="radio-item" :class="{ active: form.model.is_verify === 0 }" |
| | | @click="form.model.is_verify = 0">不支持</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="form-item" |
| | | v-if="form.model.is_virtual === 1 && form.model.virtual_auto === 0 && form.model.is_verify === 1"> |
| | | <view class="item-label">核销到期类型</view> |
| | | <view class="radio-group"> |
| | | <view class="radio-item" :class="{ active: form.model.verify_type === 10 }" |
| | | @click="form.model.verify_type = 10">按天数</view> |
| | | <view class="radio-item" :class="{ active: form.model.verify_type === 20 }" |
| | | @click="form.model.verify_type = 20">按固定时间</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="form-item" |
| | | v-if="form.model.is_virtual === 1 && form.model.virtual_auto === 0 && form.model.is_verify === 1 && form.model.verify_type === 10"> |
| | | <view class="item-label">核销有效天数</view> |
| | | <input class="item-input" v-model="form.model.verify_day" placeholder="请输入有效天数,0或留空表示永久有效" |
| | | type="number" /> |
| | | </view> |
| | | |
| | | <view class="form-item" |
| | | v-if="form.model.is_virtual === 1 && form.model.virtual_auto === 0 && form.model.is_verify === 1 && form.model.verify_type === 20"> |
| | | <view class="item-label">核销有效时间</view> |
| | | <picker mode="daterange" class="item-picker" @change="verifyTimeChange" :value="verifyTimeArray"> |
| | | <view class="picker-text">{{ verifyTimeText || '请选择核销有效时间' }}</view> |
| | | </picker> |
| | | </view> |
| | | |
| | | <!-- 券商品设置 --> |
| | | <view class="form-item" v-if="form.model.is_virtual === 2"> |
| | | <view class="item-label">抵扣金额</view> |
| | | <input class="item-input" v-model="form.model.deduction_price" placeholder="请输入抵扣金额" type="digit" /> |
| | | <view class="form-tips">该券线下核销时,实际抵扣的金额</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 规格库存 --> |
| | | <view v-show="activeTab === 'spec'" class="form-section"> |
| | | <view class="form-item"> |
| | | <view class="item-label">库存计算方式</view> |
| | | <view class="radio-group"> |
| | | <view class="radio-item" :class="{ active: form.model.deduct_stock_type === 10 }" |
| | | @click="form.model.deduct_stock_type = 10">下单减库存</view> |
| | | <view class="radio-item" :class="{ active: form.model.deduct_stock_type === 20 }" |
| | | @click="form.model.deduct_stock_type = 20">付款减库存</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">规格类型</view> |
| | | <view class="radio-group"> |
| | | <view class="radio-item" :class="{ active: form.model.spec_type === 10 }" |
| | | @click="form.model.spec_type = 10">单规格</view> |
| | | <view class="radio-item" :class="{ active: form.model.spec_type === 20 }" |
| | | @click="form.model.spec_type = 20">多规格</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 单规格 --> |
| | | <view v-if="form.model.spec_type === 10" class="spec-single"> |
| | | <view class="form-item"> |
| | | <view class="item-label">产品编码</view> |
| | | <input class="item-input" v-model="form.model.sku.product_no" placeholder="请输入产品编码" /> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">产品价格</view> |
| | | <input class="item-input" v-model="form.model.sku.product_price" placeholder="请输入产品价格" type="digit" /> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">产品划线价</view> |
| | | <input class="item-input" v-model="form.model.sku.line_price" placeholder="请输入产品划线价" |
| | | type="digit" /> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">库存数量</view> |
| | | <input class="item-input" v-model="form.model.sku.stock_num" placeholder="请输入库存数量" type="number" /> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">商品重量(Kg)</view> |
| | | <input class="item-input" v-model="form.model.sku.product_weight" placeholder="请输入商品重量(Kg)" |
| | | type="digit" /> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">商品条码</view> |
| | | <input class="item-input" v-model="form.model.sku.bar_code" placeholder="请输入商品条码" /> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 多规格 --> |
| | | <view v-else class="spec-many"> |
| | | <view class="form-item"> |
| | | <view class="item-label">规格属性</view> |
| | | <view class="spec-attrs"> |
| | | <view class="spec-attr" v-for="(attr, index) in form.model.spec_many.spec_attr" |
| | | :key="index"> |
| | | <view class="attr-header"> |
| | | <view class="attr-name">{{ attr.name }}</view> |
| | | <view class="attr-delete" @click="deleteSpecAttr(index)">×</view> |
| | | </view> |
| | | <view class="attr-values"> |
| | | <view class="attr-value" v-for="(value, vIndex) in attr.values" :key="vIndex"> |
| | | <text>{{ value }}</text> |
| | | <view class="value-delete" @click="deleteSpecValue(index, vIndex)">×</view> |
| | | </view> |
| | | <view class="attr-add-value" @click="addSpecValue(index)">+ 添加值</view> |
| | | </view> |
| | | </view> |
| | | <view class="add-spec-attr" @click="addSpecAttr">+ 添加规格属性</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="form-item" v-if="form.model.spec_many.spec_attr.length > 0"> |
| | | <view class="item-label">SKU列表</view> |
| | | <view class="sku-list"> |
| | | <view class="sku-item" v-for="(sku, index) in form.model.spec_many.spec_list" :key="index"> |
| | | <view class="sku-info">{{ sku.spec_text }}</view> |
| | | <view class="form-item"> |
| | | <view class="item-label">规格图片</view> |
| | | <view class="uploader"> |
| | | <view class="uploader-item" v-if="sku.image && sku.image.length > 0"> |
| | | <image :src="sku.image[0]" class="uploader-image"></image> |
| | | <view class="uploader-delete" @click="deleteSkuImage(index)">×</view> |
| | | </view> |
| | | <view class="uploader-add" @click="handleUpload('sku', index)">+</view> |
| | | </view> |
| | | <!-- 上传组件 --> |
| | | <uploadOne v-if="showUploadOne && uploadType === 'sku'" @getImgs="onUploadComplete"> |
| | | </uploadOne> |
| | | </view> |
| | | <view class="sku-inputs"> |
| | | <input class="sku-input" v-model="sku.spec_form.product_no" placeholder="产品编码" /> |
| | | <input class="sku-input" v-model="sku.spec_form.product_price" placeholder="产品价格" type="digit" /> |
| | | <input class="sku-input" v-model="sku.spec_form.line_price" placeholder="产品划线价" |
| | | type="digit" /> |
| | | <input class="sku-input" v-model="sku.spec_form.stock_num" placeholder="库存数量" type="number" /> |
| | | <input class="sku-input" v-model="sku.spec_form.product_weight" placeholder="商品重量(Kg)" type="digit" /> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 商品详情 --> |
| | | <view v-show="activeTab === 'content'" class="form-section"> |
| | | <view class="form-item"> |
| | | <view class="item-label">详情类型</view> |
| | | <view class="radio-group"> |
| | | <view class="radio-item" :class="{ active: form.model.content_type === 10 }" |
| | | @click="form.model.content_type = 10">图文</view> |
| | | <view class="radio-item" :class="{ active: form.model.content_type === 20 }" |
| | | @click="form.model.content_type = 20">纯图</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 图文类型 --> |
| | | <view v-if="form.model.content_type === 10" class="form-item"> |
| | | <view class="item-label">商品详情</view> |
| | | <view class="editor"> |
| | | <!-- 富文本编辑器 --> |
| | | <view class='wrapper'> |
| | | <view class='toolbar' @tap="format" style="height: 160px;overflow-y: auto;"> |
| | | <view :class="formats.bold ? 'ql-active' : ''" class="iconfont icon-zitijiacu" |
| | | data-name="bold"> |
| | | </view> |
| | | <view :class="formats.italic ? 'ql-active' : ''" class="iconfont icon-zitixieti" |
| | | data-name="italic"> |
| | | </view> |
| | | <view :class="formats.underline ? 'ql-active' : ''" class="iconfont icon-zitixiahuaxian" |
| | | data-name="underline"></view> |
| | | <view :class="formats.strike ? 'ql-active' : ''" class="iconfont icon-zitishanchuxian" |
| | | data-name="strike"></view> |
| | | <!-- #ifndef MP-BAIDU --> |
| | | <view :class="formats.align === 'left' ? 'ql-active' : ''" |
| | | class="iconfont icon-zuoduiqi" data-name="align" data-value="left"></view> |
| | | <!-- #endif --> |
| | | <view :class="formats.align === 'center' ? 'ql-active' : ''" |
| | | class="iconfont icon-juzhongduiqi" data-name="align" data-value="center"></view> |
| | | <view :class="formats.align === 'right' ? 'ql-active' : ''" |
| | | class="iconfont icon-youduiqi" data-name="align" data-value="right"></view> |
| | | <view :class="formats.align === 'justify' ? 'ql-active' : ''" |
| | | class="iconfont icon-zuoyouduiqi" data-name="align" data-value="justify"></view> |
| | | <!-- #ifndef MP-BAIDU --> |
| | | <view :class="formats.lineHeight ? 'ql-active' : ''" class="iconfont icon-line-height" |
| | | data-name="lineHeight" data-value="2"></view> |
| | | <view :class="formats.letterSpacing ? 'ql-active' : ''" |
| | | class="iconfont icon-Character-Spacing" data-name="letterSpacing" data-value="2em"> |
| | | </view> |
| | | <view :class="formats.marginTop ? 'ql-active' : ''" |
| | | class="iconfont icon-722bianjiqi_duanqianju" data-name="marginTop" |
| | | data-value="20px"></view> |
| | | <view :class="formats.marginBottom ? 'ql-active' : ''" |
| | | class="iconfont icon-723bianjiqi_duanhouju" data-name="marginBottom" |
| | | data-value="20px"></view> |
| | | <!-- #endif --> |
| | | |
| | | <view class="iconfont icon-clearedformat" @tap="removeFormat"></view> |
| | | |
| | | <!-- #ifndef MP-BAIDU --> |
| | | <view :class="formats.fontFamily ? 'ql-active' : ''" class="iconfont icon-font" |
| | | data-name="fontFamily" data-value="Pacifico"></view> |
| | | <view :class="formats.fontSize === '24px' ? 'ql-active' : ''" |
| | | class="iconfont icon-fontsize" data-name="fontSize" data-value="24px"></view> |
| | | <!-- #endif --> |
| | | <view :class="formats.color === '#0000ff' ? 'ql-active' : ''" |
| | | class="iconfont icon-text_color" data-name="color" data-value="#0000ff"></view> |
| | | <view :class="formats.backgroundColor === '#00ff00' ? 'ql-active' : ''" |
| | | class="iconfont icon-fontbgcolor" data-name="backgroundColor" data-value="#00ff00"> |
| | | </view> |
| | | <view class="iconfont icon-date" @tap="insertDate"></view> |
| | | <view class="iconfont icon--checklist" data-name="list" data-value="check"></view> |
| | | <view :class="formats.list === 'ordered' ? 'ql-active' : ''" |
| | | class="iconfont icon-youxupailie" data-name="list" data-value="ordered"></view> |
| | | <view :class="formats.list === 'bullet' ? 'ql-active' : ''" |
| | | class="iconfont icon-wuxupailie" data-name="list" data-value="bullet"></view> |
| | | |
| | | <view class="iconfont icon-undo" @tap="undo"></view> |
| | | <view class="iconfont icon-redo" @tap="redo"></view> |
| | | |
| | | <view class="iconfont icon-outdent" data-name="indent" data-value="-1"></view> |
| | | <view class="iconfont icon-indent" data-name="indent" data-value="+1"></view> |
| | | <view class="iconfont icon-fengexian" @tap="insertDivider"></view> |
| | | <view class="iconfont icon-charutupian" @tap="insertImage"></view> |
| | | <view :class="formats.header === 1 ? 'ql-active' : ''" |
| | | class="iconfont icon-format-header-1" data-name="header" :data-value="1"></view> |
| | | <view :class="formats.script === 'sub' ? 'ql-active' : ''" |
| | | class="iconfont icon-zitixiabiao" data-name="script" data-value="sub"></view> |
| | | <view :class="formats.script === 'super' ? 'ql-active' : ''" |
| | | class="iconfont icon-zitishangbiao" data-name="script" data-value="super"></view> |
| | | |
| | | <view class="iconfont icon-shanchu" @tap="clear"></view> |
| | | |
| | | <view :class="formats.direction === 'rtl' ? 'ql-active' : ''" |
| | | class="iconfont icon-direction-rtl" data-name="direction" data-value="rtl"></view> |
| | | </view> |
| | | |
| | | <view class="editor-wrapper"> |
| | | <editor id="editor" class="ql-container" placeholder="开始输入..." show-img-size |
| | | show-img-toolbar show-img-resize @statuschange="onStatusChange" |
| | | :read-only="readOnly" @ready="onEditorReady"> |
| | | </editor> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 纯图类型 --> |
| | | <view v-else-if="form.model.content_type === 20" class="form-item"> |
| | | <view class="item-label">商品详情图片</view> |
| | | <view class="uploader"> |
| | | <view class="uploader-item" v-for="(item, index) in form.model.contentImage" :key="index"> |
| | | <image :src="item.file_path" class="uploader-image"></image> |
| | | <view class="uploader-delete" @click="deleteContentImage(index)">×</view> |
| | | </view> |
| | | <view class="uploader-add" @click="handleUpload('content')">+</view> |
| | | </view> |
| | | <view class="editor-tips">提示:最多上传20张图片</view> |
| | | <!-- 上传组件 --> |
| | | <upload v-if="showUpload && uploadType === 'content'" :isupload="showUpload && uploadType === 'content'" :num="20 - form.model.contentImage.length" |
| | | @getImgs="onUploadComplete"></upload> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 高级设置 --> |
| | | <view v-show="activeTab === 'buyset'" class="form-section"> |
| | | |
| | | <!-- 积分设置 --> |
| | | <view class="form-item"> |
| | | <view class="item-label">积分设置</view> |
| | | <view class="switch-item"> |
| | | <view class="switch-label">开启积分赠送</view> |
| | | <switch v-model="form.model.is_points_gift" /> |
| | | </view> |
| | | <view class="switch-item"> |
| | | <view class="switch-label">允许积分抵扣</view> |
| | | <switch v-model="form.model.is_points_discount" /> |
| | | </view> |
| | | <view class="form-item-inner" v-if="form.model.is_points_discount"> |
| | | <view class="inner-label">最大积分抵扣数量</view> |
| | | <input class="inner-input" v-model="form.model.max_points_discount" placeholder="请输入最大积分抵扣数量" |
| | | type="number" /> |
| | | </view> |
| | | </view> |
| | | <!-- 分销设置 --> |
| | | <view class="form-item"> |
| | | <view class="item-label">团队分红设置</view> |
| | | <view class="switch-item"> |
| | | <view class="switch-label">是否参与团队分红</view> |
| | | <switch checked v-model="form.model.is_enable_team" /> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </scroll-view> |
| | | |
| | | <!-- 底部操作栏 --> |
| | | <view class="bottom-bar"> |
| | | <view class="bar-item" @click="back">返回</view> |
| | | <view class="bar-item save-btn" @click="save">保存</view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import Upload from '@/components/upload/upload'; |
| | | import UploadOne from '@/components/upload/uploadOne.vue'; |
| | | export default { |
| | | components: { |
| | | Upload, |
| | | UploadOne |
| | | }, |
| | | data() { |
| | | const now = new Date(); |
| | | return { |
| | | activeTab: 'basic', |
| | | loading: false, |
| | | // 预告时间相关 |
| | | previewTimeArray: [now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes()], |
| | | previewTimeText: '', |
| | | // 核销时间相关 |
| | | verifyTimeArray: [], |
| | | verifyTimeText: '', |
| | | // 上传组件控制 |
| | | showUpload: false, |
| | | showUploadOne: false, |
| | | // 当前操作的类型和索引 |
| | | uploadType: '', // image, video, poster, sku, content |
| | | currentSkuIndex: -1, |
| | | form: { |
| | | model: { |
| | | scene: 'add', |
| | | product_name: '', |
| | | product_no: '', |
| | | category_id: null, |
| | | image: [], |
| | | is_picture: 0, |
| | | contentImage: [], |
| | | video_id: 0, |
| | | video: {}, |
| | | poster_id: 0, |
| | | poster: {}, |
| | | selling_point: '', |
| | | spec_type: 10, |
| | | deduct_stock_type: 20, |
| | | content_type: 10, |
| | | sku: { |
| | | product_no: '', |
| | | product_price: '', |
| | | line_price: '', |
| | | stock_num: 0, |
| | | product_weight: 0, |
| | | bar_code: '' |
| | | }, |
| | | spec_many: { |
| | | spec_attr: [], |
| | | spec_list: [] |
| | | }, |
| | | content: '', |
| | | notice: '', |
| | | is_delivery_free: 0, |
| | | delivery_id: '', |
| | | product_status: 10, |
| | | audit_status: 0, |
| | | product_sort: 100, |
| | | is_points_gift: 1, |
| | | is_points_discount: 1, |
| | | max_points_discount: 0, |
| | | is_agent: 0, |
| | | is_enable_team: 1, |
| | | is_ind_agent: 0, |
| | | agent_money_type: 10, |
| | | first_money: 0, |
| | | second_money: 0, |
| | | third_money: 0, |
| | | is_virtual: 0, |
| | | limit_num: 0, |
| | | deduction_price: 0, |
| | | virtual_auto: 0, |
| | | virtual_content: '', |
| | | is_preview: 0, |
| | | preview_time: '', |
| | | is_verify: 0, |
| | | verify_type: 10, |
| | | verify_day: '', |
| | | verify_time: [], |
| | | verify_store_ids: [], |
| | | }, |
| | | category: [], |
| | | delivery: [], |
| | | gradeList: [], |
| | | specData: null, |
| | | isSpecLocked: false, |
| | | basicSetting: {}, |
| | | agentSetting: {}, |
| | | audit_setting: {}, |
| | | verifyStoreList: [], |
| | | }, |
| | | selectedCategory: '', |
| | | selectedDelivery: '' |
| | | }; |
| | | }, |
| | | onLoad() { |
| | | this.getBaseData(); |
| | | }, |
| | | methods: { |
| | | // 返回上一页 |
| | | back() { |
| | | uni.navigateBack(); |
| | | }, |
| | | |
| | | // 切换标签页 |
| | | switchTab(tab) { |
| | | this.activeTab = tab; |
| | | }, |
| | | |
| | | // 获取基础数据 |
| | | getBaseData() { |
| | | let self = this; |
| | | self.loading = true; |
| | | self._post('supplier.product/getBaseData', {}, (res) => { |
| | | if (res.code === 1) { |
| | | Object.assign(self.form, res.data); |
| | | } |
| | | self.loading = false; |
| | | }); |
| | | }, |
| | | |
| | | // 选择商品分类 |
| | | categoryChange(e) { |
| | | const index = e.detail.value; |
| | | this.form.model.category_id = this.form.category[index].category_id; |
| | | this.selectedCategory = this.form.category[index].name; |
| | | }, |
| | | |
| | | // 处理上传 |
| | | handleUpload(type, index = -1) { |
| | | this.uploadType = type; |
| | | if (type === 'image' || type === 'content' || type === 'video') { |
| | | this.showUpload = true; |
| | | } else { |
| | | this.showUploadOne = true; |
| | | } |
| | | // 记录当前操作的SKU索引 |
| | | this.currentSkuIndex = index; |
| | | }, |
| | | |
| | | // 上传完成回调 |
| | | onUploadComplete(res) { |
| | | // 关闭上传组件 |
| | | this.showUpload = false; |
| | | this.showUploadOne = false; |
| | | |
| | | if (!res || res.length === 0) return; |
| | | |
| | | // 根据上传类型处理结果 |
| | | switch (this.uploadType) { |
| | | case 'image': |
| | | // 商品图片,多个文件 |
| | | res.forEach(item => { |
| | | this.form.model.image.push(item); |
| | | }); |
| | | break; |
| | | case 'video': |
| | | // 商品视频,单个文件 |
| | | this.form.model.video = res[0]; |
| | | this.form.model.video_id = res[0].id || 1; |
| | | break; |
| | | case 'poster': |
| | | // 视频封面,单个文件 |
| | | this.form.model.poster = res[0]; |
| | | this.form.model.poster_id = res[0].id || 1; |
| | | break; |
| | | case 'sku': |
| | | // SKU图片,单个文件 |
| | | if (this.currentSkuIndex !== -1) { |
| | | this.form.model.spec_many.spec_list[this.currentSkuIndex].image = [res[0].file_path]; |
| | | } |
| | | break; |
| | | case 'content': |
| | | // 详情图片,多个文件 |
| | | res.forEach(item => { |
| | | this.form.model.contentImage.push(item); |
| | | }); |
| | | break; |
| | | } |
| | | }, |
| | | |
| | | |
| | | |
| | | // 删除图片 |
| | | deleteImage(index) { |
| | | this.form.model.image.splice(index, 1); |
| | | }, |
| | | |
| | | // 选择运费模板 |
| | | deliveryChange(e) { |
| | | const index = e.detail.value; |
| | | this.form.model.delivery_id = this.form.delivery[index].delivery_id; |
| | | this.selectedDelivery = this.form.delivery[index].name; |
| | | }, |
| | | |
| | | // 选择预告时间 |
| | | previewTimeChange(e) { |
| | | const date = new Date(e.detail.value); |
| | | this.form.model.preview_time = date.toISOString().slice(0, 19).replace('T', ' '); |
| | | this.previewTimeText = |
| | | `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`; |
| | | }, |
| | | |
| | | |
| | | |
| | | // 删除视频 |
| | | deleteVideo() { |
| | | this.form.model.video = {}; |
| | | this.form.model.video_id = 0; |
| | | }, |
| | | |
| | | |
| | | |
| | | // 删除视频封面 |
| | | deletePoster() { |
| | | this.form.model.poster = {}; |
| | | this.form.model.poster_id = 0; |
| | | }, |
| | | |
| | | // 选择核销时间 |
| | | verifyTimeChange(e) { |
| | | const startDate = new Date(e.detail.value[0]); |
| | | const endDate = new Date(e.detail.value[1]); |
| | | this.form.model.verify_time = [ |
| | | startDate.toISOString().slice(0, 10), |
| | | endDate.toISOString().slice(0, 10) |
| | | ]; |
| | | this.verifyTimeText = |
| | | `${startDate.getFullYear()}-${(startDate.getMonth() + 1).toString().padStart(2, '0')}-${startDate.getDate().toString().padStart(2, '0')} 至 ${endDate.getFullYear()}-${(endDate.getMonth() + 1).toString().padStart(2, '0')}-${endDate.getDate().toString().padStart(2, '0')}`; |
| | | }, |
| | | |
| | | |
| | | |
| | | // 删除SKU图片 |
| | | deleteSkuImage(index) { |
| | | this.form.model.spec_many.spec_list[index].image = []; |
| | | }, |
| | | |
| | | |
| | | |
| | | // 删除详情图片 |
| | | deleteContentImage(index) { |
| | | this.form.model.contentImage.splice(index, 1); |
| | | }, |
| | | |
| | | // 添加规格属性 |
| | | addSpecAttr() { |
| | | uni.showModal({ |
| | | title: '添加规格属性', |
| | | content: '', |
| | | editable: true, |
| | | placeholderText: '例如:颜色', |
| | | success: (res) => { |
| | | if (res.confirm && res.content.trim()) { |
| | | this.form.model.spec_many.spec_attr.push({ |
| | | name: res.content.trim(), |
| | | values: [] |
| | | }); |
| | | // 生成SKU列表 |
| | | this.generateSkuList(); |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // 删除规格属性 |
| | | deleteSpecAttr(index) { |
| | | this.form.model.spec_many.spec_attr.splice(index, 1); |
| | | // 重新生成SKU列表 |
| | | this.generateSkuList(); |
| | | }, |
| | | |
| | | // 添加规格值 |
| | | addSpecValue(attrIndex) { |
| | | uni.showModal({ |
| | | title: '添加规格值', |
| | | content: '', |
| | | editable: true, |
| | | placeholderText: '例如:红色', |
| | | success: (res) => { |
| | | if (res.confirm && res.content.trim()) { |
| | | const attr = this.form.model.spec_many.spec_attr[attrIndex]; |
| | | attr.values.push(res.content.trim()); |
| | | // 重新生成SKU列表 |
| | | this.generateSkuList(); |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // 删除规格值 |
| | | deleteSpecValue(attrIndex, valueIndex) { |
| | | const attr = this.form.model.spec_many.spec_attr[attrIndex]; |
| | | if (attr.values.length > 1) { |
| | | attr.values.splice(valueIndex, 1); |
| | | // 重新生成SKU列表 |
| | | this.generateSkuList(); |
| | | } |
| | | }, |
| | | |
| | | // 生成SKU列表 |
| | | generateSkuList() { |
| | | const attrs = this.form.model.spec_many.spec_attr; |
| | | if (attrs.length === 0) { |
| | | this.form.model.spec_many.spec_list = []; |
| | | return; |
| | | } |
| | | |
| | | // 生成所有可能的组合 |
| | | const combinations = this.getCombinations(attrs); |
| | | |
| | | // 生成SKU列表 |
| | | const skuList = combinations.map(comb => { |
| | | const spec_text = comb.map((val, idx) => `${attrs[idx].name}:${val}`).join('; '); |
| | | return { |
| | | spec_text, |
| | | image: [], |
| | | product_no: '', |
| | | price: '', |
| | | line_price: '', |
| | | stock: '', |
| | | weight: '', |
| | | cost_price: '', |
| | | bar_code: '' |
| | | }; |
| | | }); |
| | | |
| | | this.form.model.spec_many.spec_list = skuList; |
| | | }, |
| | | |
| | | // 获取规格值组合 |
| | | getCombinations(attrs) { |
| | | if (attrs.length === 0) return [ |
| | | [] |
| | | ]; |
| | | |
| | | const firstAttr = attrs[0]; |
| | | const remainingAttrs = attrs.slice(1); |
| | | const remainingCombinations = this.getCombinations(remainingAttrs); |
| | | |
| | | const result = []; |
| | | for (const value of firstAttr.values) { |
| | | for (const combination of remainingCombinations) { |
| | | result.push([value, ...combination]); |
| | | } |
| | | } |
| | | |
| | | return result; |
| | | }, |
| | | |
| | | // 保存商品 |
| | | save() { |
| | | let self = this; |
| | | // 先获取富文本编辑器内容 |
| | | if (self.form.model.content_type === 10 && self.editorCtx) { |
| | | // 图文类型,获取编辑器内容 |
| | | self.editorCtx.getContents({ |
| | | success: (res) => { |
| | | // 将编辑器内容赋值给表单字段 |
| | | self.form.model.content = res.html; |
| | | // 继续执行保存逻辑 |
| | | self.doSave(); |
| | | }, |
| | | fail: () => { |
| | | // 获取内容失败,继续执行保存逻辑 |
| | | self.doSave(); |
| | | } |
| | | }); |
| | | return; |
| | | } else { |
| | | // 非图文类型或编辑器未初始化,直接执行保存逻辑 |
| | | self.doSave(); |
| | | } |
| | | }, |
| | | |
| | | // 实际保存逻辑 |
| | | doSave() { |
| | | let self = this; |
| | | // 表单验证 |
| | | if (!self.form.model.product_name) { |
| | | uni.showToast({ |
| | | title: '请输入商品名称', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | if (!self.form.model.category_id) { |
| | | uni.showToast({ |
| | | title: '请选择商品分类', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | if (self.form.model.image.length === 0) { |
| | | uni.showToast({ |
| | | title: '请上传商品图片', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | // 规格库存验证 |
| | | if (self.form.model.spec_type === 10) { |
| | | // 单规格验证 |
| | | if (!self.form.model.sku.product_price || parseFloat(self.form.model.sku.product_price) <= 0) { |
| | | uni.showToast({ |
| | | title: '请输入有效的商品价格', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | if (!self.form.model.sku.stock_num || parseInt(self.form.model.sku.stock_num) < 0) { |
| | | uni.showToast({ |
| | | title: '请输入有效的库存数量', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | } else { |
| | | // 多规格验证 |
| | | if (self.form.model.spec_many.spec_attr.length === 0) { |
| | | uni.showToast({ |
| | | title: '请添加规格属性', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | for (let i = 0; i < self.form.model.spec_many.spec_list.length; i++) { |
| | | const sku = self.form.model.spec_many.spec_list[i]; |
| | | if (!sku.spec_form.product_price || parseFloat(sku.spec_form.product_price) <= 0) { |
| | | uni.showToast({ |
| | | title: '请输入有效的SKU价格', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | if (!sku.spec_form.stock_num || parseInt(sku.spec_form.stock_num) < 0) { |
| | | uni.showToast({ |
| | | title: '请输入有效的SKU库存', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 根据详情类型验证内容 |
| | | if (self.form.model.content_type === 10) { |
| | | // 图文类型,验证富文本内容 |
| | | if (!self.form.model.content || self.form.model.content.trim() === '') { |
| | | uni.showToast({ |
| | | title: '请输入商品详情', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | } else if (self.form.model.content_type === 20) { |
| | | // 纯图类型,验证详情图片 |
| | | if (self.form.model.contentImage.length === 0) { |
| | | uni.showToast({ |
| | | title: '请上传商品详情图片', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | self.loading = true; |
| | | self._post('supplier.product/add', { |
| | | params: JSON.stringify(self.form.model) |
| | | }, (res) => { |
| | | if (res.code === 0) { |
| | | uni.showToast({ |
| | | title: '保存成功' |
| | | }); |
| | | setTimeout(() => { |
| | | uni.navigateBack(); |
| | | }, 1500); |
| | | } else { |
| | | uni.showToast({ |
| | | title: res.msg || '保存失败', |
| | | icon: 'none' |
| | | }); |
| | | } |
| | | self.loading = false; |
| | | }); |
| | | }, |
| | | readOnlyChange() { |
| | | this.readOnly = !this.readOnly |
| | | }, |
| | | onEditorReady() { |
| | | // #ifdef MP-BAIDU |
| | | this.editorCtx = requireDynamicLib('editorLib').createEditorContext('editor'); |
| | | // #endif |
| | | |
| | | // #ifdef APP-PLUS || MP-WEIXIN || H5 |
| | | uni.createSelectorQuery().select('#editor').context((res) => { |
| | | this.editorCtx = res.context |
| | | }).exec() |
| | | // #endif |
| | | }, |
| | | undo() { |
| | | this.editorCtx.undo() |
| | | }, |
| | | redo() { |
| | | this.editorCtx.redo() |
| | | }, |
| | | format(e) { |
| | | let { |
| | | name, |
| | | value |
| | | } = e.target.dataset |
| | | if (!name) return |
| | | // console.log('format', name, value) |
| | | this.editorCtx.format(name, value) |
| | | }, |
| | | onStatusChange(e) { |
| | | const formats = e.detail |
| | | this.formats = formats |
| | | }, |
| | | insertDivider() { |
| | | this.editorCtx.insertDivider({ |
| | | success: function() { |
| | | console.log('insert divider success') |
| | | } |
| | | }) |
| | | }, |
| | | clear() { |
| | | uni.showModal({ |
| | | title: '清空编辑器', |
| | | content: '确定清空编辑器全部内容?', |
| | | success: res => { |
| | | if (res.confirm) { |
| | | this.editorCtx.clear({ |
| | | success: function(res) { |
| | | console.log("clear success") |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | }) |
| | | }, |
| | | removeFormat() { |
| | | this.editorCtx.removeFormat() |
| | | }, |
| | | insertDate() { |
| | | const date = new Date() |
| | | const formatDate = `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}` |
| | | this.editorCtx.insertText({ |
| | | text: formatDate |
| | | }) |
| | | }, |
| | | insertImage() { |
| | | uni.chooseImage({ |
| | | count: 1, |
| | | success: (res) => { |
| | | this.editorCtx.insertImage({ |
| | | src: res.tempFilePaths[0], |
| | | alt: '图像', |
| | | success: function() { |
| | | console.log('insert image success') |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .product-add { |
| | | background-color: #f2f2f2; |
| | | min-height: 100vh; |
| | | padding-bottom: 100rpx; |
| | | /* 为底部操作栏留出空间 */ |
| | | } |
| | | |
| | | /* 底部操作栏 */ |
| | | .bottom-bar { |
| | | position: fixed; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | height: 100rpx; |
| | | background-color: #fff; |
| | | box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.1); |
| | | padding: 0 30rpx; |
| | | box-sizing: border-box; |
| | | z-index: 999; |
| | | } |
| | | |
| | | .bar-item { |
| | | flex: 1; |
| | | height: 60rpx; |
| | | line-height: 60rpx; |
| | | text-align: center; |
| | | font-size: 28rpx; |
| | | border-radius: 30rpx; |
| | | margin: 0 10rpx; |
| | | } |
| | | |
| | | .bar-item:first-child { |
| | | border: 1rpx solid #e0e0e0; |
| | | color: #666; |
| | | } |
| | | |
| | | .save-btn { |
| | | background-color: #e62423; |
| | | color: #fff; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .top-nav { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | height: 88rpx; |
| | | background-color: #fff; |
| | | padding: 0 30rpx; |
| | | box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1); |
| | | position: fixed; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | z-index: 999; |
| | | } |
| | | |
| | | .nav-item { |
| | | font-size: 28rpx; |
| | | color: #666; |
| | | } |
| | | |
| | | .nav-title { |
| | | font-size: 32rpx; |
| | | font-weight: bold; |
| | | color: #333; |
| | | } |
| | | |
| | | .tab-bar { |
| | | background-color: #fff; |
| | | position: fixed; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | z-index: 998; |
| | | } |
| | | |
| | | .tab-scroll { |
| | | display: flex; |
| | | white-space: nowrap; |
| | | padding: 0 20rpx; |
| | | } |
| | | |
| | | .tab-item { |
| | | display: inline-block; |
| | | padding: 20rpx 30rpx; |
| | | font-size: 28rpx; |
| | | color: #666; |
| | | position: relative; |
| | | height: auto; |
| | | } |
| | | |
| | | .tab-item.active { |
| | | color: #e62423; |
| | | } |
| | | |
| | | .tab-item.active::after { |
| | | content: ''; |
| | | position: absolute; |
| | | bottom: 0; |
| | | left: 50%; |
| | | transform: translateX(-50%); |
| | | width: 40rpx; |
| | | height: 4rpx; |
| | | background-color: #e62423; |
| | | border-radius: 2rpx; |
| | | } |
| | | |
| | | .form-scroll { |
| | | padding-top: 80rpx; |
| | | padding-bottom: 20rpx; |
| | | } |
| | | |
| | | .form-section { |
| | | background-color: #fff; |
| | | margin-bottom: 20rpx; |
| | | padding: 0 30rpx; |
| | | } |
| | | |
| | | .form-item { |
| | | padding: 30rpx 0; |
| | | border-bottom: 1rpx solid #f0f0f0; |
| | | } |
| | | |
| | | .form-item:last-child { |
| | | border-bottom: none; |
| | | } |
| | | |
| | | .item-label { |
| | | font-size: 28rpx; |
| | | color: #333; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | |
| | | .item-input { |
| | | width: 100%; |
| | | height: 80rpx; |
| | | border: 1rpx solid #e0e0e0; |
| | | border-radius: 10rpx; |
| | | padding: 0 20rpx; |
| | | font-size: 28rpx; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .item-textarea { |
| | | width: 100%; |
| | | border: 1rpx solid #e0e0e0; |
| | | border-radius: 10rpx; |
| | | padding: 20rpx; |
| | | font-size: 28rpx; |
| | | box-sizing: border-box; |
| | | min-height: 120rpx; |
| | | } |
| | | |
| | | .item-picker { |
| | | width: 100%; |
| | | height: 80rpx; |
| | | border: 1rpx solid #e0e0e0; |
| | | border-radius: 10rpx; |
| | | padding: 0 20rpx; |
| | | font-size: 28rpx; |
| | | box-sizing: border-box; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .picker-text { |
| | | color: #666; |
| | | } |
| | | |
| | | .uploader { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 20rpx; |
| | | } |
| | | |
| | | .uploader-item { |
| | | position: relative; |
| | | width: 160rpx; |
| | | height: 160rpx; |
| | | } |
| | | |
| | | .uploader-image { |
| | | width: 100%; |
| | | height: 100%; |
| | | border-radius: 10rpx; |
| | | } |
| | | |
| | | .uploader-delete { |
| | | position: absolute; |
| | | top: -10rpx; |
| | | right: -10rpx; |
| | | width: 40rpx; |
| | | height: 40rpx; |
| | | background-color: rgba(0, 0, 0, 0.5); |
| | | color: #fff; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-size: 32rpx; |
| | | } |
| | | |
| | | .uploader-add { |
| | | width: 160rpx; |
| | | height: 160rpx; |
| | | border: 2rpx dashed #e0e0e0; |
| | | border-radius: 10rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-size: 64rpx; |
| | | color: #999; |
| | | } |
| | | |
| | | .radio-group { |
| | | display: flex; |
| | | gap: 40rpx; |
| | | } |
| | | |
| | | .radio-item { |
| | | padding: 15rpx 30rpx; |
| | | border: 2rpx solid #e0e0e0; |
| | | border-radius: 50rpx; |
| | | font-size: 28rpx; |
| | | color: #666; |
| | | } |
| | | |
| | | .radio-item.active { |
| | | border-color: #e62423; |
| | | color: #e62423; |
| | | background-color: rgba(230, 36, 35, 0.1); |
| | | } |
| | | |
| | | .switch-item { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | |
| | | .switch-item:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .switch-label { |
| | | font-size: 28rpx; |
| | | color: #666; |
| | | } |
| | | |
| | | /* 规格管理样式 */ |
| | | .spec-attrs { |
| | | margin-top: 20rpx; |
| | | } |
| | | |
| | | .spec-attr { |
| | | margin-bottom: 30rpx; |
| | | padding: 20rpx; |
| | | background-color: #f9f9f9; |
| | | border-radius: 10rpx; |
| | | } |
| | | |
| | | .attr-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | |
| | | .attr-name { |
| | | font-size: 28rpx; |
| | | color: #333; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .attr-delete { |
| | | width: 40rpx; |
| | | height: 40rpx; |
| | | background-color: #ff4d4f; |
| | | color: #fff; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-size: 32rpx; |
| | | } |
| | | |
| | | .attr-values { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 15rpx; |
| | | } |
| | | |
| | | .attr-value { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 10rpx 20rpx; |
| | | background-color: #fff; |
| | | border: 1rpx solid #e0e0e0; |
| | | border-radius: 20rpx; |
| | | font-size: 26rpx; |
| | | } |
| | | |
| | | .value-delete { |
| | | margin-left: 10rpx; |
| | | color: #ff4d4f; |
| | | font-size: 24rpx; |
| | | } |
| | | |
| | | .attr-add-value { |
| | | margin-top: 15rpx; |
| | | padding: 10rpx 20rpx; |
| | | background-color: #e6f7ff; |
| | | color: #1890ff; |
| | | border-radius: 20rpx; |
| | | font-size: 26rpx; |
| | | text-align: center; |
| | | width: 120rpx; |
| | | } |
| | | |
| | | .add-spec-attr { |
| | | margin-top: 20rpx; |
| | | padding: 15rpx; |
| | | background-color: #f0f9eb; |
| | | color: #52c41a; |
| | | border-radius: 10rpx; |
| | | font-size: 26rpx; |
| | | text-align: center; |
| | | } |
| | | |
| | | /* SKU列表样式 */ |
| | | .sku-list { |
| | | margin-top: 20rpx; |
| | | } |
| | | |
| | | .sku-item { |
| | | margin-bottom: 20rpx; |
| | | padding: 20rpx; |
| | | background-color: #f9f9f9; |
| | | border-radius: 10rpx; |
| | | } |
| | | |
| | | .sku-info { |
| | | font-size: 26rpx; |
| | | color: #666; |
| | | margin-bottom: 15rpx; |
| | | } |
| | | |
| | | .sku-inputs { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 20rpx; |
| | | } |
| | | |
| | | .sku-input { |
| | | width: calc(50% - 10rpx); |
| | | height: 70rpx; |
| | | border: 1rpx solid #e0e0e0; |
| | | border-radius: 8rpx; |
| | | padding: 0 15rpx; |
| | | font-size: 26rpx; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | /* 商品详情样式 */ |
| | | .editor { |
| | | position: relative; |
| | | } |
| | | |
| | | .editor-tips { |
| | | margin-top: 10rpx; |
| | | font-size: 24rpx; |
| | | color: #999; |
| | | } |
| | | |
| | | /* 表单提示 */ |
| | | .form-tips { |
| | | margin-top: 10rpx; |
| | | font-size: 24rpx; |
| | | color: #999; |
| | | } |
| | | |
| | | /* 视频样式 */ |
| | | .uploader-video { |
| | | width: 100%; |
| | | height: 200rpx; |
| | | border-radius: 10rpx; |
| | | } |
| | | |
| | | /* 高级设置样式 */ |
| | | .form-item-inner { |
| | | margin-top: 20rpx; |
| | | padding-left: 40rpx; |
| | | } |
| | | |
| | | .inner-label { |
| | | font-size: 26rpx; |
| | | color: #666; |
| | | margin-bottom: 15rpx; |
| | | display: block; |
| | | } |
| | | |
| | | .inner-input { |
| | | width: 100%; |
| | | height: 70rpx; |
| | | border: 1rpx solid #e0e0e0; |
| | | border-radius: 8rpx; |
| | | padding: 0 15rpx; |
| | | font-size: 26rpx; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | @font-face { |
| | | font-family: iconfont; |
| | | src: url("data:font/truetype;charset=utf-8;base64,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AAsAJgFuAAoAQwByAGUAYQB0AGUAZAAgAGIAeQAgAGkAYwBvAG4AZgBvAG4AdAAKAAAKQ3JlYXRlZCBieSBpY29uZm9udAoAAGkAYwBvAG4AZgBvAG4AdAAAaWNvbmZvbnQAAFIAZQBnAHUAbABhAHIAAFJlZ3VsYXIAAGkAYwBvAG4AZgBvAG4AdAAAaWNvbmZvbnQAAGkAYwBvAG4AZgBvAG4AdAAAaWNvbmZvbnQAAFYAZQByAHMAaQBvAG4AIAAxAC4AMAAAVmVyc2lvbiAxLjAAAGkAYwBvAG4AZgBvAG4AdAAAaWNvbmZvbnQAAEcAZQBuAGUAcgBhAHQAZQBkACAAYgB5ACAAcwB2AGcAMgB0AHQAZgAgAGYAcgBvAG0AIABGAG8AbgB0AGUAbABsAG8AIABwAHIAbwBqAGUAYwB0AC4AAEdlbmVyYXRlZCBieSBzdmcydHRmIGZyb20gRm9udGVsbG8gcHJvamVjdC4AAGgAdAB0AHAAOgAvAC8AZgBvAG4AdABlAGwAbABvAC4AYwBvAG0AAGh0dHA6Ly9mb250ZWxsby5jb20AAAIAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOwAAAAEAAgECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BHwEgASEBIgEjASQBJQEmAScBKAEpASoBKwEsAS0BLgEvATABMQEyATMBNAE1ATYBNwE4ATkEcmVkbwlzZWxlY3RhbGwHcHJldmlldwR1bmRvBGRhdGUHY2xlYXJ1cBU3MjNiaWFuamlxaV9kdWFuaG91anUWNzIyYmlhbmppcWlfZHVhbnFpYW5qdQotY2hlY2tsaXN0DWRpcmVjdGlvbi1sdHINZGlyZWN0aW9uLXJ0bAtmb250Ymdjb2xvcg1jbGVhcmVkZm9ybWF0BGZvbnQHb3V0ZGVudAhmb250c2l6ZQp0ZXh0X2NvbG9yD2Zvcm1hdC1oZWFkZXItMg9mb3JtYXQtaGVhZGVyLTMLbGluZS1oZWlnaHQPZm9ybWF0LWhlYWRlci0xD2Zvcm1hdC1oZWFkZXItNA9mb3JtYXQtaGVhZGVyLTUPZm9ybWF0LWhlYWRlci02EUNoYXJhY3Rlci1TcGFjaW5nBmluZGVudAZiYW9jdW4IcXVhbnBpbmcFZnV6aGkHc2hhbmNodQxiaWFuamlzZWt1YWkJZmVuZ2V4aWFuB2RpYW56YW4MY2hhcnVsaWFuamllC2NoYXJ1dHVwaWFuCnd1eHVwYWlsaWUManV6aG9uZ2R1aXFpB3lpbnlvbmcLeW91eHVwYWlsaWUIeW91ZHVpcWkJeml0aWRhaW1hCHhpYW9saWFuCXppdGlqaWFjdQ96aXRpc2hhbmNodXhpYW4Neml0aXNoYW5nYmlhbwp6aXRpYmlhb3RpDnppdGl4aWFodWF4aWFuCXppdGl4aWV0aQl6aXRpeWFuc2UIenVvZHVpcWkJeml0aXl1bGFuC3ppdGl4aWFiaWFvC3p1b3lvdWR1aXFpB2R1aWdvdXgGZ3VhbmJpDnNoZW5neWluX3NoaXRpAAAAAAAB//8AAgABAAAADAAAABYAAAACAAEAAwA6AAEABAAAAAIAAAAAAAAAAQAAAADVpCcIAAAAANhk6GIAAAAA2GToYg==") format("truetype"); |
| | | font-weight: 400; |
| | | font-style: normal; |
| | | font-display: swap |
| | | } |
| | | |
| | | .iconfont { |
| | | font-family: iconfont !important; |
| | | font-size: 16px; |
| | | font-style: normal; |
| | | -webkit-font-smoothing: antialiased; |
| | | -moz-osx-font-smoothing: grayscale |
| | | } |
| | | |
| | | .icon-redo:before { |
| | | content: "\e627" |
| | | } |
| | | |
| | | .icon-undo:before { |
| | | content: "\e633" |
| | | } |
| | | |
| | | .icon-indent:before { |
| | | content: "\eb28" |
| | | } |
| | | |
| | | .icon-outdent:before { |
| | | content: "\e6e8" |
| | | } |
| | | |
| | | .icon-fontsize:before { |
| | | content: "\e6fd" |
| | | } |
| | | |
| | | .icon-format-header-1:before { |
| | | content: "\e860" |
| | | } |
| | | |
| | | .icon-format-header-4:before { |
| | | content: "\e863" |
| | | } |
| | | |
| | | .icon-format-header-5:before { |
| | | content: "\e864" |
| | | } |
| | | |
| | | .icon-format-header-6:before { |
| | | content: "\e865" |
| | | } |
| | | |
| | | .icon-clearup:before { |
| | | content: "\e64d" |
| | | } |
| | | |
| | | .icon-preview:before { |
| | | content: "\e631" |
| | | } |
| | | |
| | | .icon-date:before { |
| | | content: "\e63e" |
| | | } |
| | | |
| | | .icon-fontbgcolor:before { |
| | | content: "\e678" |
| | | } |
| | | |
| | | .icon-clearedformat:before { |
| | | content: "\e67e" |
| | | } |
| | | |
| | | .icon-font:before { |
| | | content: "\e684" |
| | | } |
| | | |
| | | .icon-723bianjiqi_duanhouju:before { |
| | | content: "\e65f" |
| | | } |
| | | |
| | | .icon-722bianjiqi_duanqianju:before { |
| | | content: "\e660" |
| | | } |
| | | |
| | | .icon-text_color:before { |
| | | content: "\e72c" |
| | | } |
| | | |
| | | .icon-format-header-2:before { |
| | | content: "\e75c" |
| | | } |
| | | |
| | | .icon-format-header-3:before { |
| | | content: "\e75d" |
| | | } |
| | | |
| | | .icon--checklist:before { |
| | | content: "\e664" |
| | | } |
| | | |
| | | .icon-baocun:before { |
| | | content: "\ec09" |
| | | } |
| | | |
| | | .icon-line-height:before { |
| | | content: "\e7f8" |
| | | } |
| | | |
| | | .icon-quanping:before { |
| | | content: "\ec13" |
| | | } |
| | | |
| | | .icon-direction-rtl:before { |
| | | content: "\e66e" |
| | | } |
| | | |
| | | .icon-direction-ltr:before { |
| | | content: "\e66d" |
| | | } |
| | | |
| | | .icon-selectall:before { |
| | | content: "\e62b" |
| | | } |
| | | |
| | | .icon-fuzhi:before { |
| | | content: "\ec7a" |
| | | } |
| | | |
| | | .icon-shanchu:before { |
| | | content: "\ec7b" |
| | | } |
| | | |
| | | .icon-bianjisekuai:before { |
| | | content: "\ec7c" |
| | | } |
| | | |
| | | .icon-fengexian:before { |
| | | content: "\ec7f" |
| | | } |
| | | |
| | | .icon-dianzan:before { |
| | | content: "\ec80" |
| | | } |
| | | |
| | | .icon-charulianjie:before { |
| | | content: "\ec81" |
| | | } |
| | | |
| | | .icon-charutupian:before { |
| | | content: "\ec82" |
| | | } |
| | | |
| | | .icon-wuxupailie:before { |
| | | content: "\ec83" |
| | | } |
| | | |
| | | .icon-juzhongduiqi:before { |
| | | content: "\ec84" |
| | | } |
| | | |
| | | .icon-yinyong:before { |
| | | content: "\ec85" |
| | | } |
| | | |
| | | .icon-youxupailie:before { |
| | | content: "\ec86" |
| | | } |
| | | |
| | | .icon-youduiqi:before { |
| | | content: "\ec87" |
| | | } |
| | | |
| | | .icon-zitidaima:before { |
| | | content: "\ec88" |
| | | } |
| | | |
| | | .icon-xiaolian:before { |
| | | content: "\ec89" |
| | | } |
| | | |
| | | .icon-zitijiacu:before { |
| | | content: "\ec8a" |
| | | } |
| | | |
| | | .icon-zitishanchuxian:before { |
| | | content: "\ec8b" |
| | | } |
| | | |
| | | .icon-zitishangbiao:before { |
| | | content: "\ec8c" |
| | | } |
| | | |
| | | .icon-zitibiaoti:before { |
| | | content: "\ec8d" |
| | | } |
| | | |
| | | .icon-zitixiahuaxian:before { |
| | | content: "\ec8e" |
| | | } |
| | | |
| | | .icon-zitixieti:before { |
| | | content: "\ec8f" |
| | | } |
| | | |
| | | .icon-zitiyanse:before { |
| | | content: "\ec90" |
| | | } |
| | | |
| | | .icon-zuoduiqi:before { |
| | | content: "\ec91" |
| | | } |
| | | |
| | | .icon-zitiyulan:before { |
| | | content: "\ec92" |
| | | } |
| | | |
| | | .icon-zitixiabiao:before { |
| | | content: "\ec93" |
| | | } |
| | | |
| | | .icon-zuoyouduiqi:before { |
| | | content: "\ec94" |
| | | } |
| | | |
| | | .icon-duigoux:before { |
| | | content: "\ec9e" |
| | | } |
| | | |
| | | .icon-guanbi:before { |
| | | content: "\eca0" |
| | | } |
| | | |
| | | .icon-shengyin_shiti:before { |
| | | content: "\eca5" |
| | | } |
| | | |
| | | .icon-Character-Spacing:before { |
| | | content: "\e964" |
| | | } |
| | | |
| | | .page-body { |
| | | height: calc(100vh - var(--window-top) - 0px) |
| | | } |
| | | |
| | | .wrapper { |
| | | height: 100% |
| | | } |
| | | |
| | | .editor-wrapper { |
| | | height: calc(100vh - var(--window-top) - 0px - 80px - 46px); |
| | | background: #fff |
| | | } |
| | | |
| | | .iconfont { |
| | | display: inline-block; |
| | | padding: 8px 8px; |
| | | width: 24px; |
| | | height: 24px; |
| | | cursor: pointer; |
| | | font-size: 20px |
| | | } |
| | | |
| | | .toolbar { |
| | | box-sizing: border-box; |
| | | border-bottom: 0; |
| | | font-family: Helvetica Neue, Helvetica, Arial, sans-serif |
| | | } |
| | | |
| | | .ql-container { |
| | | box-sizing: border-box; |
| | | padding: 12px 15px; |
| | | width: 100%; |
| | | min-height: 30vh; |
| | | height: 100%; |
| | | /* margin-top: 20px; */ |
| | | font-size: 16px; |
| | | line-height: 1.5 |
| | | } |
| | | |
| | | .ql-active { |
| | | color: #06c |
| | | } |
| | | |
| | | .iconfont { |
| | | color: #000000; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <view class="product-edit"> |
| | | |
| | | <!-- 标签页 --> |
| | | <view class="tab-bar"> |
| | | <scroll-view scroll-x="true" class="tab-scroll"> |
| | | <view class="tab-item" :class="{ active: activeTab === 'basic' }" @click="switchTab('basic')">基础设置 |
| | | </view> |
| | | <view class="tab-item" :class="{ active: activeTab === 'spec' }" @click="switchTab('spec')">规格库存</view> |
| | | <view class="tab-item" :class="{ active: activeTab === 'content' }" @click="switchTab('content')">商品详情 |
| | | </view> |
| | | <view class="tab-item" :class="{ active: activeTab === 'buyset' }" @click="switchTab('buyset')">高级设置 |
| | | </view> |
| | | </scroll-view> |
| | | </view> |
| | | |
| | | <!-- 表单内容 --> |
| | | <scroll-view scroll-y="true" class="form-scroll"> |
| | | <!-- 基础设置 --> |
| | | <view v-show="activeTab === 'basic'" class="form-section"> |
| | | <view class="form-item"> |
| | | <view class="item-label">商品名称</view> |
| | | <input class="item-input" v-model="form.model.product_name" placeholder="请输入商品名称" /> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">商品编码</view> |
| | | <input class="item-input" v-model="form.model.product_no" placeholder="请输入商品编码" /> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">商品分类</view> |
| | | <picker class="item-picker" @change="categoryChange" :range="form.category" :range-key="'name'"> |
| | | <view class="picker-text">{{ selectedCategory || '请选择商品分类' }}</view> |
| | | </picker> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">预告商品</view> |
| | | <view class="radio-group"> |
| | | <view class="radio-item" :class="{ active: form.model.is_preview === 1 }" |
| | | @click="form.model.is_preview = 1">开启</view> |
| | | <view class="radio-item" :class="{ active: form.model.is_preview === 0 }" |
| | | @click="form.model.is_preview = 0">关闭</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="form-item" v-if="form.model.is_preview === 1"> |
| | | <view class="item-label">预告开启购买时间</view> |
| | | <picker mode="datetime" class="item-picker" @change="previewTimeChange" :value="previewTimeArray"> |
| | | <view class="picker-text">{{ previewTimeText || '请选择预告时间' }}</view> |
| | | </picker> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">销售状态</view> |
| | | <view class="radio-group"> |
| | | <view class="radio-item" :class="{ active: form.model.product_status === 10 }" |
| | | @click="form.model.product_status = 10">立即上架</view> |
| | | <view class="radio-item" :class="{ active: form.model.product_status === 20 }" |
| | | @click="form.model.product_status = 20">放入仓库</view> |
| | | </view> |
| | | <view class="form-tips">如果平台开启了商品审核,则商品审核通过后才能销售</view> |
| | | </view> |
| | | |
| | | <view class="form-item" v-if="form.audit_setting.add_audit == 1 && form.model.scene == 'add'"> |
| | | <view class="item-label">是否审核</view> |
| | | <view class="radio-group"> |
| | | <view class="radio-item" :class="{ active: form.model.audit_status === 0 }" |
| | | @click="form.model.audit_status = 0">提交审核</view> |
| | | <view class="radio-item" :class="{ active: form.model.audit_status === 40 }" |
| | | @click="form.model.audit_status = 40">保存草稿</view> |
| | | </view> |
| | | <view class="form-tips">当前平台开启了审核,审核通过后才能上架销售</view> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">商品图片</view> |
| | | <view class="uploader"> |
| | | <view class="uploader-item" v-for="(item, index) in form.model.image" :key="index"> |
| | | <image :src="item.file_path" class="uploader-image"></image> |
| | | <view class="uploader-delete" @click="deleteImage(index)">×</view> |
| | | </view> |
| | | <view class="uploader-add" @click="handleUpload('image')">+</view> |
| | | </view> |
| | | <!-- 上传组件 --> |
| | | <Upload v-if="showUpload && uploadType === 'image'" :isupload="showUpload && uploadType === 'image'" |
| | | @getImgs="onUploadComplete" type='frontid'>上传图片</Upload> |
| | | </view> |
| | | |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">商品视频</view> |
| | | <view class="uploader"> |
| | | <view v-if="form.model.video_id === 0" class="uploader-add" @click="handleUpload('video')">+ |
| | | </view> |
| | | <view v-else class="uploader-item"> |
| | | <video :src="form.model.video.file_path" class="uploader-video" controls></video> |
| | | <view class="uploader-delete" @click="deleteVideo">×</view> |
| | | </view> |
| | | </view> |
| | | <!-- 上传组件 --> |
| | | <upload v-if="showUpload && uploadType === 'video'" :num="1" file_type="video" |
| | | @getImgs="onUploadComplete"></upload> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">视频封面</view> |
| | | <view class="uploader"> |
| | | <view v-if="form.model.poster_id === 0" class="uploader-add" @click="handleUpload('poster')">+ |
| | | </view> |
| | | <view v-else class="uploader-item"> |
| | | <image :src="form.model.poster.file_path" class="uploader-image"></image> |
| | | <view class="uploader-delete" @click="deletePoster">×</view> |
| | | </view> |
| | | </view> |
| | | <!-- 上传组件 --> |
| | | <uploadOne v-if="showUploadOne && uploadType === 'poster'" @getImgs="onUploadComplete"></uploadOne> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">商品卖点</view> |
| | | <textarea class="item-textarea" v-model="form.model.selling_point" placeholder="请输入商品卖点" |
| | | :auto-height="true"></textarea> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">商品属性</view> |
| | | <view class="radio-group"> |
| | | <view class="radio-item" :class="{ active: form.model.is_virtual === 0 }" |
| | | @click="form.model.is_virtual = 0">实物商品</view> |
| | | <view class="radio-item" :class="{ active: form.model.is_virtual === 1 }" |
| | | @click="form.model.is_virtual = 1">虚拟商品</view> |
| | | <view class="radio-item" :class="{ active: form.model.is_virtual === 2 }" |
| | | @click="form.model.is_virtual = 2">券商品</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="form-item" v-if="form.model.is_virtual === 0"> |
| | | <view class="item-label">运费设置</view> |
| | | <view class="radio-group"> |
| | | <view class="radio-item" :class="{ active: form.model.is_delivery_free === 0 }" |
| | | @click="form.model.is_delivery_free = 0">包邮</view> |
| | | <view class="radio-item" :class="{ active: form.model.is_delivery_free === 1 }" |
| | | @click="form.model.is_delivery_free = 1">运费模板</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="form-item" v-if="form.model.is_delivery_free === 1"> |
| | | <view class="item-label">选择运费模板</view> |
| | | <picker class="item-picker" @change="deliveryChange" :range="form.delivery" range-key="name"> |
| | | <view class="picker-text">{{ selectedDelivery || '请选择运费模板' }}</view> |
| | | </picker> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">商品排序</view> |
| | | <input class="item-input" v-model="form.model.product_sort" placeholder="请输入商品排序" type="number" /> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">限购数量</view> |
| | | <input class="item-input" v-model="form.model.limit_num" placeholder="请输入限购数量,0为不限购" |
| | | type="number" /> |
| | | </view> |
| | | |
| | | <!-- 虚拟商品设置 --> |
| | | <view class="form-item" v-if="form.model.is_virtual === 1"> |
| | | <view class="item-label">发货类型</view> |
| | | <view class="radio-group"> |
| | | <view class="radio-item" :class="{ active: form.model.virtual_auto === 1 }" |
| | | @click="form.model.virtual_auto = 1">自动</view> |
| | | <view class="radio-item" :class="{ active: form.model.virtual_auto === 0 }" |
| | | @click="form.model.virtual_auto = 0">手动</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="form-item" v-if="form.model.is_virtual === 1"> |
| | | <view class="item-label">虚拟内容</view> |
| | | <input class="item-input" v-model="form.model.virtual_content" placeholder="请输入虚拟物品内容" /> |
| | | </view> |
| | | |
| | | <view class="form-item" v-if="form.model.is_virtual === 1 && form.model.virtual_auto === 0"> |
| | | <view class="item-label">支持线下核销</view> |
| | | <view class="radio-group"> |
| | | <view class="radio-item" :class="{ active: form.model.is_verify === 1 }" |
| | | @click="form.model.is_verify = 1">支持</view> |
| | | <view class="radio-item" :class="{ active: form.model.is_verify === 0 }" |
| | | @click="form.model.is_verify = 0">不支持</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="form-item" |
| | | v-if="form.model.is_virtual === 1 && form.model.virtual_auto === 0 && form.model.is_verify === 1"> |
| | | <view class="item-label">核销到期类型</view> |
| | | <view class="radio-group"> |
| | | <view class="radio-item" :class="{ active: form.model.verify_type === 10 }" |
| | | @click="form.model.verify_type = 10">按天数</view> |
| | | <view class="radio-item" :class="{ active: form.model.verify_type === 20 }" |
| | | @click="form.model.verify_type = 20">按固定时间</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="form-item" |
| | | v-if="form.model.is_virtual === 1 && form.model.virtual_auto === 0 && form.model.is_verify === 1 && form.model.verify_type === 10"> |
| | | <view class="item-label">核销有效天数</view> |
| | | <input class="item-input" v-model="form.model.verify_day" placeholder="请输入有效天数,0或留空表示永久有效" |
| | | type="number" /> |
| | | </view> |
| | | |
| | | <view class="form-item" |
| | | v-if="form.model.is_virtual === 1 && form.model.virtual_auto === 0 && form.model.is_verify === 1 && form.model.verify_type === 20"> |
| | | <view class="item-label">核销有效时间</view> |
| | | <picker mode="daterange" class="item-picker" @change="verifyTimeChange" :value="verifyTimeArray"> |
| | | <view class="picker-text">{{ verifyTimeText || '请选择核销有效时间' }}</view> |
| | | </picker> |
| | | </view> |
| | | |
| | | <!-- 券商品设置 --> |
| | | <view class="form-item" v-if="form.model.is_virtual === 2"> |
| | | <view class="item-label">抵扣金额</view> |
| | | <input class="item-input" v-model="form.model.deduction_price" placeholder="请输入抵扣金额" type="digit" /> |
| | | <view class="form-tips">该券线下核销时,实际抵扣的金额</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 规格库存 --> |
| | | <view v-show="activeTab === 'spec'" class="form-section"> |
| | | <view class="form-item"> |
| | | <view class="item-label">库存计算方式</view> |
| | | <view class="radio-group"> |
| | | <view class="radio-item" :class="{ active: form.model.deduct_stock_type === 10 }" |
| | | @click="form.model.deduct_stock_type = 10">下单减库存</view> |
| | | <view class="radio-item" :class="{ active: form.model.deduct_stock_type === 20 }" |
| | | @click="form.model.deduct_stock_type = 20">付款减库存</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">规格类型</view> |
| | | <view class="radio-group"> |
| | | <view class="radio-item" :class="{ active: form.model.spec_type === 10 }" |
| | | @click="form.model.spec_type = 10">单规格</view> |
| | | <view class="radio-item" :class="{ active: form.model.spec_type === 20 }" |
| | | @click="form.model.spec_type = 20">多规格</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 单规格 --> |
| | | <view v-if="form.model.spec_type === 10" class="spec-single"> |
| | | <view class="form-item"> |
| | | <view class="item-label">产品编码</view> |
| | | <input class="item-input" v-model="form.model.sku.product_no" placeholder="请输入产品编码" /> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">产品价格</view> |
| | | <input class="item-input" v-model="form.model.sku.product_price" placeholder="请输入产品价格" |
| | | type="digit" /> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">产品划线价</view> |
| | | <input class="item-input" v-model="form.model.sku.line_price" placeholder="请输入产品划线价" |
| | | type="digit" /> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">库存数量</view> |
| | | <input class="item-input" v-model="form.model.sku.stock_num" placeholder="请输入库存数量" |
| | | type="number" /> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">商品重量(Kg)</view> |
| | | <input class="item-input" v-model="form.model.sku.product_weight" placeholder="请输入商品重量(Kg)" |
| | | type="digit" /> |
| | | </view> |
| | | |
| | | <view class="form-item"> |
| | | <view class="item-label">商品条码</view> |
| | | <input class="item-input" v-model="form.model.sku.bar_code" placeholder="请输入商品条码" /> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 多规格 --> |
| | | <view v-else class="spec-many"> |
| | | <view class="form-item"> |
| | | <view class="item-label">规格属性</view> |
| | | <view class="spec-attrs"> |
| | | <view class="spec-attr" v-for="(attr, index) in form.model.spec_many.spec_attr" |
| | | :key="index"> |
| | | <view class="attr-header"> |
| | | <view class="attr-name">{{ attr.name }}</view> |
| | | <view class="attr-delete" @click="deleteSpecAttr(index)">×</view> |
| | | </view> |
| | | <view class="attr-values"> |
| | | <view class="attr-value" v-for="(value, vIndex) in attr.values" :key="vIndex"> |
| | | <text>{{ value }}</text> |
| | | <view class="value-delete" @click="deleteSpecValue(index, vIndex)">×</view> |
| | | </view> |
| | | <view class="attr-add-value" @click="addSpecValue(index)">+ 添加值</view> |
| | | </view> |
| | | </view> |
| | | <view class="add-spec-attr" @click="addSpecAttr">+ 添加规格属性</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="form-item" v-if="form.model.spec_many.spec_attr.length > 0"> |
| | | <view class="item-label">SKU列表</view> |
| | | <view class="sku-list"> |
| | | <view class="sku-item" v-for="(sku, index) in form.model.spec_many.spec_list" :key="index"> |
| | | <view class="sku-info">{{ sku.spec_text }}</view> |
| | | <view class="form-item"> |
| | | <view class="item-label">规格图片</view> |
| | | <view class="uploader"> |
| | | <view class="uploader-item" v-if="sku.image && sku.image.length > 0"> |
| | | <image :src="sku.image[0]" class="uploader-image"></image> |
| | | <view class="uploader-delete" @click="deleteSkuImage(index)">×</view> |
| | | </view> |
| | | <view class="uploader-add" @click="handleUpload('sku', index)">+</view> |
| | | </view> |
| | | <!-- 上传组件 --> |
| | | <uploadOne v-if="showUploadOne && uploadType === 'sku'" @getImgs="onUploadComplete"> |
| | | </uploadOne> |
| | | </view> |
| | | <view class="sku-inputs"> |
| | | <input class="sku-input" v-model="sku.spec_form.product_no" placeholder="产品编码" /> |
| | | <input class="sku-input" v-model="sku.spec_form.product_price" placeholder="产品价格" |
| | | type="digit" /> |
| | | <input class="sku-input" v-model="sku.spec_form.line_price" placeholder="产品划线价" |
| | | type="digit" /> |
| | | <input class="sku-input" v-model="sku.spec_form.stock_num" placeholder="库存数量" |
| | | type="number" /> |
| | | <input class="sku-input" v-model="sku.spec_form.product_weight" |
| | | placeholder="商品重量(Kg)" type="digit" /> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 商品详情 --> |
| | | <view v-show="activeTab === 'content'" class="form-section"> |
| | | <view class="form-item"> |
| | | <view class="item-label">详情类型</view> |
| | | <view class="radio-group"> |
| | | <view class="radio-item" :class="{ active: form.model.content_type === 10 }" |
| | | @click="form.model.content_type = 10">图文</view> |
| | | <view class="radio-item" :class="{ active: form.model.content_type === 20 }" |
| | | @click="form.model.content_type = 20">纯图</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 图文类型 --> |
| | | <view v-if="form.model.content_type === 10" class="form-item"> |
| | | <view class="item-label">商品详情</view> |
| | | <view class="editor"> |
| | | <!-- 富文本编辑器 --> |
| | | <view class='wrapper'> |
| | | <view class='toolbar' @tap="format" style="height: 160px;overflow-y: auto;"> |
| | | <view :class="formats.bold ? 'ql-active' : ''" class="iconfont icon-zitijiacu" |
| | | data-name="bold"> |
| | | </view> |
| | | <view :class="formats.italic ? 'ql-active' : ''" class="iconfont icon-zitixieti" |
| | | data-name="italic"> |
| | | </view> |
| | | <view :class="formats.underline ? 'ql-active' : ''" class="iconfont icon-zitixiahuaxian" |
| | | data-name="underline"></view> |
| | | <view :class="formats.strike ? 'ql-active' : ''" class="iconfont icon-zitishanchuxian" |
| | | data-name="strike"></view> |
| | | <!-- #ifndef MP-BAIDU --> |
| | | <view :class="formats.align === 'left' ? 'ql-active' : ''" |
| | | class="iconfont icon-zuoduiqi" data-name="align" data-value="left"></view> |
| | | <!-- #endif --> |
| | | <view :class="formats.align === 'center' ? 'ql-active' : ''" |
| | | class="iconfont icon-juzhongduiqi" data-name="align" data-value="center"></view> |
| | | <view :class="formats.align === 'right' ? 'ql-active' : ''" |
| | | class="iconfont icon-youduiqi" data-name="align" data-value="right"></view> |
| | | <view :class="formats.align === 'justify' ? 'ql-active' : ''" |
| | | class="iconfont icon-zuoyouduiqi" data-name="align" data-value="justify"></view> |
| | | <!-- #ifndef MP-BAIDU --> |
| | | <view :class="formats.lineHeight ? 'ql-active' : ''" class="iconfont icon-line-height" |
| | | data-name="lineHeight" data-value="2"></view> |
| | | <view :class="formats.letterSpacing ? 'ql-active' : ''" |
| | | class="iconfont icon-Character-Spacing" data-name="letterSpacing" data-value="2em"> |
| | | </view> |
| | | <view :class="formats.marginTop ? 'ql-active' : ''" |
| | | class="iconfont icon-722bianjiqi_duanqianju" data-name="marginTop" |
| | | data-value="20px"></view> |
| | | <view :class="formats.marginBottom ? 'ql-active' : ''" |
| | | class="iconfont icon-723bianjiqi_duanhouju" data-name="marginBottom" |
| | | data-value="20px"></view> |
| | | <!-- #endif --> |
| | | |
| | | <view class="iconfont icon-clearedformat" @tap="removeFormat"></view> |
| | | |
| | | <!-- #ifndef MP-BAIDU --> |
| | | <view :class="formats.fontFamily ? 'ql-active' : ''" class="iconfont icon-font" |
| | | data-name="fontFamily" data-value="Pacifico"></view> |
| | | <view :class="formats.fontSize === '24px' ? 'ql-active' : ''" |
| | | class="iconfont icon-fontsize" data-name="fontSize" data-value="24px"></view> |
| | | <!-- #endif --> |
| | | <view :class="formats.color === '#0000ff' ? 'ql-active' : ''" |
| | | class="iconfont icon-text_color" data-name="color" data-value="#0000ff"></view> |
| | | <view :class="formats.backgroundColor === '#00ff00' ? 'ql-active' : ''" |
| | | class="iconfont icon-fontbgcolor" data-name="backgroundColor" data-value="#00ff00"> |
| | | </view> |
| | | <view class="iconfont icon-date" @tap="insertDate"></view> |
| | | <view class="iconfont icon--checklist" data-name="list" data-value="check"></view> |
| | | <view :class="formats.list === 'ordered' ? 'ql-active' : ''" |
| | | class="iconfont icon-youxupailie" data-name="list" data-value="ordered"></view> |
| | | <view :class="formats.list === 'bullet' ? 'ql-active' : ''" |
| | | class="iconfont icon-wuxupailie" data-name="list" data-value="bullet"></view> |
| | | |
| | | <view class="iconfont icon-undo" @tap="undo"></view> |
| | | <view class="iconfont icon-redo" @tap="redo"></view> |
| | | |
| | | <view class="iconfont icon-outdent" data-name="indent" data-value="-1"></view> |
| | | <view class="iconfont icon-indent" data-name="indent" data-value="+1"></view> |
| | | <view class="iconfont icon-fengexian" @tap="insertDivider"></view> |
| | | <view class="iconfont icon-charutupian" @tap="insertImage"></view> |
| | | <view :class="formats.header === 1 ? 'ql-active' : ''" |
| | | class="iconfont icon-format-header-1" data-name="header" :data-value="1"></view> |
| | | <view :class="formats.script === 'sub' ? 'ql-active' : ''" |
| | | class="iconfont icon-zitixiabiao" data-name="script" data-value="sub"></view> |
| | | <view :class="formats.script === 'super' ? 'ql-active' : ''" |
| | | class="iconfont icon-zitishangbiao" data-name="script" data-value="super"></view> |
| | | |
| | | <view class="iconfont icon-shanchu" @tap="clear"></view> |
| | | |
| | | <view :class="formats.direction === 'rtl' ? 'ql-active' : ''" |
| | | class="iconfont icon-direction-rtl" data-name="direction" data-value="rtl"></view> |
| | | </view> |
| | | |
| | | <view class="editor-wrapper"> |
| | | <editor id="editor" class="ql-container" placeholder="开始输入..." show-img-size |
| | | show-img-toolbar show-img-resize @statuschange="onStatusChange" |
| | | :read-only="readOnly" @ready="onEditorReady"> |
| | | </editor> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 纯图类型 --> |
| | | <view v-else-if="form.model.content_type === 20" class="form-item"> |
| | | <view class="item-label">商品详情图片</view> |
| | | <view class="uploader"> |
| | | <view class="uploader-item" v-for="(item, index) in form.model.contentImage" :key="index"> |
| | | <image :src="item.file_path" class="uploader-image"></image> |
| | | <view class="uploader-delete" @click="deleteContentImage(index)">×</view> |
| | | </view> |
| | | <view class="uploader-add" @click="handleUpload('content')">+</view> |
| | | </view> |
| | | <view class="editor-tips">提示:最多上传20张图片</view> |
| | | <!-- 上传组件 --> |
| | | <upload v-if="showUpload && uploadType === 'content'" |
| | | :isupload="showUpload && uploadType === 'content'" :num="20 - form.model.contentImage.length" |
| | | @getImgs="onUploadComplete"></upload> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 高级设置 --> |
| | | <view v-show="activeTab === 'buyset'" class="form-section"> |
| | | |
| | | <!-- 积分设置 --> |
| | | <view class="form-item"> |
| | | <view class="item-label">积分设置</view> |
| | | <view class="switch-item"> |
| | | <view class="switch-label">开启积分赠送</view> |
| | | <switch v-model="form.model.is_points_gift" /> |
| | | </view> |
| | | <view class="switch-item"> |
| | | <view class="switch-label">允许积分抵扣</view> |
| | | <switch v-model="form.model.is_points_discount" /> |
| | | </view> |
| | | <view class="form-item-inner" v-if="form.model.is_points_discount"> |
| | | <view class="inner-label">最大积分抵扣数量</view> |
| | | <input class="inner-input" v-model="form.model.max_points_discount" placeholder="请输入最大积分抵扣数量" |
| | | type="number" /> |
| | | </view> |
| | | </view> |
| | | <!-- 分销设置 --> |
| | | <view class="form-item"> |
| | | <view class="item-label">团队分红设置</view> |
| | | <view class="switch-item"> |
| | | <view class="switch-label">是否参与团队分红</view> |
| | | <switch checked v-model="form.model.is_enable_team" /> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </scroll-view> |
| | | |
| | | <!-- 底部操作栏 --> |
| | | <view class="bottom-bar"> |
| | | <view class="bar-item" @click="back">返回</view> |
| | | <view class="bar-item save-btn" @click="save">保存</view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import Upload from '@/components/upload/upload.vue'; |
| | | import UploadOne from '@/components/upload/uploadOne.vue'; |
| | | export default { |
| | | components: { |
| | | Upload, |
| | | UploadOne |
| | | }, |
| | | data() { |
| | | const now = new Date(); |
| | | return { |
| | | activeTab: 'basic', |
| | | loading: false, |
| | | productId: '', |
| | | categoryIndex: 0, |
| | | deliveryIndex: 0, |
| | | // 预告时间相关 |
| | | previewTimeArray: [now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes()], |
| | | previewTimeText: '', |
| | | // 核销时间相关 |
| | | verifyTimeArray: [], |
| | | verifyTimeText: '', |
| | | // 富文本编辑器相关 |
| | | editorCtx: null, |
| | | editorStatus: {}, |
| | | // 上传组件控制 |
| | | showUpload: false, |
| | | showUploadOne: false, |
| | | // 当前操作的类型和索引 |
| | | uploadType: '', // image, video, poster, sku, content |
| | | currentSkuIndex: -1, |
| | | form: { |
| | | model: { |
| | | scene: 'edit', |
| | | product_name: '', |
| | | product_no: '', |
| | | category_id: null, |
| | | image: [], |
| | | is_picture: 0, |
| | | contentImage: [], |
| | | video_id: 0, |
| | | video: {}, |
| | | poster_id: 0, |
| | | poster: {}, |
| | | selling_point: '', |
| | | spec_type: 10, |
| | | deduct_stock_type: 20, |
| | | content_type: 10, |
| | | sku: { |
| | | product_no: '', |
| | | product_price: '', |
| | | line_price: '', |
| | | stock_num: 0, |
| | | product_weight: 0, |
| | | bar_code: '' |
| | | }, |
| | | spec_many: { |
| | | spec_attr: [], |
| | | spec_list: [] |
| | | }, |
| | | content: '', |
| | | notice: '', |
| | | is_delivery_free: 0, |
| | | delivery_id: '', |
| | | product_status: 10, |
| | | audit_status: 0, |
| | | product_sort: 100, |
| | | is_points_gift: 1, |
| | | is_points_discount: 1, |
| | | max_points_discount: 0, |
| | | is_agent: 0, |
| | | is_enable_team: 1, |
| | | is_ind_agent: 0, |
| | | agent_money_type: 10, |
| | | first_money: 0, |
| | | second_money: 0, |
| | | third_money: 0, |
| | | is_virtual: 0, |
| | | limit_num: 0, |
| | | deduction_price: 0, |
| | | virtual_auto: 0, |
| | | virtual_content: '', |
| | | is_preview: 0, |
| | | preview_time: '', |
| | | is_verify: 0, |
| | | verify_type: 10, |
| | | verify_day: '', |
| | | verify_time: [], |
| | | verify_store_ids: [], |
| | | }, |
| | | category: [], |
| | | delivery: [], |
| | | gradeList: [], |
| | | specData: null, |
| | | isSpecLocked: false, |
| | | basicSetting: {}, |
| | | agentSetting: {}, |
| | | audit_setting: {}, |
| | | verifyStoreList: [], |
| | | }, |
| | | selectedCategory: '', |
| | | selectedDelivery: '' |
| | | }; |
| | | }, |
| | | onLoad(option) { |
| | | this.productId = option.product_id; |
| | | this.getBaseData(); |
| | | this.getProductData(); |
| | | }, |
| | | methods: { |
| | | // 返回上一页 |
| | | back() { |
| | | uni.navigateBack(); |
| | | }, |
| | | |
| | | // 切换标签页 |
| | | switchTab(tab) { |
| | | this.activeTab = tab; |
| | | }, |
| | | |
| | | // 获取基础数据 |
| | | getBaseData() { |
| | | let self = this; |
| | | self.loading = true; |
| | | self._post('supplier.product/getBaseData', {}, (res) => { |
| | | if (res.code === 0) { |
| | | Object.assign(self.form, res.data); |
| | | } |
| | | self.loading = false; |
| | | }); |
| | | }, |
| | | |
| | | // 获取商品数据 |
| | | getProductData() { |
| | | let self = this; |
| | | self.loading = true; |
| | | self._post('supplier.product/getEditData', { |
| | | product_id: self.productId |
| | | }, (res) => { |
| | | // 合并默认值和后端返回的数据,确保 spec_many 字段始终存在 |
| | | self.form.model = Object.assign({ |
| | | spec_many: { |
| | | spec_attr: [], |
| | | spec_list: [] |
| | | } |
| | | }, res.data.model); |
| | | // 设置分类索引 |
| | | self.categoryIndex = self.form.category.findIndex(item => item.category_id === self.form |
| | | .model.category_id); |
| | | self.selectedCategory = self.form.category[self.categoryIndex]?.category_name; |
| | | // 设置运费模板索引 |
| | | self.deliveryIndex = self.form.delivery.findIndex(item => item.delivery_id === self.form |
| | | .model.delivery_id); |
| | | self.selectedDelivery = self.form.delivery[self.deliveryIndex]?.delivery_name; |
| | | self.loading = false; |
| | | }); |
| | | }, |
| | | |
| | | // 选择商品分类 |
| | | categoryChange(e) { |
| | | const index = e.detail.value; |
| | | this.form.model.category_id = this.form.category[index].category_id; |
| | | this.selectedCategory = this.form.category[index].category_name; |
| | | }, |
| | | |
| | | // 选择图片 |
| | | chooseImage() { |
| | | uni.chooseImage({ |
| | | count: 9 - this.form.model.image.length, |
| | | success: (res) => { |
| | | this.form.model.image = [...this.form.model.image, ...res.tempFilePaths]; |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // 删除图片 |
| | | deleteImage(index) { |
| | | this.form.model.image.splice(index, 1); |
| | | }, |
| | | |
| | | // 选择运费模板 |
| | | deliveryChange(e) { |
| | | const index = e.detail.value; |
| | | this.form.model.delivery_id = this.form.delivery[index].delivery_id; |
| | | this.selectedDelivery = this.form.delivery[index].name; |
| | | this.deliveryIndex = index; |
| | | }, |
| | | |
| | | // 选择预告时间 |
| | | previewTimeChange(e) { |
| | | const date = new Date(e.detail.value); |
| | | this.form.model.preview_time = date.toISOString().slice(0, 19).replace('T', ' '); |
| | | this.previewTimeText = |
| | | `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`; |
| | | }, |
| | | |
| | | // 选择视频 |
| | | chooseVideo() { |
| | | uni.chooseVideo({ |
| | | count: 1, |
| | | success: (res) => { |
| | | // 这里需要调用上传接口,暂时使用本地路径 |
| | | this.form.model.video = { |
| | | file_path: res.tempFilePath |
| | | }; |
| | | this.form.model.video_id = 1; // 模拟上传成功后的id |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // 删除视频 |
| | | deleteVideo() { |
| | | this.form.model.video = {}; |
| | | this.form.model.video_id = 0; |
| | | }, |
| | | |
| | | // 选择视频封面 |
| | | choosePoster() { |
| | | uni.chooseImage({ |
| | | count: 1, |
| | | success: (res) => { |
| | | // 这里需要调用上传接口,暂时使用本地路径 |
| | | this.form.model.poster = { |
| | | file_path: res.tempFilePaths[0] |
| | | }; |
| | | this.form.model.poster_id = 1; // 模拟上传成功后的id |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // 删除视频封面 |
| | | deletePoster() { |
| | | this.form.model.poster = {}; |
| | | this.form.model.poster_id = 0; |
| | | }, |
| | | |
| | | // 选择核销时间 |
| | | verifyTimeChange(e) { |
| | | const startDate = new Date(e.detail.value[0]); |
| | | const endDate = new Date(e.detail.value[1]); |
| | | this.form.model.verify_time = [ |
| | | startDate.toISOString().slice(0, 10), |
| | | endDate.toISOString().slice(0, 10) |
| | | ]; |
| | | this.verifyTimeText = |
| | | `${startDate.getFullYear()}-${(startDate.getMonth() + 1).toString().padStart(2, '0')}-${startDate.getDate().toString().padStart(2, '0')} 至 ${endDate.getFullYear()}-${(endDate.getMonth() + 1).toString().padStart(2, '0')}-${endDate.getDate().toString().padStart(2, '0')}`; |
| | | }, |
| | | |
| | | // 选择SKU图片 |
| | | chooseSkuImage(index) { |
| | | uni.chooseImage({ |
| | | count: 1, |
| | | success: (res) => { |
| | | // 这里需要调用上传接口,暂时使用本地路径 |
| | | this.form.model.spec_many.spec_list[index].image = res.tempFilePaths; |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // 删除SKU图片 |
| | | deleteSkuImage(index) { |
| | | this.form.model.spec_many.spec_list[index].image = []; |
| | | }, |
| | | |
| | | // 选择详情图片 |
| | | chooseContentImage() { |
| | | uni.chooseImage({ |
| | | count: 20 - this.form.model.contentImage.length, |
| | | success: (res) => { |
| | | // 这里需要调用上传接口,暂时使用本地路径 |
| | | this.form.model.contentImage = [...this.form.model.contentImage, ...res.tempFilePaths]; |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // 删除详情图片 |
| | | deleteContentImage(index) { |
| | | this.form.model.contentImage.splice(index, 1); |
| | | }, |
| | | |
| | | // 富文本编辑器相关 |
| | | onEditorReady() { |
| | | // #ifdef MP-BAIDU |
| | | this.editorCtx = requireDynamicLib('editorLib').createEditorContext('editor'); |
| | | // #endif |
| | | |
| | | // #ifdef APP-PLUS || MP-WEIXIN || H5 |
| | | uni.createSelectorQuery().select('#editor').context((res) => { |
| | | this.editorCtx = res.context |
| | | }).exec() |
| | | // #endif |
| | | }, |
| | | undo() { |
| | | this.editorCtx.undo() |
| | | }, |
| | | redo() { |
| | | this.editorCtx.redo() |
| | | }, |
| | | format(e) { |
| | | let { |
| | | name, |
| | | value |
| | | } = e.target.dataset |
| | | if (!name) return |
| | | this.editorCtx.format(name, value) |
| | | }, |
| | | onStatusChange(e) { |
| | | const formats = e.detail |
| | | this.editorStatus = formats |
| | | }, |
| | | insertDivider() { |
| | | this.editorCtx.insertDivider({ |
| | | success: function() { |
| | | console.log('insert divider success') |
| | | } |
| | | }) |
| | | }, |
| | | clear() { |
| | | uni.showModal({ |
| | | title: '清空编辑器', |
| | | content: '确定清空编辑器全部内容?', |
| | | success: res => { |
| | | if (res.confirm) { |
| | | this.editorCtx.clear({ |
| | | success: function(res) { |
| | | console.log("clear success") |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | }) |
| | | }, |
| | | removeFormat() { |
| | | this.editorCtx.removeFormat() |
| | | }, |
| | | insertDate() { |
| | | const date = new Date() |
| | | const formatDate = `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}` |
| | | this.editorCtx.insertText({ |
| | | text: formatDate |
| | | }) |
| | | }, |
| | | insertImage() { |
| | | uni.chooseImage({ |
| | | count: 1, |
| | | success: (res) => { |
| | | this.editorCtx.insertImage({ |
| | | src: res.tempFilePaths[0], |
| | | alt: '图像', |
| | | success: function() { |
| | | console.log('insert image success') |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | }, |
| | | |
| | | // 添加规格属性 |
| | | addSpecAttr() { |
| | | uni.showModal({ |
| | | title: '添加规格属性', |
| | | content: '请输入规格名称', |
| | | editable: true, |
| | | placeholderText: '例如:颜色', |
| | | success: (res) => { |
| | | if (res.confirm && res.content.trim()) { |
| | | this.form.model.spec_many.spec_attr.push({ |
| | | name: res.content.trim(), |
| | | values: [] |
| | | }); |
| | | // 生成SKU列表 |
| | | this.generateSkuList(); |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // 删除规格属性 |
| | | deleteSpecAttr(index) { |
| | | this.form.model.spec_many.spec_attr.splice(index, 1); |
| | | // 重新生成SKU列表 |
| | | this.generateSkuList(); |
| | | }, |
| | | |
| | | // 添加规格值 |
| | | addSpecValue(attrIndex) { |
| | | uni.showModal({ |
| | | title: '添加规格值', |
| | | content: '请输入规格值', |
| | | editable: true, |
| | | placeholderText: '例如:红色', |
| | | success: (res) => { |
| | | if (res.confirm && res.content.trim()) { |
| | | const attr = this.form.model.spec_many.spec_attr[attrIndex]; |
| | | attr.values.push(res.content.trim()); |
| | | // 重新生成SKU列表 |
| | | this.generateSkuList(); |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // 删除规格值 |
| | | deleteSpecValue(attrIndex, valueIndex) { |
| | | const attr = this.form.model.spec_many.spec_attr[attrIndex]; |
| | | if (attr.values.length > 1) { |
| | | attr.values.splice(valueIndex, 1); |
| | | // 重新生成SKU列表 |
| | | this.generateSkuList(); |
| | | } |
| | | }, |
| | | |
| | | // 生成SKU列表 |
| | | generateSkuList() { |
| | | const attrs = this.form.model.spec_many.spec_attr; |
| | | if (attrs.length === 0) { |
| | | this.form.model.spec_many.spec_list = []; |
| | | return; |
| | | } |
| | | |
| | | // 生成所有可能的组合 |
| | | const combinations = this.getCombinations(attrs); |
| | | |
| | | // 生成SKU列表 |
| | | const skuList = combinations.map(comb => { |
| | | const spec_text = comb.map((val, idx) => `${attrs[idx].name}:${val}`).join('; '); |
| | | return { |
| | | spec_text, |
| | | image: [], |
| | | product_no: '', |
| | | price: '', |
| | | line_price: '', |
| | | stock: '', |
| | | weight: '', |
| | | cost_price: '', |
| | | bar_code: '' |
| | | }; |
| | | }); |
| | | |
| | | this.form.model.spec_many.spec_list = skuList; |
| | | }, |
| | | |
| | | // 获取规格值组合 |
| | | getCombinations(attrs) { |
| | | if (attrs.length === 0) return [ |
| | | [] |
| | | ]; |
| | | |
| | | const firstAttr = attrs[0]; |
| | | const remainingAttrs = attrs.slice(1); |
| | | const remainingCombinations = this.getCombinations(remainingAttrs); |
| | | |
| | | const result = []; |
| | | for (const value of firstAttr.values) { |
| | | for (const combination of remainingCombinations) { |
| | | result.push([value, ...combination]); |
| | | } |
| | | } |
| | | |
| | | return result; |
| | | }, |
| | | |
| | | // 处理上传 |
| | | handleUpload(type, index = -1) { |
| | | this.uploadType = type; |
| | | if (type === 'image' || type === 'content' || type === 'video') { |
| | | this.showUpload = true; |
| | | } else { |
| | | this.showUploadOne = true; |
| | | } |
| | | // 记录当前操作的SKU索引 |
| | | this.currentSkuIndex = index; |
| | | }, |
| | | |
| | | // 上传完成回调 |
| | | onUploadComplete(res) { |
| | | // 关闭上传组件 |
| | | this.showUpload = false; |
| | | this.showUploadOne = false; |
| | | |
| | | if (!res || res.length === 0) return; |
| | | |
| | | // 根据上传类型处理结果 |
| | | switch (this.uploadType) { |
| | | case 'image': |
| | | // 商品图片,多个文件 |
| | | res.forEach(item => { |
| | | this.form.model.image.push(item.file_path); |
| | | }); |
| | | break; |
| | | case 'video': |
| | | // 商品视频,单个文件 |
| | | this.form.model.video = res[0]; |
| | | this.form.model.video_id = res[0].id || 1; |
| | | break; |
| | | case 'poster': |
| | | // 视频封面,单个文件 |
| | | this.form.model.poster = res[0]; |
| | | this.form.model.poster_id = res[0].id || 1; |
| | | break; |
| | | case 'sku': |
| | | // SKU图片,单个文件 |
| | | if (this.currentSkuIndex !== -1) { |
| | | this.form.model.spec_many.spec_list[this.currentSkuIndex].image = [res[0].file_path]; |
| | | } |
| | | break; |
| | | case 'content': |
| | | // 详情图片,多个文件 |
| | | res.forEach(item => { |
| | | this.form.model.contentImage.push(item.file_path); |
| | | }); |
| | | break; |
| | | } |
| | | }, |
| | | |
| | | // 保存商品 |
| | | save() { |
| | | let self = this; |
| | | // 先获取富文本编辑器内容 |
| | | if (self.form.model.content_type === 10 && self.editorCtx) { |
| | | // 图文类型,获取编辑器内容 |
| | | self.editorCtx.getContents({ |
| | | success: (res) => { |
| | | // 将编辑器内容赋值给表单字段 |
| | | self.form.model.content = res.html; |
| | | // 继续执行保存逻辑 |
| | | self.doSave(); |
| | | }, |
| | | fail: () => { |
| | | // 获取内容失败,继续执行保存逻辑 |
| | | self.doSave(); |
| | | } |
| | | }); |
| | | return; |
| | | } else { |
| | | // 非图文类型或编辑器未初始化,直接执行保存逻辑 |
| | | self.doSave(); |
| | | } |
| | | }, |
| | | |
| | | // 实际保存逻辑 |
| | | doSave() { |
| | | let self = this; |
| | | // 表单验证 |
| | | if (!self.form.model.product_name) { |
| | | uni.showToast({ |
| | | title: '请输入商品名称', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | if (!self.form.model.category_id) { |
| | | uni.showToast({ |
| | | title: '请选择商品分类', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | if (self.form.model.image.length === 0) { |
| | | uni.showToast({ |
| | | title: '请上传商品图片', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | // 规格库存验证 |
| | | if (self.form.model.spec_type === 10) { |
| | | // 单规格验证 |
| | | if (!self.form.model.sku.product_price || parseFloat(self.form.model.sku.product_price) <= 0) { |
| | | uni.showToast({ |
| | | title: '请输入有效的商品价格', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | if (!self.form.model.sku.stock_num || parseInt(self.form.model.sku.stock_num) < 0) { |
| | | uni.showToast({ |
| | | title: '请输入有效的库存数量', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | } else { |
| | | // 多规格验证 |
| | | if (self.form.model.spec_many.spec_attr.length === 0) { |
| | | uni.showToast({ |
| | | title: '请添加规格属性', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | for (let i = 0; i < self.form.model.spec_many.spec_list.length; i++) { |
| | | const sku = self.form.model.spec_many.spec_list[i]; |
| | | if (!sku.spec_form.product_price || parseFloat(sku.spec_form.product_price) <= 0) { |
| | | uni.showToast({ |
| | | title: '请输入有效的SKU价格', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | if (!sku.spec_form.stock_num || parseInt(sku.spec_form.stock_num) < 0) { |
| | | uni.showToast({ |
| | | title: '请输入有效的SKU库存', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 根据详情类型验证内容 |
| | | if (self.form.model.content_type === 10) { |
| | | // 图文类型,验证富文本内容 |
| | | if (!self.form.model.content || self.form.model.content.trim() === '') { |
| | | uni.showToast({ |
| | | title: '请输入商品详情', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | } else if (self.form.model.content_type === 20) { |
| | | // 纯图类型,验证详情图片 |
| | | if (self.form.model.contentImage.length === 0) { |
| | | uni.showToast({ |
| | | title: '请上传商品详情图片', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | self.loading = true; |
| | | self._post('supplier.product/edit', { |
| | | product_id: self.productId, |
| | | params: JSON.stringify(self.form.model) |
| | | }, (res) => { |
| | | if (res.code === 0) { |
| | | uni.showToast({ |
| | | title: '保存成功' |
| | | }); |
| | | setTimeout(() => { |
| | | uni.navigateBack(); |
| | | }, 1500); |
| | | } else { |
| | | uni.showToast({ |
| | | title: res.msg || '保存失败', |
| | | icon: 'none' |
| | | }); |
| | | } |
| | | self.loading = false; |
| | | }); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .product-edit { |
| | | background-color: #f2f2f2; |
| | | min-height: 100vh; |
| | | padding-bottom: 100rpx; |
| | | /* 为底部操作栏留出空间 */ |
| | | } |
| | | |
| | | /* 底部操作栏 */ |
| | | .bottom-bar { |
| | | position: fixed; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | height: 100rpx; |
| | | background-color: #fff; |
| | | box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.1); |
| | | padding: 0 30rpx; |
| | | box-sizing: border-box; |
| | | z-index: 999; |
| | | } |
| | | |
| | | .bar-item { |
| | | flex: 1; |
| | | height: 60rpx; |
| | | line-height: 60rpx; |
| | | text-align: center; |
| | | font-size: 28rpx; |
| | | border-radius: 30rpx; |
| | | margin: 0 10rpx; |
| | | } |
| | | |
| | | .bar-item:first-child { |
| | | border: 1rpx solid #e0e0e0; |
| | | color: #666; |
| | | } |
| | | |
| | | .save-btn { |
| | | background-color: #e62423; |
| | | color: #fff; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .top-nav { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | height: 88rpx; |
| | | background-color: #fff; |
| | | padding: 0 30rpx; |
| | | box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1); |
| | | position: fixed; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | z-index: 999; |
| | | } |
| | | |
| | | .nav-item { |
| | | font-size: 28rpx; |
| | | color: #666; |
| | | } |
| | | |
| | | .nav-title { |
| | | font-size: 32rpx; |
| | | font-weight: bold; |
| | | color: #333; |
| | | } |
| | | |
| | | .tab-bar { |
| | | background-color: #fff; |
| | | position: fixed; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | z-index: 998; |
| | | } |
| | | |
| | | .tab-scroll { |
| | | display: flex; |
| | | white-space: nowrap; |
| | | padding: 0 20rpx; |
| | | } |
| | | |
| | | .tab-item { |
| | | display: inline-block; |
| | | padding: 20rpx 30rpx; |
| | | font-size: 28rpx; |
| | | color: #666; |
| | | position: relative; |
| | | height: auto; |
| | | } |
| | | |
| | | .tab-item.active { |
| | | color: #e62423; |
| | | } |
| | | |
| | | .tab-item.active::after { |
| | | content: ''; |
| | | position: absolute; |
| | | bottom: 0; |
| | | left: 50%; |
| | | transform: translateX(-50%); |
| | | width: 40rpx; |
| | | height: 4rpx; |
| | | background-color: #e62423; |
| | | border-radius: 2rpx; |
| | | } |
| | | |
| | | .form-scroll { |
| | | padding-top: 80rpx; |
| | | padding-bottom: 20rpx; |
| | | } |
| | | |
| | | .form-section { |
| | | background-color: #fff; |
| | | margin-bottom: 20rpx; |
| | | padding: 0 30rpx; |
| | | } |
| | | |
| | | .form-item { |
| | | padding: 30rpx 0; |
| | | border-bottom: 1rpx solid #f0f0f0; |
| | | } |
| | | |
| | | .form-item:last-child { |
| | | border-bottom: none; |
| | | } |
| | | |
| | | .item-label { |
| | | font-size: 28rpx; |
| | | color: #333; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | |
| | | .item-input { |
| | | width: 100%; |
| | | height: 80rpx; |
| | | border: 1rpx solid #e0e0e0; |
| | | border-radius: 10rpx; |
| | | padding: 0 20rpx; |
| | | font-size: 28rpx; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .item-textarea { |
| | | width: 100%; |
| | | border: 1rpx solid #e0e0e0; |
| | | border-radius: 10rpx; |
| | | padding: 20rpx; |
| | | font-size: 28rpx; |
| | | box-sizing: border-box; |
| | | min-height: 120rpx; |
| | | } |
| | | |
| | | .item-editor { |
| | | width: 100%; |
| | | height: 500rpx; |
| | | border: 1rpx solid #e0e0e0; |
| | | border-radius: 10rpx; |
| | | box-sizing: border-box; |
| | | font-size: 28rpx; |
| | | } |
| | | |
| | | .item-picker { |
| | | width: 100%; |
| | | height: 80rpx; |
| | | border: 1rpx solid #e0e0e0; |
| | | border-radius: 10rpx; |
| | | padding: 0 20rpx; |
| | | font-size: 28rpx; |
| | | box-sizing: border-box; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .picker-text { |
| | | color: #666; |
| | | } |
| | | |
| | | .uploader { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 20rpx; |
| | | } |
| | | |
| | | .uploader-item { |
| | | position: relative; |
| | | width: 160rpx; |
| | | height: 160rpx; |
| | | } |
| | | |
| | | .uploader-image { |
| | | width: 100%; |
| | | height: 100%; |
| | | border-radius: 10rpx; |
| | | } |
| | | |
| | | .uploader-delete { |
| | | position: absolute; |
| | | top: -10rpx; |
| | | right: -10rpx; |
| | | width: 40rpx; |
| | | height: 40rpx; |
| | | background-color: rgba(0, 0, 0, 0.5); |
| | | color: #fff; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-size: 32rpx; |
| | | } |
| | | |
| | | .uploader-add { |
| | | width: 160rpx; |
| | | height: 160rpx; |
| | | border: 2rpx dashed #e0e0e0; |
| | | border-radius: 10rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-size: 64rpx; |
| | | color: #999; |
| | | } |
| | | |
| | | .radio-group { |
| | | display: flex; |
| | | gap: 40rpx; |
| | | } |
| | | |
| | | .radio-item { |
| | | padding: 15rpx 30rpx; |
| | | border: 2rpx solid #e0e0e0; |
| | | border-radius: 50rpx; |
| | | font-size: 28rpx; |
| | | color: #666; |
| | | } |
| | | |
| | | .radio-item.active { |
| | | border-color: #e62423; |
| | | color: #e62423; |
| | | background-color: rgba(230, 36, 35, 0.1); |
| | | } |
| | | |
| | | .switch-item { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | |
| | | .switch-item:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .switch-label { |
| | | font-size: 28rpx; |
| | | color: #666; |
| | | } |
| | | |
| | | /* 规格管理样式 */ |
| | | .spec-attrs { |
| | | margin-top: 20rpx; |
| | | } |
| | | |
| | | .spec-attr { |
| | | margin-bottom: 30rpx; |
| | | padding: 20rpx; |
| | | background-color: #f9f9f9; |
| | | border-radius: 10rpx; |
| | | } |
| | | |
| | | .attr-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | |
| | | .attr-name { |
| | | font-size: 28rpx; |
| | | color: #333; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .attr-delete { |
| | | width: 40rpx; |
| | | height: 40rpx; |
| | | background-color: #ff4d4f; |
| | | color: #fff; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-size: 32rpx; |
| | | } |
| | | |
| | | .attr-values { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 15rpx; |
| | | } |
| | | |
| | | .attr-value { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 10rpx 20rpx; |
| | | background-color: #fff; |
| | | border: 1rpx solid #e0e0e0; |
| | | border-radius: 20rpx; |
| | | font-size: 26rpx; |
| | | } |
| | | |
| | | .value-delete { |
| | | margin-left: 10rpx; |
| | | color: #ff4d4f; |
| | | font-size: 24rpx; |
| | | } |
| | | |
| | | .attr-add-value { |
| | | margin-top: 15rpx; |
| | | padding: 10rpx 20rpx; |
| | | background-color: #e6f7ff; |
| | | color: #1890ff; |
| | | border-radius: 20rpx; |
| | | font-size: 26rpx; |
| | | text-align: center; |
| | | width: 120rpx; |
| | | } |
| | | |
| | | .add-spec-attr { |
| | | margin-top: 20rpx; |
| | | padding: 15rpx; |
| | | background-color: #f0f9eb; |
| | | color: #52c41a; |
| | | border-radius: 10rpx; |
| | | font-size: 26rpx; |
| | | text-align: center; |
| | | } |
| | | |
| | | /* SKU列表样式 */ |
| | | .sku-list { |
| | | margin-top: 20rpx; |
| | | } |
| | | |
| | | .sku-item { |
| | | margin-bottom: 20rpx; |
| | | padding: 20rpx; |
| | | background-color: #f9f9f9; |
| | | border-radius: 10rpx; |
| | | } |
| | | |
| | | .sku-info { |
| | | font-size: 26rpx; |
| | | color: #666; |
| | | margin-bottom: 15rpx; |
| | | } |
| | | |
| | | .sku-inputs { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 20rpx; |
| | | } |
| | | |
| | | .sku-input { |
| | | width: calc(50% - 10rpx); |
| | | height: 70rpx; |
| | | border: 1rpx solid #e0e0e0; |
| | | border-radius: 8rpx; |
| | | padding: 0 15rpx; |
| | | font-size: 26rpx; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | /* 商品详情样式 */ |
| | | .editor { |
| | | position: relative; |
| | | } |
| | | |
| | | .editor-tips { |
| | | margin-top: 10rpx; |
| | | font-size: 24rpx; |
| | | color: #999; |
| | | } |
| | | |
| | | /* 表单提示 */ |
| | | .form-tips { |
| | | margin-top: 10rpx; |
| | | font-size: 24rpx; |
| | | color: #999; |
| | | } |
| | | |
| | | /* 视频样式 */ |
| | | .uploader-video { |
| | | width: 100%; |
| | | height: 200rpx; |
| | | border-radius: 10rpx; |
| | | } |
| | | |
| | | /* 高级设置样式 */ |
| | | .form-item-inner { |
| | | margin-top: 20rpx; |
| | | padding-left: 40rpx; |
| | | } |
| | | |
| | | .inner-label { |
| | | font-size: 26rpx; |
| | | color: #666; |
| | | margin-bottom: 15rpx; |
| | | display: block; |
| | | } |
| | | |
| | | .inner-input { |
| | | width: 100%; |
| | | height: 70rpx; |
| | | border: 1rpx solid #e0e0e0; |
| | | border-radius: 8rpx; |
| | | padding: 0 15rpx; |
| | | font-size: 26rpx; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | @font-face { |
| | | font-family: iconfont; |
| | | src: url("data:font/truetype;charset=utf-8;base64,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AAsAJgFuAAoAQwByAGUAYQB0AGUAZAAgAGIAeQAgAGkAYwBvAG4AZgBvAG4AdAAKAAAKQ3JlYXRlZCBieSBpY29uZm9udAoAAGkAYwBvAG4AZgBvAG4AdAAAaWNvbmZvbnQAAFIAZQBnAHUAbABhAHIAAFJlZ3VsYXIAAGkAYwBvAG4AZgBvAG4AdAAAaWNvbmZvbnQAAGkAYwBvAG4AZgBvAG4AdAAAaWNvbmZvbnQAAFYAZQByAHMAaQBvAG4AIAAxAC4AMAAAVmVyc2lvbiAxLjAAAGkAYwBvAG4AZgBvAG4AdAAAaWNvbmZvbnQAAEcAZQBuAGUAcgBhAHQAZQBkACAAYgB5ACAAcwB2AGcAMgB0AHQAZgAgAGYAcgBvAG0AIABGAG8AbgB0AGUAbABsAG8AIABwAHIAbwBqAGUAYwB0AC4AAEdlbmVyYXRlZCBieSBzdmcydHRmIGZyb20gRm9udGVsbG8gcHJvamVjdC4AAGgAdAB0AHAAOgAvAC8AZgBvAG4AdABlAGwAbABvAC4AYwBvAG0AAGh0dHA6Ly9mb250ZWxsby5jb20AAAIAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOwAAAAEAAgECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BHwEgASEBIgEjASQBJQEmAScBKAEpASoBKwEsAS0BLgEvATABMQEyATMBNAE1ATYBNwE4ATkEcmVkbwlzZWxlY3RhbGwHcHJldmlldwR1bmRvBGRhdGUHY2xlYXJ1cBU3MjNiaWFuamlxaV9kdWFuaG91anUWNzIyYmlhbmppcWlfZHVhbnFpYW5qdQotY2hlY2tsaXN0DWRpcmVjdGlvbi1sdHINZGlyZWN0aW9uLXJ0bAtmb250Ymdjb2xvcg1jbGVhcmVkZm9ybWF0BGZvbnQHb3V0ZGVudAhmb250c2l6ZQp0ZXh0X2NvbG9yD2Zvcm1hdC1oZWFkZXItMg9mb3JtYXQtaGVhZGVyLTMLbGluZS1oZWlnaHQPZm9ybWF0LWhlYWRlci0xD2Zvcm1hdC1oZWFkZXItNA9mb3JtYXQtaGVhZGVyLTUPZm9ybWF0LWhlYWRlci02EUNoYXJhY3Rlci1TcGFjaW5nBmluZGVudAZiYW9jdW4IcXVhbnBpbmcFZnV6aGkHc2hhbmNodQxiaWFuamlzZWt1YWkJZmVuZ2V4aWFuB2RpYW56YW4MY2hhcnVsaWFuamllC2NoYXJ1dHVwaWFuCnd1eHVwYWlsaWUManV6aG9uZ2R1aXFpB3lpbnlvbmcLeW91eHVwYWlsaWUIeW91ZHVpcWkJeml0aWRhaW1hCHhpYW9saWFuCXppdGlqaWFjdQ96aXRpc2hhbmNodXhpYW4Neml0aXNoYW5nYmlhbwp6aXRpYmlhb3RpDnppdGl4aWFodWF4aWFuCXppdGl4aWV0aQl6aXRpeWFuc2UIenVvZHVpcWkJeml0aXl1bGFuC3ppdGl4aWFiaWFvC3p1b3lvdWR1aXFpB2R1aWdvdXgGZ3VhbmJpDnNoZW5neWluX3NoaXRpAAAAAAAB//8AAgABAAAADAAAABYAAAACAAEAAwA6AAEABAAAAAIAAAAAAAAAAQAAAADVpCcIAAAAANhk6GIAAAAA2GToYg==") format("truetype"); |
| | | font-weight: 400; |
| | | font-style: normal; |
| | | font-display: swap |
| | | } |
| | | |
| | | .iconfont { |
| | | font-family: iconfont !important; |
| | | font-size: 16px; |
| | | font-style: normal; |
| | | -webkit-font-smoothing: antialiased; |
| | | -moz-osx-font-smoothing: grayscale |
| | | } |
| | | |
| | | .icon-redo:before { |
| | | content: "\e627" |
| | | } |
| | | |
| | | .icon-undo:before { |
| | | content: "\e633" |
| | | } |
| | | |
| | | .icon-indent:before { |
| | | content: "\eb28" |
| | | } |
| | | |
| | | .icon-outdent:before { |
| | | content: "\e6e8" |
| | | } |
| | | |
| | | .icon-fontsize:before { |
| | | content: "\e6fd" |
| | | } |
| | | |
| | | .icon-format-header-1:before { |
| | | content: "\e860" |
| | | } |
| | | |
| | | .icon-format-header-4:before { |
| | | content: "\e863" |
| | | } |
| | | |
| | | .icon-format-header-5:before { |
| | | content: "\e864" |
| | | } |
| | | |
| | | .icon-format-header-6:before { |
| | | content: "\e865" |
| | | } |
| | | |
| | | .icon-clearup:before { |
| | | content: "\e64d" |
| | | } |
| | | |
| | | .icon-preview:before { |
| | | content: "\e631" |
| | | } |
| | | |
| | | .icon-date:before { |
| | | content: "\e63e" |
| | | } |
| | | |
| | | .icon-fontbgcolor:before { |
| | | content: "\e678" |
| | | } |
| | | |
| | | .icon-clearedformat:before { |
| | | content: "\e67e" |
| | | } |
| | | |
| | | .icon-font:before { |
| | | content: "\e684" |
| | | } |
| | | |
| | | .icon-723bianjiqi_duanhouju:before { |
| | | content: "\e65f" |
| | | } |
| | | |
| | | .icon-722bianjiqi_duanqianju:before { |
| | | content: "\e660" |
| | | } |
| | | |
| | | .icon-text_color:before { |
| | | content: "\e72c" |
| | | } |
| | | |
| | | .icon-format-header-2:before { |
| | | content: "\e75c" |
| | | } |
| | | |
| | | .icon-format-header-3:before { |
| | | content: "\e75d" |
| | | } |
| | | |
| | | .icon--checklist:before { |
| | | content: "\e664" |
| | | } |
| | | |
| | | .icon-baocun:before { |
| | | content: "\ec09" |
| | | } |
| | | |
| | | .icon-line-height:before { |
| | | content: "\e7f8" |
| | | } |
| | | |
| | | .icon-quanping:before { |
| | | content: "\ec13" |
| | | } |
| | | |
| | | .icon-direction-rtl:before { |
| | | content: "\e66e" |
| | | } |
| | | |
| | | .icon-direction-ltr:before { |
| | | content: "\e66d" |
| | | } |
| | | |
| | | .icon-selectall:before { |
| | | content: "\e62b" |
| | | } |
| | | |
| | | .icon-fuzhi:before { |
| | | content: "\ec7a" |
| | | } |
| | | |
| | | .icon-shanchu:before { |
| | | content: "\ec7b" |
| | | } |
| | | |
| | | .icon-bianjisekuai:before { |
| | | content: "\ec7c" |
| | | } |
| | | |
| | | .icon-fengexian:before { |
| | | content: "\ec7f" |
| | | } |
| | | |
| | | .icon-dianzan:before { |
| | | content: "\ec80" |
| | | } |
| | | |
| | | .icon-charulianjie:before { |
| | | content: "\ec81" |
| | | } |
| | | |
| | | .icon-charutupian:before { |
| | | content: "\ec82" |
| | | } |
| | | |
| | | .icon-wuxupailie:before { |
| | | content: "\ec83" |
| | | } |
| | | |
| | | .icon-juzhongduiqi:before { |
| | | content: "\ec84" |
| | | } |
| | | |
| | | .icon-yinyong:before { |
| | | content: "\ec85" |
| | | } |
| | | |
| | | .icon-youxupailie:before { |
| | | content: "\ec86" |
| | | } |
| | | |
| | | .icon-youduiqi:before { |
| | | content: "\ec87" |
| | | } |
| | | |
| | | .icon-zitidaima:before { |
| | | content: "\ec88" |
| | | } |
| | | |
| | | .icon-xiaolian:before { |
| | | content: "\ec89" |
| | | } |
| | | |
| | | .icon-zitijiacu:before { |
| | | content: "\ec8a" |
| | | } |
| | | |
| | | .icon-zitishanchuxian:before { |
| | | content: "\ec8b" |
| | | } |
| | | |
| | | .icon-zitishangbiao:before { |
| | | content: "\ec8c" |
| | | } |
| | | |
| | | .icon-zitibiaoti:before { |
| | | content: "\ec8d" |
| | | } |
| | | |
| | | .icon-zitixiahuaxian:before { |
| | | content: "\ec8e" |
| | | } |
| | | |
| | | .icon-zitixieti:before { |
| | | content: "\ec8f" |
| | | } |
| | | |
| | | .icon-zitiyanse:before { |
| | | content: "\ec90" |
| | | } |
| | | |
| | | .icon-zuoduiqi:before { |
| | | content: "\ec91" |
| | | } |
| | | |
| | | .icon-zitiyulan:before { |
| | | content: "\ec92" |
| | | } |
| | | |
| | | .icon-zitixiabiao:before { |
| | | content: "\ec93" |
| | | } |
| | | |
| | | .icon-zuoyouduiqi:before { |
| | | content: "\ec94" |
| | | } |
| | | |
| | | .icon-duigoux:before { |
| | | content: "\ec9e" |
| | | } |
| | | |
| | | .icon-guanbi:before { |
| | | content: "\eca0" |
| | | } |
| | | |
| | | .icon-shengyin_shiti:before { |
| | | content: "\eca5" |
| | | } |
| | | |
| | | .icon-Character-Spacing:before { |
| | | content: "\e964" |
| | | } |
| | | |
| | | .page-body { |
| | | height: calc(100vh - var(--window-top) - 0px) |
| | | } |
| | | |
| | | .wrapper { |
| | | height: 100% |
| | | } |
| | | |
| | | .editor-wrapper { |
| | | height: calc(100vh - var(--window-top) - 0px - 80px - 46px); |
| | | background: #fff |
| | | } |
| | | |
| | | .iconfont { |
| | | display: inline-block; |
| | | padding: 8px 8px; |
| | | width: 24px; |
| | | height: 24px; |
| | | cursor: pointer; |
| | | font-size: 20px |
| | | } |
| | | |
| | | .toolbar { |
| | | box-sizing: border-box; |
| | | border-bottom: 0; |
| | | font-family: Helvetica Neue, Helvetica, Arial, sans-serif |
| | | } |
| | | |
| | | .ql-container { |
| | | box-sizing: border-box; |
| | | padding: 12px 15px; |
| | | width: 100%; |
| | | min-height: 30vh; |
| | | height: 100%; |
| | | /* margin-top: 20px; */ |
| | | font-size: 16px; |
| | | line-height: 1.5 |
| | | } |
| | | |
| | | .ql-active { |
| | | color: #06c |
| | | } |
| | | |
| | | .iconfont { |
| | | color: #000000; |
| | | } |
| | | </style> |
| | |
| | | url: 'pages/user/my_activity/index', |
| | | name: '连盟活动', |
| | | type: '页面', |
| | | }, |
| | | { |
| | | url: 'pages2/bonus/index/index', |
| | | name: '超级分红', |
| | | type: '菜单', |
| | | }, |
| | | { |
| | | url: 'pages/plus/vip/index', |
| | | name: 'VIP专区', |
| | | type: '菜单', |
| | | } |
| | | ], |
| | | /*选中的值*/ |
| | |
| | | <el-radio v-model="form.become" label="40">下级分销商总数</el-radio> |
| | | <el-radio v-model="form.become" label="50">累计佣金总数</el-radio> |
| | | <!-- <el-radio v-model="form.become" label="60">已提现佣金</el-radio> --> |
| | | <el-radio v-model="form.become" label="70">商户入驻和VIP会员组合条件</el-radio> |
| | | </div> |
| | | </el-form-item> |
| | | |
| | |
| | | </el-input> |
| | | <div class="tips"></div> |
| | | </el-form-item> |
| | | <el-form-item label="下线商户入驻人数需达到" v-if="form.become==70"> |
| | | <el-input v-model="form.totalsh_down" type="number" class="max-w460"> |
| | | <template slot="append">人</template> |
| | | </el-input> |
| | | </el-input> |
| | | <div class="tips"></div> |
| | | </el-form-item> |
| | | <el-form-item label="下级VIP会员达到" v-if="form.become==70"> |
| | | <el-input v-model="form.totalvip_down" type="number" class="max-w460"> |
| | | <template slot="append">人</template> |
| | | </el-input> |
| | | <div class="tips"></div> |
| | | </el-form-item> |
| | | |
| | | <!--提交--> |
| | | <div class="common-button-wrapper"> |
| | |
| | | <template slot="append">元</template> |
| | | </el-input> |
| | | </el-form-item> |
| | | <el-form-item label="VIP专区补贴" :label-width="formLabelWidth" prop="operating_subsidy"> |
| | | <el-input v-model="form.operating_subsidy" type="number" placeholder="请输入VIP专区补贴"> |
| | | <el-form-item label="下级收益补贴" :label-width="formLabelWidth" prop="operating_subsidy"> |
| | | <el-input v-model="form.operating_subsidy" type="number" placeholder="请输入下级收益补贴"> |
| | | <template slot="append">%</template> |
| | | </el-input> |
| | | </el-form-item> |
| | |
| | | <template slot="append">%</template> |
| | | </el-input> |
| | | </el-form-item> |
| | | <el-form-item label="直推店铺交易额佣金" :label-width="formLabelWidth" prop="commission"> |
| | | <el-input v-model="form.supplier_money" type="number" placeholder="请输入直推店铺交易额佣金"> |
| | | <template slot="append">%</template> |
| | | </el-input> |
| | | </el-form-item> |
| | | <el-form-item label="自动升级" :label-width="formLabelWidth" prop="auto_upgrade"> |
| | | <el-radio-group v-model="form.auto_upgrade"> |
| | |
| | | </el-radio-group> |
| | | </div> |
| | | <div class="d-s-c mt16"> |
| | | <el-checkbox v-model="form.is_purchase_count">购买次数</el-checkbox> |
| | | <el-checkbox v-model="form.is_purchase_count">购买次数VIP专区商品</el-checkbox> |
| | | <el-input v-model="form.purchase_count" type="number" :disabled="!form.is_purchase_count" style="width: 160px; margin-left: 10px;" ></el-input> |
| | | <span class="ml10">次</span> |
| | | </div> |
| | | <div class="d-s-c mt16"> |
| | | <el-checkbox v-model="form.is_supplier_count">直推商家</el-checkbox> |
| | | <el-input v-model="form.supplier_count" type="number" :disabled="!form.is_supplier_count" style="width: 160px; margin-left: 10px;" ></el-input> |
| | | <span class="ml10">家</span> |
| | | </div> |
| | | <div class="d-s-c mt16"> |
| | | <el-checkbox v-model="form.is_referee_grade">直推指定会员等级</el-checkbox> |
| | | <el-select v-model="form.referee_grade_ids" multiple :disabled="!form.is_referee_grade" style="width: 160px; margin-left: 10px;"> |
| | | <el-option |
| | | v-for="item in userGradeList" |
| | | :key="item.grade_id" |
| | | :label="item.name" |
| | | :value="item.grade_id"> |
| | | </el-option> |
| | | </el-select> |
| | | <el-input v-model="form.referee_grade_count" type="number" :disabled="!form.is_referee_grade" style="width: 160px; margin-left: 10px;" ></el-input> |
| | | <span class="ml10">人</span> |
| | | </div> |
| | | </el-form-item> |
| | | </el-form> |
| | |
| | | |
| | | <script> |
| | | import vipApi from '@/api/plus/vip.js'; |
| | | import UserApi from '@/api/user.js'; |
| | | export default { |
| | | data() { |
| | | return { |
| | |
| | | agent_money: 0, |
| | | /*推广复购佣金*/ |
| | | repurchase_money: 0, |
| | | /*VIP专区补贴*/ |
| | | /*下级收益补贴*/ |
| | | operating_subsidy: 0, |
| | | /*平台直推佣金*/ |
| | | commission: 0, |
| | | /*直推店铺交易额佣金*/ |
| | | supplier_money: 0, |
| | | /*自动升级*/ |
| | | auto_upgrade: 1, |
| | | /*升级条件*/ |
| | |
| | | is_purchase_count: 0, |
| | | /*购买次数*/ |
| | | purchase_count: 0, |
| | | /*是否开放直推商家*/ |
| | | is_supplier_count: 0, |
| | | /*直推商家*/ |
| | | supplier_count: 0, |
| | | /*是否开放直推指定会员等级*/ |
| | | is_referee_grade: 0, |
| | | /*直推指定会员等级IDs*/ |
| | | referee_grade_ids: [], |
| | | /*直推指定会员等级人数*/ |
| | | referee_grade_count: 0, |
| | | /*备注*/ |
| | | remark: '', |
| | | }, |
| | | /*用户管理模块的等级列表*/ |
| | | userGradeList: [], |
| | | /*左边长度*/ |
| | | formLabelWidth: '120px', |
| | | /*是否显示*/ |
| | |
| | | props: ['open_add'], |
| | | created() { |
| | | this.dialogVisible = this.open_add; |
| | | this.getUserGradeList(); |
| | | }, |
| | | methods: { |
| | | /*获取用户管理模块的等级列表*/ |
| | | getUserGradeList() { |
| | | let self = this; |
| | | UserApi.gradelist({}, true) |
| | | .then(res => { |
| | | self.userGradeList = res.data.list.data || res.data.list; |
| | | }) |
| | | .catch(error => {}); |
| | | }, |
| | | /*添加等级*/ |
| | | addGrade() { |
| | | let self = this; |
| | |
| | | if (valid) { |
| | | self.submit_loading = true; |
| | | params.is_purchase_count = params.is_purchase_count == true ? 1 : 0; |
| | | params.is_supplier_count = params.is_supplier_count == true ? 1 : 0; |
| | | params.is_referee_grade = params.is_referee_grade == true ? 1 : 0; |
| | | vipApi.addgrade(params, true).then(data => { |
| | | self.submit_loading = false; |
| | | self.$message({ |
| | |
| | | }; |
| | | </script> |
| | | |
| | | <style></style> |
| | | <style></style> |
| | |
| | | <template slot="append">元</template> |
| | | </el-input> |
| | | </el-form-item> |
| | | <el-form-item label="VIP专区补贴" :label-width="formLabelWidth" prop="operating_subsidy"> |
| | | <el-input v-model="form.operating_subsidy" type="number" placeholder="请输入VIP专区补贴"> |
| | | <el-form-item label="下级收益补贴" :label-width="formLabelWidth" prop="operating_subsidy"> |
| | | <el-input v-model="form.operating_subsidy" type="number" placeholder="请输入下级收益补贴"> |
| | | <template slot="append">%</template> |
| | | </el-input> |
| | | </el-form-item> |
| | | <el-form-item label="平台直推佣金" :label-width="formLabelWidth" prop="commission"> |
| | | <el-input v-model="form.commission" type="number" placeholder="请输入平台直推佣金"> |
| | | <template slot="append">%</template> |
| | | </el-input> |
| | | </el-form-item> |
| | | <el-form-item label="直推店铺交易额佣金" :label-width="formLabelWidth" prop="commission"> |
| | | <el-input v-model="form.supplier_money" type="number" placeholder="请输入直推店铺交易额佣金"> |
| | | <template slot="append">%</template> |
| | | </el-input> |
| | | </el-form-item> |
| | |
| | | </el-radio-group> |
| | | </div> |
| | | <div class="d-s-c mt16"> |
| | | <el-checkbox v-model="form.is_purchase_count">购买次数</el-checkbox> |
| | | <el-checkbox v-model="form.is_purchase_count">购买次数VIP专区商品</el-checkbox> |
| | | <el-input v-model="form.purchase_count" type="number" :disabled="!form.is_purchase_count" style="width: 160px; margin-left: 10px;" ></el-input> |
| | | <span class="ml10">次</span> |
| | | </div> |
| | | <div class="d-s-c mt16"> |
| | | <el-checkbox v-model="form.is_supplier_count">直推商家</el-checkbox> |
| | | <el-input v-model="form.supplier_count" type="number" :disabled="!form.is_supplier_count" style="width: 160px; margin-left: 10px;" ></el-input> |
| | | <span class="ml10">家</span> |
| | | </div> |
| | | <div class="d-s-c mt16"> |
| | | <el-checkbox v-model="form.is_referee_grade">直推指定会员等级</el-checkbox> |
| | | <el-select v-model="form.referee_grade_ids" multiple :disabled="!form.is_referee_grade" style="width: 160px; margin-left: 10px;"> |
| | | <el-option |
| | | v-for="item in userGradeList" |
| | | :key="item.grade_id" |
| | | :label="item.name" |
| | | :value="item.grade_id"> |
| | | </el-option> |
| | | </el-select> |
| | | <el-input v-model="form.referee_grade_count" type="number" :disabled="!form.is_referee_grade" style="width: 160px; margin-left: 10px;" ></el-input> |
| | | <span class="ml10">人</span> |
| | | </div> |
| | | </el-form-item> |
| | | </el-form> |
| | |
| | | |
| | | <script> |
| | | import vipApi from '@/api/plus/vip.js'; |
| | | import UserApi from '@/api/user.js'; |
| | | export default { |
| | | data() { |
| | | return { |
| | | /*用户管理模块的等级列表*/ |
| | | userGradeList: [], |
| | | /*左边长度*/ |
| | | formLabelWidth: '120px', |
| | | /*是否显示*/ |
| | |
| | | props: ['open_edit', 'form'], |
| | | created() { |
| | | this.form.is_purchase_count = this.form.is_purchase_count == 1 ? true : false; |
| | | this.form.is_supplier_count = this.form.is_supplier_count == 1 ? true : false; |
| | | this.form.is_referee_grade = this.form.is_referee_grade == 1 ? true : false; |
| | | // 等级id转换成数组 |
| | | for (let i = 0; i < this.form.referee_grade_ids.length; i++) { |
| | | this.form.referee_grade_ids[i] = parseInt(this.form.referee_grade_ids[i]); |
| | | } |
| | | this.dialogVisible = this.open_edit; |
| | | this.getUserGradeList(); |
| | | }, |
| | | methods: { |
| | | /*获取用户管理模块的等级列表*/ |
| | | getUserGradeList() { |
| | | let self = this; |
| | | UserApi.gradelist({}, true) |
| | | .then(res => { |
| | | self.userGradeList = res.data.list.data || res.data.list; |
| | | }) |
| | | .catch(error => {}); |
| | | }, |
| | | /*修改等级*/ |
| | | editGrade() { |
| | | let self = this; |
| | |
| | | if (valid) { |
| | | self.submit_loading = true; |
| | | params.is_purchase_count = params.is_purchase_count == true ? 1 : 0; |
| | | params.is_supplier_count = params.is_supplier_count == true ? 1 : 0; |
| | | params.is_referee_grade = params.is_referee_grade == true ? 1 : 0; |
| | | vipApi.editGrade(params, true) |
| | | .then(data => { |
| | | self.submit_loading = false; |
| | |
| | | }; |
| | | </script> |
| | | |
| | | <style></style> |
| | | <style></style> |
| | |
| | | <span class="orange">{{ scope.row.commission }}%</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="remark" label="升级条件" ></el-table-column> |
| | | <el-table-column prop="operating_subsidy" label="平台直推佣金" > |
| | | <template slot-scope="scope"> |
| | | <span class="orange">{{ scope.row.commission }}%</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="supplier_money" label="直推商家交易佣金" > |
| | | <template slot-scope="scope"> |
| | | <span class="orange">{{ scope.row.supplier_money }}%</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="remark" label="升级条件" > |
| | | <template slot-scope="scope"> |
| | | <div v-html="keepTextStyle(scope.row.remark)"></div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="create_time" label="创建时间" width="160"> |
| | | <template slot-scope="scope"> |
| | | <span>{{ scope.row.create_time }}</span> |
| | |
| | | this.getData(); |
| | | }, |
| | | methods: { |
| | | /*换行*/ |
| | | keepTextStyle(val){ |
| | | let str=val.replace(/(\\r\\n)/g,'<br/>'); |
| | | return str; |
| | | }, |
| | | /*获取列表数据*/ |
| | | getData() { |
| | | let self = this; |