wangdong 6 months ago
commit 7386d1fc30
  1. 12
      src/api/goods/index.js
  2. 2
      src/common/model/goods/MultiSpec.js
  3. 9
      src/components/Modal/GoodsModal/GoodsModal.vue
  4. 6
      src/components/SelectGoods/SelectGoods.vue
  5. 90
      src/views/dataCenter/goods/Index.vue
  6. 6
      src/views/dataCenter/goods/modules/MultiSpec.vue
  7. 58
      src/views/dataCenter/goods/modules/Update.vue

@ -15,6 +15,7 @@ const api = {
addPrice:'/goods/addPrice',
exportData:'/goods/import',
jingPin:'/goods/jingpin',
batchAddPrice:'/goods/batchAddPrice',
}
// 列表记录
@ -143,6 +144,17 @@ export function addPrice (data) {
method: 'post',
data: data
})
}
/**
* 批量加价率
* @param {*} data
*/
export function batchAddPrice (data) {
return axios({
url: api.batchAddPrice,
method: 'post',
data: data
})
}/**
* 导出
* @param {*} data

@ -141,6 +141,7 @@ export default class MultiSpec {
const specGroupArr = this.specGroupArr()
// sku记录的规格属性集(生成笛卡尔积)
const cartesianList = cartesianProductOf(specGroupArr)
console.log(cartesianList,'specGroupArr')
// 合并单元格
const rowSpanArr = this.rowSpanArr(specGroupArr, cartesianList)
// 生成sku字段名
@ -148,6 +149,7 @@ export default class MultiSpec {
// 生成sku列表数据
this.buildSkuList(cartesianList)
// 返回多规格数据
console.log(this.multiSpecData.skuList)
return this.multiSpecData
}

@ -112,6 +112,8 @@ export default {
maxNum: PropTypes.integer.def(100),
//
defaultList: PropTypes.array.def([]),
channel: PropTypes.any,
source: PropTypes.any.def(0),
},
components: {
STable,
@ -128,11 +130,16 @@ export default {
//
searchForm: this.$form.createForm(this),
//
queryParam: {},
queryParam: {
is_sale: 1,
is_pool: 1,
},
// table
columns,
// Promise
loadData: (param) => {
this.queryParam.channel = this.channel
this.queryParam = this.source == 1 ? this.queryParam : {}
return GoodsApi.list({ ...param, ...this.queryParam }).then((response) => {
return response.data.list
})

@ -6,6 +6,8 @@
:multiple="multiple"
:maxNum="maxNum"
:defaultList="selectedItems"
:channel="channel"
:source="source"
@handleSubmit="handleSelectGoodsSubmit"
/>
</div>
@ -53,7 +55,9 @@ export default {
// , multiple
maxNum: PropTypes.integer.def(100),
//
defaultList: PropTypes.array.def([])
defaultList: PropTypes.array.def([]),
channel:PropTypes.any,
source: PropTypes.any.def(0),
},
data () {
return {

@ -178,6 +178,17 @@
<input placeholder="请输入加价利润率" @input="validateAmount" v-model="rate" class="input" type="text" />
</div>
</a-modal>
<a-modal
v-model:visible="batchPrice"
width="450px"
title="批量加价"
@ok="handleBatchPrice(selectedRowKeys, batchRate)"
>
<div class="fen" style="margin-top:-10px">
<span style="margin-right: 5px">加价利润率</span>
<input placeholder="请输入加价利润率" @input="validateBatchAmount" v-model="batchRate" class="input" type="text" />
</div>
</a-modal>
<a-modal
v-model:visible="saleVisible"
width="250px"
@ -252,6 +263,12 @@
@click="priceVisible = true"
>分类加价</a-button
>
<a-button
v-if="selectedRowKeys.length"
style="background-color: #67C23A; color: #fff; border: none; border-radius: 2px"
@click="batchPrice = true"
>批量加价</a-button
>
<a-button
style="background-color: #501212; color: #fff; border: none; border-radius: 2px"
@click="handleExport(selectedRowKeys)"
@ -346,7 +363,7 @@
<a @click="handleDelete([item.goods_id])">删除</a>
</div>
</s-table>
<Update ref="UpdateRef" />
<Update ref="UpdateRef" @refresh="refreshParentMethod" />
</a-card>
</template>
<script>
@ -364,26 +381,26 @@ Vue.use(DatePicker)
const columns = [
{
title: '商品ID',
width: '100px',
width: '90px',
dataIndex: 'goods_id',
sorter: true,
},
{
title: '商品',
dataIndex: 'goods_name',
width: '320px',
width: '300px',
scopedSlots: { customRender: 'goods_name' },
},
{
title: '成本价',
width: '120px',
width: '100px',
dataIndex: 'cost_price_min',
scopedSlots: { customRender: 'cost_price_min' },
sorter: true,
},
{
title: '前台价',
width: '100px',
width: '95px',
dataIndex: 'goods_price_min',
scopedSlots: { customRender: 'goods_price_min' },
sorter: true,
@ -396,11 +413,18 @@ const columns = [
},
{
title: '利润率',
width: '110px',
width: '95px',
dataIndex: 'profit_rate',
sorter: true,
scopedSlots: { customRender: 'profit_rate' },
},
{
title: '加价率',
width: '80px',
dataIndex: 'markup_rate',
sorter: true,
scopedSlots: { customRender: 'markup_rate' },
},
{
title: '库存',
width: '80px',
@ -416,14 +440,14 @@ const columns = [
},
{
title: '商品池',
width: '100px',
width: '95px',
dataIndex: 'is_pool',
sorter: true,
scopedSlots: { customRender: 'is_pool' },
},
{
title: '状态',
width: '60px',
width: '50px',
dataIndex: 'is_sale',
scopedSlots: { customRender: 'is_sale' },
},
@ -433,6 +457,12 @@ const columns = [
dataIndex: 'create_time',
sorter: true,
},
{
title: '最后更新时间',
width: '150px',
dataIndex: 'update_time',
sorter: true,
},
{
title: '操作',
dataIndex: 'action',
@ -503,6 +533,7 @@ export default {
saleVisible: false,
priceVisible: false,
jingPinVisible: false,
batchPrice:false,
specsType: [
{ name: '全部', val: '' },
{ name: '单规格', val: 10 },
@ -537,6 +568,7 @@ export default {
categoryIds: [],
categoryPriceIds: [],
rate: '',
batchRate:'',
pickerOptions: {
disabledDate(time) {
return time.getTime() > Date.now()
@ -723,16 +755,19 @@ export default {
this.$message.error('金额不能小于0')
this.rate = ''
} else if (row.startsWith('0')) {
this.money = ''
this.rate = ''
// 2
} else if (!/^\d+(\.\d{1,2})?$/.test(row)) {
this.$message.error('请输入数字!')
this.money = ''
this.rate = ''
} else if (row.split('.')[1] && row.split('.')[1].length > 2) {
this.$message.error('金额小数部分不能超过2位,请修改')
this.rate = ''
}
},
refreshParentMethod() {
this.handleRefresh(false)
},
//
async handleEdit(id) {
//
@ -905,6 +940,36 @@ export default {
this.isLoading = false
})
},
validateBatchAmount() {
const row = this.batchRate
// 0
if (row < 0) {
this.$message.error('金额不能小于0')
this.batchRate = ''
} else if (!/^\d+(\.\d{1,2})?$/.test(row)) {
this.$message.error('请输入数字!')
this.batchRate = ''
} else if (row.split('.')[1] && row.split('.')[1].length > 2) {
this.$message.error('金额小数部分不能超过2位,请修改')
this.batchRate = ''
}
},
handleBatchPrice(goodsIds, rate) {
if (!rate) {
this.$message.warn('请输入加价利润率', 1.5)
return
}
this.isLoading = true
GoodsApi.batchAddPrice({ goodsIds, rate })
.then((result) => {
this.batchPrice = false
this.$message.success(result.message, 1.5)
this.handleRefresh()
})
.finally((result) => {
this.isLoading = false
})
},
//
handleUpdateSales(goodsIds, is_sale) {
this.isLoading = true
@ -1033,7 +1098,6 @@ export default {
}
</style>
<style lang="less" scoped>
/deep/.ant-card-body {
padding: 22px 18px;
}
@ -1055,6 +1119,10 @@ export default {
/deep/.el-picker-panel__sidebar {
width: 85px;
}
.ant-table .actions a {
padding: 20px 4px;
margin: 0;
}
// tab
.tab-list {
margin-right: 20px;

@ -95,7 +95,7 @@
bordered
>
<template slot="select_goods" slot-scope="text, item">
<SelectGoods :multiple="false" @change="handleSelectGoods($event, item)" />
<SelectGoods :multiple="false" :source='source' :channel="channel" @change="handleSelectGoods($event, item)" />
</template>
<!-- 商品名称 -->
<!-- <template slot="goods_name" slot-scope="text, item">
@ -155,7 +155,9 @@ export default {
defaultSkuList: PropTypes.array.def([]),
// ()
isSpecLocked: PropTypes.bool.def(false),
checkList: PropTypes.array.def([])
checkList: PropTypes.array.def([]),
channel:PropTypes.any,
source: PropTypes.any.def(0),
},
data () {
return {

@ -152,7 +152,9 @@
:isSpecLocked="formData.goods.isSpecLocked"
:defaultSpecList="formData.goods.specList"
:defaultSkuList="formData.goods.skuList"
:channel="formData.goods.channel"
:checkList="checkList"
:source="1"
/>
</div>
<!-- 单规格的表单内容 -->
@ -170,7 +172,12 @@
/>
<span class="ml-10"></span>
</a-form-item>
<a-form-item label="成本价" :labelCol="labelCol" :wrapperCol="wrapperCol" extra="成本价仅用于商品页展示">
<a-form-item
label="成本价"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
extra="成本价仅用于商品页展示"
>
<a-input-number :min="0" :precision="2" v-decorator="['cost_price']" />
<span class="ml-10"></span>
</a-form-item>
@ -206,7 +213,6 @@
<span class="ml-10">千克 (Kg)</span>
</a-form-item>
</div>
</div>
<!-- 商品详情 -->
<div class="tab-pane" v-show="tabKey == 2">
@ -276,10 +282,7 @@
<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"
<span class="city-name" v-for="(city, cidx) in province.citys" :key="cidx"
>{{ city.name }}{{ province.citys.length > cidx + 1 ? '、' : '' }}</span
>
<span>)</span>
@ -293,7 +296,9 @@
</p>
</template>
</a-table>
<a-button icon="environment" v-if="ruleList.length == 0" @click="handleAdd">点击添加销售区域</a-button>
<a-button icon="environment" v-if="ruleList.length == 0" @click="handleAdd"
>点击添加销售区域</a-button
>
</a-form-item>
</div>
@ -439,7 +444,7 @@ import Region from '@/common/model/Region'
const defaultItem = {
key: 0,
region: [],
region_text: []
region_text: [],
}
export default {
name: 'Update',
@ -451,7 +456,7 @@ export default {
InputNumberGroup,
MultiSpec,
AreasModal,
Region
Region,
},
data() {
return {
@ -484,11 +489,11 @@ export default {
title: '销售区域',
dataIndex: 'region_text',
width: '400px',
scopedSlots: { customRender: 'region_text' }
}
scopedSlots: { customRender: 'region_text' },
},
],
//
citysCount: null
citysCount: null,
}
},
@ -499,6 +504,7 @@ export default {
methods: {
showEdit(goodsId) {
// ID
this.visible = true
this.goodsId = goodsId
this.initData()
this.getDataList()
@ -506,7 +512,6 @@ export default {
Region.getCitysCount().then((count) => {
this.citysCount = count
})
this.visible = true
},
//
handleCancel() {
@ -516,8 +521,10 @@ export default {
//
initData(goodsId) {
// form
GoodsModel.formData.goods = {}
this.isLoading = true
GoodsModel.getFromData(this.goodsId).then(() => {
this.formData.goods.goods_images=[]
//
if (!isEmptyObject(this.form.getFieldsValue())) {
//
@ -525,8 +532,10 @@ export default {
// (form-item)
this.$nextTick(() => {
this.form.setFieldsValue(GoodsModel.getFieldsValue2())
this.ruleList = this.formData.goods.rules ? this.formData.goods.rules : []
this.onForceUpdate()
this.$forceUpdate()
})
}
// this.ruleList = record.rule.map((item, index) => { return { ...item, key: index } })
@ -585,7 +594,7 @@ export default {
//
const {
form: { validateFields },
ruleList
ruleList,
} = this
validateFields((errors, values) => {
// tab
@ -609,7 +618,6 @@ export default {
// api
values.rules = ruleList
this.onFormSubmit(values)
this.handleCancel()
return true
})
},
@ -628,11 +636,11 @@ export default {
'is_ind_delivery_type',
'delivery_type',
'is_brand',
'is_in_store'
'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']
['alone_grade_equity', 'first_money', 'second_money', 'third_money'],
]
const field = Object.keys(errors).shift()
for (const key in tabsFieldsMap) {
@ -651,10 +659,10 @@ export default {
.then((result) => {
//
this.$message.success(result.message, 1.5)
// //
// setTimeout(() => {
// this.$router.push('./index')
// }, 1500)
this.$emit('refresh')
setTimeout(() => {
this.handleCancel()
}, 500)
})
.catch(() => {
this.isBtnLoading = false
@ -687,7 +695,7 @@ export default {
//
handleAreaSubmit(result) {
const {
custom: { scene, item }
custom: { scene, item },
} = result
item.region = result.selectedCityIds
item.region_text = result.selectedText
@ -721,10 +729,10 @@ export default {
onOk() {
app.ruleList.splice(index, 1)
modal.destroy()
}
},
})
}
}
},
},
}
</script>
<style lang="less" scoped>

Loading…
Cancel
Save