|
|
@@ -1,24 +1,420 @@
|
|
|
<template>
|
|
|
<view class="container">
|
|
|
- <view class="page-header">
|
|
|
- <text class="page-title">服务角色申请</text>
|
|
|
+ <!-- 顶部导航 -->
|
|
|
+ <view class="nav-bar">
|
|
|
+ <view class="nav-back" @click="goBack">‹ 返回</view>
|
|
|
+ <text class="nav-title">服务角色申请</text>
|
|
|
+ <view class="nav-placeholder"></view>
|
|
|
</view>
|
|
|
- <view class="empty-state">
|
|
|
- <text class="empty-text">服务角色申请页面开发中</text>
|
|
|
+
|
|
|
+ <!-- 加载状态 -->
|
|
|
+ <view class="loading" v-if="loading">加载中...</view>
|
|
|
+
|
|
|
+ <template v-else-if="applyStatus === 'pending' || applyStatus === 'rejected'">
|
|
|
+ <!-- 已申请状态 -->
|
|
|
+ <view class="status-section">
|
|
|
+ <view class="status-icon">{{ applyStatus === 'pending' ? '⏳' : '❌' }}</view>
|
|
|
+ <text class="status-title">{{ applyStatus === 'pending' ? '申请审核中' : '申请被驳回' }}</text>
|
|
|
+ <text class="status-desc">{{ applyStatus === 'pending' ? '您的申请正在审核中,请耐心等待' : applyMessage || '请修改后重新申请' }}</text>
|
|
|
+ <view class="status-info" v-if="applyData">
|
|
|
+ <text class="info-text">申请时间:{{ formatTime(applyData.createdAt) }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="btn-group">
|
|
|
+ <button class="btn-primary" v-if="applyStatus === 'rejected'" @click="editApplication">重新申请</button>
|
|
|
+ <button class="btn-secondary" @click="goBack">返回首页</button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <!-- 申请表单 -->
|
|
|
+ <view v-else class="form-section">
|
|
|
+ <view class="form-card">
|
|
|
+ <view class="form-title">基本信息</view>
|
|
|
+
|
|
|
+ <view class="form-item">
|
|
|
+ <text class="label">姓名 <text class="required">*</text></text>
|
|
|
+ <input class="input" v-model="form.name" placeholder="请输入真实姓名" />
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="form-item">
|
|
|
+ <text class="label">手机号 <text class="required">*</text></text>
|
|
|
+ <input class="input" type="number" v-model="form.phone" placeholder="请输入手机号" maxlength="11" />
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="form-item">
|
|
|
+ <text class="label">选择角色 <text class="required">*</text></text>
|
|
|
+ <picker :range="roleOptions" range-key="label" @change="onRoleChange">
|
|
|
+ <view class="picker">
|
|
|
+ <text>{{ form.roleLabel || '请选择角色' }}</text>
|
|
|
+ <text class="picker-arrow">›</text>
|
|
|
+ </view>
|
|
|
+ </picker>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="form-item">
|
|
|
+ <text class="label">身份证照片 <text class="required">*</text></text>
|
|
|
+ <view class="upload-area" @click="uploadIdCard">
|
|
|
+ <image v-if="form.idCardUrl" :src="form.idCardUrl" mode="aspectFit" class="upload-preview" />
|
|
|
+ <text v-else class="upload-placeholder">+ 上传身份证</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="form-item">
|
|
|
+ <text class="label">资质证书</text>
|
|
|
+ <view class="upload-area" @click="uploadCertificate">
|
|
|
+ <image v-if="form.certificateUrl" :src="form.certificateUrl" mode="aspectFit" class="upload-preview" />
|
|
|
+ <text v-else class="upload-placeholder">+ 上传资质证书(选填)</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="form-item">
|
|
|
+ <text class="label">申请说明</text>
|
|
|
+ <textarea class="textarea" v-model="form.remark" placeholder="请简述您的资质和经验(选填)" maxlength="200" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="tips-card">
|
|
|
+ <text class="tips-title">申请须知</text>
|
|
|
+ <text class="tips-text">• 请确保填写信息真实有效</text>
|
|
|
+ <text class="tips-text">• 审核时间一般为1-3个工作日</text>
|
|
|
+ <text class="tips-text">• 审核通过后将获得相应角色权限</text>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <button class="submit-btn" :disabled="submitting" @click="submitApplication">
|
|
|
+ {{ submitting ? '提交中...' : '提交申请' }}
|
|
|
+ </button>
|
|
|
</view>
|
|
|
</view>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
+import { submitServiceRoleApply, getMyServiceRoleApply, uploadServiceRoleImage } from '@/utils/api'
|
|
|
+
|
|
|
export default {
|
|
|
- data() { return {} }
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ loading: false,
|
|
|
+ submitting: false,
|
|
|
+ applyStatus: null,
|
|
|
+ applyData: null,
|
|
|
+ applyMessage: '',
|
|
|
+ form: {
|
|
|
+ name: '',
|
|
|
+ phone: '',
|
|
|
+ role: '',
|
|
|
+ roleLabel: '',
|
|
|
+ idCardUrl: '',
|
|
|
+ certificateUrl: '',
|
|
|
+ remark: ''
|
|
|
+ },
|
|
|
+ roleOptions: [
|
|
|
+ { label: '成长规划师', value: 'teacher' },
|
|
|
+ { label: '营养师', value: 'nutritionist' },
|
|
|
+ { label: '健康管家', value: 'butler' }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onLoad() {
|
|
|
+ this.loadApplication()
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ loadApplication() {
|
|
|
+ this.loading = true
|
|
|
+ getMyServiceRoleApply().then(res => {
|
|
|
+ if (res.code === 200 && res.data) {
|
|
|
+ this.applyStatus = res.data.status
|
|
|
+ this.applyData = res.data
|
|
|
+ if (res.data.status === 'rejected') {
|
|
|
+ this.applyMessage = res.data.rejectReason || '申请未通过,请修改后重新申请'
|
|
|
+ }
|
|
|
+ } else if (res.code === 404) {
|
|
|
+ this.applyStatus = null
|
|
|
+ }
|
|
|
+ }).catch(() => {
|
|
|
+ this.applyStatus = null
|
|
|
+ }).finally(() => {
|
|
|
+ this.loading = false
|
|
|
+ })
|
|
|
+ },
|
|
|
+ onRoleChange(e) {
|
|
|
+ const idx = e.detail.value
|
|
|
+ this.form.role = this.roleOptions[idx].value
|
|
|
+ this.form.roleLabel = this.roleOptions[idx].label
|
|
|
+ },
|
|
|
+ uploadIdCard() {
|
|
|
+ this.uploadImage('idCard')
|
|
|
+ },
|
|
|
+ uploadCertificate() {
|
|
|
+ this.uploadImage('certificate')
|
|
|
+ },
|
|
|
+ uploadImage(field) {
|
|
|
+ uni.chooseImage({
|
|
|
+ count: 1,
|
|
|
+ sizeType: ['compressed'],
|
|
|
+ sourceType: ['album', 'camera'],
|
|
|
+ success: (res) => {
|
|
|
+ const tempFilePath = res.tempFilePaths[0]
|
|
|
+ uni.showLoading({ title: '上传中...' })
|
|
|
+ uploadServiceRoleImage(tempFilePath).then(uploadRes => {
|
|
|
+ uni.hideLoading()
|
|
|
+ if (uploadRes.code === 200) {
|
|
|
+ this.form[field + 'Url'] = uploadRes.data.url
|
|
|
+ }
|
|
|
+ }).catch(() => {
|
|
|
+ uni.hideLoading()
|
|
|
+ uni.showToast({ title: '上传失败', icon: 'none' })
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ submitApplication() {
|
|
|
+ if (!this.form.name) {
|
|
|
+ return uni.showToast({ title: '请输入姓名', icon: 'none' })
|
|
|
+ }
|
|
|
+ if (!this.form.phone || this.form.phone.length !== 11) {
|
|
|
+ return uni.showToast({ title: '请输入正确的手机号', icon: 'none' })
|
|
|
+ }
|
|
|
+ if (!this.form.role) {
|
|
|
+ return uni.showToast({ title: '请选择角色', icon: 'none' })
|
|
|
+ }
|
|
|
+ if (!this.form.idCardUrl) {
|
|
|
+ return uni.showToast({ title: '请上传身份证照片', icon: 'none' })
|
|
|
+ }
|
|
|
+
|
|
|
+ this.submitting = true
|
|
|
+ submitServiceRoleApply({
|
|
|
+ name: this.form.name,
|
|
|
+ phone: this.form.phone,
|
|
|
+ role: this.form.role,
|
|
|
+ idCardUrl: this.form.idCardUrl,
|
|
|
+ certificateUrl: this.form.certificateUrl,
|
|
|
+ remark: this.form.remark
|
|
|
+ }).then(res => {
|
|
|
+ this.submitting = false
|
|
|
+ if (res.code === 200) {
|
|
|
+ uni.showToast({ title: '申请已提交', icon: 'success' })
|
|
|
+ setTimeout(() => {
|
|
|
+ this.loadApplication()
|
|
|
+ }, 1500)
|
|
|
+ } else {
|
|
|
+ uni.showToast({ title: res.message || '提交失败', icon: 'none' })
|
|
|
+ }
|
|
|
+ }).catch(() => {
|
|
|
+ this.submitting = false
|
|
|
+ uni.showToast({ title: '提交失败,请重试', icon: 'none' })
|
|
|
+ })
|
|
|
+ },
|
|
|
+ editApplication() {
|
|
|
+ this.applyStatus = null
|
|
|
+ this.applyMessage = ''
|
|
|
+ },
|
|
|
+ goBack() {
|
|
|
+ uni.navigateBack()
|
|
|
+ },
|
|
|
+ formatTime(time) {
|
|
|
+ if (!time) return ''
|
|
|
+ return time.replace('T', ' ').substring(0, 16)
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
-<style>
|
|
|
-.container { min-height: 100vh; background: #f5f7fa; padding: 30rpx; }
|
|
|
-.page-header { margin-bottom: 30rpx; }
|
|
|
-.page-title { font-size: 36rpx; font-weight: 700; color: #333; }
|
|
|
-.empty-state { text-align: center; padding: 120rpx 0; }
|
|
|
-.empty-text { color: #999; font-size: 28rpx; }
|
|
|
+<style scoped>
|
|
|
+.container {
|
|
|
+ min-height: 100vh;
|
|
|
+ background: #f5f7fa;
|
|
|
+}
|
|
|
+.nav-bar {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ height: 88rpx;
|
|
|
+ background: #fff;
|
|
|
+ border-bottom: 1rpx solid #eee;
|
|
|
+ padding: 0 30rpx;
|
|
|
+}
|
|
|
+.nav-back {
|
|
|
+ font-size: 32rpx;
|
|
|
+ color: #666;
|
|
|
+ padding: 0 20rpx;
|
|
|
+}
|
|
|
+.nav-title {
|
|
|
+ flex: 1;
|
|
|
+ text-align: center;
|
|
|
+ font-size: 32rpx;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #333;
|
|
|
+}
|
|
|
+.nav-placeholder {
|
|
|
+ width: 60rpx;
|
|
|
+}
|
|
|
+.loading {
|
|
|
+ text-align: center;
|
|
|
+ padding: 100rpx;
|
|
|
+ color: #999;
|
|
|
+}
|
|
|
+.status-section {
|
|
|
+ background: #fff;
|
|
|
+ margin: 30rpx;
|
|
|
+ border-radius: 20rpx;
|
|
|
+ padding: 60rpx 40rpx;
|
|
|
+ text-align: center;
|
|
|
+}
|
|
|
+.status-icon {
|
|
|
+ font-size: 80rpx;
|
|
|
+ margin-bottom: 20rpx;
|
|
|
+}
|
|
|
+.status-title {
|
|
|
+ display: block;
|
|
|
+ font-size: 36rpx;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #333;
|
|
|
+ margin-bottom: 16rpx;
|
|
|
+}
|
|
|
+.status-desc {
|
|
|
+ display: block;
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #666;
|
|
|
+ margin-bottom: 30rpx;
|
|
|
+}
|
|
|
+.status-info {
|
|
|
+ margin-bottom: 40rpx;
|
|
|
+}
|
|
|
+.info-text {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #999;
|
|
|
+}
|
|
|
+.btn-group {
|
|
|
+ display: flex;
|
|
|
+ gap: 20rpx;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+.btn-primary {
|
|
|
+ background: linear-gradient(135deg, #F97316, #FB923C);
|
|
|
+ color: #fff;
|
|
|
+ border: none;
|
|
|
+ padding: 20rpx 60rpx;
|
|
|
+ border-radius: 40rpx;
|
|
|
+ font-size: 28rpx;
|
|
|
+}
|
|
|
+.btn-secondary {
|
|
|
+ background: #f5f7fa;
|
|
|
+ color: #666;
|
|
|
+ border: none;
|
|
|
+ padding: 20rpx 60rpx;
|
|
|
+ border-radius: 40rpx;
|
|
|
+ font-size: 28rpx;
|
|
|
+}
|
|
|
+.form-section {
|
|
|
+ padding: 30rpx;
|
|
|
+}
|
|
|
+.form-card {
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 20rpx;
|
|
|
+ padding: 30rpx;
|
|
|
+ margin-bottom: 30rpx;
|
|
|
+}
|
|
|
+.form-title {
|
|
|
+ font-size: 32rpx;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #333;
|
|
|
+ margin-bottom: 30rpx;
|
|
|
+ padding-bottom: 20rpx;
|
|
|
+ border-bottom: 1rpx solid #f0f0f0;
|
|
|
+}
|
|
|
+.form-item {
|
|
|
+ margin-bottom: 30rpx;
|
|
|
+}
|
|
|
+.label {
|
|
|
+ display: block;
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #333;
|
|
|
+ margin-bottom: 16rpx;
|
|
|
+}
|
|
|
+.required {
|
|
|
+ color: #ff4d4f;
|
|
|
+}
|
|
|
+.input {
|
|
|
+ width: 100%;
|
|
|
+ height: 80rpx;
|
|
|
+ border: 1rpx solid #e8e8e8;
|
|
|
+ border-radius: 12rpx;
|
|
|
+ padding: 0 24rpx;
|
|
|
+ font-size: 28rpx;
|
|
|
+ box-sizing: border-box;
|
|
|
+}
|
|
|
+.picker {
|
|
|
+ width: 100%;
|
|
|
+ height: 80rpx;
|
|
|
+ border: 1rpx solid #e8e8e8;
|
|
|
+ border-radius: 12rpx;
|
|
|
+ padding: 0 24rpx;
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #333;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+.picker-arrow {
|
|
|
+ color: #999;
|
|
|
+}
|
|
|
+.upload-area {
|
|
|
+ width: 200rpx;
|
|
|
+ height: 200rpx;
|
|
|
+ border: 2rpx dashed #d9d9d9;
|
|
|
+ border-radius: 12rpx;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+.upload-preview {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+}
|
|
|
+.upload-placeholder {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #999;
|
|
|
+ text-align: center;
|
|
|
+}
|
|
|
+.textarea {
|
|
|
+ width: 100%;
|
|
|
+ height: 160rpx;
|
|
|
+ border: 1rpx solid #e8e8e8;
|
|
|
+ border-radius: 12rpx;
|
|
|
+ padding: 20rpx 24rpx;
|
|
|
+ font-size: 28rpx;
|
|
|
+ box-sizing: border-box;
|
|
|
+}
|
|
|
+.tips-card {
|
|
|
+ background: #fffbe6;
|
|
|
+ border-radius: 12rpx;
|
|
|
+ padding: 24rpx;
|
|
|
+ margin-bottom: 30rpx;
|
|
|
+}
|
|
|
+.tips-title {
|
|
|
+ display: block;
|
|
|
+ font-size: 28rpx;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #fa8c16;
|
|
|
+ margin-bottom: 16rpx;
|
|
|
+}
|
|
|
+.tips-text {
|
|
|
+ display: block;
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #666;
|
|
|
+ line-height: 1.8;
|
|
|
+}
|
|
|
+.submit-btn {
|
|
|
+ background: linear-gradient(135deg, #F97316, #FB923C);
|
|
|
+ color: #fff;
|
|
|
+ border: none;
|
|
|
+ border-radius: 40rpx;
|
|
|
+ padding: 28rpx;
|
|
|
+ font-size: 32rpx;
|
|
|
+ font-weight: 600;
|
|
|
+ margin-bottom: 60rpx;
|
|
|
+}
|
|
|
+.submit-btn[disabled] {
|
|
|
+ opacity: 0.6;
|
|
|
+}
|
|
|
</style>
|