element根据输入,动态生成表格

news/2024/11/6 12:29:15/

场景:后台页面根据商品规格和规格值,动态(增删改查)在表格中生成对应的sku.

如图:

在这里插入图片描述

代码如下:

edit.html

<template xmlns=""><div class="app-container"><el-form ref="form" :model="form" label-width="80px" autocomplete="off" @submit.native.prevent><h3>基础信息</h3><div style="padding-left: 60px"><el-row><el-col :span="7"><el-form-item label="spu_id"><el-input v-model="form.id" autocomplete="off" placeholder="" :disabled="true" /></el-form-item></el-col><el-col :span="5"><el-form-item label="名称" :required="true"><el-input v-model="form.goods_name" autocomplete="off" placeholder="" /></el-form-item></el-col><el-col :span="5"><el-form-item label="商品类型" :required="true"><el-select v-model="form.goods_type" placeholder="请选择"><el-optionv-for="item in goodsTypeOptions":key="item.value":label="item.label":value="item.value"></el-option></el-select></el-form-item></el-col></el-row><el-row><el-col :span="5"><el-form-item label="品牌" :required="true"><el-select v-model="form.brand_code" style="width: 100%"><el-optionv-for="item in brandOptions":key="item.value":label="item.label":value="item.value"/></el-select></el-form-item></el-col><el-col :span="5"><el-form-item label="分类" :required="true"><el-cascaderv-model="form.cate_code"collapse-tagsclearable:options="cateOptions":props="{ multiple: false, checkStrictly: true }"filterablestyle="width: 100%"/></el-form-item></el-col></el-row><el-row><el-col :span="5"><el-form-item label="赠品" :required="true"><el-radio v-model="form.is_gift" label="1"></el-radio><el-radio v-model="form.is_gift" label="2"></el-radio></el-form-item></el-col><el-col :span="5"><el-form-item label="列表显示" :required="true"><el-radio v-model="form.is_show_video" label="1"></el-radio><el-radio v-model="form.is_show_video" label="2"></el-radio></el-form-item></el-col><el-col :span="5"><el-form-item label="是否套组" :required="true"><el-radio v-model="form.is_suite" label="1"></el-radio><el-radio v-model="form.is_suite" label="2"></el-radio></el-form-item></el-col></el-row><el-row><el-col :span="5"><el-form-item label="是否预售" :required="true"><el-radio v-model="form.is_pre_sales" label="1"></el-radio><el-radio v-model="form.is_pre_sales" label="2"></el-radio></el-form-item></el-col><el-col :span="5"><el-form-item label="是否临期" :required="true"><el-radio v-model="form.is_expire" label="1"></el-radio><el-radio v-model="form.is_expire" label="2"></el-radio></el-form-item></el-col></el-row><el-row><el-col :span="5"><el-form-item label="包装规格"><el-input v-model="form.pack_spec" autocomplete="off" placeholder="" /></el-form-item></el-col><el-col :span="5"><el-form-item label="包装数量"><el-input v-model="form.pack_count" autocomplete="off" placeholder="" /></el-form-item></el-col><el-col :span="5"><el-form-item label="销售单位"><el-input v-model="form.unit_name" autocomplete="off" placeholder="" /></el-form-item></el-col><el-col :span="5"><el-form-item label="保质期"><el-date-pickerv-model="form.expire_date"type="date"value-format="yyyy-MM-dd"placeholder="选择日期"/></el-form-item></el-col></el-row><el-row><el-col :span="24"><el-form-item label="商品图片" :required="true"><ul class="el-upload-list el-upload-list--picture-card"><vuedraggable v-model="form.images"><li v-for="(item, index) in form.images" :key="index" class="el-upload-list__item is-success animated"><img :src="item" alt="" class="el-upload-list__item-thumbnail "><i class="el-icon-close" /><span class="el-upload-list__item-actions"><!-- 预览 --><span class="el-upload-list__item-preview" @click="viewImage(item)"><i class="el-icon-zoom-in" /></span><!-- 删除 --><span class="el-upload-list__item-delete" @click="delImage(index)"><i class="el-icon-delete" /></span></span></li></vuedraggable></ul><!--            <el-button size="small" type="info" @click="uploadImageDialog = true">点击上传</el-button>--><label for="upload-btn" class="el-button el-button--info el-button--mini">上传文件</label><inputv-show="false"id="upload-btn"ref="uploadBtn"type="file"accept="image/png, image/jpeg, image/gif, image/jpg"@change="loadImg($event)"><div class="el-upload__tip">第1张为主图,其它为从图.尺寸800*800</div></el-form-item></el-col></el-row><el-row><el-col :span="7"><el-form-item label="推荐语"><el-input v-model="form.recommendation" autocomplete="off" placeholder="" /></el-form-item></el-col></el-row><el-row><el-col :span="24"><el-form-item label="描述" :required="true"><tinymce v-model="form.description" :height="300" /></el-form-item></el-col></el-row><el-row><el-col :span="12"><el-form-item label="保管事项"><el-select v-model="form.keep_desc_tpl_id" placeholder="请选择" style="width: 100%"><el-optionv-for="item in keepOptions":key="item.value":label="item.label":value="item.value"/></el-select></el-form-item></el-col><el-col :span="12"><el-form-item label="温馨提示"><el-select v-model="form.notice_desc_tpl_id" placeholder="请选择" style="width: 100%"><el-optionv-for="item in noticeOptions":key="item.value":label="item.label":value="item.value"/></el-select></el-form-item></el-col></el-row></div><h3>sku信息</h3><div style="padding-left: 60px"><sku-edit ref="skuEdit" /></div><el-form-item><el-button type="primary" @click="save">保存</el-button><router-link style="padding-left: 10px;" to="/goods/erp-goods-list"><el-button>返回列表</el-button></router-link></el-form-item></el-form><el-dialog :visible.sync="imageViewDialog"><img width="100%" :src="imageViewUrl" alt=""></el-dialog><el-dialogwidth="700px"custom-class="image-upload":visible.sync="croperImageDialog":close-on-click-modal="false"@close="emptyUpload"><div style="display:flex;justify-content: center;"><cropper ref="myCropper" @updateImageList="updateImageList" /></div><div slot="footer"><div class="dialog-footer-btn"><div><el-button @click="croperImageDialog = false">返 回</el-button><el-button type="primary" @click="cropImg">确 定</el-button></div></div></div></el-dialog></div>
</template><script>import { spuCreate, spuDetail } from '@/api/goods/goods'
import { getOptions, uploadUrl } from '@/api/common/common'
import { empty } from '@/utils/index'
import Tinymce from '@/components/Tinymce/index.vue'
import skuEdit from '@/views/goods/goods/sku_edit.vue'
import { getToken } from '@/utils/auth'
import vuedraggable from 'vuedraggable'
import cropper from '@/views/goods/component/cropper.vue'
export default {name: 'GoodsEdit',components: { Tinymce, vuedraggable, cropper, skuEdit },props: ['id'],data() {return {salesAmountLimit: 1,uploadImageDialog: false,croperImageDialog: false,imageViewDialog: false,imageViewUrl: false,uploadUrl: uploadUrl,cropperDialogVisible: false,tagOptions: [],keepOptions: [],noticeOptions: [],uppy: {},cateOptions: [],brandOptions: [],goodsTypeOptions: [],uploadHeaders: {token: getToken()},leftTagFileList: [],rightTagFileList: [],form: {},copy: false,initForm: {id: '',goods_name: '',barcode: '',cate_code: '',brand_code: '',description: '',images: [],pack_spec: '',pack_count: '',unit_name: '',expire_date: '',video: '',is_expire: '1',is_gift: '1',is_pre_sales: '1',video_cover: '',is_show_video: '1',recommendation: '',goods_type: '1',is_suite: '1',merchant_id: '',keep_desc_tpl_id: '',notice_desc_tpl_id: '',sku_map_list: [],spu_attrs: []}}},computed: {},watch: {'form.left_tag_type': {deep: true,handler(newVal, oldVal) {if ((newVal === 7 && oldVal !== 7) || (newVal !== 7 && oldVal === 7)) {this.form.left_tag = ''this.leftTagFileList = []}}},'form.right_tag_type': {deep: true,handler(newVal, oldVal) {if ((newVal === 7 && oldVal !== 7) || (newVal !== 7 && oldVal === 7)) {this.form.right_tag = ''this.rightTagFileList = []}}}},mounted() {if (this.$route.query.copy) {this.copy = JSON.parse(this.$route.query.copy)}},activated() {this.form = JSON.parse(JSON.stringify(this.initForm))this.detail()getOptions({ option_names: ['cateOptions', 'brandOptions', 'goodsTypeOptions', 'goodsDescTplOption', 'goodsKeepTplOption'] }).then(response => {this.goodsTypeOptions = response.data.goodsTypeOptionsthis.cateOptions = response.data.cateOptionsthis.brandOptions = response.data.brandOptionsthis.keepOptions = response.data.goodsKeepTplOptionthis.noticeOptions = response.data.goodsDescTplOption})},methods: {async save() {// 获取 skuEdit 子组件 的信息this.form.sku_map_list = this.$refs.skuEdit.spuInfo.sku_map_list// is_draft =1 为草稿数据 2-为审核通过的数据this.form.is_draft = 2await spuCreate(this.form)this.$message({message: '保存成功,待审核!',type: 'success'})this.form = JSON.parse(JSON.stringify(this.initForm))this.$router.push({ path: '/goods/goods/draft-list' })},detail() {const id = this.$route.query.idconst params = {}params.id = idif (empty(id)) {return}spuDetail(params).then(response => {this.form = response.datathis.$refs.skuEdit.spuInfo.sku_map_list = this.form.sku_map_listthis.$refs.skuEdit.spuAttrs = this.form.spu_attrsthis.form.is_expire = this.form.is_expire.toString()this.form.is_gift = this.form.is_gift.toString()this.form.is_show_video = this.form.is_show_video.toString()this.form.is_suite = this.form.is_suite.toString()this.form.is_pre_sales = this.form.is_pre_sales.toString()this.form.is_expire = this.form.is_expire.toString()if (this.copy) {this.form.id = ''}})},viewImage(item) {this.imageViewUrl = item.urlthis.imageViewDialog = true},delImage(index) {this.form.images.splice(index, 1)},loadImg(e) {const file = e.target.files[0]if (file.size / 1024 / 1024 > 5) {this.$message.error('上传文件不能超过5M')return false}if (!/\.(jpg|png|gif|JPG|PNG|GIF|)$/.test(file.name)) {this.$message.info('图片类型必须是jpg,png的一种')return false}const reader = new FileReader()reader.onload = (e) => {let dataif (typeof e.target.result === 'object') {data = window.URL.createObjectURL(new Blob([e.target.result]))} else {data = e.target.result}this.croperImageDialog = truethis.$nextTick(() => {this.$refs.myCropper.imgLoad(file, data)})}reader.readAsArrayBuffer(file)},emptyUpload() {this.$refs.uploadBtn.value = ''},cropImg() {this.$refs.myCropper.crop()},updateImageList(item) {this.form.images.push(item.url)this.croperImageDialog = false}}
}
</script><style lang="scss" scoped>
.app-container {overflow-y: auto;height: 100%;
}.app-container >>> .cropper-modal {opacity: 0.5;
}el-input {width: 300px;
}
</style>

子组件sku_edit.html

<template><div class=""><el-form ref="SkuEdit" label-width="110px"><el-form-item label="spu规格" required><vuedraggable v-model="spuAttrs" @start="onStart" @end="onEnd"><transition-group><template v-for="(item, index) in spuAttrs"><div :key="index" :class="(index < (spuAttrs.length - 1)) ? 'attr_select_index' : '' "><div><el-selectv-model="item.attr"filterableallow-createplaceholder="选择或创建"size="mini"@blur="addAttr($event,item,index)"@change="changeAttr($event, index)"><el-optionv-for="(cateItem, cateIndex) in cateAttrs":key="cateIndex":label="cateItem.label":value="cateIndex"/></el-select><i :key="index" class="item el-icon-sort" @mouseover="showTooltipSpec" @mouseleave="hideTooltipSpec" /><span v-if="tooltipVisibleSpec&&index===0">拖动上下排序</span><i :key="index" class="el-icon-circle-plus attr_options_add" @click="spuAttrItem(1, index + 1)" /><i v-if="spuAttrs.length>1" :key="index" class="el-icon-remove attr_options_del" @click="spuAttrItem(2,index)" /></div><div style="margin-left: 20px"><vuedraggable v-model="item.values" @start="onStart" @end="onEnd"><transition-group style="display: flex; flex-wrap: wrap;"><template v-for="(attrVal,vi) in item.values"><div :key="vi"><div style="margin-left: 15px"><el-inputv-model="item.values[vi]"placeholder="添加规格值"size="mini"style="width: 100px;"@blur="addAttrValue($event,index, vi)"/><template><i:key="vi"class="item el-icon-s-operation"@mouseover="showTooltipSpecValue"@mouseleave="hideTooltipSpecValue"/><span v-if="tooltipVisibleSpecValue&&vi===0&&index===0">拖动左右排序</span><i:key="vi"class="el-icon-circle-plus attr_val_options_add"@click="spuAttrValueItem(1,index)"/><iv-if="item.values.length>1":key="vi"class="el-icon-remove attr_val_options_del"@click="spuAttrValueItem(2,index,vi)"/></template></div></div></template></transition-group></vuedraggable></div></div></template></transition-group></vuedraggable></el-form-item><el-form-item label="映射sku" required><el-table:data="spuInfo.sku_map_list"border:header-row-style="tableHeaderRowStyle":header-cell-style="tableHeaderCellStyle":max-height="tableHeight"size="mini"style="width: 100%"empty-text="暂无数据"><el-table-columnv-for="(item,index) in spuAttrs":key="index":label="item.attr"><template slot-scope="scop"><div>{{ getAttrValue(scop.row, index) }}</div></template></el-table-column><el-table-columnprop="barcode"label="商品条码"><template slot-scope="scope"><el-inputv-model="scope.row.barcode"size="mini"placeholder="请输入商品条码"@blur="addBarcode($event,scope.row,scope.$index)"/></template></el-table-column><el-table-columnprop="price"label="售价"><template slot-scope="scope"><el-inputv-model="scope.row.price"size="mini"placeholder="请输入商品售价"@blur="addPrice($event,scope.row,scope.$index)"/></template></el-table-column><el-table-columnprop="market_price"label="市场价"><template slot-scope="scope"><el-inputv-model="scope.row.price"size="mini"placeholder="请输入商品市场价"@blur="addMarketPrice($event,scope.row,scope.$index)"/></template></el-table-column><el-table-columnprop="image"label="图片"width="100"><template slot-scope="scope"><el-uploadclass="avatar-uploader":action="uploadUrl+'?type=image'":limit="1":show-file-list="false":on-success="(res,file,fileList) => {handleAvatarSuccess(res,file,fileList,scope.$index)}":headers="uploadHeaders"><img v-if="scope.row.image!=''" :src="scope.row.image" class="avatar"><i v-else class="el-icon-plus avatar-uploader-icon" /></el-upload></template></el-table-column></el-table></el-form-item></el-form></div>
</template>
<script>
import vuedraggable from 'vuedraggable'
import { getOptions, uploadUrl } from '@/api/common/common'
import { spuDetail, saveSpu } from '@/api/goods/spu'
import { empty } from '@/utils'
import Common from '@/layout/mixin/Common'
import { getToken } from '@/utils/auth'export default {name: 'SkuEdit',components: {'vuedraggable': vuedraggable},mixins: [Common],props: ['spu_id'],data() {return {// 1-为规格 2-为规格值changeType: 1,// 变化内容changeContent: '',drag: false,tooltipVisibleSpec: false,tooltipVisibleSpecValue: false,uploadUrl: uploadUrl,spuInfo: {sku_map_list: []},uploadHeaders: {token: getToken()},cateAttrs: [],cateAttrCount: 0,spuAttrs: [],selectMapSkuVisible: false,skuListLoading: false,skuList: [],barcode: '',goodsName: '',selectSkuPage: 1,selectSkuPageSize: 30,selectSkuTotal: 0,selectSkuMapIndex: -1}},mounted() {getOptions({ option_names: ['spuSpecOptions'] }).then(response => {this.cateAttrs = response.data.spuSpecOptions})if (!empty(this.spu_id)) {this.spuInfo.id = this.spu_idspuDetail({ id: this.spu_id }).then(res => {this.cateAttrCount = Object.keys(this.cateAttrs).lengththis.spuInfo.sku_map_list = res.data.sku_map_listthis.spuAttrs = res.data.spu_attrsthis.$refs.imageCropperUpload.setImage([{ path: this.spuInfo.image, url: this.spuInfo.image_url }])})}if (empty(this.spuAttrs)) {this.spuAttrs = [{attr: '',values: ['']}]}},methods: {empty,showTooltipSpec() {console.log('showTooltipSpec','----------')setTimeout(() => {this.tooltipVisibleSpec = true}, 1000)},hideTooltipSpec() {console.log('hideTooltipSpec','----------')this.tooltipVisibleSpec = false},showTooltipSpecValue() {console.log('showTooltipSpecValue','----------')setTimeout(() => {this.tooltipVisibleSpecValue = true}, 1000)},hideTooltipSpecValue() {console.log('hideTooltipSpecValue','----------')this.tooltipVisibleSpecValue = false},onStart() {this.drag = true},handleAvatarSuccess(res, file, fileList, index) {this.spuInfo.sku_map_list[index].image = res.data[0].url},// 添加规格addAttr(e, item, index) {if (empty(e.target.value)) {return}this.spuAttrs.push({attr: e.target.value,values: ['']})// 判断this.spuAttrs.attr 是否有空值,如果有空值则删除for (let i = 0; i < this.spuAttrs.length; i++) {if (empty(this.spuAttrs[i].attr)) {this.spuAttrs.splice(i, 1)}}},addBarcode(e, row, index) {this.spuInfo.sku_map_list[index].barcode = e.target.value},addPrice(e, row, index) {this.spuInfo.sku_map_list[index].price = e.target.value},addMarketPrice(e, row, index) {this.spuInfo.sku_map_list[index].market_price = e.target.value},addAttrValue(e, index, vi) {if (empty(e.target.value)) {return}this.attrSkuMap(1, index, this.spuAttrs[index].values.length - 1)},onEnd() {this.drag = falsethis.attrSkuMap(3, 0, 0)},// 选择规格名changeAttr(e, index) {this.spuAttrs[index].values = ['']this.spuAttrs[index].attr = this.cateAttrs[index].labelthis.attrSkuMap(3, index, -1)},spuAttrItem(type, index) {if (type === 1) {this.spuAttrs.push({attr: '',values: ['']})} else {this.changeType = 1this.changeContent = this.spuAttrs[index].attrthis.spuAttrs.splice(index, 1)}this.attrSkuMap(type, index, type === 1 ? 0 : 1)},// 添加|删除规格值spuAttrValueItem(type, pIndex, subIndex) {if (type === 1) {this.spuAttrs[pIndex].values.push('')} else {this.changeType = 2this.changeContent = this.spuAttrs[pIndex].values[subIndex]this.spuAttrs[pIndex].values.splice(subIndex, 1)}this.attrSkuMap(type, pIndex, subIndex)},// 生成sku组合表格,处理每行数据xgenerateCombinations(type, pIndex, subIndex, changeIndex = 0, spliceIndex = -1, currentCombination = [], index = 0) {if (index >= this.spuAttrs.length) {// 1-新增,2-删除,3-修改if (type === 1) {// 页面新开 新增的sku情况if (empty(this.spuInfo.sku_map_list[changeIndex])) {this.spuInfo.sku_map_list.push({barcode: '',price: '',market_price: '',attrs: [],image: ''})// attrs  字段与页面显示无关,只为传给后端使用for (let j = 0; j < currentCombination.length; j++) {this.spuInfo.sku_map_list[changeIndex].attrs.push({attr: currentCombination[j].attr,value: currentCombination[j].value})}// 页面新开 编辑的sku情况} else if (currentCombination.length === this.spuInfo.sku_map_list[changeIndex].attrs.length) {for (let j = 0; j < currentCombination.length; j++) {this.spuInfo.sku_map_list[changeIndex].attrs[j].attr = currentCombination[j].attrthis.spuInfo.sku_map_list[changeIndex].attrs[j].value = currentCombination[j].value}} else if (currentCombination.length > this.spuInfo.sku_map_list[changeIndex].attrs.length) {const item = currentCombination.slice(-1)this.spuInfo.sku_map_list[changeIndex].attrs.push({attr: item.attr,value: item.value})}} else if (type === 2) {// 遍历currentCombination,把value 拼接组合,后面在循环中删除多余重复的行if (this.changeType === 1) {let currentCombinationValue = ''for (let j = 0; j < currentCombination.length; j++) {currentCombinationValue += currentCombination[j].value + '_'}for (let k = 0; k < this.spuInfo.sku_map_list.length; k++) {if (empty(this.spuInfo.sku_map_list[k])) {continue}for (let j = 0; j < this.spuInfo.sku_map_list[k].attrs.length; j++) {if (empty(this.spuInfo.sku_map_list[k].attrs[j])) {continue}if (this.changeContent === this.spuInfo.sku_map_list[k].attrs[j].attr) {// 删除规格this.spuInfo.sku_map_list[k].attrs.splice(j, 1)// 组合规格值let itemValueCombination = ''for (let m = 0; m < this.spuInfo.sku_map_list[k].attrs.length; m++) {itemValueCombination += this.spuInfo.sku_map_list[k].attrs[m].value + '_'}this.spuInfo.sku_map_list[k].combination = itemValueCombination}}}for (let v = 0; v < this.spuInfo.sku_map_list.length; v++) {let count = 0if (empty(this.spuInfo.sku_map_list[v])) {continue}if (currentCombinationValue === this.spuInfo.sku_map_list[v].combination) {count++}// 相同规格的行只保留一条if (count > 1) {this.spuInfo.sku_map_list.splice(v, 1)}}} else {for (let k = 0; k < this.spuInfo.sku_map_list.length; k++) {if (empty(this.spuInfo.sku_map_list[k]) || empty(this.spuInfo.sku_map_list[k].attrs)) {continue}const attrs = this.spuInfo.sku_map_list[k]?.attrs || []for (let j = 0; j < attrs.length; j++) {if (this.empty(attrs[j])) {continue}if (this.changeContent === attrs[j].value) {// 删除整行this.spuInfo.sku_map_list.splice(k, 1)break // 如果删除了当前行,需要跳出循环}}}}} else {for (let j = 0; j < currentCombination.length; j++) {this.spuInfo.sku_map_list[changeIndex].attrs[j].attr = currentCombination[j].attrthis.spuInfo.sku_map_list[changeIndex].attrs[j].value = currentCombination[j].value}}changeIndex++spliceIndex = -1// return 之后执行 this.generateCombinations 的逻辑return [changeIndex, spliceIndex]}// 规格和规格值都遍历for (var i = 0; i < this.spuAttrs[index].values.length; i++) {currentCombination.push({attr: this.spuAttrs[index].attr,value: this.spuAttrs[index].values[i]})// 假如有 尺寸 S M ,颜色 黄色 白色// 第一次遍历生成 {"attr":"尺寸","value":"S"}// 第二次遍历生成 {"attr":"尺寸","value":"S"},{"attr":"颜色","value":"黄色"}组合,然后在渲染到表格的第一行中// changeIndex 为行数或者组合数量// generateCombinations 自循环,遇到return [changeIndex, spliceIndex]后才往下执行const res = this.generateCombinations(type, pIndex, subIndex, changeIndex, spliceIndex, currentCombination, index + 1)changeIndex = res[0]spliceIndex = res[1]currentCombination.pop()}return [changeIndex, spliceIndex]},attrSkuMap(type, pIndex, subIndex) {this.generateCombinations(type, pIndex, subIndex)return},getAttrValue(item, i) {return item.attrs[i].value},async saveSpu() {return await saveSpu(this.spuInfo)}}
}
</script>
<style scoped lang="scss">
.cate_level1 {color: #E6A23C;
}.attr_select_index {margin-bottom: 14px;
}.attr_options_add, .attr_val_options_add {margin-left: -2px;font-size: 20px;color: #409EFF;cursor: pointer;
}.item {padding: 3px;//background-color: #fdfdfd;//border: solid 1px #eee;margin-bottom: 10px;cursor: move;
}.item:hover {background-color: #f1f1f1;cursor: move;
}.chosen {border: solid 2px #3089dc !important;
}.attr_options_del, .attr_val_options_del {margin-left: -2px;font-size: 20px;color: #F56C6C;cursor: pointer;
}.tooltip-container {position: relative;display: inline-block;
}.tooltip-text {visibility: visible;width: 120px;background-color: black;color: #fff;text-align: center;border-radius: 6px;padding: 5px 0;position: absolute;z-index: 1;bottom: 125%; /* Position the tooltip above the icon */left: 50%;margin-left: -60px;opacity: 0;transition: opacity 0.3s;
}.tooltip-container:hover .tooltip-text {visibility: visible;opacity: 1;
}.avatar-uploader .el-upload {border: 1px dashed #d9d9d9;border-radius: 6px;cursor: pointer;position: relative;overflow: hidden;
}.avatar-uploader .el-upload:hover {border-color: #409EFF;
}.avatar-uploader-icon {font-size: 28px;color: #8c939d;width: 30px;height: 30px;line-height: 30px;text-align: center;
}.avatar {width: 30px;height: 30px;display: block;
}
</style>

数据结构

{"msg": "ok","code": 10000,"data": {"id": "710432902999261184","goods_name": "spu测试ywz","cate_code": "Lthg98","brand_code": "UpsPhd","supplier_code": "","audit_status": 1,"pack_spec": "101","pack_count": "102","unit_name": "103","expire_date": "2024-10-24","images": ["https:\/\/img-hyg.hltmsp.com\/member\/image\/20240918\/c7865c97174a4eb92519edd42a98af74851785.png","https:\/\/img-hyg.hltmsp.com\/member\/image\/20240918\/4508beb29e17b950796cc5961a88b520299817.png"],"video": "","video_cover": "","is_show_video": 1,"description": "<p>spu测试spu测试spu测试<\/p>","sort": 0,"is_gift": 1,"goods_type": 1,"sales_count": 0,"is_sales_amount_limit": 1,"recommendation": "spu测试spu测试spu测试","is_search": 1,"is_pre_sales": 1,"is_expire": 1,"is_suite": 1,"merchant_id": 1,"business_type": 1,"keep_desc_tpl_id": 2,"notice_desc_tpl_id": 0,"del_status": 1,"create_time": "2024-10-31 10:06:43","update_time": "2024-10-31 10:06:43","sku_map_list": [{"id": 710432903292862464,"spu_id": "710432902999261184","goods_code": "","barcode": "spu_1234561345678ywz1","image": "https:\/\/img-hyg.hltmsp.com\/member\/image\/20240918\/c7865c97174a4eb92519edd42a98af74851785.png","search_weight": 0,"sort": 0,"sales_count": 0,"price": "99.00","market_price": "199.00","cost_price": "0.00","create_time": "2024-10-31 10:06:43","update_time": "2024-10-31 10:06:43","attrs": [{"attr": "尺寸","value": "尺寸1"},{"attr": "颜色","value": "颜色1"}]},{"id": 710432903292862465,"spu_id": "710432902999261184","goods_code": "","barcode": "spu_12345631345678ywz1","image": "https:\/\/img-hyg.hltmsp.com\/member\/image\/20240918\/c7865c97174a4eb92519edd42a98af74851785.png","search_weight": 0,"sort": 0,"sales_count": 0,"price": "99.00","market_price": "199.00","cost_price": "0.00","create_time": "2024-10-31 10:06:43","update_time": "2024-10-31 10:06:43","attrs": [{"attr": "尺寸","value": "尺寸1"},{"attr": "颜色","value": "颜色2"}]},{"id": 710432903292862466,"spu_id": "710432902999261184","goods_code": "","barcode": "spu_123456451345678ywz1","image": "https:\/\/img-hyg.hltmsp.com\/member\/image\/20240918\/c7865c97174a4eb92519edd42a98af74851785.png","search_weight": 0,"sort": 0,"sales_count": 0,"price": "99.00","market_price": "199.00","cost_price": "0.00","create_time": "2024-10-31 10:06:43","update_time": "2024-10-31 10:06:43","attrs": [{"attr": "尺寸","value": "尺寸2"},{"attr": "颜色","value": "颜色1"}]},{"id": 710432903292862467,"spu_id": "710432902999261184","goods_code": "","barcode": "spu_123456561345678ywz1","image": "https:\/\/img-hyg.hltmsp.com\/member\/image\/20240918\/c7865c97174a4eb92519edd42a98af74851785.png","search_weight": 0,"sort": 0,"sales_count": 0,"price": "99.00","market_price": "199.00","cost_price": "0.00","create_time": "2024-10-31 10:06:43","update_time": "2024-10-31 10:06:43","attrs": [{"attr": "尺寸","value": "尺寸2"},{"attr": "颜色","value": "颜色2"}]}],"spu_attrs": [{"attr": "尺寸","values": ["尺寸1","尺寸2"]},{"attr": "颜色","values": ["颜色1","颜色2"]}]},"log_id": "710498316961951744"
}

http://www.ppmy.cn/news/1544813.html

相关文章

qt QFontDialog详解

1、概述 QFontDialog 是 Qt 框架中的一个对话框类&#xff0c;用于选择字体。它提供了一个可视化的界面&#xff0c;允许用户选择所需的字体以及相关的属性&#xff0c;如字体样式、大小、粗细等。用户可以通过对话框中的选项进行选择&#xff0c;并实时预览所选字体的效果。Q…

项目模块十二:TcpServer模块

一、模块设计思路 1、目的 对所有模块整合&#xff0c;实现一个服务器模块供外部快速搭建服务器。 2、管理 监听套接字 主 Reactor&#xff0c;创建 EventLoop _baseloop 对象&#xff0c;进行对监听套接字的管理 哈希表管理所有新连接的 Channel 创建线程池进行连接的事…

python类方法、实例方法以及相互关系

在Python中&#xff0c;类方法&#xff08;class method&#xff09;是一种特殊类型的方法&#xff0c;它使用类本身作为第一个参数&#xff0c;而不是实例对象。类方法通常用于定义与类本身相关但不需要访问实例属性的操作。类方法的第一个参数通常命名为cls&#xff0c;以区别…

[Unity Demo]从零开始制作空洞骑士Hollow Knight第十九集:制作过场Cutscene系统

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、制作过场Cutscene系统 1.制作基本的视频过场和动画过场2.制作决定过场系统的播放顺序Sequence以及切换场景以后的逻辑处理二、制作跳过过场Cutscene的MenuS…

Webserver(3.3)生产者消费者模型

目录 生产者消费者简单模型条件变量信号变量 生产者消费者简单模型 //生产者消费者模型#include <stdio.h> #include<pthread.h> #include<stdlib.h> #include<unistd.h>struct Node{int num;struct Node * next; }; //头结点 struct Node * headNULL…

unreal engine5动画重定向

UE5系列文章目录 文章目录 UE5系列文章目录前言一、下载动画资源二、创建IK Rig&#xff08;IK绑定&#xff09; 前言 在Unreal Engine 5.4中&#xff0c;动画重定向&#xff08;Animation Retargeting&#xff09;和动作匹配&#xff08;Motion Matching&#xff09;是两种不…

PL端:LED闪烁

实验环境 vivado2024.1 实验任务 LED闪烁 引脚关系 硬件配置 新建一个vivado实验 创建 Verilog HDL 文件点亮 LED 点击 Project Manager 下的 Add Sources 图标&#xff08;或者使用快捷键 AltA&#xff09; 编辑led.v module led(input sys_clk,input rst_n,outp…

C语言中如何实现动态内存分配

在C语言中&#xff0c;动态内存分配是通过标准库中的malloc、calloc和free函数实现的。这些函数允许程序在运行时请求内存&#xff0c;从而提供灵活性&#xff0c;尤其是在不知道所需内存大小的情况下。下面是对这三个函数的详细解释和使用示例。 1. malloc malloc&#xff0…