124 lines
5.1 KiB
Vue
124 lines
5.1 KiB
Vue
<script setup lang="ts">
|
|
import { computed, ref, watch } from 'vue'
|
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
import { Plus } from '@element-plus/icons-vue'
|
|
import type { CategoryTree, Country, Tag } from '@/types'
|
|
import { goodsApi } from '@/api/goods'
|
|
import { countriesApi } from '@/api/countries'
|
|
import { buildCascader } from '@/utils/category-tree'
|
|
|
|
const props = defineProps<{
|
|
visible: boolean
|
|
countries: Country[]
|
|
categories: CategoryTree[]
|
|
/** 分组后的标签选项 {id,label,tags} */
|
|
tagOptionGroups: Array<{ id: string; label: string; tags: Tag[] }>
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
(e: 'update:visible', v: boolean): void
|
|
(e: 'created', good: any): void
|
|
/** 快捷新建国家后由父级刷新字典 */
|
|
(e: 'dictionaries-changed'): void
|
|
}>()
|
|
|
|
const loading = ref(false)
|
|
const form = ref({
|
|
goodName: '', goodImage: '', goodPrice: '', countryId: '',
|
|
cascaderCategory: [] as string[], categoryId: '', tagIds: [] as string[],
|
|
goodPriority: 0,
|
|
})
|
|
|
|
watch(() => props.visible, (v) => {
|
|
if (v) {
|
|
form.value = {
|
|
goodName: '', goodImage: '', goodPrice: '', countryId: '',
|
|
cascaderCategory: [], categoryId: '', tagIds: [], goodPriority: 0,
|
|
}
|
|
}
|
|
})
|
|
|
|
const categoryCascader = computed(() => buildCascader(props.categories))
|
|
|
|
function onCascaderChange(val: any) {
|
|
const path = Array.isArray(val) ? val : []
|
|
form.value.categoryId = path.length ? String(path[path.length - 1]) : ''
|
|
}
|
|
|
|
async function quickCreateCountry() {
|
|
try {
|
|
const { value } = await ElMessageBox.prompt('请输入国家名称', '新增国家', {
|
|
confirmButtonText: '新增', cancelButtonText: '取消', inputPlaceholder: '国家名称',
|
|
})
|
|
if (!value.trim()) return
|
|
const created = await countriesApi.createCountry({ countryName: value.trim() } as any)
|
|
emit('dictionaries-changed')
|
|
if (created?.id) form.value.countryId = created.id
|
|
ElMessage.success('已创建并选中')
|
|
} catch {}
|
|
}
|
|
|
|
async function handleSubmit() {
|
|
if (!form.value.goodName.trim()) { ElMessage.warning('请输入商品名称'); return }
|
|
if (!form.value.countryId) { ElMessage.warning('请选择国家'); return }
|
|
if (!form.value.categoryId) { ElMessage.warning('请选择分类'); return }
|
|
loading.value = true
|
|
try {
|
|
const created = await goodsApi.createCustomGood({
|
|
goodName: form.value.goodName.trim(),
|
|
goodImage: form.value.goodImage || undefined,
|
|
goodPrice: form.value.goodPrice || null,
|
|
countryId: Number(form.value.countryId),
|
|
categoryId: Number(form.value.categoryId),
|
|
tagIds: form.value.tagIds.map(Number),
|
|
goodPriority: form.value.goodPriority,
|
|
detail: {},
|
|
})
|
|
ElMessage.success('自定义商品已创建,可继续完善详情、尺码、包装和 SKU')
|
|
emit('update:visible', false)
|
|
emit('created', created)
|
|
} catch (error: any) {
|
|
ElMessage.error(error?.response?.data?.message || '自定义商品创建失败')
|
|
} finally { loading.value = false }
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<el-dialog :model-value="visible" title="新增自定义商品" width="620px" destroy-on-close @update:model-value="emit('update:visible', $event)">
|
|
<el-alert
|
|
title="自定义商品不关联 SDS 原产品,名称、图片、价格、详情、尺码、包装和 SKU 均可维护。"
|
|
type="info"
|
|
:closable="false"
|
|
style="margin-bottom:16px"
|
|
/>
|
|
<el-form label-width="90px">
|
|
<el-form-item label="商品名称" required><el-input v-model="form.goodName" /></el-form-item>
|
|
<el-form-item label="商品图片"><ImageUpload v-model="form.goodImage" label="上传图片" /></el-form-item>
|
|
<el-form-item label="基础价格"><el-input v-model="form.goodPrice" placeholder="例如 28.00" /></el-form-item>
|
|
<el-form-item label="国家" required>
|
|
<div class="select-inline">
|
|
<el-select v-model="form.countryId" filterable placeholder="请选择国家" style="width:100%">
|
|
<el-option v-for="c in countries" :key="c.id" :label="c.countryName" :value="c.id" />
|
|
</el-select>
|
|
<el-button text :icon="Plus" @click="quickCreateCountry" />
|
|
</div>
|
|
</el-form-item>
|
|
<el-form-item label="分类" required>
|
|
<el-cascader v-model="form.cascaderCategory" :options="categoryCascader as any" :props="{ checkStrictly: true }" placeholder="请选择分类" style="width:100%" @change="onCascaderChange" />
|
|
</el-form-item>
|
|
<el-form-item label="标签">
|
|
<el-select v-model="form.tagIds" multiple filterable placeholder="请选择标签" style="width:100%">
|
|
<el-option-group v-for="g in tagOptionGroups" :key="g.id" :label="g.label">
|
|
<el-option v-for="t in g.tags" :key="t.id" :label="t.tagName" :value="t.id" />
|
|
</el-option-group>
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item label="优先级"><el-input-number v-model="form.goodPriority" :min="0" /></el-form-item>
|
|
</el-form>
|
|
<template #footer>
|
|
<el-button @click="emit('update:visible', false)">取消</el-button>
|
|
<el-button type="primary" :loading="loading" @click="handleSubmit">创建并完善详情</el-button>
|
|
</template>
|
|
</el-dialog>
|
|
</template>
|