mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-09-22 21:02:04 +08:00
升级Vue3,iView替换ElementPlus
- 删除babel配置、更新依赖与入口初始化 - 全量替换UI组件、样式适配,新增迁移文档与标签/过滤器自动化替换脚本
This commit is contained in:
@@ -1,115 +1,124 @@
|
||||
<template>
|
||||
<div>
|
||||
<Modal v-model="visible" title="预览图片">
|
||||
<el-dialog v-model="visible" title="预览图片">
|
||||
<img v-if="visible" :src="previewPicture" style="width: 100%">
|
||||
</Modal>
|
||||
</el-dialog>
|
||||
<div class="content-goods-publish">
|
||||
<Form ref="baseInfoForm" :label-width="120" :model="baseInfoForm" :rules="baseInfoFormRule">
|
||||
<el-form ref="baseInfoForm" label-width="120px" :model="baseInfoForm" :rules="baseInfoFormRule">
|
||||
<div class="base-info-item">
|
||||
<h4>基本信息</h4>
|
||||
<div class="form-item-view">
|
||||
<FormItem label="商品分类">
|
||||
<el-form-item label="商品分类">
|
||||
<span class="goods-category-name">{{
|
||||
this.baseInfoForm.categoryName[0]
|
||||
}}</span>
|
||||
<span> > {{ this.baseInfoForm.categoryName[1] }}</span>
|
||||
<span> > {{ this.baseInfoForm.categoryName[2] }}</span>
|
||||
</FormItem>
|
||||
<FormItem label="商品名称" prop="goodsName">
|
||||
<Input v-model="baseInfoForm.goodsName" clearable placeholder="商品名称" style="width: 260px" type="text" />
|
||||
</FormItem>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品名称" prop="goodsName">
|
||||
<el-input v-model="baseInfoForm.goodsName" clearable placeholder="商品名称" style="width: 260px" type="text" />
|
||||
</el-form-item>
|
||||
|
||||
<FormItem label="商品价格" prop="price">
|
||||
<Input v-model="baseInfoForm.price" clearable placeholder="商品价格" style="width: 260px" type="text" />
|
||||
</FormItem>
|
||||
<FormItem label="商品卖点" prop="sellingPoint">
|
||||
<Input v-model="baseInfoForm.sellingPoint" :rows="4" style="width: 260px" type="textarea" />
|
||||
</FormItem>
|
||||
<FormItem label="商品品牌" prop="brandId">
|
||||
<Select v-model="baseInfoForm.brandId" filterable style="width: 200px">
|
||||
<Option v-for="item in brandList" :key="item.id" :label="item.name" :value="item.id"></Option>
|
||||
</Select>
|
||||
<Button class="refresh-icon" icon="md-refresh" shape="circle" type="text"
|
||||
@click="refresh('brand')"></Button>
|
||||
</FormItem>
|
||||
<el-form-item label="商品价格" prop="price">
|
||||
<el-input v-model="baseInfoForm.price" clearable placeholder="商品价格" style="width: 260px" type="text" />
|
||||
</el-form-item>
|
||||
<el-form-item label="商品卖点" prop="sellingPoint">
|
||||
<el-input v-model="baseInfoForm.sellingPoint" :rows="4" style="width: 260px" type="textarea" />
|
||||
</el-form-item>
|
||||
<el-form-item label="商品品牌" prop="brandId">
|
||||
<el-select v-model="baseInfoForm.brandId" filterable style="width: 200px">
|
||||
<el-option v-for="item in brandList" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
<el-button class="refresh-icon" circle link @click="refresh('brand')">
|
||||
<el-icon><Refresh /></el-icon>
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
|
||||
<FormItem class="form-item-view-el" label="计量单位" prop="goodsUnit">
|
||||
<Select v-model="baseInfoForm.goodsUnit" style="width: 100px">
|
||||
<Option v-for="(item, index) in goodsUnitList" :key="index" :value="item">{{ item }}
|
||||
</Option>
|
||||
</Select>
|
||||
<Button class="refresh-icon" icon="md-refresh" shape="circle" type="text"
|
||||
@click="refresh('goodsUnit')"></Button>
|
||||
</FormItem>
|
||||
<FormItem class="form-item-view-el" label="销售模式" prop="salesModel">
|
||||
<RadioGroup v-if="baseInfoForm.goodsType != 'VIRTUAL_GOODS'" v-model="baseInfoForm.salesModel"
|
||||
button-style="solid" type="button" @on-change="handleSalesModeChange">
|
||||
<Radio label="RETAIL" title="零售型">零售型</Radio>
|
||||
<Radio label="WHOLESALE" title="批发型">批发型</Radio>
|
||||
</RadioGroup>
|
||||
<RadioGroup v-else v-model="baseInfoForm.salesModel" button-style="solid" type="button">
|
||||
<Radio label="RETAIL" title="零售型">
|
||||
<span>虚拟型</span>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem v-if="baseInfoForm.salesModel == 'WHOLESALE'" class="form-item-view-el" label="销售规则"
|
||||
<el-form-item class="form-item-view-el" label="计量单位" prop="goodsUnit">
|
||||
<el-select v-model="baseInfoForm.goodsUnit" style="width: 100px">
|
||||
<el-option v-for="(item, index) in goodsUnitList" :key="index" :label="item" :value="item" />
|
||||
</el-select>
|
||||
<el-button class="refresh-icon" circle link @click="refresh('goodsUnit')">
|
||||
<el-icon><Refresh /></el-icon>
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item-view-el" label="销售模式" prop="salesModel">
|
||||
<el-radio-group
|
||||
v-if="baseInfoForm.goodsType != 'VIRTUAL_GOODS'"
|
||||
v-model="baseInfoForm.salesModel"
|
||||
@change="handleSalesModeChange"
|
||||
>
|
||||
<el-radio-button value="RETAIL">零售型</el-radio-button>
|
||||
<el-radio-button value="WHOLESALE">批发型</el-radio-button>
|
||||
</el-radio-group>
|
||||
<el-radio-group v-else v-model="baseInfoForm.salesModel">
|
||||
<el-radio-button value="RETAIL">虚拟型</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="baseInfoForm.salesModel == 'WHOLESALE'" class="form-item-view-el" label="销售规则"
|
||||
prop="wholesaleRule">
|
||||
<div class="form-item-view-wholesale">
|
||||
<div>
|
||||
<Table :columns="wholesaleColumns" :data="wholesaleData" border>
|
||||
<template slot="wholesaleNum" slot-scope="{ row, index }">
|
||||
<div>
|
||||
<Input v-model="wholesaleData[index].num" min="1" number type="number"
|
||||
@on-blur="checkWholesaleNum(index)">
|
||||
<span slot="append">{{
|
||||
baseInfoForm.goodsUnit || ""
|
||||
}}</span>
|
||||
</Input>
|
||||
</div>
|
||||
</template>
|
||||
<template slot="wholesalePrice" slot-scope="{ row, index }">
|
||||
<div style="
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
">
|
||||
<Input v-model="wholesaleData[index].price" min="1" number style="width: 190px" type="number"
|
||||
@on-blur="checkWholesalePrice(index)">
|
||||
<span slot="append">元</span>
|
||||
</Input>
|
||||
<Button v-if="index > 0" size="small" style="margin-left: 5px" type="error"
|
||||
@click="handleDeleteWholesaleData(index)">删除
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
</Table>
|
||||
<el-table :data="wholesaleData" border style="width: 100%">
|
||||
<el-table-column label="购买数量" align="center">
|
||||
<template #default="{ $index }">
|
||||
<el-input v-model="wholesaleData[$index].num" type="number" @blur="checkWholesaleNum($index)">
|
||||
<template #append>{{ baseInfoForm.goodsUnit || "" }}</template>
|
||||
</el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="商品单价" align="center" width="280">
|
||||
<template #default="{ $index }">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center">
|
||||
<el-input
|
||||
v-model="wholesaleData[$index].price"
|
||||
type="number"
|
||||
style="width: 190px"
|
||||
@blur="checkWholesalePrice($index)"
|
||||
>
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
<el-button
|
||||
v-if="$index > 0"
|
||||
size="small"
|
||||
style="margin-left: 5px"
|
||||
type="danger"
|
||||
@click="handleDeleteWholesaleData($index)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<Button v-if="wholesaleData.length < 3" icon="md-add" style="margin-top: 10px"
|
||||
@click="handleAddWholesaleData()">
|
||||
<el-button v-if="wholesaleData.length < 3" style="margin-top: 10px" @click="handleAddWholesaleData()">
|
||||
<el-icon><Plus /></el-icon>
|
||||
添加价格区间
|
||||
</Button>
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="form-item-view-wholesale-preview">
|
||||
<Table :columns="wholesalePreviewColumns" :data="wholesaleData" border></Table>
|
||||
<el-table :data="wholesaleData" border style="width: 100%">
|
||||
<el-table-column label="销售规则" width="300">
|
||||
<template #default="{ row }">
|
||||
当商品购买数量 ≥{{ row.num }} 时,售价为 ¥{{ row.price }}/{{ baseInfoForm.goodsUnit }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</FormItem>
|
||||
<FormItem class="form-item-view-el" label="商品发布" prop="release">
|
||||
<RadioGroup v-model="baseInfoForm.release" button-style="solid" type="button">
|
||||
<Radio :label="1" title="上架">
|
||||
<span>上架</span>
|
||||
</Radio>
|
||||
<Radio :label="0" title="下架">
|
||||
<span>下架</span>
|
||||
</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item-view-el" label="商品发布" prop="release">
|
||||
<el-radio-group v-model="baseInfoForm.release">
|
||||
<el-radio-button :value="1">上架</el-radio-button>
|
||||
<el-radio-button :value="0">下架</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<h4>商品规格及图片</h4>
|
||||
<div class="form-item-view">
|
||||
<FormItem class="form-item-view-el required" label="主图" prop="goodsGalleryFiles">
|
||||
<el-form-item class="form-item-view-el required" label="主图" prop="goodsGalleryFiles">
|
||||
<div style="display: flex; flex-wrap: wrap;">
|
||||
<vuedraggable :animation="200" :list="baseInfoForm.goodsGalleryFiles">
|
||||
<div v-for="(item, __index) in baseInfoForm.goodsGalleryFiles" :key="__index"
|
||||
@@ -118,8 +127,8 @@
|
||||
<img :src="item" />
|
||||
<div class="demo-upload-list-cover">
|
||||
<div>
|
||||
<Icon size="30" type="md-search" @click.native="handleViewGoodsPicture(item)"></Icon>
|
||||
<Icon size="30" type="md-trash" @click.native="handleRemoveGoodsPicture(item)"></Icon>
|
||||
<el-button link type="primary" @click="handleViewGoodsPicture(item)">预览</el-button>
|
||||
<el-button link type="danger" @click="handleRemoveGoodsPicture(item)">删除</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -140,85 +149,96 @@
|
||||
<!--</Upload>-->
|
||||
</div>
|
||||
<div style="width: 100%;display: flex;justify-content: start;margin-top: 10px;">
|
||||
<Button @click="handleCLickImg('goodsGalleryFiles')" type="primary">上传图片</Button>
|
||||
<el-button @click="handleCLickImg('goodsGalleryFiles')" type="primary">上传图片</el-button>
|
||||
</div>
|
||||
<Modal v-model="goodsPictureVisible" title="View Image">
|
||||
<el-dialog v-model="goodsPictureVisible" title="View Image">
|
||||
<img v-if="goodsPictureVisible" :src="previewGoodsPicture" style="width: 100%" />
|
||||
</Modal>
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
</el-dialog>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<div style="color: grey">主图仅支持png,jpg,jpeg格式,宽高至少600*600px,大小2M内,可拖拽调整主图顺序</div>
|
||||
</FormItem>
|
||||
<FormItem class="form-item-view-el" label="主图视频" prop="goodsVideo">
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item-view-el" label="主图视频" prop="goodsVideo">
|
||||
<div class="goods-video">
|
||||
<div v-if="baseInfoForm.goodsVideo">
|
||||
<div>
|
||||
<video :src="baseInfoForm.goodsVideo" class="video" controls style="max-width: 300px;" />
|
||||
</div>
|
||||
</div>
|
||||
<Upload ref="upload" :action="uploadFileUrl" :format="['avi', 'wmv', 'mpeg', 'mp4', 'mov']"
|
||||
:headers="{ ...accessToken }" :max-size="10240" :on-error="() => { loadingVideo = false }"
|
||||
:on-exceeded-size="handleVideoMaxSize" :on-format-error="handleFormatError"
|
||||
:on-progress="() => { loadingVideo = true }" :on-success="handleSuccessGoodsVideo"
|
||||
:show-upload-list="false" multiple style="margin-left: 10px" type="drag">
|
||||
<Button :loading="loadingVideo" icon="ios-cloud-upload-outline" type="text">
|
||||
<span v-if="!loadingVideo">
|
||||
{{ baseInfoForm.goodsVideo ? "已" : "" }}上传视频
|
||||
</span>
|
||||
<span v-else>
|
||||
正在上传...
|
||||
</span>
|
||||
</Button>
|
||||
</Upload>
|
||||
<el-upload
|
||||
:action="uploadFileUrl"
|
||||
:headers="{ ...accessToken }"
|
||||
accept=".avi,.wmv,.mpeg,.mp4,.mov"
|
||||
:show-file-list="false"
|
||||
:before-upload="beforeVideoUpload"
|
||||
:on-success="handleSuccessGoodsVideo"
|
||||
:on-error="() => { loadingVideo = false }"
|
||||
style="margin-left: 10px; display: inline-block"
|
||||
>
|
||||
<el-button :loading="loadingVideo" type="primary" link>
|
||||
{{ loadingVideo ? "正在上传..." : `${baseInfoForm.goodsVideo ? "已" : ""}上传视频` }}
|
||||
</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
</FormItem>
|
||||
</el-form-item>
|
||||
<div class="layout" style="width: 100%">
|
||||
<Collapse v-model="open_panel">
|
||||
<Panel name="1">
|
||||
自定义规格项
|
||||
<div slot="content">
|
||||
<Form>
|
||||
<el-collapse v-model="open_panel">
|
||||
<el-collapse-item title="自定义规格项" name="1">
|
||||
<div>
|
||||
<div v-for="(item, $index) in skuInfo" :key="$index" class="sku-item-content">
|
||||
<Card :bordered="true" class="ivu-card-body">
|
||||
<a slot="extra" style="margin-left: 6px">
|
||||
<Icon size="20" type="md-trash" @click="handleCloseSkuItem($index, item)"></Icon>
|
||||
</a>
|
||||
<el-card class="ivu-card-body">
|
||||
<template #header>
|
||||
<el-button link type="danger" @click="handleCloseSkuItem($index, item)">删除规格项</el-button>
|
||||
</template>
|
||||
<div>
|
||||
<div style="display: flex;margin-bottom: 10px;font-weight: bold">规格项</div>
|
||||
<FormItem class="sku-item-content-val flex" label="">
|
||||
<el-form-item class="sku-item-content-val flex" label="">
|
||||
|
||||
<div>
|
||||
<AutoComplete v-model="item.name" :filter-method="filterMethod" :maxlength="30"
|
||||
placeholder="请输入规格项名称" style="width: 150px" @on-focus="changeSkuItem(item.name)"
|
||||
@on-change="editSkuItem(item.name, $index, item)">
|
||||
</AutoComplete>
|
||||
<el-autocomplete
|
||||
v-model="item.name"
|
||||
:fetch-suggestions="(q, cb) => cb([])"
|
||||
maxlength="30"
|
||||
placeholder="请输入规格项名称"
|
||||
style="width: 150px"
|
||||
@focus="changeSkuItem(item.name)"
|
||||
@change="editSkuItem(item.name, $index, item)"
|
||||
/>
|
||||
|
||||
<iSwitch v-if="$index === 0" style="margin-left: 10px" size="small"
|
||||
@on-change="changeSkuOpenImage" v-model="openImage" /><span v-if="$index === 0"
|
||||
style="margin-left: 5px">添加规格图片</span>
|
||||
<el-switch
|
||||
v-if="$index === 0"
|
||||
v-model="openImage"
|
||||
style="margin-left: 10px"
|
||||
@change="changeSkuOpenImage"
|
||||
/>
|
||||
<span v-if="$index === 0" style="margin-left: 5px">添加规格图片</span>
|
||||
</div>
|
||||
</FormItem>
|
||||
</el-form-item>
|
||||
|
||||
</div>
|
||||
<div class="sku-val">
|
||||
<div style="margin-bottom: 10px;font-weight: bold;display: flex">规格值 (输入完成后,鼠标点击其他地方后生效)</div>
|
||||
<Form :model="item" class="flex">
|
||||
<el-form :model="item" class="flex">
|
||||
<!--规格值文本列表-->
|
||||
<FormItem v-for="(val, index) in item.spec_values" :key="index"
|
||||
<el-form-item v-for="(val, index) in item.spec_values" :key="index"
|
||||
class="sku-item-content-val flex" label="" style="line-height: 32px;">
|
||||
<div style="display: flex; justify-content: center; align-items: center;">
|
||||
|
||||
|
||||
<AutoComplete ref="input" v-model="val.value" :disabled="containsSameSkuItem"
|
||||
:filter-method="filterMethod" :maxlength="30" placeholder="请输入规格值"
|
||||
style="width: 180px" @on-focus="changeSkuVals(val, item.name)"
|
||||
@on-blur="checkSkuVal(val, $index, item)"
|
||||
@on-change="skuValueChange(val, index, item)">
|
||||
</AutoComplete>
|
||||
<a style="margin-left: 6px" >
|
||||
<Icon size="15" type="md-trash" @click="handleCloseSkuValue(val, index, item)">
|
||||
</Icon>
|
||||
</a>
|
||||
<el-autocomplete
|
||||
v-model="val.value"
|
||||
:disabled="containsSameSkuItem"
|
||||
:fetch-suggestions="(q, cb) => cb([])"
|
||||
maxlength="30"
|
||||
placeholder="请输入规格值"
|
||||
style="width: 180px"
|
||||
@focus="changeSkuVals(val, item.name)"
|
||||
@blur="checkSkuVal(val, $index, item)"
|
||||
@change="skuValueChange(val, index, item)"
|
||||
/>
|
||||
<el-button link type="danger" style="margin-left: 6px" @click="handleCloseSkuValue(val, index, item)">
|
||||
<el-icon><Delete /></el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 内联错误提示 -->
|
||||
@@ -231,205 +251,251 @@
|
||||
<img :src="img" style="width: 180px;height: 140px" />
|
||||
<div class="sku-upload-list-cover">
|
||||
<div style="margin-top: 50px">
|
||||
<Icon size="25" type="md-search" @click="handleView(img)"></Icon>
|
||||
<Icon size="25" type="md-trash" @click="handleRemove(val.images, __index)">
|
||||
</Icon>
|
||||
<el-icon :size="25" style="cursor:pointer;margin-right:8px" @click="handleView(img)"><ZoomIn /></el-icon>
|
||||
<el-icon :size="25" style="cursor:pointer" @click="handleRemove(val.images, __index)"><Delete /></el-icon>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</vuedraggable>
|
||||
<Upload ref="uploadSku" :action="uploadFileUrl" v-if="val.images < 1"
|
||||
:before-upload="handleBeforeUpload" :format="['jpg', 'jpeg', 'png', 'webp']"
|
||||
:headers="{ ...accessToken }" :max-size="2048" :on-error="() => { $Spin.hide(); }"
|
||||
:on-exceeded-size="handleMaxSize" :on-format-error="handleFormatError"
|
||||
:on-progress="() => { $Spin.show(); }" :on-success="(res, file) => {
|
||||
handleSuccess(res, file, val.images)
|
||||
}" :show-upload-list="false" style="width: 180px;height: 140px;margin-right: 10px"
|
||||
type="drag">
|
||||
<div>
|
||||
<Icon size="136" type="ios-camera"></Icon>
|
||||
</div>
|
||||
</Upload>
|
||||
<el-upload
|
||||
v-if="val.images.length < 1"
|
||||
:action="uploadFileUrl"
|
||||
:before-upload="handleBeforeUpload"
|
||||
:headers="{ ...accessToken }"
|
||||
:on-error="() => {}"
|
||||
:on-exceeded-size="handleMaxSize"
|
||||
:on-success="(res, file) => handleSuccess(res, file, val.images)"
|
||||
:show-file-list="false"
|
||||
accept=".jpg,.jpeg,.png,.webp"
|
||||
drag
|
||||
style="width: 180px;height: 140px;margin-right: 10px"
|
||||
>
|
||||
<el-icon :size="40"><Camera /></el-icon>
|
||||
</el-upload>
|
||||
</div>
|
||||
</FormItem>
|
||||
</el-form-item>
|
||||
|
||||
<FormItem
|
||||
<el-form-item
|
||||
v-if="item.spec_values.length < 10 && item.spec_values.length >= 1 && item.spec_values[0].value !== ''"
|
||||
class="sku-item-content-val flex" label="" style="line-height: 32px;">
|
||||
<AutoComplete ref="input" v-model="newSkuValues[$index]" :disabled="containsSameSkuItem"
|
||||
:filter-method="filterMethod" :maxlength="30" placeholder="自定义规格值"
|
||||
style="width: 180px" @on-blur="addSpec($index, item)"
|
||||
v-on:keyup.native.enter="addSpec($index, item)">
|
||||
</AutoComplete>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<el-autocomplete
|
||||
v-model="newSkuValues[$index]"
|
||||
:disabled="containsSameSkuItem"
|
||||
:fetch-suggestions="(q, cb) => cb([])"
|
||||
maxlength="30"
|
||||
placeholder="自定义规格值"
|
||||
style="width: 180px"
|
||||
@blur="addSpec($index, item)"
|
||||
@keyup.enter="addSpec($index, item)"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</Card>
|
||||
</el-card>
|
||||
</div>
|
||||
</Form>
|
||||
<div style="display: flex">
|
||||
<Button class="add-sku-btn" type="primary" @click="addSkuItem">添加规格项
|
||||
</Button>
|
||||
<el-button class="add-sku-btn" type="primary" @click="addSkuItem">添加规格项
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- <Button class="add-sku-btn" size="small" type="warning" @click="handleClearSku">清空规格项-->
|
||||
<!-- </Button>-->
|
||||
</div>
|
||||
</Panel>
|
||||
<Panel name="2">
|
||||
规格详细
|
||||
<div slot="content">
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="规格详细" name="2">
|
||||
<div v-if="needToloadSku" class="topinfo" @click="handleLoadingSkuData">点击加载sku数据</div>
|
||||
<div slot="content" :class="needToloadSku ? 'mask' : ''">
|
||||
<Table :columns="skuTableColumn" :data="skuTableData" class="mt_10" style="
|
||||
width: 100%;
|
||||
.ivu-table-overflowX {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
">
|
||||
<template slot="sn" slot-scope="{ row }">
|
||||
<Input v-model="row.sn" clearable placeholder="请输入货号"
|
||||
@on-change="updateSkuTable(row, 'sn')" />
|
||||
</template>
|
||||
<div v-if="baseInfoForm.goodsType !== 'VIRTUAL_GOODS'" slot="weight" slot-scope="{ row }">
|
||||
<Input v-model="row.weight" clearable placeholder="请输入重量"
|
||||
@on-change="updateSkuTable(row, 'weight')">
|
||||
<span slot="append">kg</span>
|
||||
</Input>
|
||||
</div>
|
||||
<template slot="quantity" slot-scope="{ row }">
|
||||
<Input v-model="row.quantity" clearable placeholder="请输入库存"
|
||||
@on-change="updateSkuTable(row, 'quantity')">
|
||||
<span slot="append">{{
|
||||
baseInfoForm.goodsUnit || ""
|
||||
}}</span>
|
||||
</Input>
|
||||
</template>
|
||||
<template slot="cost" slot-scope="{ row }">
|
||||
<Input v-model="row.cost" clearable placeholder="请输入成本价"
|
||||
@on-change="updateSkuTable(row, 'cost')">
|
||||
<span slot="append">元</span>
|
||||
</Input>
|
||||
</template>
|
||||
<template slot="price" slot-scope="{ row }">
|
||||
<Input v-model="row.price" clearable placeholder="请输入价格"
|
||||
@on-change="updateSkuTable(row, 'price')">
|
||||
<span slot="append">元</span>
|
||||
</Input>
|
||||
</template>
|
||||
<template slot="wholePrice0" slot-scope="{ row }">
|
||||
<Input v-if="wholesaleData[0]" v-model="wholesaleData[0].price" clearable disabled>
|
||||
<span slot="append">元</span>
|
||||
</Input>
|
||||
</template>
|
||||
<template slot="wholePrice1" slot-scope="{ row }">
|
||||
<Input v-if="wholesaleData[1]" v-model="wholesaleData[1].price" clearable disabled>
|
||||
<span slot="append">元</span>
|
||||
</Input>
|
||||
</template>
|
||||
<template slot="wholePrice2" slot-scope="{ row }">
|
||||
<Input v-if="wholesaleData[2]" v-model="wholesaleData[2].price" clearable disabled>
|
||||
<span slot="append">元</span>
|
||||
</Input>
|
||||
</template>
|
||||
</Table>
|
||||
<div :class="needToloadSku ? 'mask' : ''">
|
||||
<el-table :data="skuTableData" border class="mt_10" style="width: 100%">
|
||||
<el-table-column
|
||||
v-for="(col, colIndex) in skuTableColumn"
|
||||
:key="colIndex"
|
||||
:label="col.title"
|
||||
:prop="col.key"
|
||||
min-width="120"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<span v-if="col.key && !col.slot">{{ row[col.key] }}</span>
|
||||
<el-input
|
||||
v-else-if="col.slot === 'sn'"
|
||||
v-model="row.sn"
|
||||
clearable
|
||||
placeholder="请输入货号"
|
||||
@change="updateSkuTable(row, 'sn')"
|
||||
/>
|
||||
<el-input
|
||||
v-else-if="col.slot === 'weight' && baseInfoForm.goodsType !== 'VIRTUAL_GOODS'"
|
||||
v-model="row.weight"
|
||||
clearable
|
||||
placeholder="请输入重量"
|
||||
@change="updateSkuTable(row, 'weight')"
|
||||
>
|
||||
<template #append>kg</template>
|
||||
</el-input>
|
||||
<el-input
|
||||
v-else-if="col.slot === 'quantity'"
|
||||
v-model="row.quantity"
|
||||
clearable
|
||||
placeholder="请输入库存"
|
||||
@change="updateSkuTable(row, 'quantity')"
|
||||
>
|
||||
<template #append>{{ baseInfoForm.goodsUnit || "" }}</template>
|
||||
</el-input>
|
||||
<el-input
|
||||
v-else-if="col.slot === 'cost'"
|
||||
v-model="row.cost"
|
||||
clearable
|
||||
placeholder="请输入成本价"
|
||||
@change="updateSkuTable(row, 'cost')"
|
||||
>
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
<el-input
|
||||
v-else-if="col.slot === 'price'"
|
||||
v-model="row.price"
|
||||
clearable
|
||||
placeholder="请输入价格"
|
||||
@change="updateSkuTable(row, 'price')"
|
||||
>
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
<el-input
|
||||
v-else-if="col.slot === 'wholePrice0' && wholesaleData[0]"
|
||||
v-model="wholesaleData[0].price"
|
||||
disabled
|
||||
>
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
<el-input
|
||||
v-else-if="col.slot === 'wholePrice1' && wholesaleData[1]"
|
||||
v-model="wholesaleData[1].price"
|
||||
disabled
|
||||
>
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
<el-input
|
||||
v-else-if="col.slot === 'wholePrice2' && wholesaleData[2]"
|
||||
v-model="wholesaleData[2].price"
|
||||
disabled
|
||||
>
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</Panel>
|
||||
</Collapse>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</div>
|
||||
</div>
|
||||
<h4 v-if="showContent">规格描述内容</h4>
|
||||
<div v-if="showContent" class="form-item-view">
|
||||
<div>
|
||||
<FormItem :label="contentImage" class="form-item-view-el">
|
||||
<el-form-item :label="contentImage" class="form-item-view-el">
|
||||
<!-- {{item.url}} -->
|
||||
<div v-for="(item, index) in listImages.images" :key="index" style="width:100%;display:flex;">
|
||||
<img :src="item.url" style="width:100px;flex:1;margin-top:10px;cursor:pointer;"
|
||||
@click="handleView(item.url)" />
|
||||
</div>
|
||||
</FormItem>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
<h4>商品详情描述</h4>
|
||||
<div class="form-item-view">
|
||||
<div class="tree-bar">
|
||||
<FormItem class="form-item-view-el" label="店内分类" prop="shopCategory">
|
||||
<Tree ref="tree" :check-strictly="false" :data="shopCategory" show-checkbox style="text-align: left"
|
||||
@on-select-change="selectTree" @on-check-change="changeSelect"></Tree>
|
||||
</FormItem>
|
||||
<el-form-item class="form-item-view-el" label="店内分类" prop="shopCategory">
|
||||
<el-tree
|
||||
ref="tree"
|
||||
:data="shopCategory"
|
||||
show-checkbox
|
||||
node-key="id"
|
||||
:props="{ label: 'title', children: 'children' }"
|
||||
style="text-align: left"
|
||||
@node-click="(data) => selectTree([data])"
|
||||
@check="(_, ctx) => changeSelect(ctx.checkedNodes)"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<FormItem class="form-item-view-el" label="PC商品描述" prop="intro" style="width: 100%">
|
||||
<el-form-item class="form-item-view-el" label="PC商品描述" prop="intro" style="width: 100%">
|
||||
<editor ref="editor" v-model="baseInfoForm.intro" height="800px" openXss></editor>
|
||||
<div class="promise-intro-btn">
|
||||
<Button type="primary" @click="promiseIntroEditor">将PC商品描述同步到移动端描述
|
||||
</Button>
|
||||
<el-button type="primary" @click="promiseIntroEditor">将PC商品描述同步到移动端描述
|
||||
</el-button>
|
||||
</div>
|
||||
</FormItem>
|
||||
</el-form-item>
|
||||
|
||||
<FormItem class="form-item-view-el" label="移动端描述" prop="skuList" style="width: 100%">
|
||||
<el-form-item class="form-item-view-el" label="移动端描述" prop="skuList" style="width: 100%">
|
||||
<editor ref="introEditor" v-model="baseInfoForm.mobileIntro" height="800px" openXss></editor>
|
||||
</FormItem>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-if="baseInfoForm.goodsType != 'VIRTUAL_GOODS'">
|
||||
<h4>商品物流信息</h4>
|
||||
<div class="form-item-view">
|
||||
<FormItem class="form-item-view-el" label="物流模板" prop="templateId">
|
||||
<Select v-model="baseInfoForm.templateId" style="width: 200px">
|
||||
<Option v-for="item in logisticsTemplate" :key="item.id" :value="item.id">{{ item.name }}
|
||||
</Option>
|
||||
</Select>
|
||||
<Button class="refresh-icon" icon="md-refresh" shape="circle" type="text"
|
||||
@click="refresh('template')"></Button>
|
||||
</FormItem>
|
||||
<FormItem v-if="baseInfoForm.salesModel == 'WHOLESALE'" class="form-item-view-el" label="商品重量"
|
||||
<el-form-item class="form-item-view-el" label="物流模板" prop="templateId">
|
||||
<el-select v-model="baseInfoForm.templateId" style="width: 200px">
|
||||
<el-option v-for="item in logisticsTemplate" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
<el-button class="refresh-icon" circle link @click="refresh('template')">
|
||||
<el-icon><Refresh /></el-icon>
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="baseInfoForm.salesModel == 'WHOLESALE'" class="form-item-view-el" label="商品重量"
|
||||
prop="weight">
|
||||
<Input v-model="baseInfoForm.weight" placeholder="请输入商品重量">
|
||||
<span slot="append">kg</span></Input>
|
||||
</FormItem>
|
||||
<el-input v-model="baseInfoForm.weight" placeholder="请输入商品重量">
|
||||
<template #append>kg</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
<h4>参数信息</h4>
|
||||
<div class="form-item-view">
|
||||
<FormItem v-for="(paramsItem, paramsIndex) in goodsParams" :key="paramsItem.id || paramsIndex"
|
||||
<el-form-item v-for="(paramsItem, paramsIndex) in goodsParams" :key="paramsItem.id || paramsIndex"
|
||||
:label="`${paramsItem.paramName}:`"
|
||||
:prop="`goodsParams.${paramsIndex}.paramValue`"
|
||||
:rules="paramsItem.required ? { required: true, message: `${paramsItem.paramName}不能为空`, trigger: 'change' } : {}">
|
||||
<Select v-model="baseInfoForm.goodsParams[paramsIndex].paramValue" clearable placeholder="请选择" style="width: 200px"
|
||||
@on-change="(val) => selectParams(paramsItem, val, paramsIndex)">
|
||||
<Option v-for="option in getParamOptions(paramsItem.options)" :key="option" :label="option"
|
||||
:value="option">
|
||||
</Option>
|
||||
</Select>
|
||||
</FormItem>
|
||||
<el-select v-model="baseInfoForm.goodsParams[paramsIndex].paramValue" clearable placeholder="请选择" style="width: 200px"
|
||||
@change="(val) => selectParams(paramsItem, val, paramsIndex)">
|
||||
<el-option
|
||||
v-for="option in getParamOptions(paramsItem.options)"
|
||||
:key="option"
|
||||
:label="option"
|
||||
:value="option"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
</el-form>
|
||||
</div>
|
||||
<!-- 底部按钮 -->
|
||||
<div class="footer">
|
||||
<ButtonGroup>
|
||||
<Button type="primary" @click="pre">上一步</Button>
|
||||
<Button :loading="submitLoading" type="primary" @click="save">
|
||||
<div class="footer-btns">
|
||||
<el-button type="primary" @click="pre">上一步</el-button>
|
||||
<el-button :loading="submitLoading" type="primary" @click="save">
|
||||
{{ this.$route.query.id ? "保存" : "保存商品" }}
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Modal v-model="showGoodsVideo" title="查看视频">
|
||||
<el-dialog v-model="showGoodsVideo" title="查看视频">
|
||||
<div id="dplayer">
|
||||
|
||||
</div>
|
||||
</Modal>
|
||||
</el-dialog>
|
||||
|
||||
<!--<Modal width="1200px" v-model="picModelFlag">-->
|
||||
<!--<el-dialog width="1200px" v-model="picModelFlag">-->
|
||||
<!--<ossManage @callback="callbackSelected" ref="ossManage" />-->
|
||||
<!--</Modal>-->
|
||||
<Modal v-model="picModelFlag" width="1200px" @on-ok="confirmUrls">
|
||||
<ossManage ref="ossManage" :isComponent="true" :initialize="picModelFlag" @callback="callbackSelected"
|
||||
@selected="(list) => { selectedImage = list }" />
|
||||
</Modal>
|
||||
<!--</el-dialog>-->
|
||||
<el-dialog v-model="picModelFlag" width="1200px" title="选择图片" append-to-body destroy-on-close>
|
||||
<ossManage
|
||||
ref="ossManage"
|
||||
:isComponent="true"
|
||||
:initialize="picModelFlag"
|
||||
@callback="callbackSelected"
|
||||
@selected="(list) => { selectedImage = list }"
|
||||
/>
|
||||
<template #footer>
|
||||
<el-button @click="picModelFlag = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmUrls">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
@@ -437,6 +503,7 @@
|
||||
import * as API_GOODS from "@/api/goods";
|
||||
import * as API_Shop from "@/api/shops";
|
||||
import cloneObj from "@/utils/index";
|
||||
import { Camera, Delete, Plus, Refresh, ZoomIn } from "@element-plus/icons-vue";
|
||||
import vuedraggable from "vuedraggable";
|
||||
import tinymec from "@/views/lili-components/editor/index.vue";
|
||||
|
||||
@@ -450,9 +517,14 @@ import ossManage from "@/views/shop/ossManages";
|
||||
export default {
|
||||
name: "goodsOperationSec",
|
||||
components: {
|
||||
Camera,
|
||||
Delete,
|
||||
Plus,
|
||||
Refresh,
|
||||
ZoomIn,
|
||||
editor: tinymec,
|
||||
vuedraggable,
|
||||
ossManage
|
||||
ossManage,
|
||||
},
|
||||
props: {
|
||||
firstData: {
|
||||
@@ -745,21 +817,21 @@ export default {
|
||||
},
|
||||
selectParams(params, value, paramsIndex) {
|
||||
if (!Array.isArray(this.baseInfoForm.goodsParamsDTOList)) {
|
||||
this.$set(this.baseInfoForm, "goodsParamsDTOList", []);
|
||||
this.baseInfoForm.goodsParamsDTOList = [];
|
||||
}
|
||||
|
||||
// 确保baseInfoForm.goodsParams存在
|
||||
if (!Array.isArray(this.baseInfoForm.goodsParams)) {
|
||||
this.$set(this.baseInfoForm, "goodsParams", []);
|
||||
this.baseInfoForm.goodsParams = [];
|
||||
}
|
||||
|
||||
// 确保对应索引的参数项存在
|
||||
if (!this.baseInfoForm.goodsParams[paramsIndex]) {
|
||||
this.$set(this.baseInfoForm.goodsParams, paramsIndex, {});
|
||||
this.baseInfoForm.goodsParams[paramsIndex] = {};
|
||||
}
|
||||
|
||||
// 更新baseInfoForm中的值用于验证
|
||||
this.$set(this.baseInfoForm.goodsParams[paramsIndex], 'paramValue', value || '');
|
||||
this.baseInfoForm.goodsParams[paramsIndex].paramValue = value || '';
|
||||
|
||||
const list = this.baseInfoForm.goodsParamsDTOList;
|
||||
const paramId = params && params.id ? String(params.id) : "";
|
||||
@@ -770,7 +842,7 @@ export default {
|
||||
list.splice(index, 1);
|
||||
}
|
||||
// 清空表单项的值
|
||||
this.$set(params, 'paramValue', '');
|
||||
params.paramValue = '';
|
||||
return;
|
||||
}
|
||||
const newItem = {
|
||||
@@ -783,13 +855,13 @@ export default {
|
||||
};
|
||||
|
||||
if (index >= 0) {
|
||||
this.$set(list, index, newItem);
|
||||
list[index] = newItem;
|
||||
} else {
|
||||
list.push(newItem);
|
||||
}
|
||||
|
||||
// 同步更新表单项的值
|
||||
this.$set(params, 'paramValue', value);
|
||||
params.paramValue = value;
|
||||
},
|
||||
// 编辑sku图片
|
||||
editSkuPicture(row) {
|
||||
@@ -844,7 +916,6 @@ export default {
|
||||
},
|
||||
// sku图片上传成功
|
||||
handleSuccess(res, file, images) {
|
||||
this.$Spin.hide();
|
||||
if (file.response) {
|
||||
file.url = file.response.result;
|
||||
if (images) {
|
||||
@@ -942,7 +1013,6 @@ export default {
|
||||
},
|
||||
// 商品图片上传成功
|
||||
handleSuccessGoodsPicture(res, file) {
|
||||
this.$Spin.hide();
|
||||
if (file.response) {
|
||||
file.url = file.response.result;
|
||||
this.baseInfoForm.goodsGalleryFiles.push(file.url);
|
||||
@@ -1263,11 +1333,11 @@ export default {
|
||||
.sort((a, b) => Number(a.sort || 0) - Number(b.sort || 0));
|
||||
|
||||
// 初始化baseInfoForm.goodsParams用于表单验证
|
||||
this.$set(this.baseInfoForm, 'goodsParams', []);
|
||||
this.baseInfoForm.goodsParams = [];
|
||||
this.goodsParams.forEach((param, index) => {
|
||||
this.$set(this.baseInfoForm.goodsParams, index, {
|
||||
this.baseInfoForm.goodsParams[index] = {
|
||||
paramValue: param.paramValue || ''
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
// 确保表单验证能正确初始化
|
||||
@@ -1297,8 +1367,7 @@ export default {
|
||||
this.$Message.error("规格项不能为空!");
|
||||
return;
|
||||
}
|
||||
// 写入对象,下标,具体对象
|
||||
this.$set(this.skuInfo, this.skuInfo.length, {
|
||||
this.skuInfo.push({
|
||||
spec_values: [{ name: "", value: "", images: [] }],
|
||||
name: "",
|
||||
});
|
||||
@@ -1420,7 +1489,7 @@ export default {
|
||||
checkSkuVal(val, groupIndex, spec) {
|
||||
if (val.value === "") {
|
||||
// 内联错误提示,不使用弹窗
|
||||
this.$set(val, '_error', '规格值不能为空!');
|
||||
val._error = '规格值不能为空!';
|
||||
|
||||
// 如果规格项和规格名称存在,从表格数据中移除包含该空规格值的行
|
||||
if (spec && spec.name && this.skuInfo[groupIndex]) {
|
||||
@@ -1568,7 +1637,7 @@ export default {
|
||||
} else {
|
||||
itemValue.images = this.baseInfoForm.goodsGalleryFiles
|
||||
}
|
||||
this.$set(item.spec_values, item.spec_values.length, itemValue);
|
||||
item.spec_values.push(itemValue);
|
||||
|
||||
// 生成新的规格组合
|
||||
const newCombinations = this.generateSkuCombinations(this.skuInfo);
|
||||
@@ -1952,7 +2021,8 @@ export default {
|
||||
this.$nextTick(() => {
|
||||
this.skuTableData[index][item] = row[item];
|
||||
});
|
||||
// this.$set(this.skuTableData,[index][item],row[item])
|
||||
// // migrated
|
||||
(this.skuTableData,[index][item],row[item])
|
||||
},
|
||||
// 店内分类选择
|
||||
selectTree(v) {
|
||||
|
||||
Reference in New Issue
Block a user