index.vue 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998
  1. <template>
  2. <view class="matchmaker-page">
  3. <!-- 顶部导航栏 -->
  4. <view class="header">
  5. <view class="back-btn" @click="goBack">
  6. <text class="back-icon">←</text>
  7. </view>
  8. <text class="header-title">兼职红娘</text>
  9. <view class="placeholder"></view>
  10. </view>
  11. <scroll-view scroll-y class="content">
  12. <!-- 顶部Banner -->
  13. <view class="top-banner">
  14. <text class="banner-title">加入我们的红娘团队</text>
  15. <text class="banner-subtitle">成为传递幸福的使者,利用闲暇时间帮助更多人</text>
  16. <text class="banner-subtitle">找到生命中的另一半,还能获得丰厚报酬</text>
  17. </view>
  18. <!-- 申请成为红娘按钮 -->
  19. <view class="action-button" @click="scrollToForm">
  20. <text class="button-text">立即申请</text>
  21. </view>
  22. <!-- 特点列表 -->
  23. <view class="features-section">
  24. <view class="feature-card">
  25. <text class="feature-icon">⏰</text>
  26. <view class="feature-content">
  27. <text class="feature-title">时间灵活</text>
  28. <text class="feature-desc">利用碎片时间工作,不影响主业,轻松实现副业增收</text>
  29. </view>
  30. </view>
  31. <view class="feature-card">
  32. <text class="feature-icon">💰</text>
  33. <view class="feature-content">
  34. <text class="feature-title">丰厚报酬</text>
  35. <text class="feature-desc">每成功匹配一对,可获得高额佣金,多劳多得</text>
  36. </view>
  37. </view>
  38. <view class="feature-card">
  39. <text class="feature-icon">📚</text>
  40. <view class="feature-content">
  41. <text class="feature-title">免费培训</text>
  42. <text class="feature-desc">提供专业婚恋知识和匹配技巧培训,快速上手</text>
  43. </view>
  44. </view>
  45. </view>
  46. <!-- 申请表单 -->
  47. <view class="form-section" id="application-form">
  48. <view class="form-title">申请加入</view>
  49. <view class="form-group">
  50. <text class="form-label">姓名:</text>
  51. <input class="form-input" v-model="formData.name" placeholder="请输入您的姓名" />
  52. </view>
  53. <view class="form-group">
  54. <text class="form-label">手机号:</text>
  55. <input
  56. class="form-input"
  57. v-model="formData.phone"
  58. type="number"
  59. placeholder="请输入您的手机号"
  60. maxlength="11"
  61. @input="checkPhoneFormat"
  62. @blur="validatePhone"
  63. :class="{ 'input-error': phoneError }"
  64. />
  65. <!-- 错误提示文本 -->
  66. <text class="error-text" v-if="phoneError">{{ phoneErrorText }}</text>
  67. </view>
  68. <view class="form-group">
  69. <text class="form-label">电子邮箱:</text>
  70. <input class="form-input" v-model="formData.email" placeholder="请输入您的电子邮箱" />
  71. </view>
  72. <view class="form-group">
  73. <text class="form-label">年龄:</text>
  74. <input class="form-input" v-model="formData.age" type="number" placeholder="请输入您的年龄" />
  75. </view>
  76. <view class="form-group">
  77. <text class="form-label">性别:</text>
  78. <view class="radio-group">
  79. <label class="radio-item" @click="formData.gender = 2">
  80. <view class="radio" :class="{ 'radio-checked': formData.gender === 2 }"></view>
  81. <text class="radio-label">女</text>
  82. </label>
  83. <label class="radio-item" @click="formData.gender = 1">
  84. <view class="radio" :class="{ 'radio-checked': formData.gender === 1 }"></view>
  85. <text class="radio-label">男</text>
  86. </label>
  87. </view>
  88. </view>
  89. <view class="form-group">
  90. <text class="form-label">所在地区:</text>
  91. <picker mode="multiSelector" :range="multiAreaData" range-key="name" :value="multiAreaIndex" @change="onAreaChange" @columnchange="onAreaColumnChange">
  92. <view class="form-input picker-input">
  93. <text :class="{ 'placeholder-text': !areaDisplayText }">{{ areaDisplayText || '请选择省市区' }}</text>
  94. <text class="picker-arrow">></text>
  95. </view>
  96. </picker>
  97. </view>
  98. <view class="form-group">
  99. <text class="form-label">婚姻介绍经验:</text>
  100. <input class="form-input" v-model="formData.experience" placeholder="请输入您的婚姻介绍经验" />
  101. </view>
  102. <!-- <view class="form-group">
  103. <text class="form-label">可服务时间:</text>
  104. <picker mode="multiSelector" :range="timeSlotData" :value="timeSlotIndex" @change="onTimeSlotChange">
  105. <view class="form-input picker-input">
  106. <text :class="{ 'placeholder-text': !timeSlotDisplayText }">{{ timeSlotDisplayText || '请选择服务时间段' }}</text>
  107. <text class="picker-arrow">></text>
  108. </view>
  109. </picker>
  110. </view> -->
  111. <view class="form-group">
  112. <text class="form-label">个人简介:</text>
  113. <textarea
  114. class="form-textarea"
  115. v-model="formData.introduction"
  116. placeholder="请简要介绍自己,包括您的性格特点、沟通能力、对红娘工作的理解等"
  117. maxlength="500"
  118. ></textarea>
  119. </view>
  120. <button
  121. class="submit-btn"
  122. :class="{ 'btn-disabled': buttonDisabled }"
  123. :disabled="buttonDisabled"
  124. @click="handleSubmit"
  125. >
  126. {{ buttonText }}
  127. </button>
  128. </view>
  129. <!-- 更多特点 -->
  130. <view class="more-features">
  131. <view class="feature-card">
  132. <text class="feature-icon">⏰</text>
  133. <view class="feature-content">
  134. <text class="feature-title">上传身边人信息</text>
  135. <text class="feature-desc">若您身边有单身朋友,可上传其信息至平台,成功匹配后也可获得奖励</text>
  136. </view>
  137. </view>
  138. <view class="feature-card">
  139. <text class="feature-icon">⏰</text>
  140. <view class="feature-content">
  141. <text class="feature-title">佣金提现</text>
  142. <text class="feature-desc">您的匹配佣金可随时申请提现,到账迅速,让您的努力及时获得回报</text>
  143. </view>
  144. </view>
  145. </view>
  146. </scroll-view>
  147. </view>
  148. </template>
  149. <script>
  150. import api from '@/utils/api.js'
  151. import userAuth from '@/utils/userAuth.js'
  152. export default {
  153. data() {
  154. return {
  155. // 新增手机号校验字段
  156. phoneError: false,
  157. formData: {
  158. name: '',
  159. phone: '',
  160. email: '',
  161. age: '',
  162. gender: '',
  163. provinceId: null,
  164. cityId: null,
  165. areaId: null,
  166. experience: '',
  167. startTime: '',
  168. endTime: '',
  169. introduction: ''
  170. },
  171. phoneErrorText: '',
  172. // 省市区数据
  173. provinceList: [],
  174. cityList: [],
  175. areaList: [],
  176. multiAreaData: [[], [], []], // 三级联动数据
  177. multiAreaIndex: [0, 0, 0], // 三级联动索引
  178. areaDisplayText: '',
  179. // 时间段数据
  180. hourOptions: Array.from({ length: 24 }, (_, i) => {
  181. const hour = String(i).padStart(2, '0')
  182. return `${hour}:00`
  183. }),
  184. timeSlotData: [[], []], // [开始时间, 结束时间]
  185. timeSlotIndex: [0, 0],
  186. timeSlotDisplayText: '',
  187. // 按钮状态
  188. buttonText: '提交申请',
  189. buttonDisabled: false,
  190. applyStatus: null // null-未申请, 0-已通过, 1-已拒绝, 2-审核中
  191. }
  192. },
  193. onLoad() {
  194. // 初始化时间段数据
  195. this.timeSlotData = [this.hourOptions, this.hourOptions]
  196. // 加载省市区数据
  197. this.loadAreaData()
  198. // 检查申请状态
  199. this.checkApplyStatus()
  200. },
  201. methods: {
  202. // 实时校验手机号格式(输入时触发)
  203. checkPhoneFormat() {
  204. const phone = this.formData.phone.trim();
  205. this.phoneError = false;
  206. this.phoneErrorText = '';
  207. // 非空时才校验
  208. if (phone) {
  209. // 长度校验
  210. if (phone.length < 11) {
  211. this.phoneError = true;
  212. this.phoneErrorText = `手机号不足11位(当前${phone.length}位)`;
  213. } else if (phone.length > 11) {
  214. this.phoneError = true;
  215. this.phoneErrorText = '手机号超过11位';
  216. } else {
  217. // 格式校验(11位数字,以1开头)
  218. const phoneReg = /^1[3-9]\d{9}$/;
  219. if (!phoneReg.test(phone)) {
  220. this.phoneError = true;
  221. this.phoneErrorText = '手机号格式错误(请输入11位有效手机号)';
  222. }
  223. }
  224. }
  225. },
  226. // 失焦时最终校验
  227. validatePhone() {
  228. const phone = this.formData.phone.trim();
  229. if (!phone) {
  230. this.phoneError = false;
  231. this.phoneErrorText = '';
  232. return;
  233. }
  234. // 最终格式校验
  235. const phoneReg = /^1[3-9]\d{9}$/;
  236. if (!phoneReg.test(phone)) {
  237. this.phoneError = true;
  238. this.phoneErrorText = '请输入正确的11位手机号';
  239. }
  240. },
  241. // 返回上一页
  242. goBack() {
  243. uni.navigateBack()
  244. },
  245. // 滚动到表单
  246. scrollToForm() {
  247. uni.pageScrollTo({
  248. selector: '#application-form',
  249. duration: 300
  250. })
  251. },
  252. // 检查申请状态
  253. async checkApplyStatus() {
  254. try {
  255. // 获取用户ID
  256. const userId = await userAuth.checkLoginStatus({
  257. requireLogin: false,
  258. allowTestUser: false
  259. })
  260. if (!userId) {
  261. return
  262. }
  263. // 查询申请状态
  264. const result = await api.matchmaker.getApplyStatus(userId)
  265. if (result && result.hasApplied) {
  266. this.applyStatus = result.status
  267. this.updateButtonState(result.status)
  268. }
  269. } catch (error) {
  270. console.error('查询申请状态失败:', error)
  271. // 查询失败不影响页面显示,保持默认状态
  272. }
  273. },
  274. // 根据status更新按钮状态
  275. updateButtonState(status) {
  276. if (status === 2) {
  277. // 审核中
  278. this.buttonText = '审核中'
  279. this.buttonDisabled = true
  280. } else if (status === 0) {
  281. // 已成为红娘
  282. this.buttonText = '已成为红娘'
  283. this.buttonDisabled = true
  284. } else if (status === 1) {
  285. // 审核被拒绝,可以重新提交
  286. this.buttonText = '重新提交'
  287. this.buttonDisabled = false
  288. } else {
  289. // 其他状态,保持默认
  290. this.buttonText = '提交申请'
  291. this.buttonDisabled = false
  292. }
  293. },
  294. // 省市区相关方法
  295. // 加载省市区数据
  296. async loadAreaData() {
  297. try {
  298. // 加载省份列表
  299. const provinceRes = await api.area.getProvinces()
  300. if (Array.isArray(provinceRes)) {
  301. this.provinceList = provinceRes
  302. } else if (provinceRes && provinceRes.data) {
  303. this.provinceList = provinceRes.data
  304. } else if (provinceRes && provinceRes.code === 200 && provinceRes.data) {
  305. this.provinceList = provinceRes.data
  306. } else {
  307. this.provinceList = []
  308. }
  309. this.multiAreaData[0] = this.provinceList
  310. // 如果有省份,加载第一个省份的城市
  311. if (this.provinceList.length > 0) {
  312. await this.loadCitiesForProvince(this.provinceList[0].id)
  313. }
  314. } catch (e) {
  315. console.error('加载省份失败:', e)
  316. uni.showToast({
  317. title: '加载省份数据失败',
  318. icon: 'none'
  319. })
  320. }
  321. },
  322. // 根据省份ID加载城市
  323. async loadCitiesForProvince(provinceId) {
  324. if (!provinceId) return
  325. try {
  326. const cityRes = await api.area.getCities(provinceId)
  327. if (Array.isArray(cityRes)) {
  328. this.cityList = cityRes
  329. } else if (cityRes && cityRes.data) {
  330. this.cityList = cityRes.data
  331. } else if (cityRes && cityRes.code === 200 && cityRes.data) {
  332. this.cityList = cityRes.data
  333. } else {
  334. this.cityList = []
  335. }
  336. this.multiAreaData[1] = this.cityList
  337. // 如果有城市,加载第一个城市的区域
  338. if (this.cityList.length > 0) {
  339. await this.loadAreasForCity(this.cityList[0].id)
  340. }
  341. } catch (e) {
  342. console.error('加载城市失败:', e)
  343. this.cityList = []
  344. this.multiAreaData[1] = []
  345. }
  346. },
  347. // 根据城市ID加载区域
  348. async loadAreasForCity(cityId) {
  349. if (!cityId) return
  350. try {
  351. const areaRes = await api.area.getAreas(cityId)
  352. if (Array.isArray(areaRes)) {
  353. this.areaList = areaRes
  354. } else if (areaRes && areaRes.data) {
  355. this.areaList = areaRes.data
  356. } else if (areaRes && areaRes.code === 200 && areaRes.data) {
  357. this.areaList = areaRes.data
  358. } else {
  359. this.areaList = []
  360. }
  361. this.multiAreaData[2] = this.areaList
  362. } catch (e) {
  363. console.error('加载区域失败:', e)
  364. this.areaList = []
  365. this.multiAreaData[2] = []
  366. }
  367. },
  368. // 省市区选择器列变化事件
  369. async onAreaColumnChange(e) {
  370. const column = e.detail.column // 列索引:0-省,1-市,2-区
  371. const row = e.detail.value // 选中的行索引
  372. if (column === 0) {
  373. // 选择了省份
  374. const province = this.provinceList[row]
  375. if (province && province.id) {
  376. this.multiAreaIndex[0] = row
  377. this.multiAreaIndex[1] = 0
  378. this.multiAreaIndex[2] = 0
  379. // 加载该省份的城市
  380. await this.loadCitiesForProvince(province.id)
  381. }
  382. } else if (column === 1) {
  383. // 选择了城市
  384. const city = this.cityList[row]
  385. if (city && city.id) {
  386. this.multiAreaIndex[1] = row
  387. this.multiAreaIndex[2] = 0
  388. // 加载该城市的区域
  389. await this.loadAreasForCity(city.id)
  390. }
  391. } else if (column === 2) {
  392. // 选择了区域
  393. this.multiAreaIndex[2] = row
  394. }
  395. },
  396. // 省市区选择器确认事件
  397. onAreaChange(e) {
  398. const values = e.detail.value
  399. this.multiAreaIndex = values
  400. // 设置选中的省市区ID
  401. if (this.provinceList[values[0]]) {
  402. this.formData.provinceId = this.provinceList[values[0]].id
  403. }
  404. if (this.cityList[values[1]]) {
  405. this.formData.cityId = this.cityList[values[1]].id
  406. }
  407. if (this.areaList[values[2]]) {
  408. this.formData.areaId = this.areaList[values[2]].id
  409. }
  410. // 更新显示文本
  411. this.updateAreaDisplayText()
  412. },
  413. // 更新地区显示文本
  414. updateAreaDisplayText() {
  415. let text = ''
  416. if (this.provinceList[this.multiAreaIndex[0]]) {
  417. text += this.provinceList[this.multiAreaIndex[0]].name
  418. }
  419. if (this.cityList[this.multiAreaIndex[1]]) {
  420. text += ' ' + this.cityList[this.multiAreaIndex[1]].name
  421. }
  422. if (this.areaList[this.multiAreaIndex[2]]) {
  423. text += ' ' + this.areaList[this.multiAreaIndex[2]].name
  424. }
  425. this.areaDisplayText = text
  426. },
  427. // 时间段选择器确认事件
  428. onTimeSlotChange(e) {
  429. const values = e.detail.value
  430. this.timeSlotIndex = values
  431. const startTime = this.hourOptions[values[0]]
  432. const endTime = this.hourOptions[values[1]]
  433. // 验证结束时间必须大于开始时间
  434. if (values[1] <= values[0]) {
  435. uni.showToast({
  436. title: '结束时间必须大于开始时间',
  437. icon: 'none'
  438. })
  439. // 自动调整结束时间为开始时间+1
  440. if (values[0] < 23) {
  441. this.timeSlotIndex[1] = values[0] + 1
  442. this.formData.startTime = startTime
  443. this.formData.endTime = this.hourOptions[this.timeSlotIndex[1]]
  444. this.timeSlotDisplayText = `每天 ${startTime} - ${this.formData.endTime}`
  445. } else {
  446. // 如果开始时间是23:00,则结束时间设为23:00(表示到当天结束)
  447. this.formData.startTime = startTime
  448. this.formData.endTime = endTime
  449. this.timeSlotDisplayText = `每天 ${startTime} - ${endTime}`
  450. }
  451. } else {
  452. this.formData.startTime = startTime
  453. this.formData.endTime = endTime
  454. this.timeSlotDisplayText = `每天 ${startTime} - ${endTime}`
  455. }
  456. },
  457. // 提交申请
  458. async handleSubmit() {
  459. // 如果按钮被禁用,不执行提交
  460. if (this.buttonDisabled) {
  461. return
  462. }
  463. // 表单验证
  464. if (!this.formData.name) {
  465. uni.showToast({
  466. title: '请输入姓名',
  467. icon: 'none'
  468. })
  469. return
  470. }
  471. if (!this.formData.phone) {
  472. uni.showToast({
  473. title: '请输入手机号',
  474. icon: 'none'
  475. })
  476. return
  477. }
  478. // 验证手机号格式
  479. const phoneReg = /^1[3-9]\d{9}$/
  480. if (!phoneReg.test(this.formData.phone)) {
  481. uni.showToast({
  482. title: '请输入正确的手机号',
  483. icon: 'none'
  484. })
  485. return
  486. }
  487. if (!this.formData.email) {
  488. uni.showToast({
  489. title: '请输入电子邮箱',
  490. icon: 'none'
  491. })
  492. return
  493. }
  494. // 验证邮箱格式
  495. const emailReg = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
  496. if (!emailReg.test(this.formData.email)) {
  497. uni.showToast({
  498. title: '请输入正确的邮箱',
  499. icon: 'none'
  500. })
  501. return
  502. }
  503. if (!this.formData.age) {
  504. uni.showToast({
  505. title: '请输入年龄',
  506. icon: 'none'
  507. })
  508. return
  509. }
  510. if (!this.formData.gender) {
  511. uni.showToast({
  512. title: '请选择性别',
  513. icon: 'none'
  514. })
  515. return
  516. }
  517. if (!this.formData.provinceId || !this.formData.cityId || !this.formData.areaId) {
  518. uni.showToast({
  519. title: '请选择所在地区',
  520. icon: 'none'
  521. })
  522. return
  523. }
  524. if (!this.formData.experience) {
  525. uni.showToast({
  526. title: '请输入婚姻介绍经验',
  527. icon: 'none'
  528. })
  529. return
  530. }
  531. // if (!this.formData.startTime || !this.formData.endTime) {
  532. // uni.showToast({
  533. // title: '请选择可服务时间',
  534. // icon: 'none'
  535. // })
  536. // return
  537. // }
  538. if (!this.formData.introduction) {
  539. uni.showToast({
  540. title: '请输入个人简介',
  541. icon: 'none'
  542. })
  543. return
  544. }
  545. // 检查登录状态并获取用户ID
  546. const userId = await userAuth.checkLoginStatus({
  547. requireLogin: true,
  548. allowTestUser: false,
  549. redirectUrl: '/pages/part-time-matchmaker/index'
  550. })
  551. uni.showModal({
  552. title: '提交申请',
  553. content: '确认提交兼职红娘申请吗?',
  554. success: async (res) => {
  555. if (res.confirm) {
  556. uni.showLoading({
  557. title: '提交中...'
  558. })
  559. try {
  560. // 组装提交数据
  561. const submitData = {
  562. userId: userId,
  563. name: this.formData.name,
  564. phone: this.formData.phone,
  565. email: this.formData.email,
  566. age: parseInt(this.formData.age),
  567. gender: this.formData.gender,
  568. area: this.areaDisplayText, // 使用显示文本作为地区
  569. experience: this.formData.experience,
  570. serverTime: `${this.formData.startTime}-${this.formData.endTime}`,
  571. introduction: this.formData.introduction
  572. }
  573. // 调用后端接口提交申请
  574. await api.matchmaker.submitApply(submitData)
  575. uni.hideLoading()
  576. uni.showModal({
  577. title: '申请成功',
  578. content: '您的申请已提交,我们会在1-3个工作日内完成审核,请耐心等待。审核结果将通过短信或邮件通知您。',
  579. showCancel: false,
  580. success: () => {
  581. // 清空表单
  582. this.formData = {
  583. name: '',
  584. phone: '',
  585. email: '',
  586. age: '',
  587. gender: '',
  588. provinceId: null,
  589. cityId: null,
  590. areaId: null,
  591. experience: '',
  592. startTime: '',
  593. endTime: '',
  594. introduction: ''
  595. }
  596. this.multiAreaIndex = [0, 0, 0]
  597. this.areaDisplayText = ''
  598. this.timeSlotIndex = [0, 0]
  599. this.timeSlotDisplayText = ''
  600. // 重新检查申请状态,更新按钮
  601. this.checkApplyStatus()
  602. }
  603. })
  604. } catch (error) {
  605. uni.hideLoading()
  606. console.error('提交申请失败:', error)
  607. uni.showToast({
  608. title: error.message || '提交失败,请稍后重试',
  609. icon: 'none',
  610. duration: 2000
  611. })
  612. }
  613. }
  614. }
  615. })
  616. }
  617. }
  618. }
  619. </script>
  620. <style lang="scss" scoped>
  621. * {
  622. box-sizing: border-box;
  623. }
  624. .matchmaker-page {
  625. min-height: 100vh;
  626. background: #F5F5F5;
  627. display: flex;
  628. flex-direction: column;
  629. }
  630. /* 顶部导航栏 */
  631. .header {
  632. display: flex;
  633. align-items: center;
  634. justify-content: space-between;
  635. padding: 25rpx 30rpx;
  636. padding-top: calc(25rpx + env(safe-area-inset-top));
  637. background: linear-gradient(135deg, #FF8A9B 0%, #FFB4C0 100%);
  638. .back-btn {
  639. width: 70rpx;
  640. height: 70rpx;
  641. display: flex;
  642. align-items: center;
  643. justify-content: center;
  644. background: rgba(255, 255, 255, 0.2);
  645. border-radius: 50%;
  646. .back-icon {
  647. font-size: 44rpx;
  648. color: #FFFFFF;
  649. font-weight: bold;
  650. }
  651. }
  652. .header-title {
  653. font-size: 38rpx;
  654. font-weight: bold;
  655. color: #FFFFFF;
  656. }
  657. .placeholder {
  658. width: 70rpx;
  659. }
  660. }
  661. .content {
  662. flex: 1;
  663. background: #F5F5F5;
  664. padding-bottom: calc(40rpx + env(safe-area-inset-bottom));
  665. }
  666. /* 顶部Banner */
  667. .top-banner {
  668. background: linear-gradient(135deg, #E688A1 0%, #D97890 100%);
  669. padding: 50rpx 40rpx;
  670. text-align: center;
  671. .banner-title {
  672. display: block;
  673. font-size: 40rpx;
  674. font-weight: bold;
  675. color: #FFFFFF;
  676. margin-bottom: 25rpx;
  677. }
  678. .banner-subtitle {
  679. display: block;
  680. font-size: 26rpx;
  681. color: #FFFFFF;
  682. line-height: 1.6;
  683. opacity: 0.95;
  684. }
  685. }
  686. /* 兼职红娘按钮 */
  687. .action-button {
  688. margin: 35rpx 40rpx;
  689. padding: 25rpx;
  690. background: #FFFFFF;
  691. border: 3rpx solid #FF6B8A;
  692. border-radius: 15rpx;
  693. text-align: center;
  694. .button-text {
  695. font-size: 30rpx;
  696. color: #FF6B8A;
  697. font-weight: bold;
  698. }
  699. }
  700. /* 特点列表 */
  701. .features-section {
  702. padding: 0 40rpx 25rpx;
  703. }
  704. .more-features {
  705. padding: 0 40rpx 40rpx;
  706. }
  707. .features-section,
  708. .more-features {
  709. .feature-card {
  710. background: #F0F0F0;
  711. border-radius: 15rpx;
  712. padding: 30rpx;
  713. margin-bottom: 20rpx;
  714. display: flex;
  715. align-items: flex-start;
  716. .feature-icon {
  717. font-size: 42rpx;
  718. margin-right: 20rpx;
  719. flex-shrink: 0;
  720. }
  721. .feature-content {
  722. flex: 1;
  723. }
  724. .feature-title {
  725. display: block;
  726. font-size: 30rpx;
  727. font-weight: bold;
  728. color: #333333;
  729. margin-bottom: 12rpx;
  730. }
  731. .feature-desc {
  732. display: block;
  733. font-size: 24rpx;
  734. color: #666666;
  735. line-height: 1.5;
  736. }
  737. }
  738. }
  739. /* 申请表单 */
  740. .form-section {
  741. background: #FFFFFF;
  742. margin: 25rpx 40rpx;
  743. padding: 35rpx;
  744. border-radius: 15rpx;
  745. box-shadow: 0 4rpx 15rpx rgba(0, 0, 0, 0.05);
  746. box-sizing: border-box;
  747. .form-title {
  748. font-size: 34rpx;
  749. font-weight: bold;
  750. color: #333333;
  751. margin-bottom: 35rpx;
  752. text-align: center;
  753. }
  754. .form-group {
  755. margin-bottom: 30rpx;
  756. box-sizing: border-box;
  757. .input-error {
  758. border-color: #ff4757 !important;
  759. background-color: #fff5f5 !important;
  760. color: #ff4757;
  761. }
  762. .error-text {
  763. display: block;
  764. font-size: 22rpx;
  765. color: #ff4757;
  766. margin-top: 8rpx;
  767. padding-left: 5rpx;
  768. }
  769. .form-label {
  770. display: block;
  771. font-size: 26rpx;
  772. color: #333333;
  773. margin-bottom: 12rpx;
  774. font-weight: 500;
  775. }
  776. .form-input {
  777. width: 100%;
  778. height: 70rpx;
  779. padding: 0 20rpx;
  780. border: 1rpx solid #E0E0E0;
  781. border-radius: 10rpx;
  782. font-size: 26rpx;
  783. background: #FAFAFA;
  784. box-sizing: border-box;
  785. &:focus {
  786. border-color: #FF8A9B;
  787. background: #FFFFFF;
  788. }
  789. }
  790. .picker-input {
  791. display: flex;
  792. align-items: center;
  793. justify-content: space-between;
  794. cursor: pointer;
  795. .placeholder-text {
  796. color: #999999;
  797. }
  798. .picker-arrow {
  799. color: #CCCCCC;
  800. font-size: 24rpx;
  801. }
  802. }
  803. .form-textarea {
  804. width: 100%;
  805. min-height: 160rpx;
  806. padding: 15rpx 20rpx;
  807. border: 1rpx solid #E0E0E0;
  808. border-radius: 10rpx;
  809. font-size: 26rpx;
  810. line-height: 1.5;
  811. background: #FAFAFA;
  812. box-sizing: border-box;
  813. &:focus {
  814. border-color: #FF8A9B;
  815. background: #FFFFFF;
  816. }
  817. }
  818. .radio-group {
  819. display: flex;
  820. align-items: center;
  821. gap: 50rpx;
  822. .radio-item {
  823. display: flex;
  824. align-items: center;
  825. .radio {
  826. width: 36rpx;
  827. height: 36rpx;
  828. border: 3rpx solid #CCCCCC;
  829. border-radius: 50%;
  830. margin-right: 15rpx;
  831. position: relative;
  832. transition: all 0.3s;
  833. &.radio-checked {
  834. border-color: #FF6B8A;
  835. background: #FF6B8A;
  836. &::after {
  837. content: '';
  838. position: absolute;
  839. width: 16rpx;
  840. height: 16rpx;
  841. background: #FFFFFF;
  842. border-radius: 50%;
  843. top: 50%;
  844. left: 50%;
  845. transform: translate(-50%, -50%);
  846. }
  847. }
  848. }
  849. .radio-label {
  850. font-size: 28rpx;
  851. color: #333333;
  852. }
  853. }
  854. }
  855. }
  856. .submit-btn {
  857. width: 100%;
  858. height: 80rpx;
  859. background: linear-gradient(135deg, #FF8A9B 0%, #FF6B8A 100%);
  860. color: #FFFFFF;
  861. font-size: 30rpx;
  862. font-weight: bold;
  863. border: none;
  864. border-radius: 40rpx;
  865. margin-top: 30rpx;
  866. &.btn-disabled {
  867. background: #CCCCCC;
  868. color: #FFFFFF;
  869. opacity: 0.6;
  870. }
  871. }
  872. }
  873. </style>