Bladeren bron

feat(matchmaker): 实现兼职红娘申请功能

- 新增红娘申请页面,包含完整的表单验证和提交逻辑
- 添加红娘申请相关的API接口和后端实体类
- 实现省市区三级联动选择器和地区数据初始化
- 创建编辑资料页面,支持头像上传和个人信息修改
- 优化红娘工作台切换按钮样式和交互体验
- 完善错误提示信息,增强用户体验和系统健壮性
李思佳 1 maand geleden
bovenliggende
commit
217055d550

+ 7 - 0
LiangZhiYUMao/pages.json

@@ -70,6 +70,13 @@
 				"navigationStyle": "custom"
 			}
 		},
+		{
+			"path": "pages/matchmaker-workbench/edit-profile",
+			"style": {
+				"navigationBarTitleText": "编辑资料",
+				"navigationStyle": "custom"
+			}
+		},
 		{
 			"path": "pages/page3/page3",
 			"style": {

+ 24 - 68
LiangZhiYUMao/pages/index/index.vue

@@ -4,13 +4,11 @@
 		<view class="top-bar">
 			<view class="logo">婚恋</view>
 			<view class="top-right-icons">
-				<!-- 红娘工作台切换按钮 -->
-			<view v-if="userInfo.isMatchmaker && parseInt(userInfo.isMatchmaker) === 1" 
+				<!-- 红娘工作台切换按钮 - 仅登录用户显示 -->
+			<view v-if="userInfo && userInfo.userId && userInfo.isMatchmaker && parseInt(userInfo.isMatchmaker) === 1" 
 				class="matchmaker-btn" @click="openMatchmakerPopup">
-				<view class="arrow-container">
-					<view class="arrow arrow-top"></view>
-					<view class="arrow arrow-bottom"></view>
-				</view>
+				<text class="switch-icon">🔄</text>
+				<text class="switch-text">切换工作台</text>
 			</view>
 				<!-- 消息通知图标 -->
 				<view class="msg-icon" @click="goToMessages">
@@ -956,77 +954,35 @@
 
 		.matchmaker-btn {
 			position: relative;
-			width: 68rpx;
-			height: 68rpx;
+			width: auto;
+			height: auto;
 			display: flex;
 			align-items: center;
 			justify-content: center;
 			background: transparent;
-			border-radius: 4rpx;
-			transition: all 0.2s ease;
+			border-radius: 0;
+			transition: all 0.3s ease;
+			padding: 10rpx 20rpx;
+			color: #E91E63;
+			font-weight: 600;
+			border: 2rpx solid #E91E63;
+			border-radius: 25rpx;
 			
 			&:active {
-				opacity: 0.6;
-				transform: scale(0.95);
-			}
-
-			.arrow-container {
-				display: flex;
-				flex-direction: column;
-				align-items: center;
-				gap: 4rpx;
-				width: 64rpx;
-			}
-
-			.arrow {
-				position: relative;
-				width: 64rpx;
-				height: 22rpx;
-			}
-
-			.arrow::before,
-			.arrow::after {
-				content: '';
-				position: absolute;
-				transition: all 0.2s ease;
-			}
-
-			/* 上方箭头 - 向右 */
-			.arrow-top::before {
-				top: 8rpx;
-				left: 0;
-				width: 40rpx;
-				height: 6rpx;
-				background: #333;
-			}
-
-			.arrow-top::after {
-				top: 0;
-				right: 0;
-				width: 0;
-				height: 0;
-				border-top: 11rpx solid transparent;
-				border-bottom: 11rpx solid transparent;
-				border-left: 24rpx solid #333;
+				opacity: 0.8;
+				transform: scale(0.98);
+				background: rgba(233, 30, 99, 0.1);
 			}
 
-			/* 下方箭头 - 向左 */
-			.arrow-bottom::before {
-				top: 8rpx;
-				right: 0;
-				width: 40rpx;
-				height: 6rpx;
-				background: #333;
+			.switch-icon {
+				font-size: 28rpx;
+				margin-right: 8rpx;
 			}
-
-			.arrow-bottom::after {
-				top: 0;
-				left: 0;
-				width: 0;
-				height: 0;
-				border-top: 11rpx solid transparent;
-				border-bottom: 11rpx solid transparent;
-				border-right: 24rpx solid #333;
+			
+			.switch-text {
+				font-size: 26rpx;
+				color: #E91E63;
+				font-weight: 600;
 			}
 		}
 

+ 542 - 0
LiangZhiYUMao/pages/matchmaker-workbench/edit-profile.vue

@@ -0,0 +1,542 @@
+<template>
+  <view class="edit-profile">
+    <!-- 顶部导航栏 -->
+    <view class="header">
+      <view class="back-btn" @click="handleBack">
+        <text class="back-icon">←</text>
+      </view>
+      <text class="header-title">编辑资料</text>
+      <view class="right-empty"></view>
+    </view>
+
+    <scroll-view scroll-y class="content">
+      <!-- 头像上传区域 -->
+      <view class="avatar-section">
+        <view class="avatar-container">
+          <image class="avatar" :src="userInfo.avatar || defaultAvatar" mode="aspectFill"></image>
+          <view class="avatar-upload-btn" @click="handleAvatarUpload">
+            <text class="upload-icon">📷</text>
+          </view>
+        </view>
+        <text class="avatar-text">更换头像</text>
+      </view>
+
+      <!-- 表单区域 -->
+      <view class="form-section">
+        <!-- 姓名 -->
+        <view class="form-item">
+          <view class="form-label">
+            <text class="label-icon">👤</text>
+            <text class="label-text">姓名</text>
+          </view>
+          <input
+              class="form-input"
+              v-model="userInfo.name"
+              placeholder="请输入姓名"
+              placeholder-style="color: #999"
+          >
+        </view>
+
+        <!-- 性别 -->
+        <view class="form-item">
+          <view class="form-label">
+            <text class="label-icon">⚧️</text>
+            <text class="label-text">性别</text>
+          </view>
+          <picker class="form-picker gender-picker" @change="handleGenderChange" :value="genderIndex" :range="genderOptions">
+            <view class="picker-content">
+              {{ userInfo.gender || '请选择性别' }}
+            </view>
+          </picker>
+        </view>
+
+        <!-- 个人简介 -->
+        <view class="form-item">
+          <view class="form-label">
+            <text class="label-icon">📝</text>
+            <text class="label-text">个人简介</text>
+          </view>
+          <textarea
+              class="form-textarea"
+              v-model="userInfo.bio"
+              placeholder="请输入个人简介"
+              placeholder-style="color: #999"
+              maxlength="200"
+              auto-height
+          ></textarea>
+        </view>
+
+        <!-- 邮箱 -->
+        <view class="form-item">
+          <view class="form-label">
+            <text class="label-icon">📧</text>
+            <text class="label-text">邮箱</text>
+          </view>
+          <input
+              class="form-input"
+              v-model="userInfo.email"
+              placeholder="请输入邮箱"
+              placeholder-style="color: #999"
+              type="email"
+          >
+        </view>
+
+        <!-- 省市区选择 -->
+        <view class="form-item">
+          <view class="form-label">
+            <text class="label-icon">📍</text>
+            <text class="label-text">所在地区</text>
+          </view>
+          <picker
+              class="form-picker"
+              mode="multiSelector"
+              :value="multiIndex"
+              :range="multiArray"
+              @columnchange="handleColumnChange"
+              @change="handleMultiPickerChange"
+          >
+            <view class="picker-content">{{ selectedArea || '请选择地区' }}</view>
+          </picker>
+        </view>
+
+        <!-- 详细地址 -->
+        <view class="form-item">
+          <view class="form-label">
+            <text class="label-icon">🏠</text>
+            <text class="label-text">详细地址</text>
+          </view>
+          <textarea
+              class="form-textarea"
+              v-model="userInfo.address_detail"
+              placeholder="请输入详细地址"
+              placeholder-style="color: #999"
+              maxlength="255"
+              auto-height
+          ></textarea>
+        </view>
+      </view>
+
+      <!-- 保存按钮 -->
+      <view class="save-btn-section">
+        <button class="save-btn" @click="handleSave">保存</button>
+      </view>
+    </scroll-view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      // 默认头像
+      defaultAvatar: 'https://q.qlogo.cn/qqapp/1105591438/05E13358B43B3D39D6AC2D6888828201/100',
+
+      // 用户信息
+      userInfo: {
+        avatar: '',
+        name: '',
+        gender: '',
+        bio: '我是一名专业的红娘,拥有丰富的婚恋服务经验,已成功帮助1200对单身男女找到幸福。',
+        email: '',
+        province_id: '',
+        city_id: '',
+        area_id: '',
+        address_detail: '',
+        province_name: '',
+        city_name: '',
+        area_name: ''
+      },
+      
+      // 省市区多列选择器数据
+      multiArray: [
+        ['北京市', '天津市', '河北省', '山西省', '内蒙古自治区'],
+        ['石家庄市', '唐山市', '秦皇岛市', '邯郸市', '邢台市', '保定市'],
+        ['竞秀区', '莲池区', '满城区', '清苑区', '徐水区', '涞水县']
+      ],
+      multiIndex: [0, 0, 0],
+      selectedArea: '',
+      
+      // 省市区详细数据(用于动态加载)
+      areaData: {
+        '北京市': {
+          '北京市': ['东城区', '西城区', '朝阳区', '海淀区', '丰台区', '石景山区']
+        },
+        '天津市': {
+          '天津市': ['和平区', '河东区', '河西区', '南开区', '河北区', '红桥区']
+        },
+        '河北省': {
+          '石家庄市': ['长安区', '桥西区', '新华区', '井陉矿区', '裕华区', '藁城区'],
+          '唐山市': ['路南区', '路北区', '古冶区', '开平区', '丰南区', '丰润区'],
+          '秦皇岛市': ['海港区', '山海关区', '北戴河区', '抚宁区', '青龙满族自治县'],
+          '邯郸市': ['邯山区', '丛台区', '复兴区', '峰峰矿区', '肥乡区', '永年区'],
+          '邢台市': ['桥东区', '桥西区', '邢台县', '临城县', '内丘县', '柏乡县'],
+          '保定市': ['竞秀区', '莲池区', '满城区', '清苑区', '徐水区', '涞水县']
+        },
+        '山西省': {
+          '太原市': ['小店区', '迎泽区', '杏花岭区', '尖草坪区', '万柏林区', '晋源区']
+        },
+        '内蒙古自治区': {
+          '呼和浩特市': ['新城区', '回民区', '玉泉区', '赛罕区', '土默特左旗']
+        }
+      },
+
+      // 性别选项
+      genderOptions: ['男', '女'],
+      genderIndex: 0
+    }
+  },
+  onLoad() {
+    // 从本地存储获取用户信息
+    this.loadUserInfo()
+  },
+  methods: {
+    // 加载用户信息
+    loadUserInfo() {
+      const userInfo = uni.getStorageSync('matchmakerUserInfo')
+      if (userInfo) {
+        this.userInfo = {...this.userInfo, ...userInfo}
+        // 设置性别索引
+        this.genderIndex = this.genderOptions.indexOf(this.userInfo.gender) || 0
+        
+        // 如果有省市区信息,设置选中的区域文本
+        if (this.userInfo.province_name && this.userInfo.city_name && this.userInfo.area_name) {
+          this.selectedArea = `${this.userInfo.province_name} ${this.userInfo.city_name} ${this.userInfo.area_name}`
+          
+          // 设置对应的索引
+          const provinceIndex = this.multiArray[0].indexOf(this.userInfo.province_name)
+          if (provinceIndex !== -1) {
+            this.multiIndex[0] = provinceIndex
+            // 更新城市列表
+            this.updateCityList(provinceIndex)
+            
+            const cityIndex = this.multiArray[1].indexOf(this.userInfo.city_name)
+            if (cityIndex !== -1) {
+              this.multiIndex[1] = cityIndex
+              // 更新区县列表
+              this.updateAreaList(provinceIndex, cityIndex)
+              
+              const areaIndex = this.multiArray[2].indexOf(this.userInfo.area_name)
+              if (areaIndex !== -1) {
+                this.multiIndex[2] = areaIndex
+              }
+            }
+          }
+        }
+      }
+    },
+    
+    // 更新城市列表
+    updateCityList(provinceIndex) {
+      const province = this.multiArray[0][provinceIndex]
+      const cities = Object.keys(this.areaData[province] || {})
+      this.multiArray[1] = cities
+      this.multiIndex[1] = 0
+      this.updateAreaList(provinceIndex, 0)
+    },
+    
+    // 更新区县列表
+    updateAreaList(provinceIndex, cityIndex) {
+      const province = this.multiArray[0][provinceIndex]
+      const city = this.multiArray[1][cityIndex]
+      const areas = this.areaData[province]?.[city] || []
+      this.multiArray[2] = areas
+      this.multiIndex[2] = 0
+    },
+    
+    // 处理列变化
+    handleColumnChange(e) {
+      const column = e.detail.column
+      const value = e.detail.value
+      this.multiIndex[column] = value
+      
+      // 根据列索引更新对应的数据
+      if (column === 0) {
+        // 省份变化,更新城市和区县
+        this.updateCityList(value)
+      } else if (column === 1) {
+        // 城市变化,更新区县
+        this.updateAreaList(this.multiIndex[0], value)
+      }
+    },
+    
+    // 处理多列选择器确认
+    handleMultiPickerChange(e) {
+      this.multiIndex = e.detail.value
+      const province = this.multiArray[0][this.multiIndex[0]]
+      const city = this.multiArray[1][this.multiIndex[1]]
+      const area = this.multiArray[2][this.multiIndex[2]]
+      
+      this.selectedArea = `${province} ${city} ${area}`
+      
+      // 更新用户信息
+      this.userInfo.province_id = this.multiIndex[0] + 1
+      this.userInfo.city_id = this.multiIndex[1] + 1
+      this.userInfo.area_id = this.multiIndex[2] + 1
+      this.userInfo.province_name = province
+      this.userInfo.city_name = city
+      this.userInfo.area_name = area
+    },
+
+    // 返回上一页
+    async handleBack() {
+      uni.navigateBack({
+        delta: 1
+      })
+    },
+
+    // 更换头像
+    handleAvatarUpload() {
+      uni.chooseImage({
+        count: 1,
+        sizeType: ['compressed'],
+        sourceType: ['album', 'camera'],
+        success: (res) => {
+          const tempFilePath = res.tempFilePaths[0]
+          // 这里可以添加上传图片到服务器的逻辑
+          this.userInfo.avatar = tempFilePath
+          uni.showToast({
+            title: '头像更换成功',
+            icon: 'success'
+          })
+        }
+      })
+    },
+
+    // 性别选择变化
+    handleGenderChange(e) {
+      const index = e.detail.value
+      this.genderIndex = index
+      this.userInfo.gender = this.genderOptions[index]
+    },
+
+    // 保存资料
+    handleSave() {
+      // 验证表单
+      if (!this.userInfo.name) {
+        uni.showToast({
+          title: '请输入姓名',
+          icon: 'none'
+        })
+        return
+      }
+
+      if (!this.userInfo.gender) {
+        uni.showToast({
+          title: '请选择性别',
+          icon: 'none'
+        })
+        return
+      }
+
+      // 保存到本地存储
+      uni.setStorageSync('matchmakerUserInfo', this.userInfo)
+
+      // 提示保存成功
+      uni.showToast({
+        title: '资料保存成功',
+        icon: 'success'
+      })
+
+      // 返回上一页
+      setTimeout(() => {
+        this.handleBack()
+      }, 1500)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.edit-profile {
+  min-height: 100vh;
+  background: #FFFFFF;
+  display: flex;
+  flex-direction: column;
+}
+
+/* 顶部导航栏 */
+.header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 25rpx 30rpx;
+  padding-top: calc(25rpx + env(safe-area-inset-top));
+  background: #FFFFFF;
+  border-bottom: 1rpx solid #F0F0F0;
+
+  .back-btn {
+    width: 44rpx;
+    height: 44rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+
+    .back-icon {
+      font-size: 40rpx;
+      color: #333;
+    }
+  }
+
+  .header-title {
+    font-size: 38rpx;
+    font-weight: bold;
+    color: #333;
+  }
+
+  .right-empty {
+    width: 44rpx;
+  }
+}
+
+.content {
+  flex: 1;
+  padding-bottom: 40rpx;
+}
+
+/* 头像上传区域 */
+.avatar-section {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: 40rpx 0;
+  border-bottom: 1rpx solid #F0F0F0;
+
+  .avatar-container {
+    position: relative;
+    width: 160rpx;
+    height: 160rpx;
+    margin-bottom: 20rpx;
+
+    .avatar {
+      width: 100%;
+      height: 100%;
+      border-radius: 50%;
+      background: #F5F5F5;
+    }
+
+    .avatar-upload-btn {
+      position: absolute;
+      bottom: 0;
+      right: 0;
+      width: 48rpx;
+      height: 48rpx;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      background: #FFFFFF;
+      border: 2rpx solid #E91E63;
+      border-radius: 50%;
+      box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
+
+      .upload-icon {
+        font-size: 28rpx;
+        color: #E91E63;
+      }
+    }
+  }
+
+  .avatar-text {
+    font-size: 28rpx;
+    color: #E91E63;
+    font-weight: 500;
+  }
+}
+
+/* 表单区域 */
+.form-section {
+  padding: 0 30rpx;
+
+  .form-item {
+    display: flex;
+    flex-direction: column;
+    padding: 25rpx 0;
+    border-bottom: 1rpx solid #F5F5F5;
+
+    &:last-child {
+      border-bottom: none;
+    }
+
+    .form-label {
+      display: flex;
+      align-items: center;
+      margin-bottom: 15rpx;
+
+      .label-icon {
+        font-size: 28rpx;
+        margin-right: 12rpx;
+      }
+
+      .label-text {
+        font-size: 28rpx;
+        color: #333;
+        font-weight: 500;
+      }
+    }
+
+    .form-input,
+    .form-picker {
+      width: 90%;
+      font-size: 28rpx;
+      color: #333;
+      padding: 18rpx 20rpx;
+      background: #F9F9F9;
+      border-radius: 12rpx;
+      border: 1rpx solid #E0E0E0;
+
+      &.readonly {
+        background: #F5F5F5;
+        color: #999;
+      }
+    }
+
+    .form-picker {
+      display: flex;
+      align-items: center;
+
+      .picker-content {
+        flex: 1;
+      }
+    }
+    
+    /* 性别选择器特定样式 */
+    .gender-picker {
+      width: 10%;
+    }
+
+    .form-textarea {
+      width: 90%;
+      font-size: 28rpx;
+      color: #333;
+      padding: 20rpx;
+      background: #F9F9F9;
+      border-radius: 12rpx;
+      border: 1rpx solid #E0E0E0;
+      min-height: 160rpx;
+      line-height: 1.5;
+    }
+  }
+}
+
+/* 保存按钮 */
+.save-btn-section {
+  padding: 40rpx 30rpx;
+
+  .save-btn {
+    width: 100%;
+    height: 90rpx;
+    background: linear-gradient(135deg, #E91E63 0%, #FF6B8A 100%);
+    color: #FFFFFF;
+    font-size: 32rpx;
+    font-weight: bold;
+    border-radius: 45rpx;
+    border: none;
+    box-shadow: 0 6rpx 20rpx rgba(233, 30, 99, 0.3);
+    transition: all 0.3s ease;
+
+    &:active {
+      transform: scale(0.98);
+      box-shadow: 0 3rpx 10rpx rgba(233, 30, 99, 0.2);
+    }
+  }
+}
+</style>

+ 27 - 75
LiangZhiYUMao/pages/matchmaker-workbench/index.vue

@@ -4,13 +4,10 @@
 		<view class="header">
 			<text class="header-title">红娘工作台</text>
 			<view class="header-right">
-				<view class="search-icon" @click="handleSearch"></view>
 				<!-- 退出红娘工作台按钮 -->
 				<view class="exit-workbench-btn" @click="openExitPopup">
-					<view class="arrow-container">
-						<view class="arrow arrow-top"></view>
-						<view class="arrow arrow-bottom"></view>
-					</view>
+					<text class="switch-icon">🔄</text>
+					<text class="switch-text">切换首页</text>
 				</view>
 			</view>
 		</view>
@@ -281,90 +278,45 @@ export default {
 			align-items: center;
 			gap: 20rpx;
 
-			.search-icon,
 			.exit-workbench-btn {
-				width: 68rpx;
-				height: 68rpx;
 				display: flex;
 				align-items: center;
 				justify-content: center;
 			}
 
-			.search-icon {
-				background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%23999"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/></svg>');
-				background-size: 44rpx 44rpx;
-				background-repeat: no-repeat;
-				background-position: center;
-			}
-
 			/* 退出工作台按钮样式 */
 			.exit-workbench-btn {
+				position: relative;
+				width: auto;
+				height: auto;
+				display: flex;
+				align-items: center;
+				justify-content: center;
 				background: transparent;
-				border-radius: 4rpx;
-				transition: all 0.2s ease;
+				border-radius: 0;
+				transition: all 0.3s ease;
+				padding: 10rpx 20rpx;
+				color: #E91E63;
+				font-weight: 600;
+				border: 2rpx solid #E91E63;
+				border-radius: 25rpx;
+				margin-left: 20rpx;
 				
 				&:active {
-					opacity: 0.6;
-					transform: scale(0.95);
-				}
-
-				.arrow-container {
-					display: flex;
-					flex-direction: column;
-					align-items: center;
-					gap: 4rpx;
-					width: 60rpx;
+					opacity: 0.8;
+					transform: scale(0.98);
+					background: rgba(233, 30, 99, 0.1);
 				}
 
-				.arrow {
-					position: relative;
-					width: 64rpx;
-					height: 22rpx;
+				.switch-icon {
+					font-size: 28rpx;
+					margin-right: 8rpx;
 				}
-
-				.arrow::before,
-				.arrow::after {
-					content: '';
-					position: absolute;
-					transition: all 0.2s ease;
-				}
-
-				/* 上方箭头 - 向右 */
-				.arrow-top::before {
-					top: 8rpx;
-					left: 0;
-					width: 40rpx;
-					height: 6rpx;
-					background: #333;
-				}
-
-				.arrow-top::after {
-					top: 0;
-					right: 0;
-					width: 0;
-					height: 0;
-					border-top: 11rpx solid transparent;
-					border-bottom: 11rpx solid transparent;
-					border-left: 24rpx solid #333;
-				}
-
-				/* 下方箭头 - 向左 */
-				.arrow-bottom::before {
-					top: 8rpx;
-					right: 0;
-					width: 40rpx;
-					height: 6rpx;
-					background: #333;
-				}
-
-				.arrow-bottom::after {
-					top: 0;
-					left: 0;
-					width: 0;
-					height: 0;
-					border-top: 11rpx solid transparent;
-					border-bottom: 11rpx solid transparent;
-					border-right: 24rpx solid #333;
+				
+				.switch-text {
+					font-size: 26rpx;
+					color: #E91E63;
+					font-weight: 600;
 				}
 			}
 		}

+ 2 - 3
LiangZhiYUMao/pages/matchmaker-workbench/mine.vue

@@ -161,9 +161,8 @@
 			// 编辑资料
 			handleEditProfile() {
 				console.log('编辑资料')
-				uni.showToast({
-					title: '编辑资料开发中',
-					icon: 'none'
+				uni.navigateTo({
+					url: '/pages/matchmaker-workbench/edit-profile'
 				})
 			},
 			// 账户设置

+ 61 - 5
LiangZhiYUMao/pages/part-time-matchmaker/index.vue

@@ -391,7 +391,7 @@
 			},
 			
 			// 提交申请
-			handleSubmit() {
+			async handleSubmit() {
 				// 表单验证
 				if (!this.formData.name) {
 					uni.showToast({
@@ -453,6 +453,14 @@
 					return
 				}
 				
+				if (!this.formData.experience) {
+					uni.showToast({
+						title: '请输入婚姻介绍经验',
+						icon: 'none'
+					})
+					return
+				}
+				
 				if (!this.formData.startTime || !this.formData.endTime) {
 					uni.showToast({
 						title: '请选择可服务时间',
@@ -461,17 +469,57 @@
 					return
 				}
 				
+				if (!this.formData.introduction) {
+					uni.showToast({
+						title: '请输入个人简介',
+						icon: 'none'
+					})
+					return
+				}
+				
 				uni.showModal({
 					title: '提交申请',
 					content: '确认提交兼职红娘申请吗?',
-					success: (res) => {
+					success: async (res) => {
 						if (res.confirm) {
 							uni.showLoading({
 								title: '提交中...'
 							})
 							
-							// TODO: 调用后端接口提交申请
-							setTimeout(() => {
+							try {
+								// 获取当前登录用户ID
+								const userInfo = uni.getStorageSync('userInfo')
+								if (!userInfo || !userInfo.userId) {
+									uni.hideLoading()
+									uni.showToast({
+										title: '请先登录',
+										icon: 'none'
+									})
+									setTimeout(() => {
+										uni.navigateTo({
+											url: '/pages/page3/page3'
+										})
+									}, 1500)
+									return
+								}
+								
+								// 组装提交数据
+								const submitData = {
+									userId: userInfo.userId,
+									name: this.formData.name,
+									phone: this.formData.phone,
+									email: this.formData.email,
+									age: parseInt(this.formData.age),
+									gender: this.formData.gender,
+									area: this.areaDisplayText, // 使用显示文本作为地区
+									experience: this.formData.experience,
+									serverTime: `${this.formData.startTime}-${this.formData.endTime}`,
+									introduction: this.formData.introduction
+								}
+								
+								// 调用后端接口提交申请
+								await api.matchmaker.submitApply(submitData)
+								
 								uni.hideLoading()
 								uni.showModal({
 									title: '申请成功',
@@ -499,7 +547,15 @@
 										this.timeSlotDisplayText = ''
 									}
 								})
-							}, 1500)
+							} catch (error) {
+								uni.hideLoading()
+								console.error('提交申请失败:', error)
+								uni.showToast({
+									title: error.message || '提交失败,请稍后重试',
+									icon: 'none',
+									duration: 2000
+								})
+							}
 						}
 					}
 				})

+ 8 - 1
LiangZhiYUMao/utils/api.js

@@ -33,7 +33,7 @@ const request = (options) => {
             resolve(res.data.data || res.data)
           } else {
             uni.showToast({
-              title: res.data.message || '请求失败',
+              title: res.data.message || res.data.msg || '请求失败',
               icon: 'none'
             })
             reject(res.data)
@@ -256,6 +256,13 @@ export default {
       data 
     }),
     
+    // 提交红娘申请
+    submitApply: (data) => request({
+      url: '/matchmaker-apply/submit',
+      method: 'POST',
+      data
+    }),
+    
     // 工作台相关
     getWorkbenchData: () => request({ url: '/matchmaker/workbench/data' }),
     

+ 12 - 0
common/src/main/java/com/zhentao/mapper/MatchmakerApplyMapper.java

@@ -0,0 +1,12 @@
+package com.zhentao.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zhentao.pojo.MatchmakerApply;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 红娘申请Mapper接口
+ */
+@Mapper
+public interface MatchmakerApplyMapper extends BaseMapper<MatchmakerApply> {
+}

+ 53 - 0
common/src/main/java/com/zhentao/pojo/MatchmakerApply.java

@@ -0,0 +1,53 @@
+package com.zhentao.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+/**
+ * 红娘申请实体类
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@TableName("matchmaker_apply")
+public class MatchmakerApply {
+    
+    @TableId(type = IdType.AUTO)
+    private Long applyId;
+    
+    private Integer userId;
+    
+    private String name;
+    
+    private String phone;
+    
+    private String email;
+    
+    private Integer age;
+    
+    private Integer gender; // 0-未知, 1-男, 2-女
+    
+    private String area;
+    
+    private String experience;
+    
+    private String serverTime;
+    
+    private String introduction;
+    
+    private LocalDateTime createTime;
+    
+    private String createMan;
+    
+    private LocalDateTime updateTime;
+    
+    private String updateMan;
+    
+    private Integer status; // 0-正常, 1-禁止, 默认为0
+}

+ 17 - 0
common/src/main/java/com/zhentao/service/MatchmakerApplyService.java

@@ -0,0 +1,17 @@
+package com.zhentao.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zhentao.pojo.MatchmakerApply;
+
+/**
+ * 红娘申请Service接口
+ */
+public interface MatchmakerApplyService extends IService<MatchmakerApply> {
+    
+    /**
+     * 提交红娘申请
+     * @param matchmakerApply 申请信息
+     * @return 是否成功
+     */
+    boolean submitApply(MatchmakerApply matchmakerApply);
+}

+ 32 - 0
common/src/main/java/com/zhentao/service/impl/MatchmakerApplyServiceImpl.java

@@ -0,0 +1,32 @@
+package com.zhentao.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhentao.mapper.MatchmakerApplyMapper;
+import com.zhentao.pojo.MatchmakerApply;
+import com.zhentao.service.MatchmakerApplyService;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+
+/**
+ * 红娘申请Service实现类
+ */
+@Service
+public class MatchmakerApplyServiceImpl extends ServiceImpl<MatchmakerApplyMapper, MatchmakerApply> 
+        implements MatchmakerApplyService {
+    
+    @Override
+    public boolean submitApply(MatchmakerApply matchmakerApply) {
+        // 设置创建时间
+        matchmakerApply.setCreateTime(LocalDateTime.now());
+        matchmakerApply.setUpdateTime(LocalDateTime.now());
+        
+        // 设置默认状态为正常
+        if (matchmakerApply.getStatus() == null) {
+            matchmakerApply.setStatus(0);
+        }
+        
+        // 保存申请信息
+        return this.save(matchmakerApply);
+    }
+}

+ 8 - 0
common/src/main/resources/com/zhentao/mapper/MatchmakerApplyMapper.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zhentao.mapper.MatchmakerApplyMapper">
+    
+    <!-- 这里可以添加自定义SQL语句 -->
+    <!-- MyBatis-Plus已经提供了基础的CRUD操作 -->
+    
+</mapper>

+ 82 - 0
service/homePage/src/main/java/com/zhentao/controller/MatchmakerApplyController.java

@@ -0,0 +1,82 @@
+package com.zhentao.controller;
+
+import com.zhentao.common.Result;
+import com.zhentao.pojo.MatchmakerApply;
+import com.zhentao.service.MatchmakerApplyService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * 红娘申请控制器
+ */
+@RestController
+@RequestMapping("/api/matchmaker-apply")
+@CrossOrigin(origins = "*")
+public class MatchmakerApplyController {
+    
+    @Autowired
+    private MatchmakerApplyService matchmakerApplyService;
+    
+    /**
+     * 提交红娘申请
+     * @param matchmakerApply 申请信息(包含userId和表单数据)
+     * @return 申请结果
+     */
+    @PostMapping("/submit")
+    public Result<String> submitApply(@RequestBody MatchmakerApply matchmakerApply) {
+        try {
+            // 验证必填字段
+            if (matchmakerApply.getUserId() == null) {
+                return Result.error("用户ID不能为空");
+            }
+            
+            if (matchmakerApply.getName() == null || matchmakerApply.getName().trim().isEmpty()) {
+                return Result.error("姓名不能为空");
+            }
+            
+            if (matchmakerApply.getPhone() == null || matchmakerApply.getPhone().trim().isEmpty()) {
+                return Result.error("手机号不能为空");
+            }
+            
+            if (matchmakerApply.getEmail() == null || matchmakerApply.getEmail().trim().isEmpty()) {
+                return Result.error("邮箱不能为空");
+            }
+            
+            if (matchmakerApply.getAge() == null) {
+                return Result.error("年龄不能为空");
+            }
+            
+            if (matchmakerApply.getGender() == null) {
+                return Result.error("性别不能为空");
+            }
+            
+            if (matchmakerApply.getArea() == null || matchmakerApply.getArea().trim().isEmpty()) {
+                return Result.error("所在地区不能为空");
+            }
+            
+            if (matchmakerApply.getExperience() == null || matchmakerApply.getExperience().trim().isEmpty()) {
+                return Result.error("婚姻介绍经验不能为空");
+            }
+            
+            if (matchmakerApply.getServerTime() == null || matchmakerApply.getServerTime().trim().isEmpty()) {
+                return Result.error("可服务时间不能为空");
+            }
+            
+            if (matchmakerApply.getIntroduction() == null || matchmakerApply.getIntroduction().trim().isEmpty()) {
+                return Result.error("个人简介不能为空");
+            }
+            
+            // 提交申请
+            boolean success = matchmakerApplyService.submitApply(matchmakerApply);
+            
+            if (success) {
+                return Result.success("申请提交成功,请等待审核");
+            } else {
+                return Result.error("申请提交失败,请稍后重试");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return Result.error("申请提交失败:" + e.getMessage());
+        }
+    }
+}