refactor(admin): split GoodsView into dialog components; fix(GoodsView): raw member names, no primary badges, member price grid; feat(tag): 光板 maps to 不打印
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
<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>
|
||||
Reference in New Issue
Block a user