feat(category): 新增随形品类及相关设计功能

- 添加随形品类到数据库初始化脚本和类别列表
- 补充随形品类的视图类型,增加背面图支持
- 更新依赖,新增bcrypt库支持
- 前端子类型面板增加颜色选择逻辑,适配随形品类
- 类别状态管理中,simple类型也加载颜色数据,支持随形品类需求
- 设计生成页新增随形专属参数“形状描述”与自定义输入
- 提示文本根据随形品类调整,指导用户描述设计需求
- 生成设计时将形状描述拼接至最终prompt,提高表达准确性
- 样式优化,新增参数提示文字样式,增强界面友好度
- 初始化脚本清空历史数据,保证每次导入数据全新一致
This commit is contained in:
2026-03-27 19:59:22 +08:00
parent bb84747917
commit a1f56b1f8e
10 changed files with 406 additions and 310 deletions

View File

@@ -105,9 +105,21 @@
<path d="M8 12L11 15L16 9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
<p>点击下方按钮进入设计生成页面</p>
<p>选择颜色后点击下方按钮进入设计生成页面</p>
</div>
<div class="action-bar">
<!-- 随形等品类的颜色选择 -->
<template v-if="colors.length > 0">
<ColorPicker
v-model="selectedColor"
:colors="colors"
/>
<div v-if="selectedColor" class="action-bar">
<button class="btn-primary" @click="goToGenerate">
开始设计
</button>
</div>
</template>
<div v-else class="action-bar">
<button class="btn-primary" @click="goToGenerate">
开始设计
</button>

View File

@@ -60,8 +60,11 @@ export const useCategoryStore = defineStore('category', () => {
])
subTypes.value = subTypesData
colors.value = colorsData
} else {
// simple 类型也加载颜色(如随形品类需要选颜色)
const colorsData = await getColorsApi(category.id)
colors.value = colorsData
}
// simple 类型不需要加载额外数据
} finally {
loading.value = false
}

View File

@@ -53,6 +53,27 @@
<!-- 参数面板 -->
<div class="params-panel">
<!-- 形状描述仅随形品类显示 -->
<div v-if="isFreeform" class="param-group">
<label class="param-label">形状描述 <span class="param-hint">随形专属</span></label>
<div class="tag-list">
<span
v-for="opt in shapeOptions"
:key="opt"
class="tag-item"
:class="{ active: shapeDesc === opt }"
@click="selectTag('shapeDesc', opt)"
>{{ opt }}</span>
<el-input
v-model="customShape"
placeholder="自定义形状"
size="small"
class="custom-input"
@focus="shapeDesc = ''"
/>
</div>
</div>
<!-- 雕刻工艺 -->
<div class="param-group">
<label class="param-label">雕刻工艺</label>
@@ -292,6 +313,12 @@ const prompt = ref('')
const generating = computed(() => designStore.generating)
const currentDesign = computed(() => designStore.currentDesign)
// 随形专属:形状描述
const isFreeform = computed(() => categoryName.value.includes('随形'))
const shapeDesc = ref('')
const customShape = ref('')
const shapeOptions = ['原石随形', '水滴形', '不规则块状', '鹅卵石形', '片状', '柱状', '扁圆形']
// 新增参数状态
const carvingTechnique = ref('')
const designStyle = ref('')
@@ -310,11 +337,11 @@ const customScene = ref('')
// 自定义输入与标签的关联 Map
const tagRefs: Record<string, any> = {
carvingTechnique, designStyle, motif, sizeSpec, surfaceFinish, usageScene
carvingTechnique, designStyle, motif, sizeSpec, surfaceFinish, usageScene, shapeDesc
}
const customRefs: Record<string, any> = {
carvingTechnique: customCarving, designStyle: customStyle, motif: customMotif,
sizeSpec: customSize, surfaceFinish: customFinish, usageScene: customScene
sizeSpec: customSize, surfaceFinish: customFinish, usageScene: customScene, shapeDesc: customShape
}
// 选择标签时清除对应自定义输入
@@ -345,6 +372,7 @@ const sizeOptions = computed(() => {
if (name.includes('摆件')) return ['小(约8cm)', '中(约15cm)', '大(约25cm)']
if (name.includes('戒')) return ['戒面7号', '戒鞍12号', '戒鞍15号', '戒鞍18号']
if (name.includes('表带')) return ['宽18mm', '宽20mm', '宽22mm']
if (name.includes('随形')) return ['小(约60mm)', '中(约80mm)', '大(约100mm)', '特大(约150mm)']
return ['小', '中', '大']
})
@@ -357,6 +385,9 @@ const promptPlaceholder = computed(() => {
if (name.includes('珠') || name.includes('珠子')) {
return '请描述您想要的图案,如:回纹、云纹、简单素面...'
}
if (name.includes('随形')) {
return '请描述您想要的设计,如:原石随形雕刻山水、保留皮色的自然形态、利用石形雕刻动物...'
}
return '请描述您的设计需求...'
})
@@ -365,6 +396,17 @@ const goBack = () => {
router.push('/')
}
// 构建最终prompt随形品类时将形状描述拼接到前面
const _buildFinalPrompt = () => {
const userPrompt = prompt.value.trim()
if (!isFreeform.value) return userPrompt
const shape = shapeDesc.value || customShape.value
if (shape) {
return `形状:${shape}${userPrompt}`
}
return userPrompt
}
// 生成设计
const handleGenerate = async () => {
if (!categoryId.value) {
@@ -381,7 +423,7 @@ const handleGenerate = async () => {
category_id: categoryId.value,
sub_type_id: subTypeId.value || undefined,
color_id: colorId.value || undefined,
prompt: prompt.value.trim(),
prompt: _buildFinalPrompt(),
carving_technique: carvingTechnique.value || customCarving.value || undefined,
design_style: designStyle.value || customStyle.value || undefined,
motif: motif.value || customMotif.value || undefined,
@@ -589,6 +631,12 @@ $text-light: #999999;
color: $text-secondary;
margin-bottom: 8px;
letter-spacing: 1px;
.param-hint {
font-weight: 400;
font-size: 12px;
color: $secondary-color;
}
}
.tag-list {