|
|
@@ -12,7 +12,12 @@
|
|
|
<image :src="clientInfo.avatar" class="client-avatar" mode="aspectFill"></image>
|
|
|
<view class="basic-info">
|
|
|
<text class="client-name">{{ clientInfo.gender }} · {{ clientInfo.name }}</text>
|
|
|
- <text class="client-status">{{ clientInfo.status }}</text>
|
|
|
+ <view class="status-tag-wrapper">
|
|
|
+ <text class="status-tag register-tag registered">已注册</text>
|
|
|
+ <text class="status-tag match-tag" :class="{ 'matched': followForm.matchStatus === 1, 'unmatched': followForm.matchStatus === 0 || followForm.matchStatus === null }">
|
|
|
+ {{ followForm.matchStatus === 1 ? '已匹配' : '未匹配' }}
|
|
|
+ </text>
|
|
|
+ </view>
|
|
|
<view class="client-tags">
|
|
|
<text class="tag" v-for="(tag, index) in clientInfo.tags" :key="index">{{ tag }}</text>
|
|
|
</view>
|
|
|
@@ -92,7 +97,10 @@
|
|
|
</view>
|
|
|
<view class="detail-item">
|
|
|
<text class="detail-label">收入:</text>
|
|
|
- <text class="detail-value">{{ clientInfo.details.income }}</text>
|
|
|
+ <text class="detail-value">
|
|
|
+ {{ clientInfo.details.income }}
|
|
|
+ <text v-if="clientInfo.details.income && clientInfo.details.income !== '未知'">万元/年</text>
|
|
|
+ </text>
|
|
|
</view>
|
|
|
<view class="detail-item">
|
|
|
<text class="detail-label">购房情况:</text>
|
|
|
@@ -150,22 +158,26 @@
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
+ <!-- 匹配状态 -->
|
|
|
+ <view class="follow-group">
|
|
|
+ <text class="group-label">匹配状态</text>
|
|
|
+ <view class="status-tags-row">
|
|
|
+ <view class="status-tag" :class="{ active: followForm.matchStatus === 0 }" @click="handleMatchStatusChange(0)">未匹配</view>
|
|
|
+ <view class="status-tag" :class="{ active: followForm.matchStatus === 1 }" @click="handleMatchStatusChange(1)">已匹配</view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
<!-- 跟进进度 -->
|
|
|
<view class="follow-group">
|
|
|
<text class="group-label">跟进进度</text>
|
|
|
<view class="status-tags-row">
|
|
|
- <view class="status-tag" :class="{ active: followForm.progress === 'matched' }" @click="followForm.progress = 'matched'">已匹配</view>
|
|
|
<view class="status-tag" :class="{ active: followForm.progress === 'notMet' }" @click="followForm.progress = 'notMet'">未见面</view>
|
|
|
<view class="status-tag" :class="{ active: followForm.progress === 'communicating' }" @click="followForm.progress = 'communicating'">沟通中</view>
|
|
|
+ <view class="status-tag" :class="{ active: followForm.invitationStatus === 0 }" @click="handleInvitationStatusChange(0)">未邀约</view>
|
|
|
+ <view class="status-tag" :class="{ active: followForm.invitationStatus === 1 }" @click="handleInvitationStatusChange(1)">已邀约</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
- <!-- 邀约状态 -->
|
|
|
- <view class="follow-group">
|
|
|
- <text class="group-label">邀约状态</text>
|
|
|
- <view class="input-like">{{ followForm.inviteStatus || '未邀约' }}</view>
|
|
|
- </view>
|
|
|
-
|
|
|
<!-- 邀约时间 -->
|
|
|
<view class="follow-group">
|
|
|
<text class="group-label">邀约时间</text>
|
|
|
@@ -197,10 +209,12 @@ export default {
|
|
|
followForm: {
|
|
|
type: 'phone',
|
|
|
progress: 'matched',
|
|
|
- inviteStatus: '未邀约',
|
|
|
+ matchStatus: 0, // 0-未匹配,1-已匹配
|
|
|
+ invitationStatus: 0, // 0-未邀约,1-已邀约
|
|
|
inviteDate: '',
|
|
|
remark: ''
|
|
|
},
|
|
|
+ resourceId: null, // 资源ID
|
|
|
clientInfo: {
|
|
|
id: 1,
|
|
|
name: '',
|
|
|
@@ -242,6 +256,11 @@ export default {
|
|
|
if (stored === true || stored === false) {
|
|
|
this.isDarkTheme = stored
|
|
|
}
|
|
|
+
|
|
|
+ // 如果已经有resourceId,刷新统计数据
|
|
|
+ if (this.resourceId) {
|
|
|
+ this.loadFollowStatistics(this.resourceId)
|
|
|
+ }
|
|
|
},
|
|
|
onLoad(options) {
|
|
|
console.log('=== 客户详情页面 onLoad ===')
|
|
|
@@ -270,6 +289,7 @@ export default {
|
|
|
return
|
|
|
}
|
|
|
console.log('最终使用的resourceId:', resourceId, '类型:', typeof resourceId)
|
|
|
+ this.resourceId = resourceId
|
|
|
this.loadClientInfo(resourceId)
|
|
|
} else {
|
|
|
console.error('未获取到资源ID')
|
|
|
@@ -321,12 +341,272 @@ export default {
|
|
|
onInviteDateChange(e) {
|
|
|
this.followForm.inviteDate = e.detail.value
|
|
|
},
|
|
|
- // 提交跟进(暂时仅提示)
|
|
|
- handleSubmitFollow() {
|
|
|
- uni.showToast({
|
|
|
- title: '跟进已保存',
|
|
|
- icon: 'success'
|
|
|
- })
|
|
|
+ // 匹配状态变更
|
|
|
+ handleMatchStatusChange(status) {
|
|
|
+ this.followForm.matchStatus = status
|
|
|
+ },
|
|
|
+ // 邀约状态变更
|
|
|
+ handleInvitationStatusChange(status) {
|
|
|
+ this.followForm.invitationStatus = status
|
|
|
+ // 如果选择已邀约且没有设置邀约时间,提示用户选择
|
|
|
+ if (status === 1 && !this.followForm.inviteDate) {
|
|
|
+ uni.showToast({
|
|
|
+ title: '请选择邀约时间',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 加载最新的跟进信息,更新表单字段
|
|
|
+ async loadLatestFollowInfo(resourceId) {
|
|
|
+ try {
|
|
|
+ const baseUrl = process.env.NODE_ENV === 'development'
|
|
|
+ ? 'http://localhost:8083/api' // 开发环境 - 通过网关
|
|
|
+ : 'https://your-domain.com/api' // 生产环境
|
|
|
+
|
|
|
+ // 获取最新的跟进记录
|
|
|
+ const [error, res] = await uni.request({
|
|
|
+ url: `${baseUrl}/my-resource/latest-follow/${resourceId}`,
|
|
|
+ method: 'GET',
|
|
|
+ header: {
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ if (error) {
|
|
|
+ console.error('加载最新跟进信息失败:', error)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (res.statusCode === 200 && res.data && res.data.code === 200) {
|
|
|
+ const followUp = res.data.data
|
|
|
+
|
|
|
+ if (followUp) {
|
|
|
+ // 更新跟进方式(1-电话,2-面谈,3-其他)
|
|
|
+ if (followUp.followType !== null && followUp.followType !== undefined) {
|
|
|
+ const followType = followUp.followType
|
|
|
+ if (followType === 1) {
|
|
|
+ this.followForm.type = 'phone'
|
|
|
+ } else if (followType === 2) {
|
|
|
+ this.followForm.type = 'meet'
|
|
|
+ } else if (followType === 3) {
|
|
|
+ this.followForm.type = 'other'
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新跟进进度(1-已匹配,2-未见面,3-沟通中)
|
|
|
+ if (followUp.followProgress !== null && followUp.followProgress !== undefined) {
|
|
|
+ const progress = followUp.followProgress
|
|
|
+ if (progress === 1) {
|
|
|
+ this.followForm.progress = 'matched'
|
|
|
+ } else if (progress === 2) {
|
|
|
+ this.followForm.progress = 'notMet'
|
|
|
+ } else if (progress === 3) {
|
|
|
+ this.followForm.progress = 'communicating'
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新匹配状态
|
|
|
+ if (followUp.isMatch !== null && followUp.isMatch !== undefined) {
|
|
|
+ this.followForm.matchStatus = parseInt(followUp.isMatch) || 0
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新邀约状态
|
|
|
+ if (followUp.isInvitation !== null && followUp.isInvitation !== undefined) {
|
|
|
+ this.followForm.invitationStatus = parseInt(followUp.isInvitation) || 0
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新邀约时间
|
|
|
+ if (followUp.invitationTime) {
|
|
|
+ const date = new Date(followUp.invitationTime)
|
|
|
+ const year = date.getFullYear()
|
|
|
+ const month = String(date.getMonth() + 1).padStart(2, '0')
|
|
|
+ const day = String(date.getDate()).padStart(2, '0')
|
|
|
+ this.followForm.inviteDate = `${year}-${month}-${day}`
|
|
|
+ } else {
|
|
|
+ this.followForm.inviteDate = ''
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新备注
|
|
|
+ if (followUp.remark !== null && followUp.remark !== undefined) {
|
|
|
+ this.followForm.remark = followUp.remark || ''
|
|
|
+ } else {
|
|
|
+ this.followForm.remark = ''
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('表单字段已更新:', {
|
|
|
+ type: this.followForm.type,
|
|
|
+ progress: this.followForm.progress,
|
|
|
+ matchStatus: this.followForm.matchStatus,
|
|
|
+ invitationStatus: this.followForm.invitationStatus,
|
|
|
+ inviteDate: this.followForm.inviteDate,
|
|
|
+ remark: this.followForm.remark
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ console.log('暂无跟进记录,保持表单当前值')
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.error('加载最新跟进信息异常:', e)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 加载跟进统计数据
|
|
|
+ async loadFollowStatistics(resourceId) {
|
|
|
+ try {
|
|
|
+ const baseUrl = process.env.NODE_ENV === 'development'
|
|
|
+ ? 'http://localhost:8083/api' // 开发环境 - 通过网关
|
|
|
+ : 'https://your-domain.com/api' // 生产环境
|
|
|
+
|
|
|
+ const [error, res] = await uni.request({
|
|
|
+ url: `${baseUrl}/my-resource/follow-statistics/${resourceId}`,
|
|
|
+ method: 'GET',
|
|
|
+ header: {
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ if (error) {
|
|
|
+ console.error('加载统计数据失败:', error)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (res.statusCode === 200 && res.data && res.data.code === 200) {
|
|
|
+ const statistics = res.data.data
|
|
|
+ console.log('=== 统计数据响应 ===')
|
|
|
+ console.log('完整响应:', JSON.stringify(res.data, null, 2))
|
|
|
+ console.log('统计数据对象:', statistics)
|
|
|
+ console.log('followCount:', statistics?.followCount, statistics?.follow_count)
|
|
|
+ console.log('matchCount:', statistics?.matchCount, statistics?.match_count)
|
|
|
+ console.log('phoneCount:', statistics?.phoneCount, statistics?.phone_count)
|
|
|
+ console.log('interviewCount:', statistics?.interviewCount, statistics?.interview_count)
|
|
|
+
|
|
|
+ // 更新统计数据(支持驼峰和下划线两种字段名格式)
|
|
|
+ if (this.clientInfo && this.clientInfo.stats) {
|
|
|
+ const followCount = statistics?.followCount ?? statistics?.follow_count ?? 0
|
|
|
+ const matchCount = statistics?.matchCount ?? statistics?.match_count ?? 0
|
|
|
+ const phoneCount = statistics?.phoneCount ?? statistics?.phone_count ?? 0
|
|
|
+ const interviewCount = statistics?.interviewCount ?? statistics?.interview_count ?? 0
|
|
|
+
|
|
|
+ this.clientInfo.stats.followTimes = followCount
|
|
|
+ this.clientInfo.stats.matchCount = matchCount
|
|
|
+ this.clientInfo.stats.phoneCalls = phoneCount
|
|
|
+ this.clientInfo.stats.interviews = interviewCount
|
|
|
+
|
|
|
+ console.log('更新后的统计数据:', {
|
|
|
+ followTimes: this.clientInfo.stats.followTimes,
|
|
|
+ matchCount: this.clientInfo.stats.matchCount,
|
|
|
+ phoneCalls: this.clientInfo.stats.phoneCalls,
|
|
|
+ interviews: this.clientInfo.stats.interviews
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ console.warn('clientInfo或stats不存在')
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ console.error('统计数据接口返回错误:', res.data)
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.error('加载统计数据异常:', e)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 提交跟进
|
|
|
+ async handleSubmitFollow() {
|
|
|
+ if (!this.resourceId) {
|
|
|
+ uni.showToast({
|
|
|
+ title: '资源ID不存在',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ uni.showLoading({
|
|
|
+ title: '保存中...'
|
|
|
+ })
|
|
|
+
|
|
|
+ const baseUrl = process.env.NODE_ENV === 'development'
|
|
|
+ ? 'http://localhost:8083/api' // 开发环境 - 通过网关
|
|
|
+ : 'https://your-domain.com/api' // 生产环境
|
|
|
+
|
|
|
+ // 准备请求数据
|
|
|
+ // 跟进方式转换:phone->1, meet->2, other->3
|
|
|
+ let followType = 1 // 默认电话
|
|
|
+ if (this.followForm.type === 'meet') {
|
|
|
+ followType = 2
|
|
|
+ } else if (this.followForm.type === 'other') {
|
|
|
+ followType = 3
|
|
|
+ }
|
|
|
+
|
|
|
+ // 跟进进度转换:matched->1, notMet->2, communicating->3
|
|
|
+ let progress = 1 // 默认已匹配
|
|
|
+ if (this.followForm.progress === 'notMet') {
|
|
|
+ progress = 2
|
|
|
+ } else if (this.followForm.progress === 'communicating') {
|
|
|
+ progress = 3
|
|
|
+ }
|
|
|
+
|
|
|
+ const requestData = {
|
|
|
+ followType: followType,
|
|
|
+ progress: this.followForm.progress, // 保持字符串格式,后端会转换
|
|
|
+ matchStatus: this.followForm.matchStatus,
|
|
|
+ invitationStatus: this.followForm.invitationStatus,
|
|
|
+ invitationTime: this.followForm.inviteDate || null,
|
|
|
+ remark: this.followForm.remark || '' // 添加备注字段
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('保存跟进数据:', requestData)
|
|
|
+
|
|
|
+ const [error, res] = await uni.request({
|
|
|
+ url: `${baseUrl}/my-resource/update-follow/${this.resourceId}`,
|
|
|
+ method: 'PUT',
|
|
|
+ data: requestData,
|
|
|
+ header: {
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ uni.hideLoading()
|
|
|
+
|
|
|
+ if (error) {
|
|
|
+ console.error('保存跟进失败:', error)
|
|
|
+ uni.showToast({
|
|
|
+ title: '保存失败',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (res.statusCode === 200 && res.data && res.data.code === 200) {
|
|
|
+ uni.showToast({
|
|
|
+ title: '跟进已保存',
|
|
|
+ icon: 'success'
|
|
|
+ })
|
|
|
+
|
|
|
+ // 刷新统计数据
|
|
|
+ if (this.resourceId) {
|
|
|
+ this.loadFollowStatistics(this.resourceId)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 重新加载最新的跟进信息,更新表单字段
|
|
|
+ if (this.resourceId) {
|
|
|
+ this.loadLatestFollowInfo(this.resourceId)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 触发资源列表刷新事件
|
|
|
+ uni.$emit('refreshResourceList')
|
|
|
+ } else {
|
|
|
+ const errorMsg = res.data?.message || '保存失败'
|
|
|
+ uni.showToast({
|
|
|
+ title: errorMsg,
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ uni.hideLoading()
|
|
|
+ console.error('保存跟进异常:', e)
|
|
|
+ uni.showToast({
|
|
|
+ title: '保存失败,请稍后重试',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ }
|
|
|
},
|
|
|
// 从API加载客户信息
|
|
|
async loadClientInfo(resourceId) {
|
|
|
@@ -431,6 +711,24 @@ export default {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // 加载匹配状态和邀约状态
|
|
|
+ const isMatch = data.isMatch !== null && data.isMatch !== undefined ? data.isMatch :
|
|
|
+ (data.is_match !== null && data.is_match !== undefined ? data.is_match : 0)
|
|
|
+ const isInvitation = data.isInvitation !== null && data.isInvitation !== undefined ? data.isInvitation :
|
|
|
+ (data.is_Invitation !== null && data.is_Invitation !== undefined ? data.is_Invitation : 0)
|
|
|
+ const invitationTime = data.invitationTime || data.Invitation_time
|
|
|
+
|
|
|
+ this.followForm.matchStatus = parseInt(isMatch) || 0
|
|
|
+ this.followForm.invitationStatus = parseInt(isInvitation) || 0
|
|
|
+ if (invitationTime) {
|
|
|
+ // 将日期转换为YYYY-MM-DD格式
|
|
|
+ const date = new Date(invitationTime)
|
|
|
+ const year = date.getFullYear()
|
|
|
+ const month = String(date.getMonth() + 1).padStart(2, '0')
|
|
|
+ const day = String(date.getDate()).padStart(2, '0')
|
|
|
+ this.followForm.inviteDate = `${year}-${month}-${day}`
|
|
|
+ }
|
|
|
+
|
|
|
// 映射数据到clientInfo
|
|
|
this.clientInfo = {
|
|
|
id: resourceId,
|
|
|
@@ -445,7 +743,7 @@ export default {
|
|
|
originalPhone: data.phone || '', // 保存原始手机号
|
|
|
originalBackupPhone: backupPhone || '', // 保存原始备用手机号
|
|
|
stats: {
|
|
|
- followTimes: 0, // 可以从其他接口获取
|
|
|
+ followTimes: 0, // 将从统计数据接口获取
|
|
|
matchCount: 0,
|
|
|
phoneCalls: 0,
|
|
|
interviews: 0
|
|
|
@@ -470,6 +768,9 @@ export default {
|
|
|
|
|
|
console.log('=== 映射后的clientInfo ===')
|
|
|
console.log('clientInfo:', JSON.stringify(this.clientInfo, null, 2))
|
|
|
+
|
|
|
+ // 加载跟进统计数据
|
|
|
+ this.loadFollowStatistics(resourceId)
|
|
|
} else {
|
|
|
uni.showToast({
|
|
|
title: res.data.message || '加载失败',
|
|
|
@@ -592,6 +893,41 @@ export default {
|
|
|
color: #2C2C2C;
|
|
|
margin-bottom: 12rpx;
|
|
|
letter-spacing: 0.5rpx;
|
|
|
+ display: block;
|
|
|
+ }
|
|
|
+
|
|
|
+ .status-tag-wrapper {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 10rpx;
|
|
|
+ margin-bottom: 18rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .status-tag {
|
|
|
+ display: inline-block;
|
|
|
+ padding: 4rpx 12rpx;
|
|
|
+ border-radius: 12rpx;
|
|
|
+ font-size: 22rpx;
|
|
|
+ font-weight: 500;
|
|
|
+
|
|
|
+ &.register-tag {
|
|
|
+ &.registered {
|
|
|
+ background: #E8F5E9;
|
|
|
+ color: #4CAF50;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &.match-tag {
|
|
|
+ &.matched {
|
|
|
+ background: #E3F2FD;
|
|
|
+ color: #2196F3;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.unmatched {
|
|
|
+ background: #FFF3E0;
|
|
|
+ color: #FF9800;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
.client-status {
|