feat: 商品SKU编辑

feature/task1.0.0__0514__ch
向文可 3 years ago
parent 5e190cfd4f
commit 118a4affc9

@ -34,6 +34,27 @@ export const remove = (params) => {
}); });
}; };
export const searchSkus = (id) => {
return request({
url: '/mall/product/admin/productSku/list/' + id,
method: 'get',
});
};
export const createSkus = (id, data) => {
return request({
url: '/mall/product/admin/productSku/' + id,
method: 'post',
data,
});
};
export const createAndClearSkus = (id, data) => {
return request({
url: '/mall/product/admin/productSku/deleteAllAndAdd/' + id,
method: 'post',
data,
});
};
export const searchAttrs = (id) => { export const searchAttrs = (id) => {
return request({ return request({
url: '/mall/product/admin/productAttributeGroup/' + id, url: '/mall/product/admin/productAttributeGroup/' + id,
@ -54,6 +75,13 @@ export const updateAttrs = (data) => {
data, data,
}); });
}; };
export const updateAttrsSort = (data) => {
return request({
url: '/mall/product/admin/productAttributeGroup/updateSort',
method: 'put',
data,
});
};
export const removeAttrs = (params) => { export const removeAttrs = (params) => {
return request({ return request({
url: '/mall/product/admin/productAttributeGroup', url: '/mall/product/admin/productAttributeGroup',
@ -64,7 +92,7 @@ export const removeAttrs = (params) => {
export const searchAttrsValue = (id) => { export const searchAttrsValue = (id) => {
return request({ return request({
url: '/mall/product/admin/productAttribute/' + id, url: '/mall/product/admin/productAttribute/list/' + id,
method: 'get', method: 'get',
}); });
}; };

@ -21,13 +21,23 @@ const actions = {
} }
return res; return res;
}, },
sort: async (context, data) => {
let res = await api.updateAttrsSort(data);
if (res) {
ElMessage.success('保存成功');
} else {
ElMessage.error('保存失败');
}
return res;
},
remove: async (context, ids) => { remove: async (context, ids) => {
let res = null;
if (!ids.length) { if (!ids.length) {
ElMessage.warning('请选择要删除的数据'); ElMessage.warning('请选择要删除的数据');
} else { } else {
try { try {
await ElMessageBox.confirm('数据删除后无法恢复,确定要删除吗?', '危险操作'); await ElMessageBox.confirm('数据删除后无法恢复,确定要删除吗?', '危险操作');
let res = await api.removeAttrs({ id: ids.join(',') }); res = await api.removeAttrs({ id: ids.join(',') });
if (res) { if (res) {
ElMessage.success('删除成功'); ElMessage.success('删除成功');
} else { } else {
@ -37,6 +47,7 @@ const actions = {
console.info('取消删除', e); console.info('取消删除', e);
} }
} }
return res;
}, },
}; };
export default { export default {

@ -22,12 +22,13 @@ const actions = {
return res; return res;
}, },
remove: async (context, ids) => { remove: async (context, ids) => {
let res = null;
if (!ids.length) { if (!ids.length) {
ElMessage.warning('请选择要删除的数据'); ElMessage.warning('请选择要删除的数据');
} else { } else {
try { try {
await ElMessageBox.confirm('数据删除后无法恢复,确定要删除吗?', '危险操作'); await ElMessageBox.confirm('数据删除后无法恢复,确定要删除吗?', '危险操作');
let res = await api.removeAttrsValue({ id: ids.join(',') }); res = await api.removeAttrsValue({ id: ids.join(',') });
if (res) { if (res) {
ElMessage.success('删除成功'); ElMessage.success('删除成功');
} else { } else {
@ -37,6 +38,7 @@ const actions = {
console.info('取消删除', e); console.info('取消删除', e);
} }
} }
return res;
}, },
}; };
export default { export default {

@ -0,0 +1,30 @@
import * as api from '@/api/sales/product.js';
import { ElMessage } from '@/plugins/element-plus';
const state = () => ({});
const getters = {};
const mutations = {};
const actions = {
search: async (context, id) => {
let res = await api.searchSkus(id);
if (!res) {
ElMessage.error('查询商品SKU列表失败');
}
return res || [];
},
save: async (context, { id, data }) => {
let save = data.every((item) => !item.id) ? api.createAndClearSkus : api.createSkus;
let res = await save(id, data);
if (res) {
ElMessage.success('保存成功');
} else {
ElMessage.error('保存失败');
}
return res;
},
};
export default {
state,
getters,
mutations,
actions,
};

@ -49,19 +49,38 @@
:label="sku.name" :label="sku.name"
:prop="sku.id + ''" :prop="sku.id + ''"
/> />
<el-table-column align="center" header-align="center" label="售价(元)" prop="sales" width="160px"> <el-table-column align="center" header-align="center" label="售价(元)" prop="sellPrice" width="160px">
<template #default="{ row }"> <template #default="{ row }">
<el-input-number v-model="row.sales" /> <el-input-number v-model="row.sellPrice" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" header-align="center" label="商品库存" prop="inventory" width="160px"> <el-table-column align="center" header-align="center" label="商品库存" prop="stock" width="160px">
<template #default="{ row }"> <template #default="{ row }">
<el-input-number v-model="row.inventory" /> <span v-if="row.id">{{ row.stock }}</span>
<el-input-number v-else v-model="row.stock" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" header-align="center" label="成本价(元)" prop="price" width="160px"> <el-table-column align="center" header-align="center" label="增减库存" prop="stockChange" width="160px">
<template #default="{ row }"> <template #default="{ row }">
<el-input-number v-model="row.price" /> <el-input-number v-model="row.stockChange" @change="handleStockChange(row)" />
</template>
</el-table-column>
<el-table-column
align="center"
header-align="center"
label="改后库存"
prop="stockAfter"
width="160px"
/>
<el-table-column
align="center"
header-align="center"
label="成本价(元)"
prop="costPrice"
width="160px"
>
<template #default="{ row }">
<el-input-number v-model="row.costPrice" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" header-align="center" label="库存预警值" prop="warn" width="160px"> <el-table-column align="center" header-align="center" label="库存预警值" prop="warn" width="160px">
@ -70,15 +89,17 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" header-align="center" label="SKU编号" min-width="100px" prop="id" /> <el-table-column align="center" header-align="center" label="SKU编号" min-width="100px" prop="id" />
<el-table-column align="center" header-align="center" label="启用" prop="enabled" width="80px"> <el-table-column align="center" header-align="center" label="启用" prop="isEnable" width="80px">
<template #default="{ row }"> <template #default="{ row }">
<el-switch v-model="row.enabled" /> <el-switch v-model="row.isEnable" />
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</el-scrollbar> </el-scrollbar>
<div class="step-footer"> <div class="step-footer">
<el-button type="primary" @click="handleSave"></el-button> <el-button type="text" @click="handleBack"></el-button>
<el-button plain type="primary" @click="handleSave(false)"></el-button>
<el-button type="primary" @click="handleSave(true)"></el-button>
</div> </div>
</div> </div>
</template> </template>
@ -109,7 +130,17 @@
const id = route.params.id; const id = route.params.id;
if (id && id !== state.form.id) { if (id && id !== state.form.id) {
state.form.id = id; state.form.id = id;
let res = await store.dispatch('productAttrsGroup/search', id); let res = await store.dispatch('productSkus/search', id);
state.form.skuInfos = res.map((item) => {
return {
...item,
name: item.name?.split(',') || [],
attributeSymbolList: item.attributeSymbolList?.split(',') || [],
stockChange: 0,
stockAfter: item.stock,
};
});
res = await store.dispatch('productAttrsGroup/search', id);
let arr = []; let arr = [];
res.forEach((item) => { res.forEach((item) => {
arr.push( arr.push(
@ -134,7 +165,8 @@
attrsGroup.values?.forEach((value) => { attrsGroup.values?.forEach((value) => {
let temp = _.cloneDeep(row); let temp = _.cloneDeep(row);
temp[attrsGroup.id + ''] = value.name; temp[attrsGroup.id + ''] = value.name;
temp.groups.push(value.id); temp.attributeSymbolList.push(value.symbol);
temp.name.push(value.name);
res.push(temp); res.push(temp);
}); });
}); });
@ -143,29 +175,42 @@
} }
return res; return res;
}, },
[{ sales: 0, inventory: 0, price: 0, warn: 100, groups: [] }] [
{
sellPrice: 0,
stock: 0,
stockChange: 0,
costPrice: 0,
warn: 100,
isEnable: false,
name: [],
attributeSymbolList: [],
},
]
) )
.map((info) => { .map((info) => {
let row = old.find((item) => item.groups.sort().join() === info.groups.sort().join()); let row = old.find(
(item) =>
item.attributeSymbolList.sort().join() === info.attributeSymbolList.sort().join()
);
if (row) { if (row) {
Object.assign(info, row); Object.assign(info, row);
} }
return info; return info;
}); });
console.info(state.form.skuInfos, old);
}, },
{ deep: true } { deep: true }
); );
const handleAddSku = async () => { const handleAddSku = async () => {
if (state.skuName) { if (state.skuName) {
let res = await store.dispatch('productAttrsGroup', { let res = await store.dispatch('productAttrsGroup/save', {
name: state.skuName, name: state.skuName,
productId: route.params.id, productId: route.params.id,
sort: state.form.attrsGroupList.length, sort: state.form.attrsGroupList.length,
}); });
if (res) { if (res) {
state.form.skuInfos = []; state.form.skuInfos = [];
state.form.attrsGroupList.push({ name: state.skuName, values: [] }); state.form.attrsGroupList.push({ id: res, name: state.skuName, values: [] });
state.skuName = null; state.skuName = null;
} else { } else {
proxy.$message.error('添加属性规格失败'); proxy.$message.error('添加属性规格失败');
@ -178,15 +223,17 @@
let res = await store.dispatch('productAttrsGroup/remove', [state.form.attrsGroupList[index].id]); let res = await store.dispatch('productAttrsGroup/remove', [state.form.attrsGroupList[index].id]);
if (res) { if (res) {
state.form.attrsGroupList.splice(index, 1); state.form.attrsGroupList.splice(index, 1);
proxy.$message.success('删除成功');
} else {
proxy.$message.error('删除失败');
} }
}; };
const handleMove = (oldIndex, newIndex) => { const handleMove = async (oldSort, currentSort) => {
let temp = state.form.attrsGroupList[oldIndex]; let temp = state.form.attrsGroupList[oldSort];
state.form.attrsGroupList[oldIndex] = state.form.attrsGroupList[newIndex]; let res = await store.dispatch('productAttrsGroup/sort', { id: temp.id, oldSort, currentSort });
state.form.attrsGroupList[newIndex] = temp; if (res) {
state.form.attrsGroupList[oldSort] = state.form.attrsGroupList[currentSort];
state.form.attrsGroupList[currentSort] = temp;
} else {
proxy.$message.error('移动失败');
}
}; };
const handleAddValue = async (sku, index) => { const handleAddValue = async (sku, index) => {
let value = state.skuValue[index]; let value = state.skuValue[index];
@ -211,36 +258,49 @@
let res = await store.dispatch('productAttrsValue/remove', [sku.values[index].id]); let res = await store.dispatch('productAttrsValue/remove', [sku.values[index].id]);
if (res) { if (res) {
sku.values.splice(index, 1); sku.values.splice(index, 1);
proxy.$message.success('删除成功');
} else {
proxy.$message.error('删除失败');
} }
}; };
const handleSave = async () => { const handleStockChange = (row) => {
row.stockAfter = row.stock + row.stockChange;
};
const handleBack = () => {
router.push({
name: 'UpdateProduct',
params: {
id: route.params.id,
step: 1,
},
});
};
const handleSave = async (enable) => {
state.loading = true; state.loading = true;
try { if (state.form.skuInfos.length) {
await state.refsForm.validate(); let data = _.cloneDeep(state.form.skuInfos).map((item) => {
router.push({ return {
name: 'UpdateProduct', ...item,
params: { name: item.name.join(','),
id: route.params.id || state.form.id, attributeSymbolList: item.attributeSymbolList.join(','),
step: 2, };
},
}); });
} catch (e) { await store.dispatch('productSkus/save', { id: route.params.id, data });
console.info('取消保存', e); if (enable) {
//
}
await handleLoad();
} }
state.loading = false; state.loading = false;
}; };
return { return {
...toRefs(state), ...toRefs(state),
handleBack,
handleSave, handleSave,
handleAddSku, handleAddSku,
handleDelSku, handleDelSku,
handleMove, handleMove,
handleAddValue, handleAddValue,
handleDelValue, handleDelValue,
handleStockChange,
}; };
}, },
}); });
@ -251,6 +311,7 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow: hidden; overflow: hidden;
width: 100%;
.step-content { .step-content {
flex: 1; flex: 1;
overflow: auto; overflow: auto;

@ -22,6 +22,7 @@ export default (configEnv) => {
'/api': { '/api': {
// target: 'http://192.168.10.109:8090/', // 显雨 // target: 'http://192.168.10.109:8090/', // 显雨
// target: 'http://192.168.10.251:8090', // 高玉 // target: 'http://192.168.10.251:8090', // 高玉
// target: 'http://192.168.10.67:8090', // 罗战
target: 'https://k8s-horse-gateway.mashibing.cn/', // 测试地址 target: 'https://k8s-horse-gateway.mashibing.cn/', // 测试地址
// target: 'https://gateway.mashibing.cn', // 预发地址 // target: 'https://gateway.mashibing.cn', // 预发地址
// target: 'https://gateway.mashibing.com', // 生产环境 // target: 'https://gateway.mashibing.com', // 生产环境

Loading…
Cancel
Save