Browse Source

【Add】添加产品复制功能

liuxiangxin 6 months ago
parent
commit
239d4568d0

+ 183 - 1
app/Http/Controllers/Admin/Product.php

@@ -378,7 +378,6 @@ class Product extends Auth{
 		$businessList 			= $Business->getList();
 		$producerList			= $Producer->getList();
 		// 分配数据
-		$this->assign('crumbs','新增');
 		$this->assign('typeList',$typeList);
 		$this->assign('cityList',$cityList);
 		$this->assign('businessList',$businessList);
@@ -391,6 +390,189 @@ class Product extends Auth{
 		return 						$this->fetch();
 	}
 
+
+	/**
+	 * 编辑
+	 * 
+	 * */
+	public function copy( Request $request, Model $Model,Producer $Producer,Business $Business,ProductType $ProductType,ProductSpec $ProductSpec,ProductAttr $ProductAttr,ProductSkus $ProductSkus,City $City,ProductCity $ProductCity){
+		if( request()->isMethod('post') ){
+			// 验证参数
+			$request->scene('add')->validate();
+			// 组合数据
+			$data['name']			= request('name','');
+			$data['thumb']			= request('thumb','');
+			$data['poster']			= request('poster','');
+			$data['spec']			= request('spec','');
+			$data['price']			= request('price',0);
+			$data['market_price']	= request('market_price',0);
+			$data['producer_id']	= request('producer_id',0);
+			$data['business_id']	= request('business_id',0);
+			$data['quota']			= request('quota',0);
+			$data['quota_start']	= request('quota_start','');
+			$data['quota_end']		= request('quota_end','');
+			$data['stock']			= request('stock',0);
+			$data['status']			= 1;
+			$data['admin_uid']		= admin('uid');
+			$description			= request('description','');
+			$attr					= request('attr',[]);
+			$skuList				= request('sku',[]);
+			$cityIds				= request('city_ids',[]);
+			// 如果没有选择,则意味着全部
+			$cityIds				= $cityIds ? $cityIds : [1];
+			$data['quota_start']	= $data['quota_start'] ? strtotime($data['quota_start']) : 0;
+			$data['quota_end']		= $data['quota_end'] ? strtotime($data['quota_end']) : 0;
+			// 限购提示
+			if( $data['quota'] && ( !$data['quota_start'] || !$data['quota_end'] )) 	return json_send(['code'=>'error','msg'=>'限购必填限购时间','data'=>['error'=>'限购必填限购时间']]);
+			// 总库存
+			if( $skuList )			$data['stock'] = array_sum(array_column($skuList,'stock'));
+			// 获取规格属性
+			$specAttr				= $this->getSpecAttr($attr,$ProductSpec,true);
+			// 开启事务
+			DB::beginTransaction();
+			try {
+				// 写入
+				$id						= $Model->add($data);
+				// 提示新增失败
+				if( !$id )				{
+					// 回滚
+					DB::rollBack();
+					// 提示
+					return 				json_send(['code'=>'error','msg'=>'新增失败']);
+				}
+				// 组合数据
+				foreach ($specAttr as $key => $value) {
+					// 查询结果
+					$value['id']		= $ProductAttr->upsertByName($value['name'],$id,$value['spec_id']);
+					// 提示新增失败
+					if( !$value['id'] )	{
+						// 回滚
+						DB::rollBack();
+						// 提示
+						return 			json_send(['code'=>'error','msg'=>'商品属性新增失败']);
+					}
+					// 重组
+					$specAttr[$key]		= $value;
+				}
+				// 循环SKU
+				foreach ($skuList as $attrNames => $value) {
+					// 属性ID值
+					$value['attr_ids']	= [];
+					// 规格属性值组合
+					$value['attr_names']= $attrNames;
+					// 切割成数据
+					$names				= explode(',',$attrNames);
+					// 循环处理
+					foreach ($names as $name) {
+						foreach ($specAttr as $vv) {
+							if( $name == $vv['name'] )  {
+								// 提示新增失败
+								if( !$vv['id'] )	{
+									// 回滚
+									DB::rollBack();
+									// 提示
+									return 			json_send(['code'=>'error','msg'=>'属性SKU匹配失败']);
+								}
+								$value['attr_ids'][] = $vv['id'];
+							}
+						}
+					}
+					// 转成好存储的数据
+					$value['attr_ids']	= implode(',',$value['attr_ids']);
+					// 转成好存储的数据
+					$value['product_id']= $id;
+					// 转成好存储的数据
+					$value['insert_time']= time();
+					// 转成好存储的数据
+					$value['update_time']= time();
+					// SKU结果
+					$skuList[$attrNames] = $value;
+				}
+				// 循环城市范围
+				foreach ($cityIds as $key => $value) {
+					// 重组数据
+					$cityIds[$key]		= ['city_id'=>$value,'product_id'=>$id,'insert_time'=>time(),'update_time'=>time()];
+				}
+				// 写入城市范围
+				$ProductCity->query()->insert($cityIds);
+				// 返回结果
+				$result 				= $ProductSkus->insert($skuList);
+				// 提示新增失败
+				if( !$result )			{
+					// 回滚
+					DB::rollBack();
+					// 提示
+					return 				json_send(['code'=>'error','msg'=>'SKU插入失败']);
+				}
+				// 更新内容
+				$Model->updateDesc($id,$description);
+				// 提交
+				DB::commit();
+				// 记录行为
+				$this->addAdminHistory(admin('uid'),$Model->getTable(),$id,1,[],$data);
+				// 告知结果
+				return					json_send(['code'=>'success','msg'=>'新增成功','action'=>'add']);
+			} catch (\Throwable $th) {
+				// 回滚
+				DB::rollBack();
+				// 提示
+				return 				json_send(['code'=>'error','msg'=>'系统异常,写入失败','data'=>$th->getMessage()]);
+			}
+		}
+		// 接收参数
+		$id							= request('id',0);
+		// 查询数据
+		$oldData					= $Model->where(['id'=>$id])->first();
+		// 如果是没有数据
+		if( !$oldData ) 			return $this->error('查无数据');
+		// 产品信息转格式
+		$oldData					= $oldData->toArray();
+		$oldData['description']		= $Model->getDesc($id);
+		$oldData['city_ids']		= $ProductCity->getListByProductId($id);
+		// 获取产品属性
+		$attrList					= $ProductAttr->getListByProductId($id);
+		// 规格属性
+		$specList					= [];
+		// 获取数据
+		foreach ($attrList as $value) {
+			$value['active']		= 0;
+			if( !isset($specList[$value['spec_id']]) ) $specList[$value['spec_id']]		= $ProductSpec->getOne($value['spec_id']);
+			$specList[$value['spec_id']]['attr_list'][]	= $value;
+		}
+		// 产品类型
+		$skuList					= $ProductSkus->getListByProductId($id);
+		// 循环处理
+		foreach ($skuList as $key => $value) {
+			// 数据解析
+			$value['attr_ids']		= explode(',',$value['attr_ids']);
+			// 循环处理
+			foreach ( $value['attr_ids'] as $k=>$attrId ) {
+				// 获取ids对应的name
+				$value['attr_ids'][$k] = $ProductAttr->getValueById($attrId,'name');
+			}
+			// 数据合并
+			$value['attr_ids']		= implode(',',$value['attr_ids']);
+			// 重组
+			$skuList[$key]			= $value;
+		}
+		// 获取类型数据
+		$typeList				= $ProductType->getList();
+		$cityList				= $City->getCityList();
+		$businessList 			= $Business->getList();
+		$producerList			= $Producer->getList();
+		// 分配数据
+		$this->assign('typeList',$typeList);
+		$this->assign('cityList',$cityList);
+		$this->assign('businessList',$businessList);
+		$this->assign('producerList',$producerList);
+		$this->assign('oldData',$oldData);
+		$this->assign('skuList',$skuList);
+		$this->assign('specList',$specList);
+		$this->assign('crumbs','复制');
+		// 加载模板
+		return 						$this->fetch();
+	}
+
 	/**
 	 * 状态
 	 * 

+ 317 - 0
resources/views/admin/product/copy.blade.php

@@ -0,0 +1,317 @@
+@extends('admin.public.base')
+@section('body_class')
+style="margin: 0 auto;width: 96%;padding: 30px 0px;"
+@endsection
+@section('content')
+<form class="post-form" action="" method="post">
+	<div class="form-group col-sm-2">
+		<label class="control-label">产品图片</label>
+		<div id="thumb">
+			<a id="thumb-image" href="#" data-toggle="image" class="img-thumb">
+				<img src="{{path_compat($oldData['thumb'])}}" height="100" />
+			</a>
+			<input type="hidden" name="thumb" value="{{$oldData['thumb']}}" id="input-image" />
+		</div>
+	</div>
+	<div class="form-group col-sm-2">
+		<label class="control-label">产品海报</label>
+		<div id="poster">
+			<a id="poster-image" href="#" data-toggle="image" class="img-thumbnail">
+				<img src="{{path_compat($oldData['poster'])}}" height="100" />
+			</a>
+			<input type="hidden" name="poster" value="{{$oldData['poster']}}" id="input-poster" />
+		</div>
+	</div>
+	<div class="form-group col-sm-2">
+		<label class="control-label">产品名称</label>
+		<input class="form-control" required="required" type="text" placeholder="产品名称" maxlength="50" name="name" value="{{$oldData['name']}}" />
+	</div>
+	<div class="form-group col-sm-2">
+		<label class="control-label">折扣价格</label>
+		<input class="form-control" required="required" type="text" placeholder="折扣价格" min="0"  max="9999.99" name="price" value="{{$oldData['price']}}" />
+	</div>
+	<div class="form-group col-sm-2">
+		<label class="control-label">产品原价</label>
+		<input class="form-control" required="required" type="text" placeholder="产品原价" min="0" max="9999.99" name="market_price" value="{{$oldData['market_price']}}" />
+	</div>
+	<div class="form-group col-sm-2">
+		<label class="control-label">产品规格</label>
+		<input class="form-control" required="required" type="text" placeholder="产品规格" maxlength="25" name="spec" value="{{$oldData['spec']}}" />
+	</div>
+	<div class="form-group col-sm-2">
+		<label class="control-label">产品库存</label>
+		<input class="form-control" required="required" type="number" placeholder="产品库存" name="stock" value="{{$oldData['stock']}}" />
+	</div>
+	<div class="form-group col-sm-2">
+		<label class="control-label">限购数量</label>
+		<input class="form-control" required="required" type="number" placeholder="限购数量,设置为0表示不限购"  name="quota" value="{{$oldData['quota']}}" />
+	</div>
+	<div class="form-group col-sm-2">
+		<label class="control-label">限购开始</label>
+		<input class="form-control" type="datetime-local" placeholder="限购开始时间"  name="quota_start" value="{{date('Y-m-d H:i',$oldData['quota_start'])}}" />
+	</div>
+	<div class="form-group col-sm-2">
+		<label class="control-label">限购结束</label>
+		<input class="form-control" type="datetime-local" placeholder="限购结束时间" name="quota_end" value="{{date('Y-m-d H:i',$oldData['quota_end'])}}" />
+	</div>
+	<div class="form-group col-sm-2">
+		<label class="control-label">服务城市</label>
+		<select name="city_ids[]" class="form-control selectpicker" data-live-search="true" data-live-search-placeholder="搜索城市" data-none-results-text="未搜索到 {0}" title="选择城市" multiple>
+			@foreach ($cityList as $group)
+			<optgroup label="{{$group['name']}}">
+				@foreach ($group['city'] as $city)
+				<option value="{{$city['id']}}" @if(in_array($city['id'],$oldData['city_ids'])) selected @endif >{{$city['name']}}</option>
+				@endforeach
+			</optgroup>
+			@endforeach
+		</select>
+	</div>
+	<div class="form-group col-sm-2">
+		<label class="control-label">商品类型</label>
+		<select name="type_id" class="form-control" id="typeId">
+			@foreach ($typeList as $value)
+				<option value="{{$value['id']}}"  >{{$value['name']}}</option>
+			@endforeach
+		</select>
+	</div>
+	<div class="form-group col-sm-2">
+		<label class="control-label">生产厂家</label>
+		<select name="producer_id" required class="form-control selectpicker"  data-live-search="true" data-live-search-placeholder="搜索生产厂家" data-none-results-text="未搜索到 {0}" title="选择厂家">
+			@foreach ($producerList as $value)
+				<option value="{{$value['id']}}"  @if( $value['id'] == $oldData['producer_id']) selected @endif >{{$value['name']}}</option>
+			@endforeach
+		</select>
+	</div>
+	<div class="form-group col-sm-2">
+		<label class="control-label">商业公司</label>
+		<select name="business_id" required class="form-control selectpicker" data-live-search="true" data-live-search-placeholder="搜索商业公司" data-none-results-text="未搜索到 {0}" title="选择商业公司">
+			@foreach ($businessList as $value)
+				<option value="{{$value['id']}}" @if( $value['id'] == $oldData['business_id']) selected @endif >{{$value['name']}}</option>
+			@endforeach
+		</select>
+	</div>
+	<div class="form-group col-sm-12" id="add_spec">
+		@foreach ($specList as $spec)
+		<div class="form-group col-sm-12">
+			<label class="control-label">{{$spec['name']}}</label>
+			<div class="form-group col-sm-12">
+				@if( empty($spec['attr_list']))
+				<div class="form-group col-sm-3 attr_div">
+					<div class="form-group form-inline">
+						<div class="input-group col-sm-4">
+							<!-- @if ($spec['has_img'])
+							<span class="input-group-addon btn-primary" data-toggle="image" style="cursor:pointer;" title="上传图片">
+								<i class="fa fa-file-photo-o"></i>
+								<input type="hidden" name="attr[{{$spec['id']}}][thumb][]" placeholder="图片路径">
+							</span>
+							@endif -->
+							<input type="{{$spec['input_type']}}" name="attr[{{$spec['id']}}][name][]" class="form-control attr_name" required="required" placeholder="属性" />
+						</div>
+						<div class="input-group col-sm-4">
+							<input type="text" class="form-control" name="attr[{{$spec['id']}}][remark][]"  placeholder="备注" />
+							<span class="input-group-addon btn-danger remove_attr" style="cursor:pointer;">
+								<i class="fa fa-trash-o"></i>
+							</span>
+						</div>
+					</div>
+				</div>
+				@else
+					@foreach ($spec['attr_list'] as $attr)
+					<div class="form-group col-sm-3 attr_div">
+						<div class="form-group form-inline">
+							<div class="input-group col-sm-4">
+								<!-- @if ($spec['has_img'])
+								<span class="input-group-addon btn-primary" data-toggle="image" style="cursor:pointer;" title="上传图片">
+									<i class="fa fa-file-photo-o"></i>
+									<input type="hidden" name="attr[{{$spec['id']}}][thumb][]" placeholder="图片路径" vlalue="value="{{$attr['thumb']}}" ">
+								</span>
+								@endif -->
+								<input type="{{$spec['input_type']}}" name="attr[{{$spec['id']}}][name][]" class="form-control attr_name" required="required" placeholder="属性" value="{{$attr['name']}}" />
+							</div>
+							<div class="input-group col-sm-4">
+								<input type="text" class="form-control" name="attr[{{$spec['id']}}][remark][]"  placeholder="备注" value="{{$attr['remark']}}" />
+								<span class="input-group-addon btn-danger remove_attr" style="cursor:pointer;">
+									<i class="fa fa-trash-o"></i>
+								</span>
+							</div>
+						</div>
+					</div>
+					@endforeach
+				@endif
+				<div class="form-group col-sm-3 add_attr_div">
+					<div class="form-group form-inline">
+						<div class="input-group">
+							<button type="button"  class="form-control add_attr"><i class="ace-icon fa glyphicon-plus"></i>添加属性</button>
+						</div>
+					</div>
+				</div>
+			</div>
+		</div>
+		@endforeach
+		@if( !$specList )
+		<script type="text/javascript">
+			$(function(){
+				// 获取
+				var type_id	= $('#typeId').val();
+				// 获取对应的规格
+				getSpecHtml(type_id);
+			})
+		</script>
+		@endif
+	</div>
+	<div class="form-group col-sm-12" id="add_sku">
+		<div class="form-group col-sm-12">
+			<div class="table-responsive">
+				<table class="table table-striped table-bordered table-hover">
+					<thead>
+						<tr>
+							@foreach ($specList as $value)
+							<th>{{$value['name']}}</th>
+							@endforeach
+							<th>价格</th>
+							<th>库存</th>
+							<th>是否上架</th>
+							<th>操作</th>
+						</tr>
+					</thead>
+					<tbody>
+						@foreach ($skuList as $value)
+						<tr>
+							@foreach (explode(',',$value['attr_ids']) as $v)
+							<td>{{$v}}</td>
+							@endforeach
+							<td><input type="text" name="sku[{{$value['attr_ids']}}][price]" placeholder="价格" value="{{$value['price']}}"></td>
+							<td><input type="number" name="sku[{{$value['attr_ids']}}][stock]" placeholder="库存"  value="{{$value['stock']}}"></td>
+							<td>
+								<select name="sku[{{$value['attr_ids']}}][status]" >
+									<option value="0" @if( $value['status'] == 0 )  selected @endif>上架</option>
+									<option value="1" @if( $value['status'] == 1 )  selected @endif>下架</option>
+								</select>
+							</td>
+							<td>
+								<button type="button" class="btn btn-xs btn-danger remove_sku">删除 </button>
+							</td>
+						</tr>
+						@endforeach
+					</tbody>
+				</table>
+			</div>
+		</div>
+		<script type="text/javascript">
+			$(function(){
+				// 删除属性
+				$('#add_sku').on('click','.remove_sku',function(){
+					// 只有一个节点时(没有同级节点)。不允许删除
+					if( $(this).parents('tr').siblings('tr').length < 1 ) return false;
+					$(this).parents('tr').remove();
+					return false;
+				})
+			})
+		</script>
+	</div>
+	<div class="form-group col-sm-12">
+		<label class="control-label">产品简介</label>
+		<textarea required="required"  name="description" id="container" placeholder="产品简介" maxlength="1500">{{$oldData['description']}}</textarea>
+	</div>
+	<div class="form-group col-sm-12">
+		@csrf
+		<input id="send" type="submit" value="提交" class="btn btn-primary btn-block" />
+	</div>
+</form>
+@endsection
+@section('javascript')
+<script src="/static/ueditor/ueditor.config.js"></script>  
+<script src="/static/ueditor/ueditor.all.js"></script>
+<script type="text/javascript">
+	var editor = new UE.ui.Editor();
+	editor.render("container");
+</script>
+<script type="text/javascript">
+// 获取类型的规格
+function getSpecHtml(type_id){
+	$.ajax({
+		type: 'get',
+		url: "{{url('admin/product/get_spec_html')}}",
+		data: {type_id:type_id},
+		success: function(data) {
+			$('#add_spec').html(data);
+		},
+		error: function(data) {
+			
+		}
+	});
+}
+
+// 获取节点
+$(function(){
+	$('#typeId').change(function(){
+		// 获取
+		var type_id	= $('#typeId').val();
+		// 获取对应的规格
+		getSpecHtml(type_id);
+	})
+})
+</script>
+
+
+<script type="text/javascript">
+	$(function(){
+		// 添加属性
+		$('#add_spec').on('click','.add_attr',function(){
+			// 克隆
+			var copy = $(this).parents('.add_attr_div').prev().clone();
+			$(this).parents('.add_attr_div').before(copy);
+			return false;
+		});
+		// 删除属性
+		$('#add_spec').on('click','.remove_attr',function(){
+			// 只有一个节点时(没有同级节点)。不允许删除
+			// if( $(this).parents('.attr_div').siblings('.attr_div').length < 1 ) return false;
+			$(this).parents('.attr_div').remove();
+			var formData = $('#add_spec input,select').serialize();
+			$.ajax({
+				type: 'get',
+				url: "{{url('admin/product/get_sku_html?product_id='.$oldData['id'])}}",
+				data: formData,
+				success: function(data) {
+					$('#add_sku').html(data);
+				},
+				error: function(data) {
+					
+				}
+			});
+			return false;
+		})
+		// 属性名称变更
+		$('#add_spec').on('change','.attr_name',function(){
+			// 获取当前的名称
+			var name = $(this).val();
+			var formData = $('#add_spec input,select').serialize();
+			$.ajax({
+				type: 'get',
+				url: "{{url('admin/product/get_sku_html?product_id='.$oldData['id'])}}",
+				data: formData,
+				success: function(data) {
+					$('#add_sku').html(data);
+				},
+				error: function(data) {
+					
+				}
+			});
+			return false;
+		})
+	})
+</script>
+
+<script type="text/javascript">
+	$(function(){
+		// 删除规格
+		$('#add_sku').on('click','.remove_sku',function(){
+			// 只有一个节点时(没有同级节点)。不允许删除
+			// if( $(this).parents('tr').siblings('tr').length < 1 ) return false;
+			$(this).parents('tr').remove();
+			return false;
+		})
+	})
+</script>
+@endsection

+ 1 - 1
resources/views/admin/product/edit.blade.php

@@ -189,7 +189,7 @@ style="margin: 0 auto;width: 96%;padding: 30px 0px;"
 								</select>
 							</td>
 							<td>
-								<input type="hidden" name="sku[{{$value['attr_ids']}}][id]" placeholder="价格" value="{{$value['id']}}">
+								<input type="hidden" name="sku[{{$value['attr_ids']}}][id]" value="{{$value['id']}}">
 								<button type="button" class="btn btn-xs btn-danger remove_sku">删除 </button>
 							</td>
 						</tr>

+ 19 - 8
resources/views/admin/product/index.blade.php

@@ -4,7 +4,9 @@ style="margin: 0 auto;width: 96%;padding: 30px 0px;"
 @endsection
 @section('content')
 <div class="page-header">
+	@if(check_auth('admin/product/add'))
 	<a href="{{url('admin/product/add')}}" class="btn btn-primary">新增</a>
+	@endif
 </div>
 <form action="" method="get" class="form-horizontal form-line">
 	<div class="form-group col col-lg-2 col-md-2 col-sm-2 col-xs-12" style="margin-right: 2px;">
@@ -65,17 +67,26 @@ style="margin: 0 auto;width: 96%;padding: 30px 0px;"
 						<td> {{$a['quota']}} </td>
 						<td> {{date('Y/m/d H:i:s',$a['update_time'])}}</td>
 						<td>
+							@if(check_auth('admin/product/edit'))
 							<a class="btn btn-sm btn-warning" href="{{url('admin/product/edit?'.http_build_query(['id'=>$a['id']]))}}" title="查看">
 								编辑
 							</a>
-							@if ($a['status'])
-								<a class="delete btn btn-sm btn-success" data-url="{{url('admin/product/set_status?'.http_build_query(['id'=>$a['id'],'status'=>'0']))}}">
-									上架
-								</a>
-							@else
-								<a class="delete btn btn-sm btn-danger" data-url="{{url('admin/product/set_status?'.http_build_query(['id'=>$a['id'],'status'=>'1']))}}">
-									下架
-								</a>
+							@endif
+							@if(check_auth('admin/product/copy'))
+							<a class="btn btn-sm btn-primary" href="{{url('admin/product/copy?'.http_build_query(['id'=>$a['id']]))}}" title="复制">
+								复制
+							</a>
+							@endif
+							@if(check_auth('admin/product/set_status'))
+								@if ($a['status'])
+									<a class="delete btn btn-sm btn-success" data-url="{{url('admin/product/set_status?'.http_build_query(['id'=>$a['id'],'status'=>'0']))}}">
+										上架
+									</a>
+								@else
+									<a class="delete btn btn-sm btn-danger" data-url="{{url('admin/product/set_status?'.http_build_query(['id'=>$a['id'],'status'=>'1']))}}">
+										下架
+									</a>
+								@endif
 							@endif
 						</td>
 					</tr>

+ 2 - 0
routes/web.php

@@ -109,6 +109,8 @@ Route::middleware('admin')->prefix('admin')->group(function(){
     Route::any('product/add',[App\Http\Controllers\Admin\Product::class,'add']);
     // 编辑
     Route::any('product/edit',[App\Http\Controllers\Admin\Product::class,'edit']);
+    // 添加
+    Route::any('product/copy',[App\Http\Controllers\Admin\Product::class,'copy']);
     // 状态
     Route::any('product/set_status',[App\Http\Controllers\Admin\Product::class,'set_status']);
     // 状态