release: freeze 2026-10-15 validated release baseline
CI/CD Pipeline / UI Contracts (source-structure gates) (push) Canceled after 0s
CI/CD Pipeline / E2E (live stack) (push) Canceled after 0s
CI/CD Pipeline / Backend Build & Test (push) Canceled after 0s
CI/CD Pipeline / Admin Web Build (push) Canceled after 0s
CI/CD Pipeline / Mini Program Compile Check (push) Canceled after 0s
CI/CD Pipeline / Migration Validation (push) Canceled after 0s
CI/CD Pipeline / Test Shell Guard (Phase 23 Gate) (push) Canceled after 0s
CI/CD Pipeline / UI Contracts (source-structure gates) (push) Canceled after 0s
CI/CD Pipeline / E2E (live stack) (push) Canceled after 0s
CI/CD Pipeline / Backend Build & Test (push) Canceled after 0s
CI/CD Pipeline / Admin Web Build (push) Canceled after 0s
CI/CD Pipeline / Mini Program Compile Check (push) Canceled after 0s
CI/CD Pipeline / Migration Validation (push) Canceled after 0s
CI/CD Pipeline / Test Shell Guard (Phase 23 Gate) (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
const api = require('../../utils/api');
|
||||
|
||||
Page({
|
||||
data: {
|
||||
serviceId: '',
|
||||
detail: null,
|
||||
followups: [],
|
||||
followupTypes: ['followup', '需求了解', '候选建议', '活动协助', '其他'],
|
||||
loading: true,
|
||||
submitting: false,
|
||||
form: { followupType: 'followup', content: '', nextFollowupAt: '' },
|
||||
},
|
||||
|
||||
onLoad(options) {
|
||||
const serviceId = options && options.id;
|
||||
if (!serviceId) {
|
||||
wx.showToast({ title: '服务记录不存在', icon: 'none' });
|
||||
wx.navigateBack();
|
||||
return;
|
||||
}
|
||||
this.setData({ serviceId });
|
||||
this.loadDetail();
|
||||
},
|
||||
|
||||
onShow() {
|
||||
if (this.data.serviceId && !this.data.loading) this.loadDetail();
|
||||
},
|
||||
|
||||
tokenHeaders() {
|
||||
const token = wx.getStorageSync('operatorToken');
|
||||
return token ? { Authorization: `Bearer ${token}` } : {};
|
||||
},
|
||||
|
||||
async loadDetail() {
|
||||
this.setData({ loading: true });
|
||||
try {
|
||||
const detail = await api.get(`/operator/matchmaker/services/${this.data.serviceId}`, {}, this.tokenHeaders());
|
||||
this.setData({ detail: detail || null, followups: (detail && detail.followups) || [] });
|
||||
} catch (error) {
|
||||
if (error && (error.code === 'FORBIDDEN' || error.code === 'NOT_FOUND' || error.code === 'DATA_SCOPE_DENIED')) {
|
||||
wx.showModal({ title: '服务权限已变更', content: '该服务对象已结束或不再属于当前服务范围。', showCancel: false,
|
||||
success: () => wx.navigateBack() });
|
||||
} else {
|
||||
wx.showToast({ title: (error && error.message) || '加载失败', icon: 'none' });
|
||||
}
|
||||
} finally {
|
||||
this.setData({ loading: false });
|
||||
}
|
||||
},
|
||||
|
||||
onTypeChange(e) { this.setData({ 'form.followupType': this.data.followupTypes[Number(e.detail.value)] || 'followup' }); },
|
||||
onContentInput(e) { this.setData({ 'form.content': e.detail.value }); },
|
||||
onNextFollowupInput(e) { this.setData({ 'form.nextFollowupAt': e.detail.value }); },
|
||||
|
||||
async submitFollowup() {
|
||||
if (this.data.submitting) return;
|
||||
const content = (this.data.form.content || '').trim();
|
||||
if (!content) { wx.showToast({ title: '请填写服务摘要', icon: 'none' }); return; }
|
||||
this.setData({ submitting: true });
|
||||
try {
|
||||
await api.post(`/operator/matchmaker/services/${this.data.serviceId}/followup`, {
|
||||
followupType: this.data.form.followupType,
|
||||
content,
|
||||
nextFollowupAt: this.data.form.nextFollowupAt || undefined,
|
||||
}, this.tokenHeaders(), api.idempotencyKey('matchmaker-followup', this.data.serviceId));
|
||||
wx.showToast({ title: '已记录服务', icon: 'success' });
|
||||
this.setData({ 'form.content': '', 'form.nextFollowupAt': '' });
|
||||
await this.loadDetail();
|
||||
} catch (error) {
|
||||
wx.showToast({ title: (error && error.message) || '提交失败,请重试', icon: 'none' });
|
||||
} finally {
|
||||
this.setData({ submitting: false });
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1 @@
|
||||
{"navigationBarTitleText":"服务对象详情","usingComponents":{}}
|
||||
@@ -0,0 +1,39 @@
|
||||
<view class="page">
|
||||
<view wx:if="{{loading}}" class="state">加载中...</view>
|
||||
<block wx:elif="{{detail}}">
|
||||
<view class="card profile-card">
|
||||
<view class="title">服务对象</view>
|
||||
<view class="status">服务编号:{{detail.serviceDisplayId || detail.displayId}}</view>
|
||||
<view wx:if="{{detail.userDisplayNumber}}" class="status">用户编号:{{detail.userDisplayNumber}}</view>
|
||||
<view wx:if="{{detail.userProfile}}" class="profile-grid">
|
||||
<text>展示名:{{detail.userProfile.displayName || '未设置'}}</text>
|
||||
<text>年龄:{{detail.userProfile.age || '未设置'}}</text>
|
||||
<text>地区:{{detail.userProfile.regionName || '未设置'}}</text>
|
||||
<text>婚姻状态:{{detail.userProfile.maritalStatus || '未设置'}}</text>
|
||||
</view>
|
||||
<view class="status">服务状态:{{detail.status}}</view>
|
||||
<view wx:if="{{detail.description}}" class="description">服务需求:{{detail.description}}</view>
|
||||
</view>
|
||||
|
||||
<view class="card">
|
||||
<view class="title">记录服务</view>
|
||||
<picker mode="selector" range="{{followupTypes}}" value="0" bindchange="onTypeChange">
|
||||
<view class="picker">服务类型:{{form.followupType}}</view>
|
||||
</picker>
|
||||
<textarea class="textarea" maxlength="1000" placeholder="只记录完成公益服务所必需的信息" value="{{form.content}}" bindinput="onContentInput"></textarea>
|
||||
<input class="input" placeholder="下次跟进时间(可选,如 2026-10-14 15:30)" value="{{form.nextFollowupAt}}" bindinput="onNextFollowupInput" />
|
||||
<button type="primary" loading="{{submitting}}" disabled="{{submitting}}" bindtap="submitFollowup">保存服务记录</button>
|
||||
</view>
|
||||
|
||||
<view class="card">
|
||||
<view class="title">服务历史</view>
|
||||
<view wx:if="{{followups.length}}">
|
||||
<view wx:for="{{followups}}" wx:key="id" class="history-item">
|
||||
<view>{{item.followupType}} · {{item.createdAt}}</view>
|
||||
<view class="history-content">{{item.content}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view wx:else class="state">暂无服务记录</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
@@ -0,0 +1 @@
|
||||
.page{min-height:100vh;background:#f5f6fa;padding:24rpx;box-sizing:border-box}.card{background:#fff;border-radius:12rpx;padding:28rpx;margin-bottom:20rpx}.title{font-size:32rpx;font-weight:600;color:#20243a;margin-bottom:20rpx}.profile-grid{display:grid;grid-template-columns:1fr 1fr;gap:16rpx;color:#5d637d;font-size:26rpx}.status{margin-top:20rpx;color:#e96b6b;font-size:27rpx}.description{margin-top:16rpx;color:#5d637d;line-height:1.6}.picker,.input,.textarea{border:1rpx solid #e1e4ee;border-radius:8rpx;padding:20rpx;margin-bottom:18rpx;color:#5d637d}.textarea{width:100%;height:180rpx;box-sizing:border-box}.history-item{padding:18rpx 0;border-bottom:1rpx solid #edf0f5;color:#727990;font-size:24rpx}.history-content{margin-top:8rpx;color:#30364e;font-size:27rpx;line-height:1.6}.state{text-align:center;color:#8b91a6;padding:80rpx 20rpx}
|
||||
Reference in New Issue
Block a user