emoticon_xcx_back/src/views/business/GoodsManager/Goodss/components/AddDialog.vue

666 lines
25 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!--
* @Descripttion: (商品/tb_goods 添加弹窗)
* @version: (1.0)
* @Author: (lwh)
* @Date: (2023-06-19)
* @LastEditors: (lwh)
* @LastEditTime: (2023-06-19)
-->
<template>
<el-dialog v-model="props.modelValue" title="添加商品信息" width="1200px" @closed="closeDialog" @open="openDialog">
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
<el-tab-pane label="基本信息" name="base">
<el-form ref="baseFormRef" :model="formData" :rules="rules">
<el-row :gutter="20">
<el-col v-if="userid == 1" :lg="12">
<el-form-item :label-width="labelWidth" label="店铺" prop="shopGuid">
<el-input v-model='formData.shopName' disabled type="text" placeholder='点击选择店铺'>
<template #append>
<div @click="handleChooseShop">选择</div>
</template>
</el-input>
</el-form-item>
</el-col>
<el-col :lg="12">
<el-form-item :label-width="labelWidth" label="商品类目" prop="shopGoodsCategoryGuid">
<el-cascader class="w100" :options="dataList"
:props="{ checkStrictly: true, value: 'shopGoodsCategoryGuid', label: 'shopGoodsCategoryName', emitPath: false }"
placeholder="请选择商品类目" clearable v-model="formData.shopGoodsCategoryGuid">
<template #default="{ node, data }">
<span>{{ data.shopGoodsCategoryName }}</span>
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
</template>
</el-cascader>
</el-form-item>
</el-col>
<el-col :lg="12">
<el-form-item :label-width="labelWidth" label="名称" prop="goodsName">
<el-input v-model="formData.goodsName" placeholder="请输入名称" />
</el-form-item>
</el-col>
<el-col :lg="12">
<el-form-item :label-width="labelWidth" label="编码" prop="goodsCoding">
<el-input v-model="formData.goodsCoding" placeholder="请输入编码" />
</el-form-item>
</el-col>
<el-col :lg="24">
<el-form-item :label-width="labelWidth" label="图片" prop="goodsPicture">
<UploadImage ref="uploadRef" v-model="formData.goodsPicture" :data=imgData :limit="10" :fileSize="5"
:drag="true" :isShowTip="false" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :lg="12">
<el-form-item :label-width="labelWidth" label="配送模板" prop="deliveryGuid">
<el-select v-model="formData.deliveryGuid" placeholder="请选择配送模板">
<el-option v-for="item in deliveryDataList" :key="item.deliveryId" :label="item.deliveryName"
:value="item.deliveryGuid" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :lg="24">
<el-form-item :label-width="labelWidth" label="上下架状态" prop="goodsShelfStatus">
<el-radio-group v-model="formData.goodsShelfStatus">
<el-radio v-for="item in shelf_status " :key="item.dictValue" :label="parseInt(item.dictValue)">{{
item.dictLabel }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :lg="12">
<el-form-item :label-width="labelWidth" label="排序" prop="goodsSort">
<el-input-number v-model.number="formData.goodsSort" controls-position="right" :min="0" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-tab-pane>
<el-tab-pane label="规格/库存" name="sku">
<el-form ref="skuFormRef" :model="formData" :rules="rules">
<el-row :gutter="20">
<el-col :lg="12">
<el-form-item :label-width="labelWidth" label="规格类型" prop="goodsSpecType">
<el-radio-group v-model="formData.goodsSpecType">
<el-radio v-for="item in spec_type " :key="item.dictValue" :label="parseInt(item.dictValue)"
@change="handleChangeSpecType">{{
item.dictLabel }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row v-if="formData.goodsSpecType == 1">
<el-col :lg="24">
<el-form-item :label-width="labelWidth" label="商品价格" prop="goodsPriceLowest">
<div style="display: block;">
<el-input-number v-model.number="formData.goodsPriceLowest" controls-position="right" :min="0.01"
:precision="2" />
<span style="margin-left: 10px;">元</span>
<div class="input-intro">商品的实际购买金额最低0.01</div>
</div>
</el-form-item>
</el-col>
<el-col :lg="24">
<el-form-item :label-width="labelWidth" label="划线价格" prop="goodsDashedPriceLowest">
<div style="display: block;">
<el-input-number v-model.number="formData.goodsDashedPriceLowest" controls-position="right" :min="0"
:precision="2" />
<span style="margin-left: 10px;">元</span>
<div class="input-intro">划线价仅用于商品页展示</div>
</div>
</el-form-item>
</el-col>
<el-col :lg="24">
<el-form-item :label-width="labelWidth" label="库存总量" prop="goodsTotalInventory">
<div style="display: block;">
<el-input-number v-model.number="formData.goodsTotalInventory" controls-position="right" :min="0" />
<span style="margin-left: 10px;">件</span>
<div class="input-intro">商品的实际库存数量为0时用户无法下单</div>
</div>
</el-form-item>
</el-col>
<!-- TODO: Sku单个 -->
<el-col :lg="24">
<el-form-item :label-width="labelWidth" label="商品重量" prop="">
<div style="display: block;">
<el-input-number v-model.number="formData.goodsWeight" controls-position="right" :min="0"
:precision="2" />
<span style="margin-left: 10px;">Kg</span>
<div class="input-intro">商品的实际重量,用于计算运费</div>
</div>
</el-form-item>
</el-col>
<el-col :lg="12">
<el-form-item :label-width="labelWidth + 20" label="库存计算方式" prop="goodsDeductStockType">
<el-radio-group v-model="formData.goodsDeductStockType">
<el-radio v-for="item in deduct_stock_type " :key="item.dictValue" :label="parseInt(item.dictValue)">{{
item.dictLabel }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row v-if="formData.goodsSpecType == 2">
<el-col :lg="24">
<MultiSpec v-model="formData" :isAdd="true"></MultiSpec>
</el-col>
</el-row>
</el-form>
</el-tab-pane>
<el-tab-pane label="商品详情" name="detail">
<el-form ref="detailFormRef" :model="formData" :rules="rules">
<el-row :gutter="20">
<el-col :lg="24">
<el-form-item :label-width="labelWidth" label="详情" prop="goodsDetails">
<div class="copy-btn-box">
<el-button @click="handleCopyRichText" class="copy-btn">获取富文本内容</el-button>
</div>
<editor v-model="formData.goodsDetails" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-tab-pane>
<el-tab-pane label="更多设置" name="more">
<el-form ref="moreFormRef" :model="formData" :rules="rules">
<el-row :gutter="20">
<el-col :lg="24">
<el-form-item :label-width="labelWidth" label="商品卖点" prop="goodsSellingPoint">
<el-input v-model="formData.goodsSellingPoint" placeholder="请输入商品卖点" />
<div class="input-intro">一句话简述,例如:此款商品美观大方 性价比较高 不容错过</div>
</el-form-item>
</el-col>
<el-col :lg="24">
<el-form-item :label-width="labelWidth" label="服务与承诺" prop="goodsServicesIds">
<el-select v-model="formData.goodsServicesIds" multiple placeholder="请选择服务与承诺">
<el-option v-for="item in goodsServicesDataList" :key="item.goodsServicesId"
:label="item.goodsServicesName" :value="item.goodsServicesId" />
</el-select>
</el-form-item>
</el-col>
<el-col :lg="12">
<el-form-item :label-width="labelWidth" label="主图视频" prop="goodsMainImageVideo">
<div style="display: block;">
<UploadFile v-model="formData.goodsMainImageVideo" :limit="1" :fileSize="100" :data=imgData
:isShowTip="false" />
<div class="input-intro">建议视频宽高比19:9建议时长8-45秒</div>
</div>
</el-form-item>
</el-col>
<el-col :lg="12">
<el-form-item :label-width="labelWidth" label="视频封面" prop="goodsVideoCover">
<div style="display: block;">
<UploadImage ref="uploadRef" v-model="formData.goodsVideoCover" :data=imgData :limit="1" :fileSize="5"
:drag="true" :isShowTip="false" />
<div class="input-intro">建议尺寸750像素*750像素</div>
</div>
</el-form-item>
</el-col>
<el-col :lg="12">
<el-form-item :label-width="labelWidth" label="初始销量" prop="goodsSalesInitial">
<div style="display: block;">
<el-input-number v-model.number="formData.goodsSalesInitial" controls-position="right" :min="0" />
<div class="input-intro">用户端展示的销量 = 初始销量 + 实际销量</div>
</div>
</el-form-item>
</el-col>
</el-row>
<el-divider content-position="left">
<div class="divider-title">积分设置</div>
</el-divider>
<el-row>
<el-col :lg="24">
<el-form-item :label-width="labelWidth" label="积分赠送" prop="goodsIsPointsGift">
<div style="display: block;">
<el-radio-group v-model="formData.goodsIsPointsGift">
<el-radio v-for="item in is_points_gift " :key="item.dictValue" :label="parseInt(item.dictValue)">{{
item.dictLabel }}</el-radio>
</el-radio-group>
<div class="input-intro">开启后用户购买此商品将获得积分</div>
</div>
</el-form-item>
</el-col>
<el-col :lg="24">
<el-form-item :label-width="labelWidth" label="积分抵扣" prop="goodsIsPointsDiscount">
<div style="display: block;">
<el-radio-group v-model="formData.goodsIsPointsDiscount">
<el-radio v-for="item in is_points_discount " :key="item.dictValue"
:label="parseInt(item.dictValue)">{{
item.dictLabel }}</el-radio>
</el-radio-group>
<div class="input-intro">开启后用户购买此商品可以使用积分进行抵扣</div>
</div>
</el-form-item>
</el-col>
<!-- <el-col :lg="12">
<el-form-item :label-width="labelWidth" label="积分抵扣设置(0默认抵扣 1单独设置抵扣)" prop="goodsIsAlonePointsDiscount">
<el-radio-group v-model="formData.goodsIsAlonePointsDiscount">
<el-radio v-for="item in is_alone_points_discount " :key="item.dictValue"
:label="parseInt(item.dictValue)">{{ item.dictLabel }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col> -->
<!-- <el-col :lg="12">
<el-form-item :label-width="labelWidth" label="单独设置积分抵扣的配置" prop="goodsPointsDiscountConfig">
<el-input v-model="formData.goodsPointsDiscountConfig" placeholder="请输入单独设置积分抵扣的配置" />
</el-form-item>
</el-col> -->
</el-row>
<el-divider content-position="left">
<div class="divider-title">会员折扣设置</div>
</el-divider>
<el-row>
<el-col :lg="24">
<el-form-item :label-width="labelWidth" label="会员折扣" prop="goodsIsEnableGrade">
<div style="display: block;">
<el-radio-group v-model="formData.goodsIsEnableGrade">
<el-radio v-for="item in is_enable_grade " :key="item.dictValue" :label="parseInt(item.dictValue)">{{
item.dictLabel }}</el-radio>
</el-radio-group>
<div class="input-intro">开启后会员折扣,会员购买此商品可以享受会员等级折扣价</div>
</div>
</el-form-item>
</el-col>
<el-col :lg="24">
<el-form-item label="会员折扣设置" prop="goodsIsAloneGrade">
<div style="display: block;">
<el-radio-group v-model="formData.goodsIsAloneGrade">
<el-radio v-for="item in is_alone_grade " :key="item.dictValue" :label="parseInt(item.dictValue)">{{
item.dictLabel }}</el-radio>
</el-radio-group>
<div class="input-intro">默认折扣:默认为用户所属会员等级的折扣率</div>
</div>
</el-form-item>
</el-col>
<!-- <el-col :lg="12">
<el-form-item :label-width="labelWidth" label="单独设置折扣的配置" prop="goodsAloneGradeEquity">
<el-input v-model="formData.goodsAloneGradeEquity" placeholder="请输入单独设置折扣的配置" />
</el-form-item>
</el-col> -->
</el-row>
</el-form>
</el-tab-pane>
</el-tabs>
<template #footer>
<div key="dialog-footer">
<el-button type="primary" @click="handleAddClick()" :loading="loadingStatus">添加</el-button>
<el-button @click="handleResetClick()">重置</el-button>
</div>
</template>
</el-dialog>
<!-- 选择店铺 -->
<ChooseShopDialog v-model="ChooseShopDialogVisible" :data="ChooseShopDialogRow" :done="handelAddShop">
</ChooseShopDialog>
</template>
<script setup>
import { reactive, ref, watch } from "vue";
import { ElMessage } from 'element-plus'
import modal from '@/plugins/modal.js'
import { addOrUpdateGoods } from '@/api/business/GoodsManager/Goodss/goods.js';
import { shopGoodsCategoryTreeList } from '@/api/business/GoodsManager/ShopGoodsCategorys/shopGoodsCategory.js';
import { deliveryList } from '@/api/business/LogisticsManage/Deliverys/delivery.js'
import { goodsServicesList } from '@/api/business/GoodsManager/GoodsServicess/goodsServices.js'
import useUserStore from '@/store/modules/user'
import ChooseShopDialog from '@/views/business/components/ChooseShopDialog.vue';
import MultiSpec from './MultiSpec/MultiSpec.vue';
// 打开弹窗时回调
const openDialog = async () => {
if (userid != 1) {
await getTreeList()
await getDeliveryList()
await getGoodsServicesList()
}
await getdeduct_stock_type()
await getspec_type()
await getis_points_gift()
await getis_points_discount()
await getis_alone_points_discount()
await getis_enable_grade()
await getis_alone_grade()
await getshelf_status()
}
// -业务参数
// 商品规格(1单规格 2多规格)
const spec_type = ref([]);
// 库存计算方式(1下单立减库存 2付款立减库存)字典选项列表
const deduct_stock_type = ref([]);
// 是否赠送积分(1开启 0关闭)字典选项列表
const is_points_gift = ref([]);
// 是否允许使用积分抵扣(1允许 0不允许)字典选项列表
const is_points_discount = ref([]);
// 积分抵扣设置(0默认抵扣 1单独设置抵扣)字典选项列表
const is_alone_points_discount = ref([]);
// 是否开启会员折扣(1开启 0关闭)字典选项列表
const is_enable_grade = ref([]);
// 会员折扣设置(0默认等级折扣 1单独设置折扣)字典选项列表
const is_alone_grade = ref([]);
// 上下架状态(1上架 2下架)字典选项列表
const shelf_status = ref([]);
// 标签选中
const activeName = ref('base')
// 选择店铺弹窗参数
const ChooseShopDialogVisible = ref(false);
const ChooseShopDialogRow = ref({});
// 当前用户id
const userid = useUserStore().userId
// 商品类目树形列表
const dataList = ref([])
// 配送模板列表
const deliveryDataList = ref([])
// 商品服务与承诺列表
const goodsServicesDataList = ref([])
// -业务方法
// 字典获取
async function getspec_type() {
await proxy.getDicts('spec_type').then((res) => {
spec_type.value = res.data
})
}
// 字典获取
async function getdeduct_stock_type() {
await proxy.getDicts('deduct_stock_type').then((res) => {
deduct_stock_type.value = res.data
})
}
// 字典获取
async function getis_points_gift() {
await proxy.getDicts('is_points_gift').then((res) => {
is_points_gift.value = res.data
})
}
// 字典获取
async function getis_points_discount() {
await proxy.getDicts('is_points_discount').then((res) => {
is_points_discount.value = res.data
})
}
// 字典获取
async function getis_alone_points_discount() {
await proxy.getDicts('is_alone_points_discount').then((res) => {
is_alone_points_discount.value = res.data
})
}
// 字典获取
async function getis_enable_grade() {
await proxy.getDicts('is_enable_grade').then((res) => {
is_enable_grade.value = res.data
})
}
// 字典获取
async function getis_alone_grade() {
await proxy.getDicts('is_alone_grade').then((res) => {
is_alone_grade.value = res.data
})
}
// 字典获取
async function getshelf_status() {
await proxy.getDicts('shelf_status').then((res) => {
shelf_status.value = res.data
})
}
// 点击标签栏
const handleClick = (tab, event) => {
}
/** 基础信息 */
// 打开选择店铺弹窗
const handleChooseShop = () => {
ChooseShopDialogVisible.value = true
ChooseShopDialogRow.value = formData
}
// 处理添加店铺后的回调
async function handelAddShop() {
await getTreeList()
await getDeliveryList()
await getGoodsServicesList()
}
// 获取商品类目树形列表
async function getTreeList() {
shopGoodsCategoryTreeList({ shopGuid: formData?.shopGuid }).then((res) => {
if (res.code == 200) {
dataList.value = res.data
}
})
}
// 获取配送模板列表
async function getDeliveryList() {
deliveryList({
pageNum: 1,
pageSize: 10000,
shopGuid: formData?.shopGuid
}).then((res) => {
if (res.code == 200) {
deliveryDataList.value = res.data.result
}
})
}
// 获取商品服务与承诺列表
async function getGoodsServicesList() {
goodsServicesList({
pageNum: 1,
pageSize: 10000,
shopGuid: formData?.shopGuid
}).then((res) => {
if (res.code == 200) {
goodsServicesDataList.value = res.data.result
goodsServicesDataList.value.map((item) => {
if (item.goodsServicesIsDefault === 1) {
formData.goodsServicesIds.push(item.goodsServicesId)
}
})
}
})
}
async function handleCopyRichText() {
let text = await navigator.clipboard.writeText(formData.goodsDetails);
modal.msgSuccess("富文本内容复制成功")
}
// 基础信息表单
const baseFormRef = ref();
// 商品规格表单
const skuFormRef = ref();
// 商品详情表单
const detailFormRef = ref();
// 更多设置表单
const moreFormRef = ref();
// -基础参数
const loadingStatus = ref(false)
const labelWidth = 100;
const { proxy } = getCurrentInstance()
const emits = defineEmits(["update:modelValue"]);
const formData = reactive({
goodsServicesIds: [],
goodsSpecList: [],
skuList: [],
goodsSpecType: 1,
goodsDeductStockType: 1,
goodsPriceLowest: 1.00,
goodsTotalInventory: 100,
goodsSalesInitial: 0,
goodsShelfStatus: 1,
goodsSort: 100,
goodsIsPointsGift: 0,
goodsIsPointsDiscount: 0,
goodsIsEnableGrade: 0,
goodsIsAloneGrade: 0,
});
const props = defineProps({
modelValue: Boolean,
done: Function,
});
const imgData = ref({
fileDir: "Goods"
})
// 验证
const rules = reactive({
shopGuid: [{ required: true, message: "店铺不能为空", trigger: "blur" }],
shopGoodsCategoryGuid: [{ required: true, message: "商品类目不能为空", trigger: "blur" }],
goodsSpecType: [{ required: true, message: "规格类型不能为空", trigger: "blur" }],
deliveryGuid: [{ required: true, message: "配送模板不能为空", trigger: "blur" }],
goodsName: [{ required: true, message: "名称不能为空", trigger: "blur" }],
goodsPicture: [{ required: true, message: "图片不能为空", trigger: "blur" }],
goodsPriceLowest: [{ required: true, message: "价格不能为空", trigger: "blur" }],
goodsTotalInventory: [{ required: true, message: "库存总量不能为空", trigger: "blur", type: "number" }],
goodsSalesInitial: [{ required: true, message: "初始销量不能为空", trigger: "blur", type: "number" }],
goodsDetails: [{ required: true, message: "详情不能为空", trigger: "blur" }],
goodsDeductStockType: [{ required: true, message: "库存计算方式不能为空", trigger: "blur", type: "number" }],
goodsIsPointsGift: [{ required: true, message: "是否赠送积分不能为空", trigger: "blur", type: "number" }],
goodsIsPointsDiscount: [{ required: true, message: "是否允许使用积分抵扣不能为空", trigger: "blur", type: "number" }],
goodsIsAlonePointsDiscount: [{ required: true, message: "积分抵扣设置不能为空", trigger: "blur", type: "number" }],
goodsIsEnableGrade: [{ required: true, message: "是否开启会员折扣不能为空", trigger: "blur", type: "number" }],
goodsIsAloneGrade: [{ required: true, message: "会员折扣设置不能为空", trigger: "blur", type: "number" }],
goodsShelfStatus: [{ required: true, message: "上下架状态不能为空", trigger: "blur", type: "number" }],
goodsSort: [{ required: true, message: "排序不能为空", trigger: "blur", type: "number" }],
});
// -基础方法
function getFormPromise(form) {
return new Promise((resolve) => {
form.validate((res) => {
resolve(res)
})
})
}
// 提交
const handleAddClick = async () => {
console.log(formData, '表单提交');
Promise.all([baseFormRef.value, skuFormRef.value, detailFormRef.value, moreFormRef.value,].map(getFormPromise)).then(async (res) => {
const validateResult = res.every((item) => !!item)
if (validateResult) {
loadingStatus.value = true
if (formData.goodsServicesIds.length !== 0) {
formData.goodsServicesIds = formData.goodsServicesIds.join(',')
}
if (formData.goodsSpecType = 2) {
if (formData.goodsSpecList.length == 0) {
modal.msgError('商品规格不能为空!')
return
}
}
const { code } = await addOrUpdateGoods(formData);
if (code == 200) {
modal.msgSuccess('添加成功')
closeDialog();
loadingStatus.value = false
}
} else {
modal.msgError('表单未通过验证!')
}
});
};
const closeDialog = () => {
// 基础信息
formData.shopName = ""
formData.shopGuid = null
dataList.value = []
deliveryDataList.value = []
activeName.value = 'base'
// 商品规格
formData.goodsSpecList = []
formData.skuList = []
handleResetClick([baseFormRef.value, skuFormRef.value, detailFormRef.value, moreFormRef.value,]);
props.done();
emits("update:modelValue", false);
};
const handleResetClick = async (formElList) => {
if (!formElList) return;
formElList.forEach(item => {
item.resetFields();
});
};
</script>
<style>
.divider-title {
font-size: 18px;
}
.input-intro {
color: #8c8c8c;
font-size: 12px;
}
.el-divider {
margin: 50px 0;
}
.copy-btn-box{
width: 100%;
display: flex;
justify-content: right;
margin-bottom: 15px;
}
</style>