fix: 组队进原订单群;成交率有样本含0%也展示
This commit is contained in:
1 parent
b9de9ea34e
commit
77fefbe8aa
3 files changed
+213
-56
No files matched your search
@@ -2,7 +2,7 @@
|
||||
const app = getApp()
|
||||
import request from '../../utils/request.js'
|
||||
import connectionManager from '../../utils/xiaoxilj.js'
|
||||
import { attachAutoSettleFields } from '../../utils/auto-settle-display.js'
|
||||
import { bindDetailAutoSettle, stopAutoSettleTicker } from '../../utils/auto-settle-display.js'
|
||||
const COS = require('../../utils/cos-wx-sdk-v5.min.js')
|
||||
|
||||
Page({
|
||||
@@ -23,6 +23,7 @@ Page({
|
||||
shangjia_nicheng: '',
|
||||
shangjia_liuyan: '',
|
||||
tuikuan_liyou: '',
|
||||
tuikuan_tupian: [],
|
||||
chufa_liyou: '',
|
||||
chufa_zhuangtai: 0,
|
||||
chufa_jieguo: '',
|
||||
@@ -34,6 +35,8 @@ Page({
|
||||
},
|
||||
autoSettleTip: '',
|
||||
autoSettleExpireAt: '',
|
||||
autoSettleClock: '',
|
||||
autoSettleRemainText: '',
|
||||
zhuangtaiYanseMap: {
|
||||
1: '#E8F5E9', 2: '#E3F2FD', 3: '#F3E5F5', 4: '#FFF3E0',
|
||||
5: '#FFEBEE', 6: '#EFEBE9', 7: '#E0F7FA', 8: '#FFF8E1'
|
||||
@@ -70,6 +73,8 @@ Page({
|
||||
|
||||
team: null,
|
||||
isLeader: false,
|
||||
canSubmit: false,
|
||||
canModify: false,
|
||||
teamStatusText: '',
|
||||
teamShareText: '',
|
||||
showTeamForm: false,
|
||||
@@ -89,14 +94,28 @@ Page({
|
||||
this.jiexiTiaozhuanCanshu(options)
|
||||
},
|
||||
onHide() {
|
||||
stopAutoSettleTicker(this);
|
||||
const popupComp = this.selectComponent('#popupNotice');
|
||||
if (popupComp && popupComp.cleanup) {
|
||||
popupComp.cleanup();
|
||||
}
|
||||
},
|
||||
|
||||
onUnload() {
|
||||
stopAutoSettleTicker(this);
|
||||
},
|
||||
|
||||
onShow() {
|
||||
this.registerNotificationComponent();
|
||||
if (this.data._autoSettleEligible) {
|
||||
bindDetailAutoSettle(this, {
|
||||
zhuangtai: this.data.jibenShuju.zhuangtai,
|
||||
auto_settle_eligible: this.data._autoSettleEligible,
|
||||
auto_expire_at: this.data._autoExpireAt,
|
||||
auto_expire_at_ts: this.data._autoExpireAtTs,
|
||||
auto_settle_remain_seconds: this.data._autoSettleRemainBase,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
registerNotificationComponent() {
|
||||
@@ -189,6 +208,14 @@ Page({
|
||||
'xiangxiShuju.shangjia_nicheng': data.shangjia_nicheng || '',
|
||||
'xiangxiShuju.shangjia_liuyan': data.shangjia_liuyan || '',
|
||||
'xiangxiShuju.tuikuan_liyou': data.tuikuan_liyou || '',
|
||||
'xiangxiShuju.tuikuan_tupian': (data.tuikuan_tupian || []).map((url) => {
|
||||
if (url && !String(url).startsWith('http')) {
|
||||
const oss = app.globalData.ossImageUrl || ''
|
||||
const path = String(url).startsWith('/') ? String(url).substring(1) : String(url)
|
||||
return oss + path
|
||||
}
|
||||
return url
|
||||
}),
|
||||
'xiangxiShuju.chufa_liyou': data.chufa_liyou || '',
|
||||
'xiangxiShuju.chufa_zhuangtai': data.chufa_zhuangtai || 0,
|
||||
'xiangxiShuju.chufa_jieguo': data.chufa_jieguo || '',
|
||||
@@ -202,17 +229,14 @@ Page({
|
||||
'liuyan': data.dashou_liuyan || '',
|
||||
'jibenShuju.fadanpingtai': data.fadanpingtai || 0
|
||||
})
|
||||
const settled = attachAutoSettleFields({
|
||||
bindDetailAutoSettle(this, {
|
||||
zhuangtai: data.zhuangtai,
|
||||
auto_settle_eligible: data.auto_settle_eligible,
|
||||
auto_expire_at: data.auto_expire_at,
|
||||
auto_expire_at_ts: data.auto_expire_at_ts,
|
||||
auto_settle_remain_seconds: data.auto_settle_remain_seconds,
|
||||
})
|
||||
this.setData({
|
||||
autoSettleTip: settled.autoSettleTip || '',
|
||||
autoSettleExpireAt: settled.autoSettleExpireAt || '',
|
||||
})
|
||||
this.applyTeamData(data.team || null, data.fuwudashou_id || '')
|
||||
this.applyTeamData(data.team || null, data.fuwudashou_id || '', data)
|
||||
const currentStatus = data.zhuangtai || 0
|
||||
const showRefund = [4,5,6].includes(currentStatus)
|
||||
this.setData({ showRefundInfo: showRefund })
|
||||
@@ -257,6 +281,12 @@ Page({
|
||||
if (!currentUrl) return
|
||||
wx.previewImage({ current: currentUrl, urls: urls.length > 0 ? urls : [currentUrl] })
|
||||
},
|
||||
previewTuikuanTupian(e) {
|
||||
const currentUrl = e.currentTarget.dataset.url
|
||||
const urls = this.data.xiangxiShuju.tuikuan_tupian || []
|
||||
if (!currentUrl) return
|
||||
wx.previewImage({ current: currentUrl, urls: urls.length > 0 ? urls : [currentUrl] })
|
||||
},
|
||||
getFileExtension(filePath) {
|
||||
const lastDotIndex = filePath.lastIndexOf('.')
|
||||
if (lastDotIndex === -1) return '.jpg'
|
||||
@@ -348,38 +378,9 @@ Page({
|
||||
})
|
||||
},
|
||||
|
||||
// 组队群:固定进 group_{订单号}(入队时已订阅)
|
||||
// 组队沟通:复用抢单配对群,不另开 group_{订单}
|
||||
goToTeamGroupChat() {
|
||||
const uid = wx.getStorageSync('uid')
|
||||
const orderId = this.data.jibenShuju.dingdan_id
|
||||
if (!uid || !orderId) {
|
||||
wx.showToast({ title: '信息不完整', icon: 'none' })
|
||||
return
|
||||
}
|
||||
const groupId = `group_${orderId}`
|
||||
const currentUser = {
|
||||
id: 'Ds' + uid,
|
||||
name: wx.getStorageSync('nicheng') || app.globalData.dashouNicheng || '打手',
|
||||
avatar: '',
|
||||
}
|
||||
const payload = encodeURIComponent(JSON.stringify({
|
||||
groupId,
|
||||
orderId,
|
||||
groupName: (this.data.jibenShuju.nicheng || '订单') + ' · 组队群',
|
||||
orderDesc: this.data.jibenShuju.jieshao || '',
|
||||
orderJine: this.data.jibenShuju.jine || '',
|
||||
orderZhuangtai: this.data.jibenShuju.zhuangtai,
|
||||
currentUserId: currentUser.id,
|
||||
currentUserName: currentUser.name,
|
||||
isCross: this.data.jibenShuju.fadanpingtai || 0,
|
||||
}))
|
||||
wx.navigateTo({
|
||||
url: `/pages/group-chat/group-chat?data=${payload}`,
|
||||
fail: (err) => {
|
||||
console.error('进入组队群失败', err)
|
||||
wx.showToast({ title: '无法打开群聊', icon: 'none' })
|
||||
},
|
||||
})
|
||||
this.goToChatWithBoss()
|
||||
},
|
||||
|
||||
async getCOSZhengshu() {
|
||||
@@ -485,6 +486,10 @@ Page({
|
||||
},
|
||||
|
||||
tijiaoDingdan() {
|
||||
if (!this.data.canSubmit && !this.data.isLeader) {
|
||||
wx.showToast({ title: '仅队长可提交交付', icon: 'none' })
|
||||
return
|
||||
}
|
||||
this.showAnnouncementAndConfirm()
|
||||
},
|
||||
|
||||
@@ -616,6 +621,10 @@ Page({
|
||||
return fullUrl
|
||||
},
|
||||
enterModify() {
|
||||
if (!this.data.canModify && !this.data.isLeader) {
|
||||
wx.showToast({ title: '仅队长可修改交付', icon: 'none' })
|
||||
return
|
||||
}
|
||||
const { dashou_jiaofu, dashou_liuyan } = this.data.xiangxiShuju
|
||||
this.setData({
|
||||
isModifying: true,
|
||||
@@ -789,19 +798,32 @@ Page({
|
||||
}
|
||||
},
|
||||
|
||||
applyTeamData(team, playerId) {
|
||||
applyTeamData(team, playerId, detailData) {
|
||||
const uid = String(wx.getStorageSync('uid') || '')
|
||||
const statusMap = { 1: '招募中', 2: '已锁定', 3: '已结束', 4: '已取消', 5: '已作废' }
|
||||
const pid = String(playerId || this.data.xiangxiShuju.fuwudashou_id || '')
|
||||
const d = detailData || {}
|
||||
let isLeader = false
|
||||
if (team) {
|
||||
if (typeof d.is_team_leader === 'boolean') {
|
||||
isLeader = d.is_team_leader
|
||||
} else if (team) {
|
||||
isLeader = String(team.leader_uid || '') === uid
|
||||
} else {
|
||||
isLeader = !!pid && pid === uid
|
||||
}
|
||||
const zt = Number(d.zhuangtai != null ? d.zhuangtai : this.data.jibenShuju.zhuangtai)
|
||||
let canSubmit = typeof d.can_submit === 'boolean' ? d.can_submit : (isLeader && zt === 2)
|
||||
let canModify = typeof d.can_modify === 'boolean' ? d.can_modify : (isLeader && (zt === 4 || zt === 8))
|
||||
// 有组队时强制仅队长
|
||||
if (team && !isLeader) {
|
||||
canSubmit = false
|
||||
canModify = false
|
||||
}
|
||||
this.setData({
|
||||
team: team || null,
|
||||
isLeader,
|
||||
canSubmit,
|
||||
canModify,
|
||||
teamStatusText: team ? (statusMap[team.status] || '未知') : '',
|
||||
teamShareText: team ? Number(team.display_share_amount || 0).toFixed(2) : '',
|
||||
})
|
||||
|
||||
@@ -100,9 +100,13 @@
|
||||
<text class="item-value zhuangtai-text">{{zhuangtaiWenziMap[jibenShuju.zhuangtai] || '未知状态'}}</text>
|
||||
</view>
|
||||
|
||||
<view class="info-item-row" wx:if="{{autoSettleTip}}">
|
||||
<view class="info-item-row auto-settle-row" wx:if="{{autoSettleTip || autoSettleClock}}">
|
||||
<text class="item-label">自动结算:</text>
|
||||
<text class="item-value auto-settle-text">{{autoSettleTip}}<text wx:if="{{autoSettleExpireAt}}">({{autoSettleExpireAt}})</text></text>
|
||||
<view class="auto-settle-value">
|
||||
<text class="auto-settle-clock" wx:if="{{autoSettleClock}}">{{autoSettleClock}}</text>
|
||||
<text class="item-value auto-settle-text">{{autoSettleTip}}</text>
|
||||
<text class="auto-settle-expire" wx:if="{{autoSettleExpireAt}}">到期 {{autoSettleExpireAt}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 发单平台信息 -->
|
||||
@@ -157,7 +161,7 @@
|
||||
</view>
|
||||
|
||||
<view class="team-actions">
|
||||
<view class="team-chat-btn" bindtap="goToTeamGroupChat">进入组队群聊</view>
|
||||
<view class="team-chat-btn" bindtap="goToTeamGroupChat">进入订单群聊</view>
|
||||
<view class="team-action-btn ghost" wx:if="{{isLeader && team.status == 1 && jibenShuju.zhuangtai == 2}}" bindtap="lockTeam">关停招募</view>
|
||||
</view>
|
||||
</block>
|
||||
@@ -205,14 +209,28 @@
|
||||
<!-- 退款信息区域 -->
|
||||
<view
|
||||
class="tuikuan-area"
|
||||
wx:if="{{showRefundInfo && xiangxiShuju.tuikuan_liyou}}"
|
||||
wx:if="{{showRefundInfo && (xiangxiShuju.tuikuan_liyou || xiangxiShuju.tuikuan_tupian.length)}}"
|
||||
>
|
||||
<view class="info-title">退款信息</view>
|
||||
|
||||
<view class="info-item-row">
|
||||
<view class="info-item-row" wx:if="{{xiangxiShuju.tuikuan_liyou}}">
|
||||
<text class="item-label">退款理由:</text>
|
||||
<text class="item-value">{{xiangxiShuju.tuikuan_liyou}}</text>
|
||||
</view>
|
||||
<view class="info-item-row" wx:if="{{xiangxiShuju.tuikuan_tupian.length}}" style="flex-direction:column;align-items:flex-start;">
|
||||
<text class="item-label" style="margin-bottom:12rpx;">相关图片:</text>
|
||||
<view style="display:flex;flex-wrap:wrap;">
|
||||
<block wx:for="{{xiangxiShuju.tuikuan_tupian}}" wx:key="*this">
|
||||
<image
|
||||
src="{{item}}"
|
||||
mode="aspectFill"
|
||||
style="width:140rpx;height:140rpx;margin:0 12rpx 12rpx 0;border-radius:8rpx;"
|
||||
bindtap="previewTuikuanTupian"
|
||||
data-url="{{item}}"
|
||||
/>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 处罚申请信息区域 -->
|
||||
@@ -254,7 +272,7 @@
|
||||
|
||||
<!-- 接单员交付历史(只读模式) -->
|
||||
<view class="dashou-jiaofu-area" wx:if="{{!isModifying && xiangxiShuju.dashou_jiaofu.length > 0}}">
|
||||
<view class="info-title">我的交付</view>
|
||||
<view class="info-title">{{isLeader ? '订单交付' : '订单交付(只读)'}}</view>
|
||||
|
||||
<!-- 接单员交付图片 -->
|
||||
<view class="dashou-jiaofu-container">
|
||||
@@ -286,8 +304,8 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 🆕 修改模式下的可编辑区域(当 isModifying 为 true 时显示) -->
|
||||
<view class="dashou-jiaofu-area" wx:if="{{isModifying}}">
|
||||
<!-- 修改模式(仅队长 canModify) -->
|
||||
<view class="dashou-jiaofu-area" wx:if="{{isModifying && canModify}}">
|
||||
<view class="info-title">修改交付</view>
|
||||
|
||||
<!-- 图片编辑区域 -->
|
||||
@@ -353,8 +371,8 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提交订单区域(仅状态=2时显示,保持不变) -->
|
||||
<view class="tijiao-area" wx:if="{{jibenShuju.zhuangtai == 2}}">
|
||||
<!-- 提交订单:仅队长(或非组队接单人) -->
|
||||
<view class="tijiao-area" wx:if="{{jibenShuju.zhuangtai == 2 && canSubmit}}">
|
||||
<view class="info-title">提交订单</view>
|
||||
|
||||
<!-- 选择图片 -->
|
||||
@@ -421,8 +439,8 @@
|
||||
<!-- ========== 底部按钮区域 ========== -->
|
||||
<view class="bottom-btns-container" wx:if="{{!isLoading}}">
|
||||
|
||||
<!-- 🆕 修改模式下的按钮(取消/确认) -->
|
||||
<block wx:if="{{isModifying}}">
|
||||
<!-- 修改模式按钮(仅队长 canModify) -->
|
||||
<block wx:if="{{isModifying && canModify}}">
|
||||
<view class="btn-row">
|
||||
<view
|
||||
class="bottom-btn cancel-modify-btn"
|
||||
@@ -471,8 +489,8 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 🆕 新增:修改按钮(仅当状态为4或8时显示) -->
|
||||
<view class="btn-row" wx:if="{{jibenShuju.zhuangtai == 4 || jibenShuju.zhuangtai == 8}}">
|
||||
<!-- 修改交付:仅队长 -->
|
||||
<view class="btn-row" wx:if="{{canModify && (jibenShuju.zhuangtai == 4 || jibenShuju.zhuangtai == 8)}}">
|
||||
<view
|
||||
class="bottom-btn modify-btn full-width"
|
||||
bindtap="enterModify"
|
||||
@@ -482,15 +500,21 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提交按钮(仅状态=2时显示) -->
|
||||
<!-- 提交:仅队长 -->
|
||||
<view
|
||||
class="bottom-btn submit-btn"
|
||||
wx:if="{{jibenShuju.zhuangtai == 2}}"
|
||||
wx:if="{{canSubmit && jibenShuju.zhuangtai == 2}}"
|
||||
bindtap="tijiaoDingdan"
|
||||
>
|
||||
<text class="btn-text">{{isSubmitting ? '提交中...' : '立即提交'}}</text>
|
||||
<view class="btn-shine"></view>
|
||||
</view>
|
||||
<view
|
||||
class="team-member-tip"
|
||||
wx:if="{{team && !isLeader && jibenShuju.zhuangtai == 2}}"
|
||||
>
|
||||
<text>组队中仅队长可提交交付,请等待队长操作</text>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
</view>
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* 成交指标展示:后端有样本就展示(含真实 0%),无样本不造假。
|
||||
* - 成交率/罚款率:有 rate / rate_text 即展示
|
||||
* - 均时:有 avg_deal_hours_text 才展示
|
||||
*/
|
||||
|
||||
function parseRate(textOrNum) {
|
||||
if (textOrNum == null || textOrNum === '') return null;
|
||||
if (typeof textOrNum === 'number') {
|
||||
return Number.isFinite(textOrNum) ? textOrNum : null;
|
||||
}
|
||||
const s = String(textOrNum).trim().replace(/%/g, '');
|
||||
const n = Number(s);
|
||||
return Number.isFinite(n) ? n : null;
|
||||
}
|
||||
|
||||
function formatRateText(rate, fallbackText) {
|
||||
if (fallbackText) return fallbackText;
|
||||
const pct = parseRate(rate);
|
||||
if (pct == null) return '';
|
||||
const asPercent = pct > 1 ? pct : pct * 100;
|
||||
return `${asPercent.toFixed(1)}%`;
|
||||
}
|
||||
|
||||
function hasRateValue(rate, text) {
|
||||
if (text != null && String(text).trim() !== '') return true;
|
||||
return rate != null && rate !== '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 把接口 data 收成列表顶栏可用结构;全无可展示则返回 null
|
||||
*/
|
||||
export function sanitizeMyDealStat(raw, role = 'merchant') {
|
||||
if (!raw || typeof raw !== 'object') return null;
|
||||
const out = { role: raw.role || role };
|
||||
const chips = [];
|
||||
|
||||
const dealRate = raw.deal_rate != null ? raw.deal_rate : raw.deal_rate_text;
|
||||
if (hasRateValue(raw.deal_rate, raw.deal_rate_text)) {
|
||||
const pct = parseRate(dealRate);
|
||||
out.deal_rate = pct == null ? 0 : (pct > 1 ? pct / 100 : pct);
|
||||
out.deal_rate_text = formatRateText(dealRate, raw.deal_rate_text);
|
||||
out.deal_label = '成交率';
|
||||
chips.push({ k: 'deal', t: `成交率 ${out.deal_rate_text}` });
|
||||
}
|
||||
|
||||
const fineKey = role === 'dashou' ? 'fined_rate' : 'fine_rate';
|
||||
const fineTextKey = role === 'dashou' ? 'fined_rate_text' : 'fine_rate_text';
|
||||
const fineRate = raw[fineKey] != null
|
||||
? raw[fineKey]
|
||||
: (raw[fineTextKey] || raw.fine_rate_text || raw.fined_rate_text);
|
||||
const fineText = raw[fineTextKey] || raw.fine_rate_text || raw.fined_rate_text;
|
||||
if (hasRateValue(raw[fineKey] != null ? raw[fineKey] : raw.fine_rate, fineText)) {
|
||||
const finePct = parseRate(fineRate);
|
||||
out[fineKey] = finePct == null ? 0 : (finePct > 1 ? finePct / 100 : finePct);
|
||||
out[fineTextKey] = formatRateText(fineRate, fineText);
|
||||
out.fine_label = role === 'dashou' ? '被罚款率' : '罚款率';
|
||||
chips.push({
|
||||
k: 'fine',
|
||||
t: `${out.fine_label} ${out[fineTextKey]}`,
|
||||
});
|
||||
}
|
||||
|
||||
if (raw.avg_deal_hours_text) {
|
||||
out.avg_deal_hours_text = raw.avg_deal_hours_text;
|
||||
out.avg_deal_hours = raw.avg_deal_hours;
|
||||
chips.push({ k: 'avg', t: `均时 ${raw.avg_deal_hours_text}`, hl: true });
|
||||
}
|
||||
|
||||
if (!chips.length) return null;
|
||||
out.chips = chips;
|
||||
out.order_count = raw.order_count;
|
||||
out.completed_count = raw.completed_count;
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* 抢单池/组队卡片芯片:后端给了哪个字段就展示哪个(含 0%)
|
||||
*/
|
||||
export function buildDealStatChips(stat, opts = {}) {
|
||||
if (!stat || typeof stat !== 'object') return [];
|
||||
const dealLabel = opts.dealLabel || '成交率';
|
||||
const fineLabel = opts.fineLabel || '罚款率';
|
||||
const chips = [];
|
||||
|
||||
if (hasRateValue(stat.deal_rate, stat.deal_rate_text)) {
|
||||
const text = formatRateText(
|
||||
stat.deal_rate != null ? stat.deal_rate : stat.deal_rate_text,
|
||||
stat.deal_rate_text,
|
||||
);
|
||||
chips.push({ k: 'deal', t: `${dealLabel} ${text}` });
|
||||
}
|
||||
|
||||
const fineRaw = stat.fine_rate != null
|
||||
? stat.fine_rate
|
||||
: (stat.fined_rate != null ? stat.fined_rate : (stat.fine_rate_text || stat.fined_rate_text));
|
||||
const fineText = stat.fine_rate_text || stat.fined_rate_text;
|
||||
if (hasRateValue(stat.fine_rate != null ? stat.fine_rate : stat.fined_rate, fineText)) {
|
||||
chips.push({ k: 'fine', t: `${fineLabel} ${formatRateText(fineRaw, fineText)}` });
|
||||
}
|
||||
|
||||
if (stat.avg_deal_hours_text) {
|
||||
chips.push({ k: 'avg', t: `均时 ${stat.avg_deal_hours_text}`, hl: true });
|
||||
}
|
||||
return chips;
|
||||
}
|
||||
|
||||
export const DEAL_STAT_HELP = {
|
||||
merchant: '成交率=已结算÷有效单量;罚款率=已缴纳罚单÷有效单量;均时=平均结算耗时。有样本即展示(含 0%)。',
|
||||
dashou: '成交率=已结算÷接单量;被罚款率=已缴纳罚单÷接单量。有样本即展示(含 0%)。',
|
||||
};
|
||||
Reference in new issue
Block a user