hookehuyr

refactor(PlanSchemes): 统一方案A样式实现模式以保持视觉一致性

重构方案A组件布局与样式,使其与方案B保持一致
- 使用相同的容器结构、卡片布局和背景样式
- 将自定义图片替换为IconFont图标组件
- 使用NutUI Radio/Checkbox组件替换自定义选择器
- 统一输入框的边框、圆角和内边距样式
- 移除冗余的图标资源引用,优化代码结构
......@@ -41,6 +41,8 @@ src/
├── components/ # 通用组件
│ ├── PosterBuilder/ # 海报生成器(可选)
│ ├── time-picker-data/ # 时间选择器
│ ├── PlanPopup/ # 录入计划书弹窗容器
│ ├── PlanSchemes/ # 录入计划书方案组件
│ ├── indexNav.vue # 底部导航
│ └── qrCode.vue # 二维码组件(可选)
├── composables/ # Composition API hooks
......
......@@ -13,9 +13,16 @@ declare module 'vue' {
NavHeader: typeof import('./src/components/NavHeader.vue')['default']
NutAvatar: typeof import('@nutui/nutui-taro')['Avatar']
NutButton: typeof import('@nutui/nutui-taro')['Button']
NutCheckbox: typeof import('@nutui/nutui-taro')['Checkbox']
NutCheckboxGroup: typeof import('@nutui/nutui-taro')['CheckboxGroup']
NutForm: typeof import('@nutui/nutui-taro')['Form']
NutFormItem: typeof import('@nutui/nutui-taro')['FormItem']
NutIcon: typeof import('@nutui/nutui-taro')['Icon']
NutInput: typeof import('@nutui/nutui-taro')['Input']
NutPicker: typeof import('@nutui/nutui-taro')['Picker']
NutPopup: typeof import('@nutui/nutui-taro')['Popup']
NutRadio: typeof import('@nutui/nutui-taro')['Radio']
NutRadioGroup: typeof import('@nutui/nutui-taro')['RadioGroup']
NutSearchbar: typeof import('@nutui/nutui-taro')['Searchbar']
NutTabPane: typeof import('@nutui/nutui-taro')['TabPane']
NutTabs: typeof import('@nutui/nutui-taro')['Tabs']
......
## [2026-01-31] - 统一方案A样式实现模式
### 优化
- 调整录入计划书方案A布局与样式 (`src/components/PlanSchemes/SchemeA.vue`)
- 使用与方案B一致的容器结构与卡片布局
- 统一背景、圆角与输入样式,保持视觉一致性
---
**详细信息**
- **修改文件**: `src/components/PlanSchemes/SchemeA.vue`
- **技术栈**: Vue 3, Tailwind CSS, NutUI
## [2026-01-31] - 集成录入计划书方案B
### 新增
......
<template>
<div class="flex flex-col h-full bg-white">
<!-- Header -->
<div class="flex justify-between items-center px-6 py-6 border-b border-gray-100">
<span class="text-lg font-normal text-gray-800">申请计划书</span>
<img
class="w-6 h-6"
src="https://lanhu-oss-2537-2.lanhuapp.com/SketchPng9edea6fd27cf6cb2ff57c90a0834dcda1f86b6072ce07f5e7e07069c2d3b3e9e"
@click="close"
/>
<div class="flex flex-col h-full bg-gray-50">
<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">申请计划书</span>
<IconFont name="close" size="16" color="#9CA3AF" @click="close" />
</div>
<!-- Scrollable Content -->
<div class="flex-1 overflow-y-auto px-6 py-4">
<!-- 客户姓名 -->
<div class="text-sm text-gray-700 mb-2">客户姓名</div>
<nut-input
v-model="form.name"
placeholder="请输入客户姓名"
class="!border !border-gray-200 !rounded-lg !px-3 !py-2 mb-4"
:border="false"
/>
<!-- 性别 -->
<div class="text-sm text-gray-700 mb-2">性别</div>
<div class="flex items-center mb-4">
<div
class="flex items-center mr-8 cursor-pointer"
@click="form.gender = 'male'"
>
<img
class="w-5 h-5 mr-2"
src="https://lanhu-oss-2537-2.lanhuapp.com/SketchPngaa89ac8577908dfb2901e1067741dcdc9a5b58739da04a5243e45c296275f5ef"
<div class="flex-1 overflow-y-auto p-4">
<div class="bg-white rounded-xl p-5 shadow-sm">
<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.name"
placeholder="请输入客户姓名"
class="!p-0 !bg-transparent !text-sm !text-gray-900"
:border="false"
/>
<span :class="form.gender === 'male' ? 'text-blue-600 font-bold' : 'text-gray-800'">男</span>
</div>
<div
class="flex items-center cursor-pointer"
@click="form.gender = 'female'"
>
<img
class="w-5 h-5 mr-2"
src="https://lanhu-oss-2537-2.lanhuapp.com/SketchPng86258dc38e0dde555b09ba68a94fb042ce0172628791dc178dd1a7c0c89a824f"
<div class="text-sm text-gray-600 mb-2">性别</div>
<nut-radio-group v-model="form.gender" direction="horizontal" class="mb-4">
<nut-radio label="male" class="mr-8">男</nut-radio>
<nut-radio label="female">女</nut-radio>
</nut-radio-group>
<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.age"
type="digit"
placeholder="请输入年龄"
class="!p-0 !bg-transparent !text-sm !text-gray-900"
:border="false"
/>
<span :class="form.gender === 'female' ? 'text-blue-600 font-bold' : 'text-gray-800'">女</span>
</div>
</div>
<!-- 年龄 -->
<div class="text-sm text-gray-700 mb-2">年龄</div>
<nut-input
v-model="form.age"
type="digit"
placeholder="请输入年龄"
class="!border !border-gray-200 !rounded-lg !px-3 !py-2 mb-4"
:border="false"
/>
<!-- 行业 -->
<div class="text-sm text-gray-700 mb-2">行业</div>
<div
class="flex justify-between items-center p-3 border border-gray-200 rounded-lg mb-4 bg-white"
@click="showIndustryPicker = true"
>
<span :class="form.industry ? 'text-gray-900' : 'text-gray-400'" class="text-sm">
{{ form.industry || '请选择职业' }}
</span>
<img
class="w-3.5 h-3.5"
src="https://lanhu-oss-2537-2.lanhuapp.com/SketchPngcf768ccd4a7e2a9d761be1bbd425d7c09e15f44c66570d21e5e9121448ccada5"
/>
</div>
<!-- 年收入区间 -->
<div class="text-sm text-gray-700 mb-2">年收入区间</div>
<div class="relative mb-4">
<nut-input
v-model="form.income"
type="digit"
placeholder="请输入年收入"
class="!border !border-gray-200 !rounded-lg !px-3 !py-2 !pr-10"
:border="false"
/>
<span class="absolute right-3 top-1/2 -translate-y-1/2 text-gray-500 text-sm">万元</span>
</div>
<!-- 家庭结构 -->
<div class="text-sm text-gray-700 mb-2">家庭结构</div>
<div class="flex flex-wrap gap-4 mb-4">
<div class="text-sm text-gray-600 mb-2">行业</div>
<div
v-for="item in familyOptions"
:key="item.value"
class="flex items-center cursor-pointer min-w-[60px]"
@click="toggleSelection('family', item.value)"
class="flex justify-between items-center border border-gray-200 rounded-lg p-3 mb-4 overflow-hidden"
@click="showIndustryPicker = true"
>
<img :src="item.icon" class="w-5 h-5 mr-2" />
<span :class="form.family.includes(item.value) ? 'text-blue-600 font-bold' : 'text-gray-800'" class="text-sm">
{{ item.label }}
<span :class="form.industry ? 'text-gray-900' : 'text-gray-400'" class="text-sm">
{{ form.industry || '请选择职业' }}
</span>
<IconFont name="right" size="14" color="#9CA3AF" />
</div>
</div>
<!-- 保险需求 -->
<div class="text-sm text-gray-700 mb-2">保险需求</div>
<div class="flex flex-wrap gap-4 mb-4">
<div
v-for="item in insuranceOptions"
:key="item.value"
class="flex items-center cursor-pointer min-w-[85px]"
@click="toggleSelection('insurance', item.value)"
>
<img :src="item.icon" class="w-5 h-5 mr-2" />
<span :class="form.insurance.includes(item.value) ? 'text-blue-600 font-bold' : 'text-gray-800'" class="text-sm">
<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.income"
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>
<div class="text-sm text-gray-600 mb-3">家庭结构(多选)</div>
<div class="flex flex-wrap gap-3 mb-5">
<div
v-for="item in familyOptions"
:key="item.value"
class="px-4 py-2 rounded-lg text-sm cursor-pointer transition-colors border"
:class="form.family.includes(item.value) ? 'bg-blue-600 text-white border-blue-600' : 'bg-gray-50 text-gray-600 border-gray-200'"
@click="toggleSelection('family', item.value)"
>
{{ item.label }}
</span>
</div>
</div>
</div>
<!-- 期望收益率 -->
<div class="text-sm text-gray-700 mb-2">期望收益率</div>
<div class="relative mb-8">
<nut-input
v-model="form.returnRate"
type="digit"
placeholder="请输入期望收益率"
class="!border !border-gray-200 !rounded-lg !px-3 !py-2 !pr-10"
:border="false"
/>
<span class="absolute right-3 top-1/2 -translate-y-1/2 text-gray-500 text-sm">%</span>
<div class="text-sm text-gray-600 mb-3">保险需求(多选)</div>
<div class="flex flex-wrap gap-3 mb-5">
<div
v-for="item in insuranceOptions"
:key="item.value"
class="px-4 py-2 rounded-lg text-sm cursor-pointer transition-colors border"
:class="form.insurance.includes(item.value) ? 'bg-blue-600 text-white border-blue-600' : 'bg-gray-50 text-gray-600 border-gray-200'"
@click="toggleSelection('insurance', item.value)"
>
{{ item.label }}
</div>
</div>
<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.returnRate"
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>
</div>
</div>
<!-- Footer Buttons -->
<div class="p-6 pt-2 pb-8 flex justify-between gap-4 border-t border-gray-100 bg-white">
<div
class="flex-1 py-3 text-center border border-blue-600 text-blue-600 rounded-lg text-base"
<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
<div
class="flex-1 py-3 text-center bg-blue-600 text-white rounded-lg text-base"
@click="submit"
>
......@@ -190,19 +156,17 @@ const industryColumns = [
];
const familyOptions = [
{ label: '配偶', value: 'spouse', icon: 'https://lanhu-oss-2537-2.lanhuapp.com/SketchPng78cf3ef069859580d9e4f17fc5095d6fbf460f1437ac3deaa43ab0a5a71a775e' },
{ label: '子女', value: 'children', icon: 'https://lanhu-oss-2537-2.lanhuapp.com/SketchPng845af3ba96be197313380a56d1607660c93f44687cb6e966dbf28c9d51142dd9' },
{ label: '父母', value: 'parents', icon: 'https://lanhu-oss-2537-2.lanhuapp.com/SketchPng845af3ba96be197313380a56d1607660c93f44687cb6e966dbf28c9d51142dd9' }, // Using same icon as placeholder from design if needed, or check if unique one exists. Design uses same for parents/others in reference code snippet (lines 70, 78) but distinct in variable name logic? Actually design uses specific URLs. I copied from reference.
{ label: '其他', value: 'others', icon: 'https://lanhu-oss-2537-2.lanhuapp.com/SketchPng845af3ba96be197313380a56d1607660c93f44687cb6e966dbf28c9d51142dd9' },
{ label: '配偶', value: 'spouse' },
{ label: '子女', value: 'children' },
{ label: '父母', value: 'parents' },
{ label: '其他', value: 'others' },
];
// Reference code lines 70, 78 use the same URL as 62 (children). I'll use them as is.
const insuranceOptions = [
{ label: '人身保障', value: 'life', icon: 'https://lanhu-oss-2537-2.lanhuapp.com/SketchPng78cf3ef069859580d9e4f17fc5095d6fbf460f1437ac3deaa43ab0a5a71a775e' },
{ label: '财富传承', value: 'wealth', icon: 'https://lanhu-oss-2537-2.lanhuapp.com/SketchPng845af3ba96be197313380a56d1607660c93f44687cb6e966dbf28c9d51142dd9' },
{ label: '子女教育', value: 'education', icon: 'https://lanhu-oss-2537-2.lanhuapp.com/SketchPng845af3ba96be197313380a56d1607660c93f44687cb6e966dbf28c9d51142dd9' },
{ label: '养老规划', value: 'pension', icon: 'https://lanhu-oss-2537-2.lanhuapp.com/SketchPng845af3ba96be197313380a56d1607660c93f44687cb6e966dbf28c9d51142dd9' },
{ label: '人身保障', value: 'life' },
{ label: '财富传承', value: 'wealth' },
{ label: '子女教育', value: 'education' },
{ label: '养老规划', value: 'pension' },
];
const toggleSelection = (field, value) => {
......@@ -235,5 +199,6 @@ const submit = () => {
:deep(.nut-input) {
padding: 0;
background: transparent;
border-radius: inherit;
}
</style>
......
......@@ -3,11 +3,7 @@
<!-- 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">保险计划书申请</span>
<img
class="w-5 h-5"
src="https://lanhu-oss-2537-2.lanhuapp.com/SketchPng43284a8c3fc98c60509d6d415fed8113414c4c0b072fa0f3b41fc26e76a03b15"
@click="close"
/>
<IconFont name="close" size="16" color="#9CA3AF" @click="close" />
</div>
<!-- Scrollable Content -->
......@@ -29,54 +25,28 @@
</div>
</div>
<!-- 附加计划 & 性别 -->
<div class="flex justify-between items-center mb-5">
<span class="text-base text-gray-900">附加计划</span>
<div class="flex items-center">
<span class="text-sm text-gray-600 mr-4">性别</span>
<div class="flex items-center">
<div
class="flex items-center mr-4 cursor-pointer"
@click="form.gender = 'female'"
>
<img
class="w-4.5 h-4.5 mr-1"
src="https://lanhu-oss-2537-2.lanhuapp.com/SketchPng1015590381802ed3f770814c3e05e4b73e6534f72e97a9a0721c459ed1dbac6a"
/>
<span :class="form.gender === 'female' ? 'text-blue-600 font-bold' : 'text-gray-800'" class="text-sm">女</span>
</div>
<div
class="flex items-center cursor-pointer"
@click="form.gender = 'male'"
>
<img
class="w-4.5 h-4.5 mr-1"
src="https://lanhu-oss-2537-2.lanhuapp.com/SketchPngb0bb17420dba3691281e919f69d1e06a69d343e53ee68ad570ec2fe340cdb09c"
/>
<span :class="form.gender === 'male' ? 'text-blue-600 font-bold' : 'text-gray-500'" class="text-sm">男</span>
</div>
</div>
</div>
<!-- 附加计划 -->
<div class="mb-5">
<span class="text-base text-gray-900">附加计划</span>
</div>
<!-- 性别 -->
<div class="text-sm text-gray-600 mb-2">性别</div>
<nut-radio-group v-model="form.gender" direction="horizontal" class="mb-4">
<nut-radio label="female" class="mr-8">女</nut-radio>
<nut-radio label="male">男</nut-radio>
</nut-radio-group>
<!-- 年龄 -->
<div class="flex justify-between items-center mb-5">
<span class="text-sm text-gray-600">年龄</span>
<div class="flex items-center">
<nut-input
v-model="form.age"
type="digit"
placeholder="请输入"
class="!p-0 !bg-transparent !w-16 !text-right !text-gray-900 !text-sm"
:border="false"
input-align="right"
/>
<span class="text-sm text-gray-900 mx-1">周岁</span>
<img
class="w-4 h-4"
src="https://lanhu-oss-2537-2.lanhuapp.com/SketchPng4f1ca24a37fc014649249f2a5db80cdec300bf86076429fb76cc42dff9b59f3d"
/>
</div>
<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.age"
type="digit"
placeholder="请输入年龄"
class="!p-0 !bg-transparent !text-sm !text-gray-900"
:border="false"
/>
</div>
<!-- 保险期间 -->
......@@ -89,45 +59,39 @@
<!-- 交费期间 -->
<div class="text-sm text-gray-600 mb-3">交费期间</div>
<div class="flex flex-wrap gap-3 mb-5">
<div
<nut-radio-group v-model="form.paymentPeriod" direction="horizontal" class="mb-4">
<nut-radio
v-for="period in paymentPeriods"
:key="period"
class="px-4 py-2 rounded-lg text-sm cursor-pointer transition-colors border"
:class="form.paymentPeriod === period ? 'bg-blue-600 text-white border-blue-600' : 'bg-gray-50 text-gray-600 border-gray-200'"
@click="form.paymentPeriod = period"
:label="period"
class="mr-6"
>
{{ period }}
</div>
</div>
</nut-radio>
</nut-radio-group>
<!-- 年交保费 -->
<div class="text-sm text-gray-600 mb-2">年交保费</div>
<div class="bg-gray-50 rounded-lg border border-gray-200 p-3 flex justify-between items-center">
<nut-input
<div class="border border-gray-200 rounded-lg mb-4 flex items-center overflow-hidden">
<nut-input
v-model="form.premium"
type="digit"
placeholder="请输入保费"
class="!p-0 !bg-transparent flex-1 !text-base !text-gray-900"
class="!p-0 !bg-transparent flex-1 !text-sm !text-gray-900"
:border="false"
/>
<span class="text-sm text-gray-500 ml-2">美元</span>
<span class="text-sm text-gray-500 shrink-0 ml-2 mr-5">美元</span>
</div>
</div>
</div>
<!-- Footer Buttons -->
<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 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 class="flex-1 py-3 text-center bg-blue-600 text-white rounded-lg text-base" @click="submit">
提交申请
</div>
</div>
......@@ -154,7 +118,7 @@ const form = reactive({
premium: '100000',
});
const paymentPeriods = ['10年交', '3年交', '5年交', '躸交', '2年交'];
const paymentPeriods = ['10年交', '3年交', '5年交', '2年交'];
const close = () => {
emit('close');
......@@ -170,5 +134,6 @@ const submit = () => {
:deep(.nut-input) {
padding: 0;
background: transparent;
border-radius: inherit;
}
</style>
......