144 lines
5.4 KiB
Vue
144 lines
5.4 KiB
Vue
<script setup lang="ts">
|
|
import { computed, ref } from 'vue'
|
|
import { ElMessage } from 'element-plus'
|
|
import { Delete, Plus } from '@element-plus/icons-vue'
|
|
import type { CustomMemberVariantInput } from '@/types'
|
|
import { productFamiliesApi } from '@/api/product-families'
|
|
import ImageUpload from '@/components/ImageUpload.vue'
|
|
|
|
const props = defineProps<{ modelValue: boolean; familyId: string | null }>()
|
|
const emit = defineEmits<{
|
|
(e: 'update:modelValue', v: boolean): void
|
|
(e: 'created'): void
|
|
}>()
|
|
|
|
const visible = computed({
|
|
get: () => props.modelValue,
|
|
set: (v) => emit('update:modelValue', v),
|
|
})
|
|
|
|
const submitting = ref(false)
|
|
const form = ref({
|
|
goodName: '',
|
|
goodImage: '',
|
|
logisticsLabel: '',
|
|
craftLabel: '',
|
|
skuCode: '',
|
|
warehouseLabel: '',
|
|
})
|
|
const variants = ref<CustomMemberVariantInput[]>([{ sku: '', sizeId: '', sizeName: '', colorId: '', colorName: '', price: 0 }])
|
|
|
|
function addVariant() {
|
|
variants.value.push({ sku: '', sizeId: '', sizeName: '', colorId: '', colorName: '', price: 0 })
|
|
}
|
|
function removeVariant(i: number) {
|
|
variants.value.splice(i, 1)
|
|
}
|
|
|
|
function reset() {
|
|
form.value = { goodName: '', goodImage: '', logisticsLabel: '', craftLabel: '', skuCode: '', warehouseLabel: '' }
|
|
variants.value = [{ sku: '', sizeId: '', sizeName: '', colorId: '', colorName: '', price: 0 }]
|
|
}
|
|
|
|
async function submit() {
|
|
if (!props.familyId) return
|
|
if (!form.value.goodName.trim() || !form.value.logisticsLabel.trim() || !form.value.craftLabel.trim()) {
|
|
ElMessage.warning('名称、物流、工艺为必填(价格矩阵归因依赖)')
|
|
return
|
|
}
|
|
const payload = variants.value.filter((v) => v.sku.trim())
|
|
if (!payload.length) {
|
|
ElMessage.warning('至少一条变体(含价格)')
|
|
return
|
|
}
|
|
submitting.value = true
|
|
try {
|
|
await productFamiliesApi.createCustomMember(props.familyId, {
|
|
goodName: form.value.goodName.trim(),
|
|
goodImage: form.value.goodImage || null,
|
|
logisticsLabel: form.value.logisticsLabel.trim(),
|
|
craftLabel: form.value.craftLabel.trim(),
|
|
skuCode: form.value.skuCode.trim() || null,
|
|
warehouseLabel: form.value.warehouseLabel.trim() || null,
|
|
variants: payload.map((v) => ({
|
|
sku: v.sku.trim(),
|
|
sizeId: v.sizeId?.trim() || null,
|
|
sizeName: v.sizeName?.trim() || null,
|
|
colorId: v.colorId?.trim() || null,
|
|
colorName: v.colorName?.trim() || null,
|
|
price: v.price,
|
|
})),
|
|
})
|
|
ElMessage.success('自定义成员已创建,族已重算')
|
|
visible.value = false
|
|
reset()
|
|
emit('created')
|
|
} catch (e: any) {
|
|
ElMessage.error(e?.response?.data?.message ?? '创建失败')
|
|
} finally {
|
|
submitting.value = false
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<el-dialog v-model="visible" title="新建自定义成员(人工商品)" width="720px" destroy-on-close @closed="reset">
|
|
<el-form label-width="90px">
|
|
<el-form-item label="商品名" required>
|
|
<el-input v-model="form.goodName" placeholder="如 美国(海运)180g纯棉T恤-DG001-烫画" />
|
|
</el-form-item>
|
|
<el-form-item label="主图">
|
|
<ImageUpload v-model="form.goodImage" label="上传图片" />
|
|
</el-form-item>
|
|
<el-row :gutter="12">
|
|
<el-col :span="12">
|
|
<el-form-item label="物流" required>
|
|
<el-input v-model="form.logisticsLabel" placeholder="如 海运(矩阵归因必填)" />
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="12">
|
|
<el-form-item label="工艺" required>
|
|
<el-input v-model="form.craftLabel" placeholder="如 烫画 / 双面印花(必填)" />
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
<el-row :gutter="12">
|
|
<el-col :span="12">
|
|
<el-form-item label="SKU 编码">
|
|
<el-input v-model="form.skuCode" placeholder="可留空" />
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="12">
|
|
<el-form-item label="仓库">
|
|
<el-input v-model="form.warehouseLabel" placeholder="可留空" />
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
<el-form-item label="变体价格">
|
|
<div class="cmd-variants">
|
|
<div v-for="(v, i) in variants" :key="i" class="cmd-variant-row">
|
|
<el-input v-model="v.sku" placeholder="SKU" style="width: 150px" />
|
|
<el-input v-model="v.sizeId" placeholder="尺码ID(size_S)" style="width: 120px" />
|
|
<el-input v-model="v.sizeName" placeholder="尺码名(S)" style="width: 80px" />
|
|
<el-input v-model="v.colorId" placeholder="颜色ID" style="width: 120px" />
|
|
<el-input v-model="v.colorName" placeholder="颜色名" style="width: 80px" />
|
|
<el-input-number v-model="v.price" :min="0.01" :precision="2" :controls="false" placeholder="价格" style="width: 100px" />
|
|
<el-button link type="danger" :icon="Delete" :disabled="variants.length <= 1" @click="removeVariant(i)" />
|
|
</div>
|
|
<el-button size="small" :icon="Plus" @click="addVariant">加一行</el-button>
|
|
</div>
|
|
</el-form-item>
|
|
</el-form>
|
|
<template #footer>
|
|
<el-button @click="visible = false">取消</el-button>
|
|
<el-button type="primary" :loading="submitting" @click="submit">创建并入族</el-button>
|
|
</template>
|
|
</el-dialog>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.cmd-variants { display: flex; flex-direction: column; gap: 6px; width: 100%; }
|
|
.cmd-variant-row { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
|
|
</style>
|