项目中要求商品有多个规格,实现的步骤如下,其中规格名修改,规格值的添加和删除代码没有贴出来

我们要实现的是如下图:

多规格商品如何存到es_css

直接上代码

前端代码

{extend name="admin/public/content" /} {block name="css"}
<style>
  .el-main {
    padding: 0px !important;
  }
  .products-detail-imgwrap {
    width: 300px;
  }
  .normal-img {
    max-width: 100%;
    max-height: 100%;
  }
  .padding15 {
    padding: 10px 15px;
  }
  .mb10 {
    margin-bottom: 10px;
  }
  .part{border-top: 1px solid #dddd;display: block;height: 86px;}
</style>
<style>
  .goods-spec {
    display: flex;
    justify-content: space-between;
    margin-bottom: 10px;
  }
  .goods-spec .goods-spec-add {
    margin-right: 15px;
  }

  .goods-container .button-new-tag {
    height: 32px;
    line-height: 30px;
    padding-top: 0;
    padding-bottom: 0;
  }
  .goods-container .input-new-tag {
    width: 90px;
    margin-right: 10px;
    vertical-align: bottom;
  }
  .goods-container .el-tag {
    margin-right: 10px;
  }
  .goods-container .goods-content {
    margin-bottom: 10px;
    padding: 14px;
    border: 1px solid #ebeef5;
    border-radius: 4px;
    background-color: #fcfcfc;
  }
  .goods-content .goods-content-box {
    display: flex;
    align-items: center;
  }
  .goods-content-box .goods-content-left {
    flex: 1;
  }
  .el-upload--picture-card, .avatar-uploader{
    width: 50px;
    height: 50px;
  }

</style>

{/block} {block name="body"}
<div class="ack-content" v-loading="loading">
  <el-form :model="ruleForm" ref="ruleForm" label-width="150px" enctype="multipart/form-data">
    <el-radio-group v-model="tabShow" style="margin-bottom: 15px;">
      <el-radio-button label="1">商品基本信息</el-radio-button>
      <el-radio-button label="2">商品图册</el-radio-button>
      <el-radio-button label="3">商品规格设置</el-radio-button>
      <el-radio-button label="4">门店价会员价设置</el-radio-button>
  </el-radio-group>
    <!-- 商品基本信息开始 -->
    <div class="block ruleForm-width" style="margin-bottom: 15px;" v-show="tabShow == 1">
      <div class="layui-card padding15">

        <el-row class="mb10">
          <el-col style="width:150px;">选择分类:</el-col>
          <el-col style="width:400px;">
            <el-cascader
            @change="goodsTypeChange"
            clearable
            filterable
            placeholder="选择商品类型"
            v-model="searchCateSelectedOption"
            :options="searchCateOptions"
          >
          </el-cascader>
          </el-col>
        </el-row>
    
        <el-row class="mb10">
          <el-col style="width:150px;">规格:</el-col>
          <el-col style="width:400px;">
            <el-input
              v-model="productDetail.spec" type="text"
            ></el-input>
          </el-col>
        </el-row>
    
        <!-- <el-row class="mb10" v-if="server_id == 1338">
          <el-col style="width:150px;">品牌:</el-col>
          <el-col style="width:400px;">
            <el-input
              v-model="productDetail.spec" type="text"
            ></el-input>
          </el-col>
        </el-row> -->
        <el-row class="mb10">
          <el-col style="width:150px;"> 商品品牌<font style="color: #f60;">*</font>:</el-col>
          <el-col style="width:400px;">
            <el-select v-model="brandSelectedOption" style="width:400px;" placeholder="商品品牌" collapse-tags size="small" filterable clearable default-first-option>
                <el-option
                        v-for="item in brandList"
                        :key="item.id"
                        :label="item.brand_name"
                        :value="item.id"
                        @change="brandChange"
                      >
                </el-option>
            </el-select>
          </el-col>
        </el-row>
        <el-row class="mb10">
          <el-col style="width:150px;"> 商品名称:</el-col>
          <el-col style="width:400px;">
            <el-input
              style="color: #b91616;font-size: 13px;margin-right:30px;"
              v-model="productDetail.products_title"
            ></el-input>
          </el-col>
        </el-row>
        <el-row class="mb10">
          <el-col style="width:150px;">商品价格:</el-col>
          <el-col style="width:400px;">
            <el-input style="color: #b91616;font-size: 13px;margin-right:30px;" v-model="productDetail.products_price" type="number"></el-input>
          </el-col>
        </el-row>
        <el-row class="mb10">
          <el-col style="width:150px;">商品折扣价:</el-col>
          <el-col style="width:400px;">
            <el-input style="color: #b91616;font-size: 13px;margin-right:30px;"
                    v-model="productDetail.products_discount_price" type="number"
            ></el-input>
          </el-col>
        </el-row>
        <el-row class="mb10">
          <el-col style="width:150px;">销售价格:</el-col>
          <el-col style="width:400px;">
            <el-input
                    style="color: #b91616;font-size: 13px;margin-right:30px;"
                    v-model="productDetail.products_sale_price" type="number"
            ></el-input>
          </el-col>
        </el-row>
        <!-- <el-row class="mb10" v-show="is_spec == true">
          <el-col style="width:150px;">所属服务规格:</el-col>
          <el-col style="width:400px;">
          
            <div>
                <span style="width:150px;display: inline-block;" v-show="is_part == 1">服务部位</span>
                <span style="width:50px;display: inline-block;height: 1px;" v-show="is_part == 2"></span>
                <span style="width:120px;display: inline-block;">车身结构</span>
                <span style="width:120px;display: inline-block;">价格</span>
            </div>
            <div :style="width">
              <div class="part" style="border-top:0;" v-for="(item,index) in part">
                <el-col style="width:150px" v-show="is_part == 1" >
                  <el-checkbox v-model="item.checked" :label="item.server_name" :key="item.server_name" style="margin: 30px;" @change="changeServerId(index, item.server_id, $event)">{{item.server_name}}</el-checkbox>
                </el-col>
                <el-col style="width:50px;height: 1px;" v-show="is_part == 2" ></el-col>
                <el-col style="width:120px">
                  <span style="width:100px" v-for="itemAttr, attrIndex in item.attr">
                    <el-checkbox v-model="itemAttr.checked" :label="itemAttr.name" style="margin: 10px;"  @change="changeAttr(index, itemAttr.name, $event)"></el-checkbox>
                  </span>
                </el-col>
                <el-col style="width:120px" v-for="itemAttr, attrIndex in item.attr">
                  <span style="width:100px">
                    <el-input placeholder="请输入价格" v-model="itemAttr.price" size="small" style="margin: 5px;width:150px;" @change="changePrice(index, attrIndex, itemAttr.price)"><template slot="append">元</template></el-input>
                  </span>
                </el-col>
              </div>
            
            </div>
          </div>
          </el-col>
        </el-row> -->
        <el-row class="mb10">
          <el-col style="width:150px;">是否特价:</el-col>
          <el-col style="width:400px;">
            <el-switch v-model="productDetail.is_price"></el-switch>
          </el-col>
        </el-row>
        <el-row class="mb10">
          <el-col style="width:150px;">商品特价:</el-col>
          <el-col style="width:400px;">
            <el-input style="color: #b91616;font-size: 13px;margin-right:30px;" v-model="productDetail.spec_price" type="number"></el-input>
          </el-col>
        </el-row>
        <el-row class="mb10">
          <el-col style="width:150px;">净含量:</el-col>
          <el-col style="width:400px;">
            <el-input
              v-model="productDetail.amount" type="number"
            ></el-input>
          </el-col>
        </el-row>
        <el-row class="mb10">
          <el-col style="width:150px;">库存:</el-col>
          <el-col style="width:400px;">
            <el-input
              v-model="productDetail.products_quantity" type="number"
            ></el-input>
          </el-col>
        </el-row>
        <el-row class="mb10">
          <el-col style="width:150px;"> 价格说明:</el-col>
          <el-col style="width:600px;">
            <el-input
              v-model="productDetail.price_desc" type="textarea"
            ></el-input>
          </el-col>
        </el-row>
        <!-- <el-row class="mb10">
          <el-col style="width:150px;">选择单位:</el-col>
          <el-col style="width:400px;">
            <el-select v-model="unitSelectedOption" placeholder="请选择" style="width: 400px;">
              <el-option
                v-for="item in unitOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value">
              </el-option>
            </el-select>
          </el-col>
        </el-row> -->
        
        
           
           
      </div>
    </div>
    <!-- 商品基本信息结束 -->
     <!-- 商品图册开始 -->
  <div class="block ruleForm-width" style="margin-bottom: 15px;padding-left: 20px;" v-show="tabShow == 2">
    <el-row class="mb10">
      <el-col style="width:150px;">商品图片(点击上传):</el-col>
      <el-upload
              :action="action"
              class="avatar-uploader"
              list-type="picture-card"
              :on-preview="handlePictureCardPreview"
              :on-remove="handleRemove"
              limit="10"
              :on-exceed="imgExceedNum"
              :multiple="true"
              :show-file-list="true"
              :file-list="productDetail.products_image_arr"
              :on-success="successImg"
              list-type="file"
              data="productDetail.products_image_arr.name"
              :on-preview="preview">
        <i class="el-icon-plus"></i>
      </el-upload>
      <el-dialog :visible.sync="dialogVisible">
        <img width="100%" :src="dialogImageUrl" alt="">
      </el-dialog>
    </el-row>
    <el-row class="mb10" >
      <el-col style="width:150px;"> 商品详情图(最多20张):</el-col>
      <el-upload
              :action="action"
              class="avatar-uploader"
              list-type="picture-card"
              :on-preview="handlePictureCardPreview1"
              :on-remove="handleRemove1"
              limit="20"
              :on-exceed="imgExceedNum1"
              :multiple="true"
              :show-file-list="true"
              :file-list="productDetail.products_descs_arr"
              :on-success="successImg1"
              list-type="file"
              data="productDetail.products_descs_arr.name"
              :on-preview="preview">
        <i class="el-icon-plus"></i>
      </el-upload>
      <el-dialog :visible.sync="dialogVisible">
        <img width="100%" :src="dialogImageUrl" alt="">
      </el-dialog>
    </el-row>
  </div>
  <!-- 商品图册结束 -->
   <!-- 商品规格开始 -->
   <div class="block ruleForm-width" style="margin-bottom: 15px;padding-left: 20px;" v-show="tabShow == 3">
    <!-- 多规格添加 -->
    <!-- <el-row class="mb10" >
      <el-col :span="24" v-for="cate, index in Specitem"> 
        <h5 style="padding:20px;">{{cate.name}}:</h5>
        <el-checkbox-group v-model="ruleForm.Specitem" style="margin-left: 24px;">
          <el-checkbox v-for="item,itemIndex in cate.children" :id="'man' + index + itemIndex" :label="item.id" :key="item.id" v-model="item.selected">{{item.name}}</el-checkbox>
        </el-checkbox-group>
      </el-col>
    </el-row> -->
    <!-- 多规添加结束 -->
    <!-- 多规格设置 -->
    <el-row class="mb10">
      <div id="app">
        <div style="padding:14px;">
          <!-- <div class="goods-spec">
            <span>商品规格</span>
            <el-link type="primary" @click="addPrivateSpec" class="goods-spec-add">添加规格</el-link>
          </div> -->
          <div class="goods-container" v-for="(attr, index) in Specitem" :key="index">
            <div class="goods-content">
              <div class="goods-content-box">
                <div class="goods-content-left">
                  <el-form label-width="80px" style="width:1000px">
                    <el-form-item label="规格名">
                      <el-input v-model="attr.name" placeholder="请输入规格名" style="width:200px"></el-input>
                    </el-form-item>
                    <el-form-item label="规格值">
                      <!-- <el-tag v-for="tag in attr.children" :key="tag" closable :disable-transitions="false" @close="handleClose(tag, attr)">
                        {{ tag.name }}
                      </el-tag> -->
                      <el-checkbox-group v-model="ruleForm.Specitem" style="margin-left: 14px;" >
                        <el-checkbox v-for="item,itemIndex in attr.children" :id="'man' + index + itemIndex" :label="item.id" :key="item.id" v-model="item.selected" @change="handleCheckedSpecChange(attr.id, item.id)" >{{item.name}}</el-checkbox>
                      </el-checkbox-group>
                      <el-input
                        class="input-new-tag"
                        v-if="attr.inputVisible"
                        v-model="attr.inputValue"
                        :ref="`saveTagInput${index}`"
                        size="small"
                        @keyup.enter.native="handleInputConfirm(attr.inputValue, attr)"
                        @blur="handleInputConfirm(attr.inputValue, attr)"
                      >
                      </el-input>
                      <el-button v-else class="button-new-tag" size="small" @click="showInput(attr, index)">+ 添加</el-button>
                    </el-form-item>
                  </el-form>
                </div>
                <div class="goods-content-right">
                  <el-link type="danger" @click="delPrivateSpec(index)">删除规格</el-link>
                </div>
              </div>
            </div>
          </div>
  
      
          <el-table ref="multipleTable" :data="tableColumnList.tableBodyList" stripe tooltip-effect="dark" style="width: 100%;margin-top:1%;">
            <el-table-column :label="item.name" :property="item.name" v-for="item in tableColumnList.tableHeaderList" :key="item.name" align="center">
              <template slot-scope="scope">
                <span >{{ scope.row[scope.column.property] }}</span>
              </template>
            </el-table-column>
            <el-table-column label="价格(元)">
              <template slot-scope="scope">
                <el-input v-model.number="scope.row.price" @change="priceChange(scope.row)"></el-input>
              </template>
            </el-table-column>
            <el-table-column label="库存">
              <template slot-scope="scope">
                <el-input v-model.number="scope.row.stock" @change="priceChange(scope.row)"></el-input>
              </template>
            </el-table-column>
            <el-table-column label="图片" >
              <!-- <template slot-scope="scope">
                <el-button type="text" @click="handleClick(scope.row)">上传规格图</el-button>
		         	</template> -->
           
                <template slot-scope="scope" class="iconImg" >
                  <el-upload
                  :key="timer"
                  :action="action"
                  class="avatar-uploader"
                  list-type="picture-card"
                  :on-preview="handlePictureCardPreview2"
                  :on-remove="handleRemove2"
                  :multiple="true"
                  :show-file-list="false"
                  :file-list="uploadFileList"
                  :on-success="(response, file, fileList) =>successImg2(response, file, fileList,scope)"
                  limit="1"
                  :on-exceed="imgExceedNum2"
                >
                <img v-if="scope.row.spec_item_image" :src="scope.row.spec_item_image" class="avatar" style="width: 50px;height: 50px;display: block;margin: auto;">
                <i v-else class="el-icon-plus avatar-uploader-icon" style="width: 50px;height: 50px;display: block;margin: auto;font-size:40px;"></i>
                <!-- <i class="el-icon-plus" ></i> -->
                </el-upload>
                    <!-- <el-upload
                    :action="action"
                    class="avatar-uploader"
                    list-type="picture-card"
                    :on-preview="handlePictureCardPreview2"
                    :on-remove="handleRemove2"
                 
                    :multiple="true"
                    :show-file-list="true"
                    :file-list="scope.row.spec_item_image"
                    :on-success="successImg2"
                    list-type="file"
                    data="scope.row.spec_item_image.name"
                    :on-preview="preview" >
                    <i class="el-icon-plus" ></i>
                    </el-upload> -->
                    <!-- <el-dialog :visible.sync="dialogVisible" >
                      <img  :src="dialogImageUrl" alt="" >
                    </el-dialog> -->
                </template>
            </el-table-column>
            <el-table-column prop="" label="操作" >
              <template slot-scope="scope">
                 
                  <el-tooltip class="item" effect="dark" content="谨慎删除,不可恢复" placement="top" >
                      <a href="javascript:;" @click="delProduct(scope)">
                          <i class="layui-icon layui-icon-delete"></i><cite>删除</cite>
                      </a>
                  </el-tooltip>
              </template>
          </el-table-column>
          </el-table>
        </div>
      </div>

      
    </el-row>
    <!-- 多规格设置结束 -->
    <!-- <template v-for="cate, index in Specitem">
      
      <h5 style="padding:20px;">{{cate.name}}</h5>
        <el-radio-group v-model="ruleForm.Specitem[index]" style="margin-left: 24px;">
          <el-radio-button v-for="item,itemIndex in cate.children" :id="'man' + index + itemIndex" :label="item.id" :key="item.id" v-model="item.selected"  >{{item.name}}</el-radio-button>
        </el-radio-group>
        <div style="margin: 15px 0;"></div>
    </template> -->
    <!-- <el-row class="mb10" >
      <el-col style="width:150px;"> 商品规格图片(最多1张):</el-col>
      <el-upload
              :action="action"
              class="avatar-uploader"
              list-type="picture-card"
              :on-preview="handlePictureCardPreview2"
              :on-remove="handleRemove2"
              limit="1"
              :on-exceed="imgExceedNum2"
              :multiple="true"
              :show-file-list="true"
              :file-list="productDetail.spec_item_image"
              :on-success="successImg2"
              list-type="file"
              data="productDetail.spec_item_image.name"
              :on-preview="preview">
        <i class="el-icon-plus"></i>
      </el-upload>
      <el-dialog :visible.sync="dialogVisible">
        <img width="100%" :src="dialogImageUrl" alt="">
      </el-dialog>
    </el-row> -->
    
  </div>
  <!-- 商品规格结束-->
  <!-- 会员价、门店价设置开始@change="changeOriginalPriceValue(item,item.attr)" -->
  <div class="block ruleForm-width" style="margin-bottom: 15px;" v-show="tabShow == 4">
    <el-row class="mb10" style="width:800px;margin-left: 20px;">
      <el-input v-model="productDetail.rebate" placeholder="如:0.85" style="width: 215px;" controls-position="right" ref="index1"><template slot="prepend" >会员价折扣</template></el-input>
      
  </el-row>
  <el-row class="mb10" style="margin-left: 20px;">
    <span style="color:red">如下是设置的门店售价,会员价等于门店价X会员折扣自动计算</span>
  </el-row>
    <el-row class="mb10" v-for="item,index in productDetail.member_price"  :key="index" :label="item.attr">
     
      <el-col style="width:300px;margin-left: 20px;" >
      
          <el-input v-model="item.price" controls-position="right" :precision="2" :step="1" :min="0" size="small"  @input="changeOriginalPriceValue(item,index)"><template slot="prepend" >{{item.attr}}</template></el-input>
      </el-col>
      <el-col :span="6">
        <el-input v-model="meprice[index]"  placeholder="会员价" size="small"  :disabled=true></el-input>
      </el-col>
    </el-row>
    <el-row class="mb10" v-show="is_spec == true">
      <el-col style="width:150px;">所属服务规格:</el-col>
      <el-col style="width:400px;">
      
        <div>
            <span style="width:150px;display: inline-block;" v-show="is_part == 1">服务部位</span>
            <span style="width:50px;display: inline-block;height: 1px;" v-show="is_part == 2"></span>
            <span style="width:120px;display: inline-block;">车身结构</span>
            <span style="width:120px;display: inline-block;">价格</span>
        </div>
        <div :style="width">
          <div class="part" style="border-top:0;" v-for="(item,index) in part">
            <el-col style="width:150px" v-show="is_part == 1" >
              <el-checkbox v-model="item.checked" :label="item.server_name" :key="item.server_name" style="margin: 30px;" @change="changeServerId(index, item.server_id, $event)">{{item.server_name}}</el-checkbox>
            </el-col>
            <el-col style="width:50px;height: 1px;" v-show="is_part == 2" ></el-col>
            <el-col style="width:120px">
              <span style="width:100px" v-for="itemAttr, attrIndex in item.attr">
                <el-checkbox v-model="itemAttr.checked" :label="itemAttr.name" style="margin: 10px;"  @change="changeAttr(index, itemAttr.name, $event)"></el-checkbox>
              </span>
            </el-col>
            <el-col style="width:120px" v-for="itemAttr, attrIndex in item.attr">
              <span style="width:100px">
                <el-input placeholder="请输入价格" v-model="itemAttr.price" size="small" style="margin: 5px;width:150px;" @change="changePrice(index, attrIndex, itemAttr.price)"><template slot="append">元</template></el-input>
              </span>
            </el-col>
          </div>
        
        </div>
      </div>
      </el-col>
    </el-row> 
  </br>
    <el-row style="margin-left: 20px;">
      <el-button type="primary" @click="submitForm('ruleForm')">确认保存</el-button>
    </el-row>
  </div>
  <!-- 会员价、门店价设置结束 -->
  </el-form>
  <!-- 规格图片上传会话框 -->

  <el-dialog title="上传图片" :visible.sync="uploadQcVisible" @closed="closePic">
    <el-upload
      :key="timer"
      :action="action"
      class="avatar-uploader"
      list-type="picture-card"
      :on-preview="handlePictureCardPreview2"
      :on-remove="handleRemove2"
      :multiple="true"
      :show-file-list="true"
      :file-list="uploadFileList"
      :on-success="successImg2"
      limit="1"
      :on-exceed="imgExceedNum2"
    >
    <i class="el-icon-plus" ></i>
    </el-upload>
  </el-dialog>
  <!-- 规格图片上传会话框结束 -->
</div>
{/block} {block name="js"}
<script>
  //引入layui
  layui.config({
      base: '__STATIC__/admin/static/' //静态资源所在路径
    }).extend({
      index: 'lib/index' //主入口模块
    }).use('index');
  // vue 渲染数据
  var vm = new Vue({
    el: '#app',
    data: {
      tabShow:1,
      isDialogFormVisible: false,
      uploadQcVisible:false,
      timer:'',
      uploadFileList:[],
      tempObj:[],
      loading: false,
      orderDetail: {},
      ruleForm : {
        Specitem:[]
      },
      meprice:[],
      order_id: '',
      //商品信息START
      storeList: [],
      attr_price:'',
      is_spec: false,
      width: 'width: auto;',
      server_id: JSON.parse('{$server_id}'),//'{$server_id}',
      // 商品sku
      tableColumnList:{
        tableHeaderList: [],
        tableBodyList: []
      },
      //new 选中的规格项
      spec_arr:{},
      // part: [
      //   {
      //     server_id: 1,
      //     server_name: '1111',
      //     attr: [
      //       {
      //         name: '轿车',
      //         price: '20.00'
      //       },
      //       {
      //         name: 'SUV',
      //         price: '30.00'
      //       },
      //     ]
      //   },
      //   {
      //     server_id: 2,
      //     server_name: '2222',
      //     attr: [
      //       {
      //         name: '轿车',
      //         price: '20.00'
      //       },
      //       {
      //         name: 'SUV',
      //         price: '30.00'
      //       },
      //     ]
      //   },
      // ],
      part: [],
      productDetail: {
        products_title: '',
        products_price: 0,
        products_image_arr: [],
        store: [],
        sps:[],
        price_desc:'',
        products_category: '',
        products_quantity: 0,
        spec: '',
        amount: '',
        defaultCheckedKeys: [], //服务分类选中值
        products_attr: [],
        products_descs_arr:[],
        Specitem:[],
        spec_item_image:'',
        is_price:false,
        member_price:[],//会员价
        rebate:'',
        spec_price:'',
          // {
          //   server_id: '',
          //   attrSpec: '',
          //   price: ''
          // }
        //]
      },
      cateOptions: [], //分类列表
      cateSelectedOption: [], //分类选中值
      Specitem:[],//分类下的规格项
      spec_disabled:true,
      specOptions:[],  //规格列表
      specSelectedOption:'',//规格选中值
      //搜索分类
      searchCateSelectedOption:[],
      searchCateOptions:[],
      unitOptions: [{ //单位列表
        value: 1,
        label: '毫升'
      }, {
        value: 2,
        label: '升'
      }, {
        value: 3,
        label: '克'
      }, {
        value: 4,
        label: '千克'
      }, {
        value: 5,
        label: '个'
      }],
      spec_item_image:[],
      unitSelectedOption: '',//单位选中值
      brand_disabled:true,
      brandSelectedOption:'',//品牌选中值
      brandList:[],//品牌列表
      storeOptions: [],
      spsOptions: [], 
      showTree:true,
      dialogImageUrl: '',
      dialogVisible: false,
      delImageUrl:[],
      defaultImageNames:['products_image','products_image_2','products_image_3','products_image_4','products_image_5'],
      store_id: '{$store_id}',
      store_server_id: '{$store_server_id}',
      type: '{$type}',
      copy: '{$copy}',
      attr: '{$attr}',
      is_part: 0,
      tt:'',
      temp:[],
      attrName: [],
      attrPrice: [],
      server: [
        {
          server_id: '',
          attr: [
            {
              attr_name: '',
              price: ''
            }
          ]
        }
      ],
      server_id:'{$server_id}',
      action: '/admin/Product/uploadDetail',
      
    },
    created() {
      //引用公共js勿删 {include file='admin/public/js'/}
      let cate_id = '{$cate_id}';
     
      if(cate_id!=0){
        this.getSpecItemLists(cate_id)
        this.getBrandList(cate_id)
      }
      //获取数据
      this.get();
      this.getStoreList();
      this.getCateList();
      this.getSpsList();
      this.getPart();
      // console.log(this.type);
      /*console.log(this.cateOptions);*/
    },
    methods: {
    // 添加规格
    addPrivateSpec(index) {
        // this.privateGoodsItem.push({
        //   privateSpecName: '',
        //   dynamicTags: [],
        //   inputVisible: false,
        //   inputValue: ''
        // })
      },
      closePic(){
        this.timer = new Date().getTime()
        // this.uploadFileList = []
      },
      //规格图上传
      handleClick(row){
        this.uploadQcVisible=true;
        this.tempObj = row
        //判断row.piclist是否已经传过数据
        if(row.spec_item_image.length !== 0){
            this.uploadFileList = Object.assign([],row.spec_item_image)
        }
        console.log(row)
      },
      delPrivateSpec(index) {
            this.privateGoodsItem.splice(index, 1)
      },
      handleInputConfirm(val, attr) {
        if (val) {
          attr.dynamicTags.push(val)
        }
        attr.inputVisible = false
        attr.inputValue = ''
      },
      handleClose(tag, item) {
        item.dynamicTags.splice(item.dynamicTags.indexOf(tag), 1)
      },
      showInput(attr, index) {
        attr.inputVisible = true
        this.$nextTick((_) => {
          this.$refs[`saveTagInput${index}`][0].$refs.input.focus()
        })
      },
    // 笛卡尔积算法
    cartesianProductOf(...args) {
        return args.reduce(
          (total, current) => {
            let ret = []
            total.forEach((a) => {
              current.forEach((b) => {
                ret.push(a.concat([b]))
              })
            })
            return ret
          },
          [[]]
        )
      },
      //移除数组中的元素返回新数组
      remove(arr, item) {
        let newArr = arr.slice(0);
          for (let i = newArr.length; i >= 0; i--) {
              if (newArr[i] === item) {
                  newArr.splice(i, 1)
            }
        }
        return newArr
      },
      // 选择规格
      handleCheckedSpecChange(spec_id,item_id){
        
          let _this=this;
          if(Object.keys(this.spec_arr)==0){
            if(!this.spec_arr.hasOwnProperty(spec_id)){
                this.spec_arr[spec_id] = [];
                this.spec_arr[spec_id].push(item_id);
            }
          }else{
            if(this.spec_arr.hasOwnProperty(spec_id)){
              this.spec_arr[spec_id].forEach((itemarr,index)=>{
                
                        if(itemarr==item_id){
                   
                                let narr=this.remove(this.spec_arr[spec_id], item_id);
                                this.spec_arr[spec_id] = [];
                                if(narr.length>0){
                                      for (let i = 0; i < narr.length; i++) {
                                        this.spec_arr[spec_id].push(narr[i]);
                                      }
                                  
                                }else{
                                  delete this.spec_arr[spec_id];
                                }
                        }else{
                          if(this.spec_arr[spec_id].indexOf(this.spec_arr[spec_id][index])==index){
                            this.spec_arr[spec_id].push(item_id);
                          }
                         
                        }
                });
               
               
            }else{
                this.spec_arr[spec_id] = [];
                this.spec_arr[spec_id].push(item_id);
            }
          }
          // console.log(this.spec_arr)
          axios.post('/admin/Goodsspec/getSpecInput',{data:this.spec_arr,checkarr:this.ruleForm.Specitem}).then(res => {
                this.tableColumnList=res.data;
          })
      },
      // 移除某一列
      delProduct(arr){
        let key=arr.$index;
        let newarr=this.tableColumnList
        axios.post('/admin/Goodsspec/getDatahandle',{data:newarr,key:key}).then(res => {
             
                this.tableColumnList=res.data;
                console.log(this.tableColumnList)
          })
         
      },
      priceChange(val){
        console.log(val)
      },
      getPart() {
        let products_id = '{$products_id}';
        if(products_id =='') {
          axios.get('/admin/product/getPart?store_id={$store_id}&store_server_id={$store_server_id}&type={$type}').then(res => {
            this.is_spec = res.data.is_spec;
            this.part = res.data.part;
            this.is_part = res.data.is_part;
            if(res.data.is_part == 0) {
              this.width = 'width: 300px'
            }
            //console.log(this.part)
          })
        } else {
          axios.get('/admin/product/getPart?products_id={$products_id}&store_server_id={$store_server_id}&type={$type}').then(res => {
            this.is_spec = res.data.is_spec;
            this.part = res.data.part;
            this.is_part = res.data.is_part;
            if(res.data.is_part == 0) {
              this.width = 'width: 300px'
            }
          })
        }
      },
      //车型原价
      changeOriginalPriceValue(item,type) {
   
               let zhekou=this.$refs.index1.value;//设置的折扣
               zhekou= zhekou?zhekou:1;
              
                let flag = true;
                let _this=this.productDetail.member_price;
                const option={ attr:item.attr,price:item.price,server_type:this.type-1};
                if(this.productDetail.member_price.length==0){
                    _this.push(option);
                }else{
                    _this.forEach((itemarr,index)=>{
                        if(itemarr.attr==item.attr){
                             
                            _this[index].server_type=this.type;
                            _this[index].price=item.price;
                            flag=false;
                        }
                    })
                    if(flag){
                        _this.push(option);
                    }
                }
                this.meprice[type]=zhekou*item.price;
               
            
                
            },
      changeServerId(index, value, e){
        if(e == true) {
          this.temp.push({'server_id':value});
          for(let l = 0; l < this.part[index].attr.length; l++) {
            this.part[index].attr[l].checked = true
          }
          this.productDetail.products_attr = this.temp;
        } else {
          for(let l = 0; l < this.part[index].attr.length; l++) {
            this.part[index].attr[l].checked = false
            for(let j = 0; j < this.part[index].attr[l].length; j++) {
              this.part[index].attr[l].price = 0
            }
          }
          
        }
      },
      
      changeAttr(index, attrIndex, attr, e) {
        let num = 0;
        for(let i = 0; i < this.part[index].attr.length; i++) {
          if(this.part[index].attr[i].checked == true) {
            num++;

          } else {
            this.part[index].attr[i].price = 0
          }

        }
      },
      changePrice(index, attrIndex, attr, value) {
      },
      objectSpanMethod({ row, column, rowIndex, columnIndex }) {
        if (columnIndex === 0) {
          if (rowIndex % 2 === 0) {
            return {
              rowspan: 2,
              colspan: 1
            };
          } else {
            return {
              rowspan: 0,
              colspan: 0
            };
          }
        }
      },
      get() {
        this.loading = true;
        let products_id = '{$products_id}';
        axios
          .get('/admin/Product/storeProductDetail', {
            params: { products_id: products_id}
          }).then(res => {
            if (res.data) {
              this.loading = false;
              this.productDetail = res.data;
              this.meprice = res.data.meprice;
              this.brandSelectedOption=res.data.b_id;
              if(res.data.key){
                this.ruleForm.Specitem=[]; 
                this.ruleForm.Specitem = res.data.key;
              }
               
              
              this.$set(this.productDetail,'defaultCheckedKeys',this.formatTreeData(res.data.sps_ids));
              this.searchCateSelectedOption = res.data.cate_selected;
              this.formatPdDetail();
            }
          });
      },
      //编辑保存
      submitForm(){
        /*console.log(this.unitSelectedOption);
        return false;*/

        let _this = this;
        //处理图片的数组
        //let This = this
        // if(this.productDetail.products_image_arr && this.productDetail.products_image_arr.length > 0) {
        //   for (let i=0; i<this.productDetail.products_image_arr.length; i++) {
        //     if (this.productDetail.products_image_arr[i].raw) {
        //         let reader = new FileReader();
        //         reader.readAsDataURL(this.productDetail.products_image_arr[i].raw);
        //         reader.onload = function(e) {
        //           _this.productDetail.products_image_arr[i].base64Val = this.result;
        //         };
        //         _this.productDetail.products_image_arr[i].isNewAdd = 1
        //     }
        //   }
        // }
        setTimeout(function(){
            _this.productDetail.products_attr = _this.part;
            let data = {
                // store_id: _this.productDetail.store_id,
                store_id: _this.store_id,
                products_id:_this.productDetail.products_id ? _this.productDetail.products_id : 0,
                products_title:_this.productDetail.products_title,
                products_price:_this.productDetail.products_price,
                products_discount_price:_this.productDetail.products_discount_price,
                products_sale_price:_this.productDetail.products_sale_price,
                cateSelectedOption:_this.cateSelectedOption,
                products_image_arr:_this.productDetail.products_image_arr,
                products_descs_arr:_this.productDetail.products_descs_arr,
                delImageUrl:_this.delImageUrl,
                products_quantity: _this.productDetail.products_quantity,
                b_id: _this.brandSelectedOption,
                Specitem: _this.ruleForm.Specitem,//商品规格
                tag:_this.productDetail.tag,
                product_base_id:_this.productDetail.product_base_id,
                spec: _this.productDetail.spec,
                amount: _this.productDetail.amount,
                is_price: _this.productDetail.is_price,
                store_server_id: _this.store_server_id,
                type: _this.type,
                copy: _this.copy,
                attr:_this.attr,
                products_attr: _this.productDetail.products_attr,
                add_server_id:_this.server_id,
                spec_item_image:_this.productDetail.spec_item_image,
                price_desc:_this.productDetail.price_desc,
                member_price:_this.productDetail.member_price,
                rebate:_this.productDetail.rebate,
                spec_price:_this.productDetail.spec_price,
                //products_unit:_this.unitSelectedOption,
                tableColumnList:_this.tableColumnList
            }
            _this.loading = true;
            console.log(_this.tableColumnList)
            // console.log(_this.tempObj)
            console.log(data)
            return
            axios.post('/admin/Product/saveProductDetail', data).then(res => {
                // console.log(res); return;
            _this.loading = false;
            if (res.code == 200) {
                _this.$message({
                    type: 'success',
                    message: res.message
                });
                setTimeout(function(){
                    var index = parent.layer.getFrameIndex(window.name);
                    parent.layer.close(index);
                    parent.location.reload();
                },10)
            }else {
                _this.$message({
                    type: 'error',
                    message: res.message
                });
            }
          });
        },10)
      },
      changeBookingTime(order_id) {
        this.isDialogFormVisible = !this.isDialogFormVisible;
        this.order_id = order_id;
      },
      formatPdDetail() {
        this.$nextTick(() => {
          this.cateSelectedOption = [
            this.productDetail.category_pid,
            this.productDetail.products_category
          ];
        });
      },
      formatCateList(arr) {
        arr.forEach(item => {
          item.label = item.name;
          item.value = item.id;
          if (item.children) {
            this.formatCateList(item.children);
          }
        });
        return arr;
      },
      getCateList() {
        this.loading = true;
        let type = this.type;
        let server_id = this.server_id

        axios.get('/admin/Product/cateList', { params: {'type':type,'server_id':server_id} }).then(res => {
          if (res.data) {
            this.loading = false;
            this.cateOptions = this.formatCateList(res.data);
            this.searchCateOptions = this.formatCateList(res.data);
          }
        });
      },
      brandChange(arr) {
      
      },
      getSpecItemLists(cate_id){
          axios.get('/admin/Product/getSpecItem', { params: {'cate_id':cate_id}}).then(res => {
                  this.Specitem = res.data.lists;
                  this.ruleForm.Specitem=res.data.keys;
        })
      },
      // handleCheckedManServerChange(value) {
      //           let checkedCount = value.length;
      //           this.checkAll = checkedCount === this.Specitem.length;
      //           this.isIndeterminate = checkedCount > 0 && checkedCount < this.Specitem.length;
      // },
      getBrandList(cate_id){
        this.loading = true;

        let cate_arr = this.cateSelectedOption;
        end = cate_arr[cate_arr.length-1];
        if(cate_id){
          end=cate_id
        }
        //console.log(cate_arr);
        //console.log(end);
        axios.get('/admin/Index/getSelectOption', { params: {'act':'goods_brand','cate_id':end}}).then(res => {
          this.loading = false;

          if(res.data.rows.length == 0){
            this.brand_disabled = true;
          }
          this.brandList = res.data.rows
          //console.log(res.data.rows)
        }); 
      },
      goodsTypeChange(val){
        if(val){
            let cate_id=val[1]
            session_arr = [];
            for(let i = 0; i < val.length; i++){
              session_arr[i] = val[i];
            }
            this.loading = true;
            axios.get('/admin/Index/getSelectOption', { params: {'act':'goods_brand','cate_id':val.pop()}}).then(res => {
              this.loading = false; 
              this.brandList = res.data.rows
              this.searchCateOptions = Object.assign([], this.searchCateOptions, []);
              this.searchCateSelectedOption= Object.assign([],this.searchCateSelectedOption, []);
              this.searchCateSelectedOption = session_arr;
              this.cateSelectedOption=session_arr;
              this.brandSelectedOption = ''
              
              this.getSpecItemLists(cate_id)
            })
        }
        
      },
      cateChange(arr) {
       
        this.productDetail.products_category = arr.length
          ? arr[arr.length - 1]
          : '';
          let cate_id=arr[1]

        //console.log(this.searchCateSelectedOption);
        session_arr = [];
        for(let i = 0; i < arr.length; i++){
	        session_arr[i] = arr[i];
        }
        // this.loading = true;
        axios.get('/admin/Index/getSelectOption', { params: {'act':'goods_brand','cate_id':arr.pop()}}).then(res => {

          // this.loading = false; 
          this.brandList = res.data.rows
          this.searchCateOptions = Object.assign([], this.searchCateOptions, []);
          this.searchCateSelectedOption= Object.assign([],this.searchCateSelectedOption, []);
          this.searchCateSelectedOption = session_arr;
          this.cateSelectedOption = session_arr;
          this.brandSelectedOption = ''
        
        
        })
      },
      getStoreList(){
        this.loading = true;
        axios.get('/admin/Index/getSelectOption', { params: {'act':'store'}}).then(res => {
          this.storeOptions = res.data.rows
        });
      },
      getSpsList() {
        this.loading = true;
        axios.get('/admin/Index/getSelectOption', { params: {'act':'sps'}}).then(res => {
          this.spsOptions = res.data.rows
        });
      },
      //服务类目切换
      treeChange(nowNode, allNode){
        /**
         * allNode:{
         *   checkedKeys:Array[id,id,...,id],
         *   checkedNodes:Array[obj,obj,...,obj],
         *   halfCheckedKeys:Array[id,id,...,id],
         *   halfCheckedNodes:Array[obj,obj,...,obj]
         * }
         * 
         */
        this.$set(this.productDetail,'defaultCheckedKeys',allNode.checkedKeys);
        //console.log(this.productDetail.defaultCheckedKeys)
      },
      //服务类目数据格式化
      formatTreeData(arr){
        let newArr = [];
        if(arr && arr.length > 0) {
          arr.forEach(item => {
            if(Array.isArray(item)){
              newArr.push(...item);
            }else{
              newArr.push(item);
            }
          });
        }
        return newArr;
      },
    
      handlePictureCardPreview(file) {
        this.dialogImageUrl = file.url;
        this.dialogVisible = true;
      },
      handlePictureCardPreview1(file) {
        this.dialogImageUrl1 = file.url;
        this.dialogVisible1 = true;
      },
      handlePictureCardPreview2(file) {
        this.dialogImageUrl1 = file.url;
        this.dialogVisible1 = true;
      },
      imgExceedNum(){
        this.$message({
          type: 'error',
          message: '最多只能上传10张图片'
        });
      },
      imgExceedNum1(){
        this.$message({
          type: 'error',
          message: '最多只能上传20张图片'
        });
      },
      imgExceedNum2(){
        this.$message({
          type: 'error',
          message: '最多只能上传1张图片'
        });
      },
      // 从fileList 中移除 file
      removeFileFromFileList(file,fileList){
        // 移除图片
        const index = fileList.findIndex((currentValue)=>{
            return currentValue.uid == file.uid
          })
        fileList.splice(index,1)
      },
      removeFileFromFileList1(file,fileList){
        // 移除图片
        const index = fileList.findIndex((currentValue)=>{
            return currentValue.uid == file.uid
          })
        fileList.splice(index,1)
      },
      removeFileFromFileList2(file,fileList){
        // 移除图片
        const index = fileList.findIndex((currentValue)=>{
            return currentValue.uid == file.uid
          })
        fileList.splice(index,1)
      },
      // 修改fileList URL 值
      updateFileListUrl(file,fileList,response){
        fileList.forEach(item => {
          if(item.uid == file.uid){
            item.url = response.data.filePath
          }
        });
      },
      updateFileListUrl1(file,fileList,response){
        fileList.forEach(item => {
          if(item.uid == file.uid){
            item.url = response.data.filePath
          }
        });
      },
      updateFileListUrl2(file,fileList,response){
        fileList.forEach(item => {
          if(item.uid == file.uid){
            item.url = response.data.filePath
          }
        });
      },
      // 更新submit 图片数组
      updateProductsImageArr(fileList){
        console.log(fileList)
        // 初始化变量
        this.productDetail.products_image_arr = []
        fileList.forEach(item => {
        console.log(item)

          this.productDetail.products_image_arr.push(item)
        });

        console.log(this.productDetail.products_image_arr)
      },
      // 更新submit 详情图片数组
      updateProductsImageArr1(fileList){
        console.log(fileList)
        // 初始化变量
        this.productDetail.products_descs_arr = []
        fileList.forEach(item => {
        console.log(item)

          this.productDetail.products_descs_arr.push(item)
        });

        console.log(this.productDetail.products_descs_arr)
      },
          // 更新submit 详情图片数组
          updateProductsImageArr2(fileList){
        console.log(fileList)
        // 初始化变量
        this.productDetail.spec_item_image = []
        fileList.forEach(item => {
        console.log(item)

          this.productDetail.spec_item_image.push(item)
        });

        console.log(this.productDetail.spec_item_image)
      },
      //检查是否是商品库图片
      checkIsProductsBaseUrl(file){
        if(file.is_products_base_url===true){
          return true;
        }
        return false;
      },
      // 远程删除 服务器图片接口
      async checkRemoteDeleteImage(url){
     
        let data = {
          url:url
        }
        const res = await axios.post('/admin/Product/deleteImageFromDisk',data)
        if(res.code!=200){
          return false
        }
        return true
      },
      successImg(response,file,fileList){
          // this.productDetail.products_image_arr = fileList
          console.log(fileList)
        // 上传失败
        if(response.code!=200){
          // 移除图片
          this.removeFileFromFileList(file,fileList)
          // 错误提示信息
          return this.$message.error(response.message)
        }
        // 上传成功
        // 修改fileList url (删除使用)
        this.updateFileListUrl(file,fileList,response)
        // 更新图片数组
        console.log(fileList) 
        this.updateProductsImageArr(fileList)
        // return

        this.$message.success('上传成功')
        console.log(this.productDetail.products_image_arr)
      },
      successImg1(response,file,fileList){
        console.log(fileList)
        // 上传失败
        if(response.code!=200){
          // 移除图片
          this.removeFileFromFileList1(file,fileList)
          // 错误提示信息
          return this.$message.error(response.message)
        }
        // 上传成功
        // 修改fileList url (删除使用)
        this.updateFileListUrl1(file,fileList,response)
        // 更新图片数组
        console.log(fileList) 
        this.updateProductsImageArr1(fileList)
        // return

        this.$message.success('上传成功')
        console.log(this.productDetail.products_descs_arr)
      },
      //规格图片上传成功
      successImg2(response,file,fileList,row){
        console.log(fileList)
        console.log(row)
        // this.tempObj.spec_item_image.push({ name: file.name, url: response.data, status: file.status, uid: file.uid })
        // 上传失败
        if(response.code!=200){
          // 移除图片
          this.removeFileFromFileList2(file,fileList)
          // 错误提示信息
          return this.$message.error(response.message)
        }
       
      this.tableColumnList.tableBodyList[row.$index].spec_item_image=response.data.fullPath
        // 上传成功
        // 修改fileList url (删除使用)
        // this.updateFileListUrl2(file,fileList,response)
        // 更新图片数组
        // console.log(fileList) 
        // this.updateProductsImageArr2(fileList)
        // return

        this.$message.success('上传成功')
        this.timer = new Date().getTime()
        // console.log(this.productDetail.products_descs_arr)
      },
      // 文件删除回调
      handleRemove(file, fileList) {
     
      // 不是商品库图片 请求接口删除
        if(false === this.checkIsProductsBaseUrl(file)){
          // 请求删除图片
          const url = file.url
          const res = this.checkRemoteDeleteImage(url)
          // 失败
          if(false===res){
            this.fileList.push(file)
            return this.$message.error('删除失败')
          }
        }

        // 是商品库图片只更新前端数据
        // 成功

        this.updateProductsImageArr(fileList)
        this.$message.success('删除成功')

      },
      handleRemove1(file, fileList) {

      // console.log(this.checkIsProductsBaseUrl(file))
      // return 
      // 不是商品库图片 请求接口删除
      if(false === this.checkIsProductsBaseUrl(file)){
        // 请求删除图片
        const url = file.url
        const res = this.checkRemoteDeleteImage(url)
        // 失败
        if(false===res){
          this.fileList.push(file)
          return this.$message.error('删除失败')
        }
      }

      // 是商品库图片只更新前端数据
      // 成功

      this.updateProductsImageArr1(fileList)
      this.$message.success('删除成功')

      },
      handleRemove2(file, fileList) {

      // console.log(this.checkIsProductsBaseUrl(file))
      // return 
      // 不是商品库图片 请求接口删除
      if(false === this.checkIsProductsBaseUrl(file)){
        // 请求删除图片
        const url = file.url
        const res = this.checkRemoteDeleteImage(url)
        // 失败
        if(false===res){
          this.fileList.push(file)
          return this.$message.error('删除失败')
        }
      }

      // 是商品库图片只更新前端数据
      // 成功

      this.updateProductsImageArr2(fileList)
      this.$message.success('删除成功')

    },
      imageChange(file,fileList) {
        //console.log(file)
        //console.log(fileList)
      },
      handleAvatarSuccess(res, file) {
          this.imageUrl = URL.createObjectURL(file.raw);
      },
      beforeAvatarUpload(file) {
          const isJPG = file.type === 'image/jpeg';
          const isLt2M = file.size / 1024 / 1024 < 2;

          if (!isJPG) {
              this.$message.error('上传头像图片只能是 JPG 格式!');
          }
          if (!isLt2M) {
              this.$message.error('上传头像图片大小不能超过 2MB!');
          }
          return isJPG && isLt2M;
      },
      preview(file) {
          //console.log(file)
      },
    },
  });
</script>
{/block}

php部分代码(主要是处理规格部分的)

<?php


namespace app\admin\controller;

use Symfony\Component\HttpFoundation\Session\Session;
use think\Request;
use think\Cache;
use think\Db;
use File\ExtraUpload;
use think\Exception;
use app\admin\Model\Product as ProductModel;
/**
 * @desc 商品规格操作类
 * Class Store
 * @package app\admin\controller
 */
class Goodsspec extends Base
{

    public function getSpecInput(){
        $spec_arr=post('data/a');
        $checkarr=post('checkarr/a');//选中的
       
        $products_id=post('products_id');
        $keys_tmp=[];
        if($products_id){
            $goods=db('seller_products_tmp')->field('products_sale_price,products_quantity,products_image,key')->where('products_id',$products_id)->whereOr('pid',$products_id)->select();
            $keys=array_column($goods,'key');
            $keys_tmp=implode('_',$keys);
            $keys_tmp=array_unique(explode('_',$keys_tmp));
            $spec_item=db('spec_item')->whereIn('id',$keys_tmp)->field('id,spec_id')->select();
            $spec_arr_tmp=[];
            foreach($spec_item as $k=>$v){
                $spec_arr_tmp[$v['spec_id']][]=$v['id'];
            }
            $spec_arr=$spec_arr_tmp;
        }
        if(empty($spec_arr)){
            $tableColumnList['tableBodyList']=[];
            $tableColumnList['tableHeaderList']=[];
            response($tableColumnList);
        }
      
        
        
        foreach($spec_arr as $k=>$v){
            $spec_arr[$k]=array_unique($v);
        }
        // 排序
        foreach ($spec_arr as $k => $v)
        {
            $spec_arr_sort[$k] = count($v);
        }
        
        asort($spec_arr_sort);   

        foreach ($spec_arr_sort as $key =>$val)
        {
            $spec_arr2[$key] = $spec_arr[$key];
        }
        $clo_name = array_keys($spec_arr2);         
        $spec_arr2 = combineDika($spec_arr2); //  获取 规格的 笛卡尔积 
        $spec = db('spec')->column('name','id'); // 规格表
        $specItem =db('spec_item')->column('id,item,spec_id','id');//规格项 
        $tableHeaderList=[];
        $tableBodyList=[];
        foreach ($clo_name as $k => $v) {
            
            $tableHeaderList[$k]['name']=$spec[$v];
        }
        
        foreach ($spec_arr2 as $k => $v) {
           $str=implode('_',$v);
            $item_key_name = array();
            foreach ($v as $k2 => $v2) {
                $key_data=$this->get_array_seach($products_id,$str);
                $tableBodyList[$k][$spec[$specItem[$v2]['spec_id']]]= $specItem[$v2]['item'];
                $tableBodyList[$k]['price']=$key_data?$key_data['products_sale_price']:0;
                $tableBodyList[$k]['stock']= $key_data?$key_data['products_quantity']:0;
                $tableBodyList[$k]['products_id']=$key_data?$key_data['products_id']:'';
                $tableBodyList[$k]['keys']=$str;
                $tableBodyList[$k]['spec_item_image']= $key_data?config('image_path').$key_data['products_image']:'';
            }
           
        } 
        // halt($tableBodyList);
        // $tableBodyList['column']=$spec_arr2;
        $columnLists['tableBodyList']=$tableBodyList;
        $columnLists['tableHeaderList']=$tableHeaderList;
        $tableColumnList['lists']=$columnLists;
        if($keys_tmp){
            $keys_tmp=array_merge($keys_tmp);
            foreach($keys_tmp as $k=>$v){
                $keys_tmp[$k]=intval($v);
            }
        }
        $tableColumnList['valuekeys']=$keys_tmp;
        response($tableColumnList);
    }
    public function get_array_seach($products_id,$keys){
        $goods=db('seller_products_tmp')->field('products_sale_price,products_quantity,products_image,key,products_id')->where('products_id',$products_id)->whereOr('pid',$products_id)->select();
        $data=[];
        foreach($goods as $k=>$v){
            if($v['key']==$keys){
                $data=$v;
                continue;
            }
        }
        return $data;
    }
    /**
     * 移除某一列数据 function
     *
     * @Author YJ 
     * @DateTime 2021-03-08
     * @return void
     */
    public function getDatahandle(){
        $data=post('data/a');
        $spec=post('spec/a');
        $key=post('key');//移除的key
        $arr=$data['tableBodyList'][$key];
        foreach($data['tableBodyList'] as $k=>$v){
            if($key==$k){
                unset($data['tableBodyList'][$k]);
            }
        }
        sort($data['tableBodyList']);
      
        $news_key=[];
        $tmp_keys='';
        foreach($data['tableBodyList'] as $k=>$v){
            $tmp_keys.=$v['keys']."_";
        }
        if($tmp_keys){
            $aaa=array_unique(array_filter(explode('_',$tmp_keys)));
            foreach ($aaa as  $value) {
                array_push($news_key,intval($value));
            }
        }
        $cc=array_intersect($news_key,$spec);
      
        $lists['lists']=$data;
        $lists['keys']=$cc;
        response($lists);
    }

}

获取当前分类下的规格

/**
     * 分类下的规格 function
     *
     * @Author YJ 
     * @DateTime 2021-01-21
     * @return void
     */
    public function getSpecItem(){
        $cate_id=get('cate_id','number');
        $manServer = db('spec')->where('cate_id',$cate_id)->order('id asc')->select();
        foreach ($manServer as $v) {
            $children=$this->_getSpecItem($v['id']);
            if(!empty($children)){
                $data[] = [
                    'id'            => $v['id'],
                    'name'          => $v['name'],
                    'children'      =>$children ,
                    'selected'      => false,
                    'indeterminate' => false,
                    'manCheckAll'   => false
                ];
            }
            
        }
        
        $keys=[];
        // if($data){
        //     foreach ($data as $k => $v) {
        //         if($v['children']){
        //             foreach ($v['children'] as $kk => $vv) {
        //                 array_push($keys,$vv['id']);break;
        //             }
        //         }
                
        //     }
        // }
        
        $res['lists']=$data;
        $res['keys']=$keys;
        response($res);
    }
    /**
     * 规格下的属性 function
     *
     * @Author YJ 
     * @DateTime 2021-01-21
     * @param [type] $spec_id
     * @return void
     */
    public function _getSpecItem($spec_id){
        $manServer = db('spec_item')->where('spec_id',$spec_id)->select();
        foreach ($manServer as $v) {
            $data[] = [
                'name'          => $v['item'],
                'id'            => $v['id'],
                'selected'      => false,
                'indeterminate' => false
            ];
        }
        return $data;
    }

有待完善,不喜勿喷。