|
|
@@ -8,29 +8,22 @@
|
|
|
</view>
|
|
|
<text class="page-title">{{ isEditMode ? '编辑书籍' : '创建书籍' }}</text>
|
|
|
</view>
|
|
|
- <!-- 模式切换独立行 -->
|
|
|
- <view v-if="!isEditMode" class="mode-bar">
|
|
|
- <text class="mode-switch" @click="switchToInteractive">切换到交互模式</text>
|
|
|
- </view>
|
|
|
</view>
|
|
|
|
|
|
<!-- 主内容区 -->
|
|
|
<view class="main-content">
|
|
|
<view class="card">
|
|
|
|
|
|
- <!-- ========== 基础信息区 ========== -->
|
|
|
<view class="section">
|
|
|
- <text class="section-title">基础信息</text>
|
|
|
|
|
|
<!-- 内容描述 + 字数计数 -->
|
|
|
<view class="form-item">
|
|
|
- <text class="form-label">内容描述 *</text>
|
|
|
<view class="textarea-wrapper">
|
|
|
<textarea
|
|
|
v-model="newBook.description"
|
|
|
class="form-textarea"
|
|
|
:class="{ 'error': attemptedCreate && !newBook.description.trim() }"
|
|
|
- placeholder="描述这本书的内容、主题、写作目的..."
|
|
|
+ placeholder="例如:教小学生学习编程的入门书,内容生动有趣,通过趣味案例引导孩子入门Python..."
|
|
|
:maxlength="500"
|
|
|
@blur="detectScaleFromDesc"
|
|
|
/>
|
|
|
@@ -45,7 +38,6 @@
|
|
|
:disabled="isRecommending || !newBook.description.trim()"
|
|
|
@click="requestSmartRecommend"
|
|
|
>
|
|
|
- <text class="recommend-icon">{{ isRecommending ? '⏳' : '✨' }}</text>
|
|
|
<text class="recommend-text">{{ isRecommending ? '推荐中...' : 'AI自动优化描述' }}</text>
|
|
|
</button>
|
|
|
</view>
|
|
|
@@ -57,38 +49,22 @@
|
|
|
:disabled="!canCreateBook || creating"
|
|
|
@click="createNewBook"
|
|
|
>
|
|
|
- {{ creating ? '创建中...' : '🚀 创建书籍' }}
|
|
|
+ {{ creating ? '创建中...' : '创建书籍' }}
|
|
|
</button>
|
|
|
</view>
|
|
|
|
|
|
- <!-- 书籍规模 chip 选择 -->
|
|
|
+ <!-- 书籍规模 -->
|
|
|
<view class="form-item">
|
|
|
- <text class="form-label">书籍规模 *</text>
|
|
|
- <view class="scale-chips">
|
|
|
- <view
|
|
|
- v-for="scale in commonScales"
|
|
|
- :key="scale.value"
|
|
|
- :class="['chip', newBook.bookScale === scale.value ? 'active' : '']"
|
|
|
- @click="onScaleChipClick(scale.value)"
|
|
|
- >
|
|
|
- {{ scale.label }} {{ scale.audio }}
|
|
|
- </view>
|
|
|
+ <view class="selector-field" @click="showScalePicker">
|
|
|
+ <text class="selector-value">{{ getScaleDisplay(newBook.bookScale) || '请选择书籍规模' }}</text>
|
|
|
+ <text class="selector-arrow">▼</text>
|
|
|
</view>
|
|
|
- <picker
|
|
|
- mode="selector"
|
|
|
- :range="bookScales"
|
|
|
- range-key="label"
|
|
|
- :value="bookScales.findIndex(s => s.value === newBook.bookScale)"
|
|
|
- @change="onBookScaleChange"
|
|
|
- >
|
|
|
- <text class="more-scales">更多规模 ▼</text>
|
|
|
- </picker>
|
|
|
</view>
|
|
|
|
|
|
<!-- 预估信息(选择规模后显示在最上方) -->
|
|
|
<view v-if="!isEditMode && bookEstimate && bookEstimate.words && bookEstimate.audioMinutes" class="estimate-card">
|
|
|
<view class="estimate-row">
|
|
|
- <text class="estimate-label">📊 预估:</text>
|
|
|
+ <text class="estimate-label">预估:</text>
|
|
|
<text class="estimate-value">{{ bookEstimate.words.min }}~{{ bookEstimate.words.max }}字</text>
|
|
|
<text class="estimate-sep">|</text>
|
|
|
<text class="estimate-value">{{ bookEstimate.audioMinutes.min }}~{{ bookEstimate.audioMinutes.max }}分钟</text>
|
|
|
@@ -96,81 +72,51 @@
|
|
|
<text class="estimate-value">约{{ bookEstimate.estimatedChapters }}章</text>
|
|
|
</view>
|
|
|
<view v-if="quotaCheck" class="quota-row">
|
|
|
- <text v-if="quotaCheck.allowed" class="quota-ok">✅ 额度充足</text>
|
|
|
- <text v-else class="quota-warn">⚠️ {{ quotaCheck.reason }}</text>
|
|
|
+ <text v-if="quotaCheck.allowed" class="quota-ok">额度充足</text>
|
|
|
+ <text v-else class="quota-warn">{{ quotaCheck.reason }}</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
- <!-- ========== 读者配置区 ========== -->
|
|
|
<view class="section">
|
|
|
- <text class="section-title">读者配置</text>
|
|
|
-
|
|
|
<!-- 面向人群 -->
|
|
|
<view class="form-item">
|
|
|
- <text class="form-label">面向人群</text>
|
|
|
- <view class="chip-group">
|
|
|
- <view
|
|
|
- v-for="audience in audiences"
|
|
|
- :key="audience.value"
|
|
|
- :class="['chip', newBook.targetAudience === audience.value ? 'active' : '']"
|
|
|
- @click="newBook.targetAudience = audience.value; syncToDescription('面向人群', audience.value)"
|
|
|
- >
|
|
|
- <text class="chip-icon">{{ audience.icon }}</text>
|
|
|
- <text class="chip-text">{{ audience.label }}</text>
|
|
|
- </view>
|
|
|
+ <view class="selector-field" @click="showAudiencePicker">
|
|
|
+ <text class="selector-label">面向人群</text>
|
|
|
+ <text class="selector-value">{{ getAudienceLabel(newBook.targetAudience) || '请选择' }}</text>
|
|
|
+ <text class="selector-arrow">▼</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
<!-- 知识难度 -->
|
|
|
<view class="form-item">
|
|
|
- <text class="form-label">知识难度</text>
|
|
|
- <view class="chip-group">
|
|
|
- <view
|
|
|
- v-for="level in knowledgeLevels"
|
|
|
- :key="level.value"
|
|
|
- :class="['chip', newBook.knowledgeLevel === level.value ? 'active' : '']"
|
|
|
- @click="newBook.knowledgeLevel = level.value; syncToDescription('知识难度', level.value)"
|
|
|
- >
|
|
|
- <text class="chip-icon">{{ level.icon }}</text>
|
|
|
- <text class="chip-text">{{ level.label }}</text>
|
|
|
- </view>
|
|
|
+ <view class="selector-field" @click="showKnowledgeLevelPicker">
|
|
|
+ <text class="selector-label">知识难度</text>
|
|
|
+ <text class="selector-value">{{ getKnowledgeLevelLabel(newBook.knowledgeLevel) || '请选择' }}</text>
|
|
|
+ <text class="selector-arrow">▼</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
<!-- 书籍类型 -->
|
|
|
<view class="form-item">
|
|
|
- <text class="form-label">书籍类型</text>
|
|
|
- <view class="chip-group">
|
|
|
- <view
|
|
|
- v-for="bt in bookTypes"
|
|
|
- :key="bt.value"
|
|
|
- :class="['chip', newBook.bookType === bt.value ? 'active' : '']"
|
|
|
- @click="newBook.bookType = bt.value; syncToDescription('书籍类型', bt.value)"
|
|
|
- >
|
|
|
- <text class="chip-icon">{{ bt.icon }}</text>
|
|
|
- <text class="chip-text">{{ bt.label }}</text>
|
|
|
- </view>
|
|
|
+ <view class="selector-field" @click="showBookTypePicker">
|
|
|
+ <text class="selector-label">书籍类型</text>
|
|
|
+ <text class="selector-value">{{ getBookTypeLabel(newBook.bookType) || '请选择' }}</text>
|
|
|
+ <text class="selector-arrow">▼</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
<!-- 大纲层级 -->
|
|
|
<view class="form-item">
|
|
|
- <text class="form-label">大纲层级</text>
|
|
|
- <view class="chip-group">
|
|
|
- <view
|
|
|
- v-for="opt in outlineLevelOptions"
|
|
|
- :key="opt.value"
|
|
|
- :class="['chip', newBook.outlineLevel === opt.value ? 'active' : '']"
|
|
|
- @click="newBook.outlineLevel = opt.value; syncToDescription('大纲层级', opt.value)"
|
|
|
- >
|
|
|
- <text class="chip-text">{{ opt.label }}</text>
|
|
|
- </view>
|
|
|
+ <view class="selector-field" @click="showOutlineLevelPicker">
|
|
|
+ <text class="selector-label">大纲层级</text>
|
|
|
+ <text class="selector-value">{{ getOutlineLevelLabel(newBook.outlineLevel) || '请选择' }}</text>
|
|
|
+ <text class="selector-arrow">▼</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
- <!-- ========== 高级定制区(默认展开) ========== -->
|
|
|
+ <!-- ========== 高级定制区(默认折叠) ========== -->
|
|
|
<view class="section">
|
|
|
<view class="section-header" @click="showAdvancedOptions = !showAdvancedOptions">
|
|
|
<text class="section-title">高级定制</text>
|
|
|
@@ -180,65 +126,37 @@
|
|
|
<view v-if="showAdvancedOptions" class="section-content">
|
|
|
<!-- 快速模板 -->
|
|
|
<view class="form-item">
|
|
|
- <text class="form-label">📋 快速模板</text>
|
|
|
- <view class="template-grid">
|
|
|
- <view
|
|
|
- v-for="template in quickTemplates"
|
|
|
- :key="template.name"
|
|
|
- class="template-card"
|
|
|
- @click="applyTemplate(template)"
|
|
|
- >
|
|
|
- <text class="template-icon">{{ template.icon }}</text>
|
|
|
- <text class="template-name">{{ template.name }}</text>
|
|
|
- <text class="template-desc">{{ template.desc }}</text>
|
|
|
- </view>
|
|
|
+ <view class="selector-field" @click="showTemplatePicker">
|
|
|
+ <text class="selector-label">快速模板</text>
|
|
|
+ <text class="selector-value">{{ selectedTemplateName || '请选择模板(可选)' }}</text>
|
|
|
+ <text class="selector-arrow">▼</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
<!-- 写作风格 -->
|
|
|
<view class="form-item">
|
|
|
- <text class="form-label">写作风格</text>
|
|
|
- <view class="chip-group">
|
|
|
- <view
|
|
|
- v-for="style in styles"
|
|
|
- :key="style"
|
|
|
- :class="['chip', newBook.style === style ? 'active' : '']"
|
|
|
- @click="newBook.style = style; syncToDescription('写作风格', style)"
|
|
|
- >
|
|
|
- {{ style }}
|
|
|
- </view>
|
|
|
+ <view class="selector-field" @click="showStylePicker">
|
|
|
+ <text class="selector-label">写作风格</text>
|
|
|
+ <text class="selector-value">{{ newBook.style || '请选择' }}</text>
|
|
|
+ <text class="selector-arrow">▼</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
<!-- 行业领域 -->
|
|
|
<view class="form-item">
|
|
|
- <text class="form-label">行业领域</text>
|
|
|
- <view class="chip-group">
|
|
|
- <view
|
|
|
- v-for="industry in industries"
|
|
|
- :key="industry.value"
|
|
|
- :class="['chip', newBook.industry === industry.value ? 'active' : '']"
|
|
|
- @click="newBook.industry = industry.value; syncToDescription('行业领域', industry.label)"
|
|
|
- >
|
|
|
- <text class="chip-icon">{{ industry.icon }}</text>
|
|
|
- <text class="chip-text">{{ industry.label }}</text>
|
|
|
- </view>
|
|
|
+ <view class="selector-field" @click="showIndustryPicker">
|
|
|
+ <text class="selector-label">行业领域</text>
|
|
|
+ <text class="selector-value">{{ getIndustryLabel(newBook.industry) || '请选择' }}</text>
|
|
|
+ <text class="selector-arrow">▼</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
<!-- 特殊要求 (多选) -->
|
|
|
<view class="form-item">
|
|
|
- <text class="form-label">特殊要求</text>
|
|
|
- <view class="chip-group">
|
|
|
- <view
|
|
|
- v-for="feature in specialFeatures"
|
|
|
- :key="feature.value"
|
|
|
- :class="['chip', newBook.specialFeatures.includes(feature.value) ? 'active' : '']"
|
|
|
- @click="toggleSpecialFeature(feature.value)"
|
|
|
- >
|
|
|
- <text class="chip-icon">{{ feature.icon }}</text>
|
|
|
- <text class="chip-text">{{ feature.label }}</text>
|
|
|
- </view>
|
|
|
+ <view class="selector-field" @click="showSpecialFeaturesPicker">
|
|
|
+ <text class="selector-label">特殊要求</text>
|
|
|
+ <text class="selector-value">{{ getSpecialFeaturesLabel() || '请选择' }}</text>
|
|
|
+ <text class="selector-arrow">▼</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
@@ -250,7 +168,7 @@
|
|
|
{{ creating ? '保存中...' : '保存修改' }}
|
|
|
</button>
|
|
|
<template v-else>
|
|
|
- <button class="btn-cancel" @click="goBack">取消</button>
|
|
|
+ <button class="btn-primary" @click="switchToInteractive">切换到交互模式</button>
|
|
|
<button
|
|
|
class="btn-primary"
|
|
|
:disabled="!canCreateBook || creating"
|
|
|
@@ -275,7 +193,7 @@ const BASE_URL = getApiBaseUrl();
|
|
|
|
|
|
// 创建表单
|
|
|
const creating = ref(false);
|
|
|
-const showAdvancedOptions = ref(true); // 默认展开高级选项
|
|
|
+const showAdvancedOptions = ref(false); // 默认隐藏高级选项
|
|
|
const isRecommending = ref(false);
|
|
|
const attemptedCreate = ref(false);
|
|
|
const isEditMode = ref(false);
|
|
|
@@ -490,6 +408,132 @@ const canCreateBook = computed(() => {
|
|
|
return !!newBook.value.description.trim();
|
|
|
});
|
|
|
|
|
|
+// 选中模板名称
|
|
|
+const selectedTemplateName = ref('');
|
|
|
+
|
|
|
+// 辅助函数:获取标签
|
|
|
+function getAudienceLabel(val: string) {
|
|
|
+ return audiences.find(a => a.value === val)?.label || '';
|
|
|
+}
|
|
|
+function getKnowledgeLevelLabel(val: string) {
|
|
|
+ return knowledgeLevels.find(l => l.value === val)?.label || '';
|
|
|
+}
|
|
|
+function getBookTypeLabel(val: string) {
|
|
|
+ return bookTypes.find(b => b.value === val)?.label || '';
|
|
|
+}
|
|
|
+function getOutlineLevelLabel(val: string) {
|
|
|
+ return outlineLevelOptions.find(o => o.value === val)?.label || '';
|
|
|
+}
|
|
|
+function getIndustryLabel(val: string) {
|
|
|
+ return industries.find(i => i.value === val)?.label || '';
|
|
|
+}
|
|
|
+function getSpecialFeaturesLabel() {
|
|
|
+ if (!newBook.value.specialFeatures.length) return '';
|
|
|
+ return newBook.value.specialFeatures.join('、');
|
|
|
+}
|
|
|
+
|
|
|
+// 弹出选择器
|
|
|
+function showAudiencePicker() {
|
|
|
+ uni.showActionSheet({
|
|
|
+ itemList: audiences.map(a => a.label),
|
|
|
+ success: (res) => {
|
|
|
+ const selected = audiences[res.tapIndex];
|
|
|
+ newBook.value.targetAudience = selected.value;
|
|
|
+ syncToDescription('面向人群', selected.value);
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function showKnowledgeLevelPicker() {
|
|
|
+ uni.showActionSheet({
|
|
|
+ itemList: knowledgeLevels.map(l => l.label),
|
|
|
+ success: (res) => {
|
|
|
+ const selected = knowledgeLevels[res.tapIndex];
|
|
|
+ newBook.value.knowledgeLevel = selected.value;
|
|
|
+ syncToDescription('知识难度', selected.value);
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function showBookTypePicker() {
|
|
|
+ uni.showActionSheet({
|
|
|
+ itemList: bookTypes.map(b => b.label),
|
|
|
+ success: (res) => {
|
|
|
+ const selected = bookTypes[res.tapIndex];
|
|
|
+ newBook.value.bookType = selected.value;
|
|
|
+ syncToDescription('书籍类型', selected.value);
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function showOutlineLevelPicker() {
|
|
|
+ uni.showActionSheet({
|
|
|
+ itemList: outlineLevelOptions.map(o => o.label),
|
|
|
+ success: (res) => {
|
|
|
+ const selected = outlineLevelOptions[res.tapIndex];
|
|
|
+ newBook.value.outlineLevel = selected.value;
|
|
|
+ syncToDescription('大纲层级', selected.value);
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function showStylePicker() {
|
|
|
+ uni.showActionSheet({
|
|
|
+ itemList: styles,
|
|
|
+ success: (res) => {
|
|
|
+ const selected = styles[res.tapIndex];
|
|
|
+ newBook.value.style = selected;
|
|
|
+ syncToDescription('写作风格', selected);
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function showIndustryPicker() {
|
|
|
+ uni.showActionSheet({
|
|
|
+ itemList: industries.map(i => i.label),
|
|
|
+ success: (res) => {
|
|
|
+ const selected = industries[res.tapIndex];
|
|
|
+ newBook.value.industry = selected.value;
|
|
|
+ syncToDescription('行业领域', selected.label);
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function showSpecialFeaturesPicker() {
|
|
|
+ const selected = newBook.value.specialFeatures;
|
|
|
+ const items = specialFeatures.map(f => {
|
|
|
+ const checked = selected.includes(f.value);
|
|
|
+ return checked ? `${f.label} ✓` : f.label;
|
|
|
+ });
|
|
|
+ uni.showActionSheet({
|
|
|
+ itemList: items,
|
|
|
+ success: (res) => {
|
|
|
+ toggleSpecialFeature(specialFeatures[res.tapIndex].value);
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function showScalePicker() {
|
|
|
+ uni.showActionSheet({
|
|
|
+ itemList: bookScales.map(s => s.label),
|
|
|
+ success: (res) => {
|
|
|
+ const selected = bookScales[res.tapIndex];
|
|
|
+ onScaleChipClick(selected.value);
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function showTemplatePicker() {
|
|
|
+ const templateNames = quickTemplates.map(t => t.name);
|
|
|
+ uni.showActionSheet({
|
|
|
+ itemList: templateNames,
|
|
|
+ success: (res) => {
|
|
|
+ applyTemplate(quickTemplates[res.tapIndex]);
|
|
|
+ selectedTemplateName.value = quickTemplates[res.tapIndex].name;
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
// 切换特殊要求
|
|
|
function toggleSpecialFeature(feature: string) {
|
|
|
const features = newBook.value.specialFeatures;
|
|
|
@@ -513,6 +557,7 @@ function applyTemplate(template: typeof quickTemplates[0]) {
|
|
|
|
|
|
// 自动展开高级选项
|
|
|
showAdvancedOptions.value = true;
|
|
|
+ selectedTemplateName.value = template.name;
|
|
|
|
|
|
uni.showToast({
|
|
|
title: `已应用${template.name}模板`,
|
|
|
@@ -649,10 +694,6 @@ async function onBookScaleChange(e: any) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-function switchToInteractive() {
|
|
|
- uni.redirectTo({ url: '/pages/book-generator/interactive' });
|
|
|
-}
|
|
|
-
|
|
|
// AI 预览检测规模(用户未手动选时,描述失焦自动触发)
|
|
|
let detectTimer: any = null;
|
|
|
async function detectScaleFromDesc() {
|
|
|
@@ -680,6 +721,10 @@ async function detectScaleFromDesc() {
|
|
|
}, 800);
|
|
|
}
|
|
|
|
|
|
+function switchToInteractive() {
|
|
|
+ uni.navigateTo({ url: '/pages/book-generator/interactive' });
|
|
|
+}
|
|
|
+
|
|
|
function goBack() {
|
|
|
const pages = getCurrentPages();
|
|
|
if (pages.length > 1) {
|
|
|
@@ -840,12 +885,8 @@ onLoad(async (query: any) => {
|
|
|
text-align: center;
|
|
|
}
|
|
|
|
|
|
-/* 模式切换独立行 */
|
|
|
-.mode-bar { padding: 0 32rpx 16rpx 32rpx; }
|
|
|
-.mode-switch { display: flex; align-items: center; justify-content: center; width: 100%; height: 72rpx; background: linear-gradient(135deg, #4f46e5 0%, #6366f1 100%); color: #fff; border-radius: 12rpx; font-size: 26rpx; font-weight: 600; }
|
|
|
-
|
|
|
.main-content {
|
|
|
- padding-top: calc(88rpx + 16rpx + 72rpx + 16rpx + env(safe-area-inset-top));
|
|
|
+ padding-top: calc(88rpx + 16rpx + env(safe-area-inset-top));
|
|
|
}
|
|
|
|
|
|
.card {
|
|
|
@@ -864,6 +905,19 @@ onLoad(async (query: any) => {
|
|
|
.form-hint { font-size: 24rpx; color: #9ca3af; margin-bottom: 16rpx; display: block; }
|
|
|
.form-hint-small { font-size: 24rpx; color: #9ca3af; margin-bottom: 16rpx; display: block; }
|
|
|
|
|
|
+.selector-field {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 20rpx 24rpx;
|
|
|
+ background: #f3f4f6;
|
|
|
+ border-radius: 12rpx;
|
|
|
+ border: 2rpx solid #e5e7eb;
|
|
|
+}
|
|
|
+.selector-label { font-size: 28rpx; color: #374151; font-weight: 600; }
|
|
|
+.selector-value { font-size: 28rpx; color: #9ca3af; flex: 1; text-align: right; margin-right: 12rpx; }
|
|
|
+.selector-arrow { font-size: 22rpx; color: #9ca3af; }
|
|
|
+
|
|
|
.form-input {
|
|
|
width: 100%;
|
|
|
height: 88rpx;
|
|
|
@@ -896,38 +950,6 @@ onLoad(async (query: any) => {
|
|
|
color: #9ca3af;
|
|
|
}
|
|
|
|
|
|
-.chip-group { display: flex; flex-wrap: wrap; gap: 12rpx; }
|
|
|
-.chip {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- gap: 8rpx;
|
|
|
- padding: 12rpx 20rpx;
|
|
|
- background: #f3f4f6;
|
|
|
- border-radius: 24rpx;
|
|
|
- font-size: 24rpx;
|
|
|
- color: #4b5563;
|
|
|
- transition: all 0.2s;
|
|
|
-}
|
|
|
-.chip.active { background: linear-gradient(135deg, #4f46e5 0%, #6366f1 100%); color: white; }
|
|
|
-.chip-icon { font-size: 24rpx; }
|
|
|
-.chip-text { font-size: 24rpx; }
|
|
|
-
|
|
|
-.template-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16rpx; margin-top: 16rpx; }
|
|
|
-.template-card {
|
|
|
- padding: 20rpx;
|
|
|
- background: #f9fafb;
|
|
|
- border: 2rpx solid #e5e7eb;
|
|
|
- border-radius: 12rpx;
|
|
|
- text-align: center;
|
|
|
- transition: all 0.2s;
|
|
|
-}
|
|
|
-.template-card:active { transform: scale(1.02); box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.1); }
|
|
|
-.template-icon { font-size: 40rpx; display: block; margin-bottom: 8rpx; }
|
|
|
-.template-name { font-size: 26rpx; font-weight: 600; color: #1f2937; display: block; }
|
|
|
-.template-desc { font-size: 22rpx; color: #9ca3af; display: block; margin-top: 4rpx; }
|
|
|
-
|
|
|
-.scale-chips { display: flex; flex-wrap: wrap; gap: 12rpx; margin-bottom: 16rpx; }
|
|
|
-.more-scales { font-size: 24rpx; color: #6366f1; padding: 12rpx 0; }
|
|
|
|
|
|
/* 预估卡片 */
|
|
|
.estimate-card {
|
|
|
@@ -957,7 +979,6 @@ onLoad(async (query: any) => {
|
|
|
border: none;
|
|
|
}
|
|
|
.btn-smart-recommend[disabled] { opacity: 0.5; }
|
|
|
-.recommend-icon { font-size: 32rpx; }
|
|
|
.recommend-text { font-size: 28rpx; font-weight: 600; color: white; }
|
|
|
|
|
|
/* 快速创建按钮 */
|