hookehuyr

feat(plan): 集成录入计划书方案B并扩展弹窗组件

新增方案B内容组件,包含币种、计划、性别、年龄等字段,并还原设计稿布局与交互。
修改首页,将热卖产品的"计划书"按钮点击事件改为弹出录入界面,实现多方案演示。
扩展组件类型声明,注册新增组件以供使用。
...@@ -13,6 +13,8 @@ declare module 'vue' { ...@@ -13,6 +13,8 @@ declare module 'vue' {
13 NavHeader: typeof import('./src/components/NavHeader.vue')['default'] 13 NavHeader: typeof import('./src/components/NavHeader.vue')['default']
14 NutAvatar: typeof import('@nutui/nutui-taro')['Avatar'] 14 NutAvatar: typeof import('@nutui/nutui-taro')['Avatar']
15 NutButton: typeof import('@nutui/nutui-taro')['Button'] 15 NutButton: typeof import('@nutui/nutui-taro')['Button']
16 + NutInput: typeof import('@nutui/nutui-taro')['Input']
17 + NutPicker: typeof import('@nutui/nutui-taro')['Picker']
16 NutPopup: typeof import('@nutui/nutui-taro')['Popup'] 18 NutPopup: typeof import('@nutui/nutui-taro')['Popup']
17 NutSearchbar: typeof import('@nutui/nutui-taro')['Searchbar'] 19 NutSearchbar: typeof import('@nutui/nutui-taro')['Searchbar']
18 NutTabPane: typeof import('@nutui/nutui-taro')['TabPane'] 20 NutTabPane: typeof import('@nutui/nutui-taro')['TabPane']
...@@ -22,11 +24,14 @@ declare module 'vue' { ...@@ -22,11 +24,14 @@ declare module 'vue' {
22 OfficeViewer: typeof import('./src/components/OfficeViewer.vue')['default'] 24 OfficeViewer: typeof import('./src/components/OfficeViewer.vue')['default']
23 PdfPreview: typeof import('./src/components/PdfPreview.vue')['default'] 25 PdfPreview: typeof import('./src/components/PdfPreview.vue')['default']
24 Picker: typeof import('./src/components/time-picker-data/picker.vue')['default'] 26 Picker: typeof import('./src/components/time-picker-data/picker.vue')['default']
27 + PlanPopup: typeof import('./src/components/PlanPopup/index.vue')['default']
25 PosterBuilder: typeof import('./src/components/PosterBuilder/index.vue')['default'] 28 PosterBuilder: typeof import('./src/components/PosterBuilder/index.vue')['default']
26 QrCode: typeof import('./src/components/qrCode.vue')['default'] 29 QrCode: typeof import('./src/components/qrCode.vue')['default']
27 QrCodeSearch: typeof import('./src/components/qrCodeSearch.vue')['default'] 30 QrCodeSearch: typeof import('./src/components/qrCodeSearch.vue')['default']
28 RouterLink: typeof import('vue-router')['RouterLink'] 31 RouterLink: typeof import('vue-router')['RouterLink']
29 RouterView: typeof import('vue-router')['RouterView'] 32 RouterView: typeof import('vue-router')['RouterView']
33 + SchemeA: typeof import('./src/components/PlanSchemes/SchemeA.vue')['default']
34 + SchemeB: typeof import('./src/components/PlanSchemes/SchemeB.vue')['default']
30 SectionCard: typeof import('./src/components/SectionCard.vue')['default'] 35 SectionCard: typeof import('./src/components/SectionCard.vue')['default']
31 SectionItem: typeof import('./src/components/SectionItem.vue')['default'] 36 SectionItem: typeof import('./src/components/SectionItem.vue')['default']
32 TabBar: typeof import('./src/components/TabBar.vue')['default'] 37 TabBar: typeof import('./src/components/TabBar.vue')['default']
......
1 +## [2026-01-31] - 集成录入计划书方案B
2 +
3 +### 新增
4 +- 新增录入计划书方案B内容组件 (`src/components/PlanSchemes/SchemeB.vue`)
5 + - 还原设计稿 (`docs/design/manulife-V1/录入计划书/方案B`) 布局与交互
6 + - 包含币种、计划、性别、年龄、保险期间、交费期间、保费等字段
7 +
8 +### 变更
9 +- 修改首页 (`src/pages/index/index.vue`)
10 + - 引入 `PlanPopup`, `SchemeA`, `SchemeB` 组件
11 + - 将热卖产品的"计划书"按钮点击事件改为弹出录入界面
12 + - 第一个产品对应方案A,第二个产品对应方案B,实现多方案演示
13 +
14 +---
15 +
16 +**详细信息**
17 +- **新增文件**: `src/components/PlanSchemes/SchemeB.vue`
18 +- **修改文件**: `src/pages/index/index.vue`
19 +- **技术栈**: Vue 3, Tailwind CSS, NutUI
20 +
21 +## [2026-01-31] - 新增录入计划书功能
22 +
23 +### 新增
24 +- 新增录入计划书弹窗容器组件 (`src/components/PlanPopup`)
25 + - 使用 `nut-popup` 实现底部弹出的 90% 高度弹窗
26 + - 支持 `slot` 插入不同内容,具备良好的扩展性
27 +- 新增录入计划书方案A内容组件 (`src/components/PlanSchemes/SchemeA.vue`)
28 + - 还原设计稿 (`docs/design/manulife-V1/录入计划书/方案A`) 布局与交互
29 + - 使用 Tailwind CSS 和 NutUI 组件 (`nut-input`, `nut-picker`, `nut-button` 等) 实现
30 + - 包含完整的表单逻辑:姓名、性别、年龄、行业、年收入、家庭结构、保险需求、期望收益率
31 + - 使用图标和交互式选择器提升用户体验
32 +
33 +---
34 +
35 +**详细信息**
36 +- **新增文件**: `src/components/PlanPopup/index.vue`, `src/components/PlanSchemes/SchemeA.vue`
37 +- **技术栈**: Vue 3, Tailwind CSS, NutUI
38 +- **测试状态**: 已通过
39 +- **备注**:
40 + - 为后续新增其他方案预留了目录结构 (`src/components/PlanSchemes/`)
41 +
1 ## [2026-01-31] - 重构文件操作逻辑,消除代码重复 42 ## [2026-01-31] - 重构文件操作逻辑,消除代码重复
2 43
3 ### 重构 44 ### 重构
......
1 +<!--
2 + * @Date: 2026-01-31 12:49:11
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2026-01-31 12:50:32
5 + * @FilePath: /manulife-weapp/src/components/PlanPopup/index.vue
6 + * @Description: 文件描述
7 +-->
8 +<template>
9 + <nut-popup :visible="visible" position="bottom" round :style="{ height: '90%' }"
10 + @update:visible="emit('update:visible', $event)" :close-on-click-overlay="true">
11 + <div class="h-full flex flex-col bg-white overflow-hidden rounded-t-2xl">
12 + <slot></slot>
13 + </div>
14 + </nut-popup>
15 +</template>
16 +
17 +<script setup>
18 +/**
19 + * @description 录入计划书弹窗容器组件
20 + * @param {boolean} visible - 控制弹窗显示隐藏
21 + * @emits update:visible - 更新 visible 状态
22 + */
23 +import { defineProps, defineEmits } from 'vue';
24 +
25 +const props = defineProps({
26 + visible: {
27 + type: Boolean,
28 + default: false,
29 + },
30 +});
31 +
32 +const emit = defineEmits(['update:visible']);
33 +</script>
34 +
35 +<style lang="less" scoped>
36 +:deep(.nut-popup) {
37 + border-top-left-radius: 16px;
38 + border-top-right-radius: 16px;
39 +}
40 +</style>
1 +<template>
2 + <div class="flex flex-col h-full bg-white">
3 + <!-- Header -->
4 + <div class="flex justify-between items-center px-6 py-6 border-b border-gray-100">
5 + <span class="text-lg font-normal text-gray-800">申请计划书</span>
6 + <img
7 + class="w-6 h-6"
8 + src="https://lanhu-oss-2537-2.lanhuapp.com/SketchPng9edea6fd27cf6cb2ff57c90a0834dcda1f86b6072ce07f5e7e07069c2d3b3e9e"
9 + @click="close"
10 + />
11 + </div>
12 +
13 + <!-- Scrollable Content -->
14 + <div class="flex-1 overflow-y-auto px-6 py-4">
15 + <!-- 客户姓名 -->
16 + <div class="text-sm text-gray-700 mb-2">客户姓名</div>
17 + <nut-input
18 + v-model="form.name"
19 + placeholder="请输入客户姓名"
20 + class="!border !border-gray-200 !rounded-lg !px-3 !py-2 mb-4"
21 + :border="false"
22 + />
23 +
24 + <!-- 性别 -->
25 + <div class="text-sm text-gray-700 mb-2">性别</div>
26 + <div class="flex items-center mb-4">
27 + <div
28 + class="flex items-center mr-8 cursor-pointer"
29 + @click="form.gender = 'male'"
30 + >
31 + <img
32 + class="w-5 h-5 mr-2"
33 + src="https://lanhu-oss-2537-2.lanhuapp.com/SketchPngaa89ac8577908dfb2901e1067741dcdc9a5b58739da04a5243e45c296275f5ef"
34 + />
35 + <span :class="form.gender === 'male' ? 'text-blue-600 font-bold' : 'text-gray-800'">男</span>
36 + </div>
37 + <div
38 + class="flex items-center cursor-pointer"
39 + @click="form.gender = 'female'"
40 + >
41 + <img
42 + class="w-5 h-5 mr-2"
43 + src="https://lanhu-oss-2537-2.lanhuapp.com/SketchPng86258dc38e0dde555b09ba68a94fb042ce0172628791dc178dd1a7c0c89a824f"
44 + />
45 + <span :class="form.gender === 'female' ? 'text-blue-600 font-bold' : 'text-gray-800'">女</span>
46 + </div>
47 + </div>
48 +
49 + <!-- 年龄 -->
50 + <div class="text-sm text-gray-700 mb-2">年龄</div>
51 + <nut-input
52 + v-model="form.age"
53 + type="digit"
54 + placeholder="请输入年龄"
55 + class="!border !border-gray-200 !rounded-lg !px-3 !py-2 mb-4"
56 + :border="false"
57 + />
58 +
59 + <!-- 行业 -->
60 + <div class="text-sm text-gray-700 mb-2">行业</div>
61 + <div
62 + class="flex justify-between items-center p-3 border border-gray-200 rounded-lg mb-4 bg-white"
63 + @click="showIndustryPicker = true"
64 + >
65 + <span :class="form.industry ? 'text-gray-900' : 'text-gray-400'" class="text-sm">
66 + {{ form.industry || '请选择职业' }}
67 + </span>
68 + <img
69 + class="w-3.5 h-3.5"
70 + src="https://lanhu-oss-2537-2.lanhuapp.com/SketchPngcf768ccd4a7e2a9d761be1bbd425d7c09e15f44c66570d21e5e9121448ccada5"
71 + />
72 + </div>
73 +
74 + <!-- 年收入区间 -->
75 + <div class="text-sm text-gray-700 mb-2">年收入区间</div>
76 + <div class="relative mb-4">
77 + <nut-input
78 + v-model="form.income"
79 + type="digit"
80 + placeholder="请输入年收入"
81 + class="!border !border-gray-200 !rounded-lg !px-3 !py-2 !pr-10"
82 + :border="false"
83 + />
84 + <span class="absolute right-3 top-1/2 -translate-y-1/2 text-gray-500 text-sm">万元</span>
85 + </div>
86 +
87 + <!-- 家庭结构 -->
88 + <div class="text-sm text-gray-700 mb-2">家庭结构</div>
89 + <div class="flex flex-wrap gap-4 mb-4">
90 + <div
91 + v-for="item in familyOptions"
92 + :key="item.value"
93 + class="flex items-center cursor-pointer min-w-[60px]"
94 + @click="toggleSelection('family', item.value)"
95 + >
96 + <img :src="item.icon" class="w-5 h-5 mr-2" />
97 + <span :class="form.family.includes(item.value) ? 'text-blue-600 font-bold' : 'text-gray-800'" class="text-sm">
98 + {{ item.label }}
99 + </span>
100 + </div>
101 + </div>
102 +
103 + <!-- 保险需求 -->
104 + <div class="text-sm text-gray-700 mb-2">保险需求</div>
105 + <div class="flex flex-wrap gap-4 mb-4">
106 + <div
107 + v-for="item in insuranceOptions"
108 + :key="item.value"
109 + class="flex items-center cursor-pointer min-w-[85px]"
110 + @click="toggleSelection('insurance', item.value)"
111 + >
112 + <img :src="item.icon" class="w-5 h-5 mr-2" />
113 + <span :class="form.insurance.includes(item.value) ? 'text-blue-600 font-bold' : 'text-gray-800'" class="text-sm">
114 + {{ item.label }}
115 + </span>
116 + </div>
117 + </div>
118 +
119 + <!-- 期望收益率 -->
120 + <div class="text-sm text-gray-700 mb-2">期望收益率</div>
121 + <div class="relative mb-8">
122 + <nut-input
123 + v-model="form.returnRate"
124 + type="digit"
125 + placeholder="请输入期望收益率"
126 + class="!border !border-gray-200 !rounded-lg !px-3 !py-2 !pr-10"
127 + :border="false"
128 + />
129 + <span class="absolute right-3 top-1/2 -translate-y-1/2 text-gray-500 text-sm">%</span>
130 + </div>
131 + </div>
132 +
133 + <!-- Footer Buttons -->
134 + <div class="p-6 pt-2 pb-8 flex justify-between gap-4 border-t border-gray-100 bg-white">
135 + <div
136 + class="flex-1 py-3 text-center border border-blue-600 text-blue-600 rounded-lg text-base"
137 + @click="close"
138 + >
139 + 取消
140 + </div>
141 + <div
142 + class="flex-1 py-3 text-center bg-blue-600 text-white rounded-lg text-base"
143 + @click="submit"
144 + >
145 + 提交申请
146 + </div>
147 + </div>
148 +
149 + <!-- Industry Picker -->
150 + <nut-popup position="bottom" v-model:visible="showIndustryPicker">
151 + <nut-picker
152 + :columns="industryColumns"
153 + title="选择行业"
154 + @confirm="confirmIndustry"
155 + @cancel="showIndustryPicker = false"
156 + />
157 + </nut-popup>
158 + </div>
159 +</template>
160 +
161 +<script setup>
162 +/**
163 + * @description 录入计划书 - 方案A 内容组件
164 + * @emits close - 关闭弹窗事件
165 + * @emits submit - 提交事件,携带表单数据
166 + */
167 +import { ref, reactive } from 'vue';
168 +
169 +const emit = defineEmits(['close', 'submit']);
170 +
171 +const form = reactive({
172 + name: '',
173 + gender: '', // 'male' | 'female'
174 + age: '',
175 + industry: '',
176 + income: '',
177 + family: [],
178 + insurance: [],
179 + returnRate: '',
180 +});
181 +
182 +const showIndustryPicker = ref(false);
183 +
184 +const industryColumns = [
185 + { text: 'IT/互联网', value: 'it' },
186 + { text: '金融', value: 'finance' },
187 + { text: '教育', value: 'education' },
188 + { text: '医疗', value: 'medical' },
189 + { text: '其他', value: 'other' },
190 +];
191 +
192 +const familyOptions = [
193 + { label: '配偶', value: 'spouse', icon: 'https://lanhu-oss-2537-2.lanhuapp.com/SketchPng78cf3ef069859580d9e4f17fc5095d6fbf460f1437ac3deaa43ab0a5a71a775e' },
194 + { label: '子女', value: 'children', icon: 'https://lanhu-oss-2537-2.lanhuapp.com/SketchPng845af3ba96be197313380a56d1607660c93f44687cb6e966dbf28c9d51142dd9' },
195 + { 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.
196 + { label: '其他', value: 'others', icon: 'https://lanhu-oss-2537-2.lanhuapp.com/SketchPng845af3ba96be197313380a56d1607660c93f44687cb6e966dbf28c9d51142dd9' },
197 +];
198 +
199 +// Reference code lines 70, 78 use the same URL as 62 (children). I'll use them as is.
200 +
201 +const insuranceOptions = [
202 + { label: '人身保障', value: 'life', icon: 'https://lanhu-oss-2537-2.lanhuapp.com/SketchPng78cf3ef069859580d9e4f17fc5095d6fbf460f1437ac3deaa43ab0a5a71a775e' },
203 + { label: '财富传承', value: 'wealth', icon: 'https://lanhu-oss-2537-2.lanhuapp.com/SketchPng845af3ba96be197313380a56d1607660c93f44687cb6e966dbf28c9d51142dd9' },
204 + { label: '子女教育', value: 'education', icon: 'https://lanhu-oss-2537-2.lanhuapp.com/SketchPng845af3ba96be197313380a56d1607660c93f44687cb6e966dbf28c9d51142dd9' },
205 + { label: '养老规划', value: 'pension', icon: 'https://lanhu-oss-2537-2.lanhuapp.com/SketchPng845af3ba96be197313380a56d1607660c93f44687cb6e966dbf28c9d51142dd9' },
206 +];
207 +
208 +const toggleSelection = (field, value) => {
209 + const index = form[field].indexOf(value);
210 + if (index === -1) {
211 + form[field].push(value);
212 + } else {
213 + form[field].splice(index, 1);
214 + }
215 +};
216 +
217 +const confirmIndustry = ({ selectedValue, selectedOptions }) => {
218 + form.industry = selectedOptions[0].text;
219 + showIndustryPicker.value = false;
220 +};
221 +
222 +const close = () => {
223 + emit('close');
224 +};
225 +
226 +const submit = () => {
227 + // Validate form if needed
228 + console.log('Submit form:', form);
229 + emit('submit', form);
230 +};
231 +</script>
232 +
233 +<style lang="less" scoped>
234 +/* Override NutUI input styles to match design */
235 +:deep(.nut-input) {
236 + padding: 0;
237 + background: transparent;
238 +}
239 +</style>
1 +<template>
2 + <div class="flex flex-col h-full bg-gray-50">
3 + <!-- Header -->
4 + <div class="flex justify-between items-center px-5 py-5 bg-white rounded-t-xl">
5 + <span class="text-lg font-normal text-gray-900">保险计划书申请</span>
6 + <img
7 + class="w-5 h-5"
8 + src="https://lanhu-oss-2537-2.lanhuapp.com/SketchPng43284a8c3fc98c60509d6d415fed8113414c4c0b072fa0f3b41fc26e76a03b15"
9 + @click="close"
10 + />
11 + </div>
12 +
13 + <!-- Scrollable Content -->
14 + <div class="flex-1 overflow-y-auto p-4">
15 + <div class="bg-white rounded-xl p-5 shadow-sm">
16 + <!-- 币种 -->
17 + <div class="flex justify-between items-start mb-5">
18 + <span class="text-sm text-gray-600 mt-1.5">币种</span>
19 + <div class="bg-blue-50 rounded-md px-3 py-1.5">
20 + <span class="text-sm text-blue-600">美元保单</span>
21 + </div>
22 + </div>
23 +
24 + <!-- 计划 -->
25 + <div class="flex justify-between items-start mb-5">
26 + <span class="text-sm text-gray-600 mt-1.5">计划</span>
27 + <div class="bg-blue-50 rounded-md px-3 py-1.5">
28 + <span class="text-sm text-blue-600">基础情景</span>
29 + </div>
30 + </div>
31 +
32 + <!-- 附加计划 & 性别 -->
33 + <div class="flex justify-between items-center mb-5">
34 + <span class="text-base text-gray-900">附加计划</span>
35 + <div class="flex items-center">
36 + <span class="text-sm text-gray-600 mr-4">性别</span>
37 + <div class="flex items-center">
38 + <div
39 + class="flex items-center mr-4 cursor-pointer"
40 + @click="form.gender = 'female'"
41 + >
42 + <img
43 + class="w-4.5 h-4.5 mr-1"
44 + src="https://lanhu-oss-2537-2.lanhuapp.com/SketchPng1015590381802ed3f770814c3e05e4b73e6534f72e97a9a0721c459ed1dbac6a"
45 + />
46 + <span :class="form.gender === 'female' ? 'text-blue-600 font-bold' : 'text-gray-800'" class="text-sm">女</span>
47 + </div>
48 + <div
49 + class="flex items-center cursor-pointer"
50 + @click="form.gender = 'male'"
51 + >
52 + <img
53 + class="w-4.5 h-4.5 mr-1"
54 + src="https://lanhu-oss-2537-2.lanhuapp.com/SketchPngb0bb17420dba3691281e919f69d1e06a69d343e53ee68ad570ec2fe340cdb09c"
55 + />
56 + <span :class="form.gender === 'male' ? 'text-blue-600 font-bold' : 'text-gray-500'" class="text-sm">男</span>
57 + </div>
58 + </div>
59 + </div>
60 + </div>
61 +
62 + <!-- 年龄 -->
63 + <div class="flex justify-between items-center mb-5">
64 + <span class="text-sm text-gray-600">年龄</span>
65 + <div class="flex items-center">
66 + <nut-input
67 + v-model="form.age"
68 + type="digit"
69 + placeholder="请输入"
70 + class="!p-0 !bg-transparent !w-16 !text-right !text-gray-900 !text-sm"
71 + :border="false"
72 + input-align="right"
73 + />
74 + <span class="text-sm text-gray-900 mx-1">周岁</span>
75 + <img
76 + class="w-4 h-4"
77 + src="https://lanhu-oss-2537-2.lanhuapp.com/SketchPng4f1ca24a37fc014649249f2a5db80cdec300bf86076429fb76cc42dff9b59f3d"
78 + />
79 + </div>
80 + </div>
81 +
82 + <!-- 保险期间 -->
83 + <div class="flex justify-between items-start mb-5">
84 + <span class="text-sm text-gray-600 mt-1.5">保险期间</span>
85 + <div class="bg-blue-50 rounded-md px-3 py-1.5">
86 + <span class="text-sm text-blue-600">终身</span>
87 + </div>
88 + </div>
89 +
90 + <!-- 交费期间 -->
91 + <div class="text-sm text-gray-600 mb-3">交费期间</div>
92 + <div class="flex flex-wrap gap-3 mb-5">
93 + <div
94 + v-for="period in paymentPeriods"
95 + :key="period"
96 + class="px-4 py-2 rounded-lg text-sm cursor-pointer transition-colors border"
97 + :class="form.paymentPeriod === period ? 'bg-blue-600 text-white border-blue-600' : 'bg-gray-50 text-gray-600 border-gray-200'"
98 + @click="form.paymentPeriod = period"
99 + >
100 + {{ period }}
101 + </div>
102 + </div>
103 +
104 + <!-- 年交保费 -->
105 + <div class="text-sm text-gray-600 mb-2">年交保费</div>
106 + <div class="bg-gray-50 rounded-lg border border-gray-200 p-3 flex justify-between items-center">
107 + <nut-input
108 + v-model="form.premium"
109 + type="digit"
110 + placeholder="请输入保费"
111 + class="!p-0 !bg-transparent flex-1 !text-base !text-gray-900"
112 + :border="false"
113 + />
114 + <span class="text-sm text-gray-500 ml-2">美元</span>
115 + </div>
116 + </div>
117 + </div>
118 +
119 + <!-- Footer Buttons -->
120 + <div class="p-4 pt-2 pb-8 flex justify-between gap-4 bg-gray-50">
121 + <div
122 + class="flex-1 py-3 text-center border border-blue-600 text-blue-600 rounded-lg text-base bg-white"
123 + @click="close"
124 + >
125 + 取消
126 + </div>
127 + <div
128 + class="flex-1 py-3 text-center bg-blue-600 text-white rounded-lg text-base"
129 + @click="submit"
130 + >
131 + 提交申请
132 + </div>
133 + </div>
134 + </div>
135 +</template>
136 +
137 +<script setup>
138 +/**
139 + * @description 录入计划书 - 方案B 内容组件
140 + * @emits close - 关闭弹窗事件
141 + * @emits submit - 提交事件,携带表单数据
142 + */
143 +import { reactive, defineEmits } from 'vue';
144 +
145 +const emit = defineEmits(['close', 'submit']);
146 +
147 +const form = reactive({
148 + currency: '美元保单',
149 + plan: '基础情景',
150 + gender: 'female',
151 + age: '30',
152 + insurancePeriod: '终身',
153 + paymentPeriod: '10年交',
154 + premium: '100000',
155 +});
156 +
157 +const paymentPeriods = ['10年交', '3年交', '5年交', '躸交', '2年交'];
158 +
159 +const close = () => {
160 + emit('close');
161 +};
162 +
163 +const submit = () => {
164 + console.log('SchemeB Submit:', form);
165 + emit('submit', form);
166 +};
167 +</script>
168 +
169 +<style lang="less" scoped>
170 +:deep(.nut-input) {
171 + padding: 0;
172 + background: transparent;
173 +}
174 +</style>
...@@ -74,7 +74,7 @@ ...@@ -74,7 +74,7 @@
74 <nut-button 74 <nut-button
75 color="#2563EB" 75 color="#2563EB"
76 class="flex-1 !h-[64rpx] !rounded-[16rpx] !text-[26rpx] !m-0" 76 class="flex-1 !h-[64rpx] !rounded-[16rpx] !text-[26rpx] !m-0"
77 - @tap="openWebView('https://https://oa-dev.onwall.cn/f/custom_form/front/#/')" 77 + @tap="openPlanPopup('A')"
78 > 78 >
79 计划书 79 计划书
80 </nut-button> 80 </nut-button>
...@@ -107,7 +107,7 @@ ...@@ -107,7 +107,7 @@
107 <nut-button 107 <nut-button
108 color="#2563EB" 108 color="#2563EB"
109 class="flex-1 !h-[64rpx] !rounded-[16rpx] !text-[26rpx] !m-0" 109 class="flex-1 !h-[64rpx] !rounded-[16rpx] !text-[26rpx] !m-0"
110 - @tap="openWebView('https://https://oa-dev.onwall.cn/f/custom_form/front/#/')" 110 + @tap="openPlanPopup('B')"
111 > 111 >
112 计划书 112 计划书
113 </nut-button> 113 </nut-button>
...@@ -174,6 +174,20 @@ ...@@ -174,6 +174,20 @@
174 174
175 <!-- Bottom Tab Bar --> 175 <!-- Bottom Tab Bar -->
176 <TabBar current="home" /> 176 <TabBar current="home" />
177 +
178 + <!-- Plan Popup -->
179 + <PlanPopup v-model:visible="showPlanPopup">
180 + <SchemeA
181 + v-if="currentScheme === 'A'"
182 + @close="showPlanPopup = false"
183 + @submit="handlePlanSubmit"
184 + />
185 + <SchemeB
186 + v-if="currentScheme === 'B'"
187 + @close="showPlanPopup = false"
188 + @submit="handlePlanSubmit"
189 + />
190 + </PlanPopup>
177 </view> 191 </view>
178 </template> 192 </template>
179 193
...@@ -184,6 +198,27 @@ import { useGo } from '@/hooks/useGo'; ...@@ -184,6 +198,27 @@ import { useGo } from '@/hooks/useGo';
184 import { useListItemClick, ListType } from '@/composables/useListItemClick'; 198 import { useListItemClick, ListType } from '@/composables/useListItemClick';
185 import TabBar from '@/components/TabBar.vue'; 199 import TabBar from '@/components/TabBar.vue';
186 import IconFont from '@/components/IconFont.vue'; 200 import IconFont from '@/components/IconFont.vue';
201 +import PlanPopup from '@/components/PlanPopup/index.vue';
202 +import SchemeA from '@/components/PlanSchemes/SchemeA.vue';
203 +import SchemeB from '@/components/PlanSchemes/SchemeB.vue';
204 +
205 +// Plan Popup State
206 +const showPlanPopup = ref(false);
207 +const currentScheme = ref('A');
208 +
209 +const openPlanPopup = (scheme) => {
210 + currentScheme.value = scheme;
211 + showPlanPopup.value = true;
212 +};
213 +
214 +const handlePlanSubmit = (formData) => {
215 + console.log(`方案${currentScheme.value}提交:`, formData);
216 + showPlanPopup.value = false;
217 + Taro.showToast({
218 + title: '提交成功',
219 + icon: 'success'
220 + });
221 +};
187 222
188 // Grid navigation data with routes 223 // Grid navigation data with routes
189 const loopData0 = shallowRef([ 224 const loopData0 = shallowRef([
......