feature/0423
wanghousheng 9 months ago
parent 685c66d19b
commit cd48e901f4
  1. 159
      src/views/goods/Index.vue
  2. 828
      src/views/goods/modules/Update.vue

@ -36,16 +36,18 @@
</a-form-item>
<a-form-item label="商品价格">
<div style="display: flex" class="goodsType">
<a-input v-decorator="['goods_price_min']" placeholder="请输入" /><span style="padding: 0 3px 0 5px"
>-</span
<a-input v-decorator="['goods_price_min']" placeholder="请输入" /><span
style="padding: 0 3px 0 5px"
>-</span
>
<a-input style="margin-left: 5px" v-decorator="['goods_price_max']" placeholder="请输入" />
</div>
</a-form-item>
<a-form-item label="利润率">
<div style="display: flex" class="goodsType">
<a-input v-decorator="['profit_rate_min']" placeholder="请输入" /><span style="padding: 0 3px 0 5px"
>-</span
<a-input v-decorator="['profit_rate_min']" placeholder="请输入" /><span
style="padding: 0 3px 0 5px"
>-</span
>
<a-input style="margin-left: 5px" v-decorator="['profit_rate_max']" placeholder="请输入" />
</div>
@ -65,27 +67,41 @@
<a-radio-button value="sold_out">已售罄</a-radio-button>
</a-radio-group>
</div>
<a-button v-if="$auth('/goods/create')" class="fl-l" type="primary" icon="plus" @click="handleCreate()"
>创建商品</a-button
<a-button
v-if="$auth('/goods/create')"
class="fl-l"
type="primary"
icon="plus"
@click="handleCreate()"
>创建商品</a-button
>
<a-button
v-if="$module('goods-import') && $auth('/goods/import/batch')"
class="fl-l"
icon="arrow-up"
@click="handleImport()"
>批量导入</a-button
>批量导入</a-button
>
<a-button style="background-color: #501212; color: #fff; border: none" @click="handleExport(selectedRowKeys)"
>导出</a-button
<a-button
style="background-color: #501212; color: #fff; border: none"
@click="handleExport(selectedRowKeys)"
>导出</a-button
>
<a-button class="fl-l" style="background-color: #f0baae; border: none" type="primary" @click="handleModify()"
>批量修改</a-button
<a-button
class="fl-l"
style="background-color: #f0baae; border: none"
type="primary"
@click="handleModify()"
>批量修改</a-button
>
<div v-if="selectedRowKeys.length" class="button-group">
<a-button-group class="ml-10">
<a-button v-action:status icon="arrow-up" @click="handleUpdateStatus(selectedRowKeys, true)">上架</a-button>
<a-button v-action:status icon="arrow-down" @click="handleUpdateStatus(selectedRowKeys, false)"
>下架</a-button
<a-button
v-action:status
icon="arrow-down"
@click="handleUpdateStatus(selectedRowKeys, false)"
>下架</a-button
>
<a-button v-action:delete icon="delete" @click="handleDelete(selectedRowKeys)">删除</a-button>
</a-button-group>
@ -121,22 +137,26 @@
class="cur-p"
:color="text == 10 ? 'green' : 'red'"
@click="handleUpdateStatus([item.goods_id], text != 10)"
>{{ text == 10 ? '上架' : '下架' }}</a-tag
>{{ text == 10 ? '上架' : '下架' }}</a-tag
>
</span>
<!-- 操作项 -->
<div class="actions" slot="action" slot-scope="text, item">
<router-link v-if="$auth('/goods/update')" :to="{ path: '/goods/update', query: { goodsId: item.goods_id } }"
>编辑</router-link
>
<!-- <router-link
v-if="$auth('/goods/update')"
:to="{ path: '/goods/update', query: { goodsId: item.goods_id } }"
>编辑</router-link
> -->
<a @click="handleEdit(item.goods_id)">编辑</a>
<router-link
v-if="$module('goods-copy') && $auth('/goods/copy')"
:to="{ path: '/goods/copy', query: { goodsId: item.goods_id } }"
>复制</router-link
>复制</router-link
>
<a v-action:delete @click="handleDelete([item.goods_id])">删除</a>
</div>
</s-table>
<Update ref="UpdateRef" />
</a-card>
</template>
@ -145,108 +165,109 @@ import * as GoodsApi from '@/api/goods'
import { ContentHeader, STable } from '@/components'
import CategoryModel from '@/common/model/Category'
import store from '../../store'
import Update from './modules/Update'
//
const columns = [
{
title: '商品ID',
dataIndex: 'goods_id',
width: '80px',
sorter: true,
sorter: true
},
{
title: '渠道',
width: '50px',
dataIndex: 'channel_name',
dataIndex: 'channel_name'
},
{
title: '商品编号',
dataIndex: 'goods_no',
width: '100px',
width: '100px'
},
{
title: '商品图片',
width: '100px',
dataIndex: 'goods_image',
scopedSlots: { customRender: 'goods_image' },
scopedSlots: { customRender: 'goods_image' }
},
{
title: '商品名称',
dataIndex: 'goods_name',
width: '260px',
scopedSlots: { customRender: 'goods_name' },
scopedSlots: { customRender: 'goods_name' }
},
{
title: '商品价格',
width: '90px',
dataIndex: 'goods_price_min',
scopedSlots: { customRender: 'goods_price_min' },
sorter: true,
sorter: true
},
{
title: '成本价',
width: '80px',
dataIndex: 'cost_price_min',
scopedSlots: { customRender: 'cost_price_min' },
sorter: true,
sorter: true
},
{
title: '利润',
width: '80px',
dataIndex: 'profit',
sorter: true,
sorter: true
},
{
title: '利润率',
width: '80px',
dataIndex: 'profit_rate',
sorter: true,
scopedSlots: { customRender: 'profit_rate' },
scopedSlots: { customRender: 'profit_rate' }
},
{
title: '总销量',
width: '80px',
dataIndex: 'sales_actual',
sorter: true,
sorter: true
},
{
title: '库存总量',
width: '90px',
dataIndex: 'stock_total',
sorter: true,
sorter: true
},
{
title: '状态',
width: '60px',
dataIndex: 'status',
scopedSlots: { customRender: 'status' },
scopedSlots: { customRender: 'status' }
},
{
title: '排序',
width: '80px',
dataIndex: 'sort',
sorter: true,
sorter: true
},
{
title: '添加时间',
width: '130px',
width: '150px',
dataIndex: 'create_time',
sorter: true,
sorter: true
},
{
title: '操作',
dataIndex: 'action',
width: '150px',
scopedSlots: { customRender: 'action' },
},
scopedSlots: { customRender: 'action' }
}
]
export default {
name: 'Index',
components: {
ContentHeader,
STable,
Update
},
data() {
data () {
return {
//
searchForm: this.$form.createForm(this),
@ -256,7 +277,7 @@ export default {
queryParam: {
listType: 'all',
spec_type: '',
channel: '',
channel: ''
},
//
isLoading: false,
@ -269,7 +290,7 @@ export default {
const data = { ...param, ...this.queryParam }
const orderEnum = {
ascend: 'asc',
descend: 'desc',
descend: 'desc'
}
if (data.sortField && data.sortOrder && orderEnum[data.sortOrder]) {
@ -288,40 +309,40 @@ export default {
specsType: [
{ name: '全部', val: '' },
{ name: '单规格', val: 10 },
{ name: '多规格', val: 20 },
{ name: '多规格', val: 20 }
],
checkList: [],
checkList: []
}
},
created() {
created () {
//
if (this.$route.query.listType) {
this.queryParam.listType = this.$route.query.listType
}
//
this.getCategoryList()
this.getDataList() //
this.getDataList() //
},
computed: {
rowSelection() {
rowSelection () {
return {
selectedRowKeys: this.selectedRowKeys,
onChange: this.onSelectChange,
onChange: this.onSelectChange
}
},
}
},
methods: {
//
handleModify() {
handleModify () {
this.$router.push('/goods/modify')
},
//
handleExport(goodsIds) {
handleExport (goodsIds) {
const formData = this.searchForm.getFieldsValue()
this.isLoading = true
var index = window.publicConfig.BASE_API.indexOf('?')
var resolve = window.publicConfig.BASE_API.substring(0, index)
let params =
const params =
'&goodsName=' +
(formData.goodsName || '') +
'&goodsNo=' +
@ -345,10 +366,10 @@ export default {
console.log(params)
window.open(resolve + '?s=/admin/goods/export' + params)
},
getChannel(val) {
getChannel (val) {
this.queryParam.channel = val
},
getDataList() {
getDataList () {
return GoodsApi.getDataList().then((result) => {
const obj = result.data
Object.keys(obj).forEach((item) => {
@ -356,22 +377,22 @@ export default {
})
})
},
onchangeSpecs(val) {
onchangeSpecs (val) {
this.queryParam.spec_type = val
},
//
onSelectChange(selectedRowKeys) {
onSelectChange (selectedRowKeys) {
this.selectedRowKeys = selectedRowKeys
},
// tab
handleTabs(e) {
handleTabs (e) {
this.queryParam.listType = e.target.value
this.handleRefresh(true)
},
//
handleSearch(e) {
handleSearch (e) {
e.preventDefault()
this.searchForm.validateFields((error, values) => {
if (!error) {
@ -382,12 +403,12 @@ export default {
},
//
handleReset() {
handleReset () {
this.searchForm.resetFields()
},
//
getCategoryList() {
getCategoryList () {
this.isLoading = true
CategoryModel.getListFromScreen()
.then((selectList) => {
@ -397,7 +418,7 @@ export default {
},
// ()
handleUpdateStatus(goodsIds, state = true) {
handleUpdateStatus (goodsIds, state = true) {
if (!this.$auth('/goods/index.status')) {
return false
}
@ -414,29 +435,33 @@ export default {
},
//
handleDelete(goodsIds) {
handleDelete (goodsIds) {
const app = this
const modal = this.$confirm({
title: '您确定要删除该记录吗?',
content: '删除后不可恢复',
onOk() {
onOk () {
return GoodsApi.deleted({ goodsIds })
.then((result) => {
app.$message.success(result.message, 1.5)
app.handleRefresh()
})
.finally((result) => modal.destroy())
},
}
})
},
//
async handleEdit (id) {
//
this.$refs.UpdateRef.initData(id)
},
//
handleCreate() {
handleCreate () {
this.$router.push('/goods/create')
},
//
handleImport() {
handleImport () {
this.$router.push('/goods/import/batch')
},
@ -444,11 +469,11 @@ export default {
* 刷新列表
* @param Boolean bool 强制刷新到第一页
*/
handleRefresh(bool = false) {
handleRefresh (bool = false) {
this.selectedRowKeys = []
this.$refs.table.refresh(bool)
},
},
}
}
}
</script>
<style lang="less" scoped>

@ -0,0 +1,828 @@
<template>
<a-modal
title="编辑商品"
width="90%"
:visible="visible"
:confirmLoading="confirmLoading"
:maskClosable="false"
:destroyOnClose="true"
@ok="handleSubmit"
@cancel="handleCancel"
>
<a-card :bordered="false">
<a-spin :spinning="isLoading">
<a-form :form="form" @submit="handleSubmit" :selfUpdate="true">
<a-tabs :activeKey="tabKey" :tabBarStyle="{ marginBottom: '30px' }" @change="handleTabs">
<a-tab-pane :key="0" tab="基本信息"></a-tab-pane>
<a-tab-pane :key="1" tab="规格/库存"></a-tab-pane>
<a-tab-pane :key="2" tab="商品详情"></a-tab-pane>
<a-tab-pane :key="3" tab="更多设置"></a-tab-pane>
</a-tabs>
<div class="tabs-content">
<!-- 基本信息 -->
<div class="tab-pane" v-show="tabKey == 0">
<a-form-item label="商品类型" :labelCol="labelCol" :wrapperCol="wrapperCol">
<GoodsType
:onlyShowChecked="true"
v-decorator="['goods_type', { rules: [{ required: true }] }]"
@change="onForceUpdate(true)"
/>
</a-form-item>
<a-form-item label="商品名称" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input
placeholder="请输入商品名称"
v-decorator="['goods_name', { rules: [{ required: true, min: 2, message: '请输入至少2个字符' }] }]"
/>
</a-form-item>
<a-form-item label="商品型号" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input
placeholder="请输入商品型号"
v-decorator="['cmmdty_model', { rules: [{ required: true, min: 2, message: '请输入至少2个字符' }] }]"
/>
</a-form-item>
<a-form-item label="商品分类" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-tree-select
placeholder="请选择商品分类"
:dropdownStyle="{ maxHeight: '500px', overflow: 'auto' }"
:treeData="formData.categoryList"
treeCheckable
treeCheckStrictly
allowClear
v-decorator="['categorys', { rules: [{ required: true, message: '请至少选择1个商品分类' }] }]"
></a-tree-select>
<div class="form-item-help">
<router-link target="_blank" :to="{ path: '/goods/category/index' }">去新增</router-link>
<a href="javascript:;" @click="onReloadCategoryList">刷新</a>
</div>
</a-form-item>
<a-form-item
label="商品图片"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
extra="建议尺寸:750*750像素, 最多上传10张, 可拖拽图片调整顺序, 第1张将作为商品首图"
>
<SelectImage
multiple
:maxNum="10"
:defaultList="formData.goods.goods_images"
v-decorator="['imagesIds', { rules: [{ required: true, message: '请至少上传1张商品图片' }] }]"
/>
</a-form-item>
<a-form-item label="商品来源" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group v-decorator="['goods_source', { initialValue: 0, rules: [{ required: true }] }]">
<a-radio value="JD">京东</a-radio>
<a-radio value="SN">苏宁</a-radio>
<a-radio value="GC">工厂</a-radio>
<a-radio value="CC">仓储</a-radio>
<a-radio value="ZC">自采</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="发货时效" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group v-decorator="['delivery_time', { initialValue: 0, rules: [{ required: true }] }]">
<a-radio :value="0">24小时</a-radio>
<a-radio :value="1">48小时</a-radio>
<a-radio :value="2">72小时</a-radio>
<a-radio :value="3">7天内</a-radio>
<a-radio :value="4">15天内</a-radio>
<a-radio :value="5">30天内</a-radio>
<a-radio :value="6">45天内</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="是否大牌正品" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group v-decorator="['is_brand', { initialValue: 0, rules: [{ required: true }] }]">
<a-radio :value="0"></a-radio>
<a-radio :value="1"></a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="是否新品首发" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group v-decorator="['is_new', { initialValue: 0, rules: [{ required: true }] }]">
<a-radio :value="0"></a-radio>
<a-radio :value="1"></a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="是否审单" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group v-decorator="['is_check', { initialValue: 0, rules: [{ required: true }] }]">
<a-radio :value="0"></a-radio>
<a-radio :value="1"></a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="是否店内" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group v-decorator="['is_in_store', { initialValue: 0, rules: [{ required: true }] }]">
<a-radio :value="0"></a-radio>
<a-radio :value="1"></a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="商品编码" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input placeholder="请输入商品编码" v-decorator="['goods_no']" />
</a-form-item>
<a-form-item label="所属分类排行(0表示不参加排行)" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input placeholder="所属分类排行" v-decorator="['paihang']" />
</a-form-item>
<a-form-item label="热卖指数" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input placeholder="热卖指数" v-decorator="['remaizhishu']" />
</a-form-item>
<a-form-item
v-if="form.getFieldValue('goods_type') == 10"
label="配送方式"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
>
<a-radio-group
v-decorator="['is_ind_delivery_type', { initialValue: 0, rules: [{ required: true }] }]"
@change="onForceUpdate()"
>
<a-radio :value="0">系统默认</a-radio>
<a-radio :value="1">单独配置</a-radio>
</a-radio-group>
<div v-show="form.getFieldValue('is_ind_delivery_type')">
<a-form-item extra="需在 [设置 - 配送方式] 中,开启支持的配送方式才可生效">
<a-checkbox-group
:options="[
{ label: '快递配送', value: 10 },
{ label: '上门自提', value: 20 },
]"
v-decorator="[
'delivery_type',
{ initialValue: [10, 20], rules: [{ required: true, message: '配送方式至少选择一个' }] },
]"
/>
</a-form-item>
</div>
</a-form-item>
<a-form-item
v-if="form.getFieldValue('goods_type') == 10"
label="运费模板"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
>
<a-select
style="width: 300px"
v-decorator="['delivery_id', { rules: [{ required: true, message: '请选择运费模板' }] }]"
placeholder="请选择运费模板"
>
<a-select-option
v-for="(item, index) in formData.deliveryList"
:key="index"
:value="item.delivery_id"
>{{ item.name }}</a-select-option
>
</a-select>
<div class="form-item-help">
<router-link target="_blank" :to="{ path: '/setting/delivery/template/create' }">新增模板</router-link>
<a href="javascript:;" @click="onReloadDeliveryList">刷新</a>
</div>
</a-form-item>
<a-form-item label="商品状态" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group v-decorator="['status', { initialValue: 10, rules: [{ required: true }] }]">
<a-radio :value="10">上架</a-radio>
<a-radio :value="20">下架</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="商品排序" :labelCol="labelCol" :wrapperCol="wrapperCol" extra="数字越小越靠前">
<a-input-number :min="0" v-decorator="['sort', { initialValue: 100, rules: [{ required: true }] }]" />
</a-form-item>
<a-form-item class="mt-20" :wrapperCol="{ span: wrapperCol.span, offset: labelCol.span }">
<a-button type="primary" @click="handleTabs(1)" style="margin-left: 20px">下一步</a-button>
</a-form-item>
</div>
<!-- 规格/库存 -->
<div class="tab-pane" v-show="tabKey == 1">
<a-form-item label="规格类型" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group
v-decorator="['spec_type', { initialValue: 10, rules: [{ required: true }] }]"
@change="onForceUpdate()"
>
<a-radio :value="10" :disabled="formData.goods.isSpecLocked">单规格</a-radio>
<a-radio :value="20" :disabled="formData.goods.isSpecLocked">多规格</a-radio>
</a-radio-group>
<p v-if="formData.goods.isSpecLocked" class="form-item-help">
<small class="c-red">该商品当前正在参与其他活动商品规格不允许更改</small>
</p>
</a-form-item>
<!-- 多规格的表单内容 -->
<div v-if="form.getFieldValue('spec_type') == 20">
<MultiSpec
ref="MultiSpec"
:isSpecLocked="formData.goods.isSpecLocked"
:defaultSpecList="formData.goods.specList"
:defaultSkuList="formData.goods.skuList"
/>
</div>
<!-- 单规格的表单内容 -->
<div v-if="form.getFieldValue('spec_type') == 10">
<a-form-item
label="商品价格"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
extra="商品的实际购买金额,最低0.01"
>
<a-input-number
:min="0.01"
:precision="2"
v-decorator="['goods_price', { rules: [{ required: true, message: '请输入商品价格' }] }]"
/>
<span class="ml-10"></span>
</a-form-item>
<a-form-item label="成本价" :labelCol="labelCol" :wrapperCol="wrapperCol" extra="成本价仅用于商品页展示">
<a-input-number :min="0.01" :precision="2" v-decorator="['cost_price']" />
<span class="ml-10"></span>
</a-form-item>
<a-form-item
label="当前库存数量"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
extra="商品的实际库存数量,为0时用户无法下单"
>
<a-input-number
:min="0"
:precision="0"
v-decorator="[
'stock_num',
{ initialValue: 100, rules: [{ required: true, message: '请输入库存数量' }] },
]"
/>
<span class="ml-10"></span>
</a-form-item>
<a-form-item
label="商品重量"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
extra="商品的实际重量,用于计算运费"
>
<a-input-number
:min="0"
v-decorator="[
'goods_weight',
{ initialValue: 0, rules: [{ required: true, message: '请输入库存数量' }] },
]"
/>
<span class="ml-10">千克 (Kg)</span>
</a-form-item>
</div>
<a-form-item label="库存计算方式" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group v-decorator="['deduct_stock_type', { initialValue: 10, rules: [{ required: true }] }]">
<a-radio :value="10">下单减库存</a-radio>
<a-radio :value="20">付款减库存</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item
label="商品限购"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
extra="用于限制每人购买该商品的数量"
>
<a-radio-group
v-decorator="['is_restrict', { initialValue: 0, rules: [{ required: true }] }]"
@change="onForceUpdate()"
>
<a-radio :value="0">关闭</a-radio>
<a-radio :value="1">开启</a-radio>
</a-radio-group>
<div class="mt-10" v-if="form.getFieldValue('is_restrict')">
<a-form-item>
<span class="mr-10">总限购</span>
<a-input-number
:min="1"
:precision="0"
v-decorator="['restrict_total', { rules: [{ required: true, message: '请输入总限购数量' }] }]"
/>
<span class="ml-10">/</span>
</a-form-item>
<a-form-item>
<span class="mr-10">每单限购</span>
<a-input-number
:min="1"
:precision="0"
v-decorator="['restrict_single', { rules: [{ required: true, message: '请输入每单限购数量' }] }]"
/>
<span class="ml-10">/</span>
</a-form-item>
</div>
</a-form-item>
<a-form-item class="mt-20" :wrapperCol="{ span: wrapperCol.span, offset: labelCol.span }">
<a-button type="primary" @click="handleTabs(0)" style="margin-left: 20px">上一步</a-button>
<a-button type="primary" @click="handleTabs(2)" style="margin-left: 20px">下一步</a-button>
</a-form-item>
</div>
<!-- 商品详情 -->
<div class="tab-pane" v-show="tabKey == 2">
<a-form-item label="商品详情" :labelCol="labelCol" :wrapperCol="{ span: 16 }">
<Ueditor v-decorator="['content', { rules: [{ required: true, message: '商品详情不能为空' }] }]" />
</a-form-item>
<a-form-item class="mt-20" :wrapperCol="{ span: wrapperCol.span, offset: labelCol.span }">
<a-button type="primary" @click="handleTabs(1)" style="margin-left: 20px">上一步</a-button>
<a-button type="primary" @click="handleTabs(3)" style="margin-left: 20px">下一步</a-button>
</a-form-item>
</div>
<!-- 更多设置 -->
<div class="tab-pane" v-show="tabKey == 3">
<a-form-item
label="主图视频"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
extra="建议视频宽高比19:9,建议时长8-45秒"
>
<SelectVideo
:multiple="false"
:defaultList="formData.goods.video ? [formData.goods.video] : []"
v-decorator="['video_id']"
/>
</a-form-item>
<a-form-item
label="视频封面"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
extra="建议尺寸:750像素*750像素"
>
<SelectImage
:multiple="false"
:defaultList="formData.goods.videoCover ? [formData.goods.videoCover] : []"
v-decorator="['video_cover_id']"
/>
</a-form-item>
<a-form-item
label="商品卖点"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
extra="一句话简述,例如:此款商品美观大方 性价比较高 不容错过"
>
<a-input placeholder="请输入商品卖点" v-decorator="['selling_point']" />
</a-form-item>
<a-form-item label="服务与承诺" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-select
v-if="formData.serviceList"
mode="multiple"
v-decorator="['serviceIds']"
placeholder="请选择服务与承诺"
>
<a-select-option v-for="(item, index) in formData.serviceList" :key="index" :value="item.service_id">{{
item.name
}}</a-select-option>
</a-select>
<div class="form-item-help">
<router-link target="_blank" :to="{ path: '/goods/service/index' }">去新增</router-link>
<a href="javascript:;" @click="onReloadServiceList">刷新</a>
</div>
</a-form-item>
<a-form-item
label="初始销量"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
extra="用户端展示的销量 = 初始销量 + 实际销量"
>
<a-input-number v-decorator="['sales_initial', { initialValue: 0 }]" />
</a-form-item>
<div>
<a-divider orientation="left">销售区域</a-divider>
<a-form-item label="销售区域" :labelCol="labelCol" :wrapperCol="{ span: 15 }">
<a-table
v-show="ruleList.length"
class="table-rules"
:columns="columns"
:dataSource="ruleList"
:pagination="false"
bordered
>
<!-- 销售区域 -->
<template slot="region_text" slot-scope="text, item, index">
<p class="content">
<span v-for="(province, pidx) in text" :key="pidx">
<span>{{ province.name }}</span>
<template v-if="province.citys.length">
<span>(</span>
<span
class="city-name"
v-for="(city, cidx) in province.citys"
:key="cidx"
>{{ city.name }}{{ province.citys.length > cidx + 1 ? '、' : '' }}</span
>
<span>)</span>
</template>
<span>{{ ' ' }}</span>
</span>
</p>
<p class="operation">
<a href="javascript:void(0);" class="edit" @click="handleEdit(index, item)">编辑</a>
<a href="javascript:void(0);" class="delete" @click="handleDelete(index)">删除</a>
</p>
</template>
</a-table>
<a-button icon="environment" v-if="ruleList.length == 0" @click="handleAdd">点击添加销售区域</a-button>
</a-form-item>
</div>
<div v-show="$module('market-points')">
<a-divider orientation="left">积分设置</a-divider>
<a-form-item
label="积分赠送"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
extra="开启后用户购买此商品将获得积分"
>
<a-radio-group v-decorator="['is_points_gift', { initialValue: 1, rules: [{ required: true }] }]">
<a-radio :value="1">开启</a-radio>
<a-radio :value="0">关闭</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item
label="积分抵扣"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
extra="开启后用户购买此商品可以使用积分进行抵扣"
>
<a-radio-group v-decorator="['is_points_discount', { initialValue: 1, rules: [{ required: true }] }]">
<a-radio :value="1">开启</a-radio>
<a-radio :value="0">关闭</a-radio>
</a-radio-group>
</a-form-item>
</div>
<div v-show="$module('user-grade')">
<a-divider orientation="left">会员折扣设置</a-divider>
<a-form-item
label="会员折扣"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
extra="开启后会员折扣,会员购买此商品可以享受会员等级折扣价"
>
<a-radio-group
v-decorator="['is_enable_grade', { initialValue: 1, rules: [{ required: true }] }]"
@change="onForceUpdate(true)"
>
<a-radio :value="1">开启</a-radio>
<a-radio :value="0">关闭</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item
v-show="form.getFieldValue('is_enable_grade')"
label="会员折扣设置"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
>
<a-radio-group
v-decorator="['is_alone_grade', { initialValue: 0, rules: [{ required: true }] }]"
@change="onForceUpdate(true)"
>
<a-radio :value="0">默认等级折扣</a-radio>
<a-radio :value="1">单独设置折扣</a-radio>
</a-radio-group>
<!-- 会员等级列表 -->
<div v-show="form.getFieldValue('is_alone_grade')">
<a-form-item v-for="item in formData.userGradeList" :key="item.grade_id">
<InputNumberGroup
:addonBefore="item.name"
addonAfter="折"
:inputProps="{ min: 0, max: 9.9 }"
v-decorator="[
`alone_grade_equity[grade_id:${item.grade_id}]`,
{
initialValue: formData.defaultUserGradeValue[item.grade_id],
rules: [{ required: true, message: '折扣率不能为空' }],
},
]"
/>
</a-form-item>
</div>
<div class="form-item-help">
<p class="extra" v-if="form.getFieldValue('is_alone_grade')">
单独折扣折扣率范围0.0-9.9例如: 9.8代表98折0代表不折扣
</p>
<p class="extra" v-else>默认折扣默认为用户所属会员等级的折扣率</p>
</div>
</a-form-item>
</div>
<div v-show="$module('apps-dealer')">
<a-divider orientation="left">分销设置</a-divider>
<a-form-item label="分销佣金" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group
v-decorator="['is_ind_dealer', { initialValue: 0, rules: [{ required: true }] }]"
@change="onForceUpdate(true)"
>
<a-radio :value="0">系统默认</a-radio>
<a-radio :value="1">单独设置</a-radio>
</a-radio-group>
<div class="form-item-help">
<p class="extra">若使用分销功能必须在 [分销中心 - 分销设置] 中开启</p>
</div>
</a-form-item>
<a-form-item
v-show="form.getFieldValue('is_ind_dealer')"
label="分销佣金类型"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
>
<a-radio-group
v-decorator="['dealer_money_type', { initialValue: 10, rules: [{ required: true }] }]"
@change="onForceUpdate(true)"
>
<a-radio :value="10">百分比</a-radio>
<a-radio :value="20">固定金额</a-radio>
</a-radio-group>
<!-- 分销等级列表 -->
<a-form-item v-for="(item, index) in formData.dealer.levelList" :key="index">
<InputNumberGroup
:addonBefore="item.name"
:addonAfter="form.getFieldValue('dealer_money_type') == 10 ? '%' : '元'"
:inputProps="{ min: 0, precision: 2 }"
v-decorator="[item.value, { rules: [{ required: true, message: '佣金不能为空' }] }]"
/>
</a-form-item>
</a-form-item>
<a-form-item class="mt-20" :wrapperCol="{ span: wrapperCol.span, offset: labelCol.span }">
<a-button type="primary" @click="handleTabs(2)" style="margin-left: 20px">上一步</a-button>
</a-form-item>
</div>
</div>
</div>
</a-form>
<AreasModal ref="AreasModal" @handleSubmit="handleAreaSubmit" :loading="isBtnLoading"/>
</a-spin>
</a-card>
</a-modal>
</template>
<script>
import * as GoodsApi from '@/api/goods'
import { SelectImage, SelectVideo, Ueditor, InputNumberGroup } from '@/components'
import GoodsModel from '@/common/model/goods/Index'
import GoodsType from './GoodsType'
import MultiSpec from './MultiSpec'
import { isEmptyObject } from '@/utils/util'
import { AreasModal } from '@/components/Modal'
const defaultItem = {
key: 0,
region: [],
region_text: []
}
export default {
components: {
GoodsType,
SelectImage,
SelectVideo,
Ueditor,
InputNumberGroup,
MultiSpec,
AreasModal
},
props: {
//
},
data () {
return {
categoryList: [],
//
title: '',
// modal()
visible: false,
// modal() loading
confirmLoading: false,
//
tabKey: 0,
//
labelCol: { span: 3 },
//
wrapperCol: { span: 10 },
// loading
isLoading: false,
isBtnLoading: false,
//
form: this.$form.createForm(this),
// ID
goodsId: null,
//
formData: GoodsModel.formData,
checkList: [],
//
ruleList: [],
//
columns: [
{
title: '销售区域',
dataIndex: 'region_text',
width: '400px',
scopedSlots: { customRender: 'region_text' }
}
],
//
citysCount: null
}
},
methods: {
initData (goodsId) {
this.visible = true
// ID
this.goodsId = goodsId
// form
this.isLoading = true
GoodsModel.getFromData(this.goodsId).then(() => {
//
if (!isEmptyObject(this.form.getFieldsValue())) {
//
this.form.setFieldsValue(GoodsModel.getFieldsValue())
// (form-item)
this.$nextTick(() => {
this.form.setFieldsValue(GoodsModel.getFieldsValue2())
this.onForceUpdate()
// console.log(this.formData.formData.goods.skuList)
})
}
this.isLoading = false
})
},
//
onForceUpdate (bool = false) {
this.$forceUpdate()
// booltrue $forceUpdate,
// $forceUpdate, v-decoratorform.getFieldValue
bool &&
setTimeout(() => {
this.$forceUpdate()
}, 10)
},
// tab
handleTabs (key) {
this.tabKey = key
},
//
onReloadCategoryList () {
this.isLoading = true
GoodsModel.getCategoryList().then(() => {
this.isLoading = false
})
},
//
onReloadServiceList () {
this.isLoading = true
GoodsModel.getServiceList().then(() => {
this.isLoading = false
})
},
//
onReloadDeliveryList () {
this.isLoading = true
GoodsModel.getDeliveryList().then(() => {
this.isLoading = false
})
},
//
handleCancel () {
this.visible = false
this.form.resetFields()
},
//
handleSubmit (e) {
e.preventDefault()
//
const {
form: { validateFields },
ruleList
} = this
validateFields((errors, values) => {
// tab
if (errors) {
this.onTargetTabError(errors)
return false
}
//
if (values.spec_type === 20) {
const MultiSpec = this.$refs.MultiSpec
if (!MultiSpec.verifyForm()) {
this.tabKey = 1
return false
}
//
values.specData = MultiSpec.getFromSpecData()
}
values.rules = ruleList
// ID
values.categoryIds = values.categorys.map((item) => item.value)
delete values.categorys
// api
this.onFormSubmit(values)
return true
})
},
// tab
onTargetTabError (errors) {
// tabKey
//
const tabsFieldsMap = [
[
'goods_type',
'goods_name',
'categorys',
'imagesIds',
'delivery_id',
'is_ind_delivery_type',
'delivery_type',
'is_brand',
'is_in_store'
],
['spec_type', 'goods_price', 'is_restrict', 'restrict_total', 'restrict_single', 'cost_price'],
['content'],
['alone_grade_equity', 'first_money', 'second_money', 'third_money']
]
const field = Object.keys(errors).shift()
for (const key in tabsFieldsMap) {
if (tabsFieldsMap[key].indexOf(field) > -1) {
this.tabKey = parseInt(key)
break
}
}
},
// api
onFormSubmit (values) {
this.isLoading = true
this.isBtnLoading = true
GoodsApi.edit({ goodsId: this.goodsId, form: values })
.then((result) => {
//
this.$message.success(result.message, 1.5)
setTimeout(() => {
this.handleCancel()
}, 1500)
})
.catch(() => {
this.isBtnLoading = false
})
.finally(() => (this.isLoading = false))
},
//
handleAdd () {
const index = this.ruleList.length
const newItem = { ...defaultItem, key: index }
// id(id)
const excludedCityIds = this.getExcludedCityIds()
if (excludedCityIds.length === this.citysCount) {
this.$message.error('已选择了所有的区域', 0.8)
return false
}
//
this.handleAreasModal('add', index, newItem, excludedCityIds)
},
//
handleEdit (index, item) {
// id(id)
const excludedCityIds = this.getExcludedCityIds()
//
this.handleAreasModal('edit', index, item, excludedCityIds)
},
//
handleAreaSubmit (result) {
const {
custom: { scene, item }
} = result
item.region = result.selectedCityIds
item.region_text = result.selectedText
if (scene === 'add') {
this.ruleList.push(item)
}
},
// id(id)
getExcludedCityIds () {
const excludedCityIds = []
this.ruleList.forEach((item) => {
item.region.forEach((cityId) => {
excludedCityIds.push(cityId)
})
})
return excludedCityIds
},
//
handleAreasModal (scene, index, item, excludedCityIds) {
this.$refs.AreasModal.handle({ scene, index, item }, item.region, excludedCityIds)
},
//
handleDelete (index) {
const app = this
const modal = this.$confirm({
title: '您确定要删除该记录吗?',
onOk () {
app.ruleList.splice(index, 1)
modal.destroy()
}
})
}
}
}
</script>
Loading…
Cancel
Save