PLAN_SCHEME_GUIDE.md
12.5 KB
录入计划书方案开发规范
版本: v1.0 更新日期: 2026-01-31 用途: 指导新增计划书方案(SchemeC、SchemeD 等)的开发
目录
组件结构规范
基础结构
所有方案组件必须遵循以下三层结构:
<template>
<div class="flex flex-col h-full bg-gray-50">
<!-- 1. 顶部标题栏 -->
<div class="flex justify-between items-center px-5 py-5 bg-white rounded-t-xl">
<span class="text-lg font-normal text-gray-900">{{ title }}</span>
<IconFont name="close" size="16" color="#9CA3AF" @click="close" />
</div>
<!-- 2. 滚动内容区 -->
<div class="flex-1 overflow-y-auto p-4">
<div class="bg-white rounded-xl p-5 shadow-sm">
<!-- 表单字段 -->
</div>
</div>
<!-- 3. 底部按钮区 -->
<div class="p-4 pt-2 pb-8 flex justify-between gap-4 bg-gray-50">
<div class="flex-1 py-3 text-center border border-blue-600 text-blue-600 rounded-lg text-base bg-white"
@click="close">
取消
</div>
<div class="flex-1 py-3 text-center bg-blue-600 text-white rounded-lg text-base" @click="submit">
提交申请
</div>
</div>
</div>
</template>
Props 定义
const props = defineProps({
title: {
type: String,
default: '申请计划书'
}
});
Emits 定义
const emit = defineEmits(['close', 'submit']);
表单字段规范
1. 标准文本输入框
适用场景: 客户姓名、年龄、金额等
<div class="text-sm text-gray-600 mb-2">字段标签</div>
<div class="border border-gray-200 rounded-lg mb-4 overflow-hidden">
<nut-input
v-model="form.fieldName"
type="text"
placeholder="请输入..."
class="!p-0 !bg-transparent !text-sm !text-gray-900"
:border="false"
/>
</div>
关键样式:
- 容器:
border border-gray-200 rounded-lg mb-4 overflow-hidden - 输入框:
!p-0 !bg-transparent !text-sm !text-gray-900 - 数字类型: 使用
type="digit"
2. 带单位的输入框
适用场景: 年收入区间、期望收益率、年交保费等
<div class="text-sm text-gray-600 mb-2">字段标签</div>
<div class="border border-gray-200 rounded-lg mb-4 flex items-center overflow-hidden">
<nut-input
v-model="form.fieldName"
type="digit"
placeholder="请输入..."
class="!p-0 !bg-transparent flex-1 !text-sm !text-gray-900"
:border="false"
/>
<span class="text-sm text-gray-500 shrink-0 ml-2 mr-5">单位</span>
</div>
关键点:
- 输入框:
flex-1(占据剩余空间) - 单位文字:
shrink-0 ml-2(防止被挤压) - 可选:
mr-5(右侧留白,可选)
3. 下拉选择框
适用场景: 行业选择等需要 Picker 的场景
<div class="text-sm text-gray-600 mb-2">字段标签</div>
<div
class="flex justify-between items-center border border-gray-200 rounded-lg p-3 mb-4 overflow-hidden"
@click="showPicker = true"
>
<span :class="form.fieldName ? 'text-gray-900' : 'text-gray-400'" class="text-sm">
{{ form.fieldName || '请选择...' }}
</span>
<IconFont name="right" size="14" color="#9CA3AF" />
</div>
<!-- Picker Popup -->
<nut-popup position="bottom" v-model:visible="showPicker">
<nut-picker
:columns="pickerColumns"
title="选择标题"
@confirm="confirmPicker"
@cancel="showPicker = false"
/>
</nut-popup>
关键点:
- 容器保留
p-3内边距(因为有可点击内容) - 右侧箭头图标:
IconFont name="right" - 占位文字颜色:
text-gray-400 - 已选文字颜色:
text-gray-900
4. 单选字段
适用场景: 性别、交费期间等
<div class="text-sm text-gray-600 mb-2">字段标签</div>
<nut-radio-group v-model="form.fieldName" direction="horizontal" class="mb-4">
<nut-radio
v-for="option in options"
:key="option.value"
:label="option.value"
class="mr-8"
>
{{ option.label }}
</nut-radio>
</nut-radio-group>
关键点:
-
direction="horizontal"- 水平排列 -
class="mb-4"- 底部间距 -
class="mr-8"- 选项间距(两个选项) -
class="mr-6"- 选项间距(三个及以上选项)
5. 多选字段
适用场景: 家庭结构、保险需求等
<div class="text-sm text-gray-600 mb-3">字段标签(多选)</div>
<div class="flex flex-wrap gap-3 mb-5">
<div
v-for="option in options"
:key="option.value"
class="px-4 py-2 rounded-lg text-sm cursor-pointer transition-colors border"
:class="form.fieldName.includes(option.value) ? 'bg-blue-600 text-white border-blue-600' : 'bg-gray-50 text-gray-600 border-gray-200'"
@click="toggleSelection('fieldName', option.value)"
>
{{ option.label }}
</div>
</div>
关键点:
- 标签使用
mb-3,容器使用mb-5 -
flex flex-wrap gap-3- 自动换行 -
cursor-pointer transition-colors- 交互效果 - 选中状态:
bg-blue-600 text-white border-blue-600 - 未选中状态:
bg-gray-50 text-gray-600 border-gray-200
多选切换逻辑:
const toggleSelection = (field, value) => {
const index = form[field].indexOf(value);
if (index === -1) {
form[field].push(value); // 添加选中
} else {
form[field].splice(index, 1); // 取消选中
}
};
6. 只读展示字段
适用场景: 币种、计划、保险期间等固定值展示
<div class="flex justify-between items-start mb-5">
<span class="text-sm text-gray-600 mt-1.5">字段标签</span>
<div class="bg-blue-50 rounded-md px-3 py-1.5">
<span class="text-sm text-blue-600">显示值</span>
</div>
</div>
关键点:
-
flex justify-between items-start- 标签和内容两端对齐 - 标签:
text-sm text-gray-600 mt-1.5(顶部对齐) - 内容:
bg-blue-50 rounded-md px-3 py-1.5 - 文字:
text-sm text-blue-600
样式规范
颜色系统
| 用途 | 颜色值 | Tailwind 类 |
|---|---|---|
| 主色 | #2563EB | blue-600 |
| 标签文字 | #4B5563 | gray-600 |
| 输入文字 | #111827 | gray-900 |
| 占位文字 | #9CA3AF | gray-400 |
| 边框 | #E5E7EB | gray-200 |
| 背景 | #F9FAFB | gray-50 |
| 图标 | #9CA3AF | gray-400 |
间距系统
| 位置 | 间距 | Tailwind 类 |
|---|---|---|
| 标签与输入框 | 8px | mb-2 |
| 输入框底部 | 16px | mb-4 |
| 多选按钮底部 | 20px | mb-5 |
| 单选选项间距 | 32px | mr-8 |
| 多选按钮间距 | 12px | gap-3 |
| 顶部标题栏 | 20px | px-5 py-5 |
| 内容卡片 | 20px | p-5 |
圆角系统
| 元素 | 圆角 | Tailwind 类 |
|---|---|---|
| 卡片 | 12px | rounded-xl |
| 输入框/按钮 | 8px | rounded-lg |
| 标签 | 6px | rounded-md |
文字大小
| 用途 | 大小 | Tailwind 类 |
|---|---|---|
| 标题 | 18px | text-lg |
| 正文 | 14px | text-sm |
| 按钮 | 16px | text-base |
交互规范
全局样式覆盖
所有方案组件必须包含以下样式:
<style lang="less" scoped>
/* Override NutUI input styles to match design */
:deep(.nut-input) {
padding: 0;
background: transparent;
border-radius: inherit;
}
</style>
图标使用
关闭图标:
<IconFont name="close" size="16" color="#9CA3AF" @click="close" />
右侧箭头:
<IconFont name="right" size="14" color="#9CA3AF" />
提示图标:
<IconFont name="tips" size="14" color="#9CA3AF" />
数据结构
Reactive 表单对象
const form = reactive({
// 文本字段
textField: '',
// 数字字段
numberField: '',
// 单选字段
radioField: 'defaultValue',
// 多选字段
multiSelectField: [],
// 带单位字段
amountField: ''
});
选项数据结构
单选选项:
const options = [
{ label: '显示文本', value: 'value1' },
{ label: '显示文本', value: 'value2' }
];
多选选项:
const options = [
{ label: '显示文本', value: 'value1' },
{ label: '显示文本', value: 'value2' }
];
Picker 数据:
const pickerColumns = [
{ text: '显示文本', value: 'value1' },
{ text: '显示文本', value: 'value2' }
];
代码模板
完整组件模板
<template>
<div class="flex flex-col h-full bg-gray-50">
<!-- Header -->
<div class="flex justify-between items-center px-5 py-5 bg-white rounded-t-xl">
<span class="text-lg font-normal text-gray-900">{{ title }}</span>
<IconFont name="close" size="16" color="#9CA3AF" @click="close" />
</div>
<!-- Content -->
<div class="flex-1 overflow-y-auto p-4">
<div class="bg-white rounded-xl p-5 shadow-sm">
<!-- 表单字段区域 -->
</div>
</div>
<!-- Footer -->
<div class="p-4 pt-2 pb-8 flex justify-between gap-4 bg-gray-50">
<div
class="flex-1 py-3 text-center border border-blue-600 text-blue-600 rounded-lg text-base bg-white"
@click="close"
>
取消
</div>
<div
class="flex-1 py-3 text-center bg-blue-600 text-white rounded-lg text-base"
@click="submit"
>
提交申请
</div>
</div>
</div>
</template>
<script setup>
/**
* @description 录入计划书 - 方案X 内容组件
* @emits close - 关闭弹窗事件
* @emits submit - 提交事件,携带表单数据
*/
import { reactive } from 'vue';
const props = defineProps({
title: {
type: String,
default: '申请计划书'
}
});
const emit = defineEmits(['close', 'submit']);
const form = reactive({
// 定义表单字段
fieldName: ''
});
const close = () => {
emit('close');
};
const submit = () => {
console.log('Submit form:', form);
emit('submit', form);
};
</script>
<style lang="less" scoped>
/* Override NutUI input styles to match design */
:deep(.nut-input) {
padding: 0;
background: transparent;
border-radius: inherit;
}
</style>
检查清单
开发前检查
- 阅读本文档
- 确认字段类型(输入/单选/多选/下拉)
- 准备选项数据
- 确认是否有 Picker 弹窗
代码规范检查
-
使用
<script setup>语法 - Props/Emits 定义完整
-
表单对象使用
reactive -
多选逻辑使用
toggleSelection函数 - 包含 JSDoc 注释
样式检查
-
所有输入框容器有
overflow-hidden -
输入框使用
!p-0 !bg-transparent -
圆角使用
rounded-lg -
边框颜色使用
border-gray-200 -
带单位输入框使用
flex-1和shrink-0
组件检查
-
关闭按钮使用
IconFont -
单选使用
nut-radio-group - 多选使用自定义按钮样式
-
Picker 使用
nut-popup+nut-picker
测试检查
- 输入框文字不贴边(有适当间距)
- 圆角显示正常
- 单选只能选中一个
- 多选可以选中多个
- Picker 弹窗正常弹出和选择
- 提交按钮触发 emit 事件
常见问题
Q: 输入框圆角被截掉?
A: 确保容器添加了 overflow-hidden,并且样式覆盖中有 border-radius: inherit。
Q: 带单位的输入框,单位文字被挤压?
A: 确保:
- 输入框有
flex-1 - 单位文字有
shrink-0 - 可选:添加右侧留白
mr-5
Q: 多选按钮样式不一致?
A: 复制标准模板,检查:
- 未选中状态:
bg-gray-50 text-gray-600 border-gray-200 - 选中状态:
bg-blue-600 text-white border-blue-600 - 必须包含:
cursor-pointer transition-colors
Q: Picker 弹窗不显示?
A: 检查:
-
v-model:visible绑定正确 - Picker 数据格式正确:
{ text: '', value: '' } - 确认事件处理正确
Q: 单选/多选数据格式?
A:
- 单选:字符串
form.field = 'value' - 多选:数组
form.field = ['value1', 'value2']
版本历史
| 版本 | 日期 | 更新内容 | 作者 |
|---|---|---|---|
| v1.0 | 2026-01-31 | 初始版本,基于 SchemeA 和 SchemeB 总结 | Claude Code |
相关文件
- SchemeA.vue - 方案A 实现
- SchemeB.vue - 方案B 实现
- IconFont.vue - 图标组件
- 项目 CLAUDE.md - 项目整体规范