restore: 恢复橙色逍遥梦UI版本(2ea2860)到主分支
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2,7 +2,15 @@ const app = getApp();
|
||||
import { formatDate } from '../../static/lib/utils';
|
||||
import { sendGroupMessage } from '../../utils/message-sender';
|
||||
import { getLocalImUserId } from '../../utils/im-user.js';
|
||||
import { resolveAvatarUrl } from '../../utils/avatar.js';
|
||||
import { resolveAvatarUrl, getDefaultAvatarUrl, resolveAvatarFromStorage } from '../../utils/avatar.js';
|
||||
import { getZhuangtaiText, isPairGroupId, normalizeGroupMessage, recordConversationOpen } from '../../utils/group-chat.js';
|
||||
import request from '../../utils/request';
|
||||
import {
|
||||
fetchHistoryMessages,
|
||||
getOldestHistoryTimestamp,
|
||||
mergeHistoryMessages,
|
||||
waitChatImReady,
|
||||
} from '../../utils/chat-history.js';
|
||||
|
||||
Page({
|
||||
data: {
|
||||
@@ -11,6 +19,10 @@ Page({
|
||||
groupAvatar: '',
|
||||
orderId: '',
|
||||
isCross: 0,
|
||||
orderZhuangtai: null,
|
||||
orderZhuangtaiText: '',
|
||||
orderJieshao: '',
|
||||
orderJine: '',
|
||||
currentUser: null,
|
||||
messages: [],
|
||||
inputText: '',
|
||||
@@ -30,7 +42,8 @@ Page({
|
||||
pendingImage: '',
|
||||
pendingImageFile: null,
|
||||
keyboardHeight: 0,
|
||||
bottomSafeHeight: 10
|
||||
bottomSafeHeight: 140,
|
||||
defaultAvatarUrl: '',
|
||||
},
|
||||
onLoad(options) {
|
||||
let p = { groupId: '', groupName: '订单群聊', groupAvatar: '', orderId: '', isCross: 0,
|
||||
@@ -41,37 +54,79 @@ Page({
|
||||
p = { ...p, ...d };
|
||||
} catch (e) {}
|
||||
}
|
||||
const orderIdStr = String(p.orderId || '').replace(/^group_/, '') ||
|
||||
(p.groupId && !isPairGroupId(p.groupId) ? String(p.groupId).replace(/^group_/, '') : '');
|
||||
const groupId = p.groupId
|
||||
? String(p.groupId)
|
||||
: (orderIdStr ? `group_${orderIdStr}` : '');
|
||||
const zt = p.orderZhuangtai;
|
||||
const defAvatar = getDefaultAvatarUrl(app);
|
||||
this.setData({
|
||||
groupId: p.groupId,
|
||||
groupId,
|
||||
groupName: p.groupName,
|
||||
groupAvatar: p.groupAvatar,
|
||||
orderId: p.orderId,
|
||||
isCross: p.isCross
|
||||
groupAvatar: resolveAvatarUrl(p.groupAvatar, app) || defAvatar,
|
||||
orderId: orderIdStr,
|
||||
isCross: p.isCross,
|
||||
orderJieshao: p.orderDesc || p.orderJieshao || '',
|
||||
orderJine: p.orderJine || '',
|
||||
orderZhuangtai: zt,
|
||||
orderZhuangtaiText: zt != null ? getZhuangtaiText(zt) : '',
|
||||
defaultAvatarUrl: defAvatar,
|
||||
});
|
||||
wx.setNavigationBarTitle({ title: this.data.groupName });
|
||||
if (p.currentUserId) {
|
||||
this.setData({
|
||||
currentUser: {
|
||||
id: p.currentUserId,
|
||||
name: p.currentUserName || `用户${p.currentUserId.replace(/^[A-Za-z]+/,'')}`,
|
||||
avatar: resolveAvatarUrl(p.currentUserAvatar, app)
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.ensureCurrentUser(p);
|
||||
},
|
||||
|
||||
ensureCurrentUser(p) {
|
||||
p = p || {};
|
||||
const localImId = getLocalImUserId(app);
|
||||
const uid = wx.getStorageSync('uid') || '';
|
||||
const userId = localImId || p.currentUserId || '';
|
||||
if (!userId) {
|
||||
this.initCurrentUser();
|
||||
return;
|
||||
}
|
||||
const defAvatar = getDefaultAvatarUrl(app);
|
||||
const rawAvatar = p.currentUserAvatar
|
||||
|| wx.getStorageSync('touxiang')
|
||||
|| app.globalData.currentUser?.avatar
|
||||
|| '';
|
||||
const name = p.currentUserName
|
||||
|| app.globalData.currentUser?.name
|
||||
|| wx.getStorageSync('nicheng')
|
||||
|| app.globalData.dashouNicheng
|
||||
|| app.globalData.nicheng
|
||||
|| `用户${uid}`;
|
||||
const avatar = resolveAvatarUrl(rawAvatar, app) || defAvatar;
|
||||
const currentUser = { id: userId, name, avatar: avatar || defAvatar };
|
||||
app.globalData.currentUser = { ...app.globalData.currentUser, ...currentUser };
|
||||
this.setData({ currentUser });
|
||||
},
|
||||
|
||||
getMyChatProfile() {
|
||||
const cu = this.data.currentUser;
|
||||
const defAvatar = getDefaultAvatarUrl(app);
|
||||
if (cu && cu.id) {
|
||||
return {
|
||||
id: cu.id,
|
||||
name: cu.name || `用户${wx.getStorageSync('uid') || ''}`,
|
||||
avatar: resolveAvatarUrl(cu.avatar, app) || defAvatar,
|
||||
};
|
||||
}
|
||||
const imId = getLocalImUserId(app);
|
||||
const uid = wx.getStorageSync('uid') || '';
|
||||
return {
|
||||
id: imId || '',
|
||||
name: wx.getStorageSync('nicheng') || app.globalData.nicheng || `用户${uid}`,
|
||||
avatar: resolveAvatarFromStorage(app) || defAvatar,
|
||||
};
|
||||
},
|
||||
|
||||
initCurrentUser() {
|
||||
const imId = getLocalImUserId(app);
|
||||
const uid = wx.getStorageSync('uid');
|
||||
this.setData({
|
||||
currentUser: {
|
||||
id: imId || ('Boss' + uid),
|
||||
name: app.globalData.currentUser?.name || `用户${uid}`,
|
||||
avatar: resolveAvatarUrl(wx.getStorageSync('touxiang'), app),
|
||||
},
|
||||
});
|
||||
const profile = this.getMyChatProfile();
|
||||
if (!profile.id) return;
|
||||
this.setData({ currentUser: profile });
|
||||
app.globalData.currentUser = { ...app.globalData.currentUser, ...profile };
|
||||
},
|
||||
|
||||
buildImageFile(tempPath, size) {
|
||||
@@ -84,14 +139,99 @@ Page({
|
||||
|
||||
normalizeMessage(msg) {
|
||||
if (!msg) return msg;
|
||||
msg = normalizeGroupMessage(msg);
|
||||
if (!msg.payload) msg.payload = {};
|
||||
if (msg.type === 'image') {
|
||||
const p = msg.payload;
|
||||
if (!p.url) p.url = p.thumbnail || p.thumb || p.imageUrl || '';
|
||||
const defAvatar = getDefaultAvatarUrl(app);
|
||||
const me = this.getMyChatProfile();
|
||||
if (me.id && msg.senderId === me.id) {
|
||||
msg.senderData = {
|
||||
name: me.name,
|
||||
avatar: me.avatar || defAvatar,
|
||||
};
|
||||
} else if (msg.senderData?.avatar) {
|
||||
msg.senderData.avatar = resolveAvatarUrl(msg.senderData.avatar, app) || defAvatar;
|
||||
} else if (msg.senderData) {
|
||||
msg.senderData.avatar = defAvatar;
|
||||
}
|
||||
if (msg.type === 'image' && msg.payload?.url && !String(msg.payload.url).startsWith('http')) {
|
||||
msg.payload.url = resolveAvatarUrl(msg.payload.url, app) || msg.payload.url;
|
||||
}
|
||||
return msg;
|
||||
},
|
||||
|
||||
mapIdentityForApi() {
|
||||
const role = app.globalData.currentRole || wx.getStorageSync('currentRole') || 'normal';
|
||||
if (role === 'dashou') return 'dashou';
|
||||
if (role === 'shangjia') return 'shangjia';
|
||||
return 'normal';
|
||||
},
|
||||
|
||||
async refreshLatestOrderBar() {
|
||||
const { groupId, orderId } = this.data;
|
||||
if (!groupId && !orderId) return;
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/dingdan/ltpddd',
|
||||
method: 'POST',
|
||||
data: {
|
||||
groupId,
|
||||
dingdan_id: orderId,
|
||||
identityType: this.mapIdentityForApi(),
|
||||
},
|
||||
});
|
||||
const body = res?.data || {};
|
||||
const latest = body.data?.latest;
|
||||
if (!latest) return;
|
||||
this.setData({
|
||||
orderId: latest.dingdan_id,
|
||||
orderJieshao: latest.jieshao || '',
|
||||
orderJine: latest.jine || '',
|
||||
orderZhuangtai: latest.zhuangtai,
|
||||
orderZhuangtaiText: getZhuangtaiText(latest.zhuangtai),
|
||||
});
|
||||
} catch (e) {
|
||||
console.warn('刷新最新订单条失败', e);
|
||||
}
|
||||
},
|
||||
|
||||
async refreshOrderStatus() {
|
||||
const { orderId } = this.data;
|
||||
if (!orderId) return;
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/dingdan/ltddzt',
|
||||
method: 'POST',
|
||||
data: {
|
||||
dingdan_id: orderId,
|
||||
identityType: this.mapIdentityForApi(),
|
||||
},
|
||||
});
|
||||
const body = res?.data || {};
|
||||
const st = body.data;
|
||||
if (!st) return;
|
||||
this.setData({
|
||||
orderJieshao: st.jieshao || this.data.orderJieshao,
|
||||
orderJine: st.jine || this.data.orderJine,
|
||||
orderZhuangtai: st.zhuangtai,
|
||||
orderZhuangtaiText: getZhuangtaiText(st.zhuangtai),
|
||||
});
|
||||
} catch (e) {
|
||||
console.warn('刷新订单状态失败', e);
|
||||
}
|
||||
},
|
||||
|
||||
startOrderStatusPoll() {
|
||||
this.stopOrderStatusPoll();
|
||||
this._orderPollTimer = setInterval(() => this.refreshOrderStatus(), 15000);
|
||||
},
|
||||
|
||||
stopOrderStatusPoll() {
|
||||
if (this._orderPollTimer) {
|
||||
clearInterval(this._orderPollTimer);
|
||||
this._orderPollTimer = null;
|
||||
}
|
||||
},
|
||||
|
||||
mergeSentMessage(localId, sent) {
|
||||
if (!sent) {
|
||||
this.updateMsg(localId, 'success');
|
||||
@@ -112,54 +252,90 @@ Page({
|
||||
},
|
||||
|
||||
onShow() {
|
||||
const defAvatar = getDefaultAvatarUrl(app);
|
||||
this.setData({
|
||||
defaultAvatarUrl: defAvatar,
|
||||
groupAvatar: resolveAvatarUrl(this.data.groupAvatar, app) || defAvatar,
|
||||
});
|
||||
this.ensureCurrentUser({});
|
||||
if (this.data.groupId) {
|
||||
if (!app.globalData.pageState) app.globalData.pageState = {};
|
||||
app.globalData.pageState.lastOpenedConvId = this.data.groupId;
|
||||
recordConversationOpen({ groupId: this.data.groupId });
|
||||
}
|
||||
this.refreshLatestOrderBar();
|
||||
this.startOrderStatusPoll();
|
||||
this.autoConnect();
|
||||
},
|
||||
|
||||
onHide() {
|
||||
if (this.data.groupId) {
|
||||
recordConversationOpen({ groupId: this.data.groupId });
|
||||
}
|
||||
this.stopOrderStatusPoll();
|
||||
this.clearAllListeners();
|
||||
},
|
||||
|
||||
autoConnect() {
|
||||
const targetUserId = getLocalImUserId(app);
|
||||
onUnload() {
|
||||
this.stopOrderStatusPoll();
|
||||
},
|
||||
|
||||
async autoConnect() {
|
||||
const targetUserId = this.data.currentUser?.id || getLocalImUserId(app);
|
||||
if (!targetUserId) return;
|
||||
|
||||
const afterReady = async () => {
|
||||
await this.subscribeGroupIfNeeded();
|
||||
this.setupAllListeners();
|
||||
await this.loadHistory(true);
|
||||
this.markGroupMessageAsRead();
|
||||
};
|
||||
|
||||
try {
|
||||
const ok = await waitChatImReady(app, 12000);
|
||||
if (ok) {
|
||||
await afterReady();
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('[群聊] IM 连接失败', e);
|
||||
}
|
||||
|
||||
const status = wx.goEasy.getConnectionStatus ? wx.goEasy.getConnectionStatus() : 'disconnected';
|
||||
if (status === 'connected' || status === 'reconnected') {
|
||||
const currentUserId = wx.goEasy.im ? wx.goEasy.im.userId : null;
|
||||
if (currentUserId === targetUserId) {
|
||||
this.subscribeGroupIfNeeded();
|
||||
this.setupAllListeners();
|
||||
this.loadHistory(true);
|
||||
await afterReady();
|
||||
return;
|
||||
} else {
|
||||
wx.goEasy.disconnect();
|
||||
}
|
||||
wx.goEasy.disconnect();
|
||||
}
|
||||
this.connectGoEasy(targetUserId);
|
||||
},
|
||||
|
||||
connectGoEasy(userId) {
|
||||
const { currentUser } = this.data;
|
||||
if (!currentUser) return;
|
||||
const me = this.getMyChatProfile();
|
||||
if (!me.id) return;
|
||||
const defAvatar = getDefaultAvatarUrl(app);
|
||||
wx.goEasy.connect({
|
||||
id: userId,
|
||||
data: {
|
||||
name: currentUser.name,
|
||||
avatar: resolveAvatarUrl(currentUser.avatar, app),
|
||||
name: me.name,
|
||||
avatar: me.avatar || defAvatar,
|
||||
},
|
||||
onSuccess: () => {
|
||||
this.subscribeGroupIfNeeded();
|
||||
this.setupAllListeners();
|
||||
this.loadHistory(true).then(()=>{
|
||||
this.markGroupMessageAsRead
|
||||
|
||||
this.subscribeGroupIfNeeded().then(() => {
|
||||
this.setupAllListeners();
|
||||
this.loadHistory(true);
|
||||
this.markGroupMessageAsRead();
|
||||
});
|
||||
},
|
||||
onFailed: (error) => {
|
||||
if (error.code === 408) {
|
||||
this.subscribeGroupIfNeeded();
|
||||
this.setupAllListeners();
|
||||
this.loadHistory(true);
|
||||
this.subscribeGroupIfNeeded().then(() => {
|
||||
this.setupAllListeners();
|
||||
this.loadHistory(true);
|
||||
});
|
||||
} else {
|
||||
wx.showToast({ title: '连接失败,请重试', icon: 'none' });
|
||||
}
|
||||
@@ -169,11 +345,16 @@ Page({
|
||||
|
||||
subscribeGroupIfNeeded() {
|
||||
const { groupId } = this.data;
|
||||
if (!groupId) return;
|
||||
wx.goEasy.im.subscribeGroup({
|
||||
groupIds: [groupId],
|
||||
onSuccess: () => {},
|
||||
onFailed: () => {}
|
||||
if (!groupId || !wx.goEasy?.im?.subscribeGroup) return Promise.resolve();
|
||||
return new Promise((resolve) => {
|
||||
wx.goEasy.im.subscribeGroup({
|
||||
groupIds: [String(groupId)],
|
||||
onSuccess: () => resolve(true),
|
||||
onFailed: (error) => {
|
||||
console.warn('subscribeGroup failed', error);
|
||||
resolve(false);
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
@@ -197,57 +378,95 @@ Page({
|
||||
|
||||
onPullDownRefresh() {
|
||||
if (this.data.loadingHistory) return;
|
||||
if (!this.data.hasMore) {
|
||||
wx.showToast({ title: '没有更早的消息了', icon: 'none' });
|
||||
this.setData({ isRefreshing: false });
|
||||
wx.stopPullDownRefresh();
|
||||
return;
|
||||
}
|
||||
this.setData({ isRefreshing: true });
|
||||
this.loadHistory(false).finally(() => { this.setData({ isRefreshing: false }); wx.stopPullDownRefresh(); });
|
||||
this.loadHistory(false).finally(() => {
|
||||
this.setData({ isRefreshing: false });
|
||||
wx.stopPullDownRefresh();
|
||||
});
|
||||
},
|
||||
|
||||
loadHistory(refresh) {
|
||||
if (!refresh && !this.data.hasMore) return Promise.resolve();
|
||||
return new Promise((resolve) => {
|
||||
this.setData({ loadingHistory: true });
|
||||
const { groupId, lastTimestamp } = this.data;
|
||||
const ts = refresh ? null : lastTimestamp;
|
||||
wx.goEasy.im.history({
|
||||
type: wx.GoEasy.IM_SCENE.GROUP,
|
||||
id: groupId,
|
||||
lastTimestamp: ts,
|
||||
limit: 20,
|
||||
onSuccess: (res) => {
|
||||
let list = res.content || [];
|
||||
list.sort((a, b) => a.timestamp - b.timestamp);
|
||||
list.forEach((m, idx) => {
|
||||
m = this.normalizeMessage(m);
|
||||
list[idx] = m;
|
||||
m.formattedTime = formatDate(m.timestamp);
|
||||
if (idx === 0) m.showTime = true;
|
||||
else m.showTime = (m.timestamp - list[idx-1].timestamp) / 60000 > 5;
|
||||
if (!m.senderData) m.senderData = { name: '未知用户', avatar: '' };
|
||||
});
|
||||
let final = refresh ? list : [...list, ...this.data.messages];
|
||||
if (!refresh) {
|
||||
for (let i = 0; i < final.length; i++) {
|
||||
if (i === 0) final[i].showTime = true;
|
||||
else final[i].showTime = (final[i].timestamp - final[i-1].timestamp) / 60000 > 5;
|
||||
}
|
||||
}
|
||||
const ids = new Set();
|
||||
const unique = [];
|
||||
for (const m of final) { if (!ids.has(m.messageId)) { ids.add(m.messageId); unique.push(m); } }
|
||||
const update = {
|
||||
messages: unique,
|
||||
hasMore: list.length >= 20,
|
||||
lastTimestamp: unique.length ? unique[0].timestamp : lastTimestamp,
|
||||
loadingHistory: false
|
||||
};
|
||||
if (refresh) update.scrollToView = 'msg-bottom';
|
||||
this.setData(update);
|
||||
resolve();
|
||||
},
|
||||
onFailed: () => { this.setData({ loadingHistory: false }); resolve(); }
|
||||
});
|
||||
mapHistoryMessage(m, idx, list) {
|
||||
m = this.normalizeMessage(m);
|
||||
m.formattedTime = formatDate(m.timestamp);
|
||||
if (idx === 0) m.showTime = true;
|
||||
else m.showTime = (m.timestamp - list[idx - 1].timestamp) / 60000 > 5;
|
||||
if (!m.senderData) m.senderData = { name: '未知用户', avatar: '' };
|
||||
return m;
|
||||
},
|
||||
|
||||
async fetchGroupHistoryPage(gid, lastTimestamp) {
|
||||
return fetchHistoryMessages({
|
||||
scene: wx.GoEasy.IM_SCENE.GROUP,
|
||||
id: gid,
|
||||
lastTimestamp,
|
||||
limit: 20,
|
||||
});
|
||||
},
|
||||
|
||||
async loadHistory(refresh) {
|
||||
if (!refresh && !this.data.hasMore) return;
|
||||
if (this.data.loadingHistory) return;
|
||||
if (!this.data.groupId) return;
|
||||
|
||||
this.setData({ loadingHistory: true });
|
||||
try {
|
||||
const ready = await waitChatImReady(app, 12000);
|
||||
if (!ready) {
|
||||
wx.showToast({ title: '消息服务未连接,请稍后重试', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
|
||||
await this.subscribeGroupIfNeeded();
|
||||
|
||||
const ts = refresh
|
||||
? null
|
||||
: getOldestHistoryTimestamp(this.data.messages, this.data.lastTimestamp);
|
||||
if (!refresh && ts == null) {
|
||||
this.setData({ hasMore: false });
|
||||
wx.showToast({ title: '没有更早的消息了', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
|
||||
let raw = await this.fetchGroupHistoryPage(this.data.groupId, ts);
|
||||
|
||||
if (refresh && raw.length === 0 && isPairGroupId(this.data.groupId) && this.data.orderId) {
|
||||
const legacyId = `group_${this.data.orderId}`;
|
||||
if (legacyId !== this.data.groupId) {
|
||||
raw = await this.fetchGroupHistoryPage(legacyId, ts);
|
||||
}
|
||||
}
|
||||
|
||||
const merged = mergeHistoryMessages({
|
||||
incoming: raw,
|
||||
existing: this.data.messages,
|
||||
refresh,
|
||||
limit: 20,
|
||||
mapMessage: (m, idx, list) => this.mapHistoryMessage(m, idx, list),
|
||||
});
|
||||
|
||||
const update = {
|
||||
messages: merged.messages,
|
||||
hasMore: merged.hasMore,
|
||||
lastTimestamp: merged.lastTimestamp,
|
||||
};
|
||||
if (refresh) update.scrollToView = 'msg-bottom';
|
||||
this.setData(update);
|
||||
} catch (e) {
|
||||
console.warn('[群聊] 历史消息加载失败', e);
|
||||
if (!refresh) {
|
||||
wx.showToast({ title: '加载历史消息失败', icon: 'none' });
|
||||
}
|
||||
} finally {
|
||||
this.setData({ loadingHistory: false });
|
||||
}
|
||||
},
|
||||
|
||||
listenNewMsg() {
|
||||
if (this._msgHandler) wx.goEasy.im.off(wx.GoEasy.IM_EVENT.GROUP_MESSAGE_RECEIVED, this._msgHandler);
|
||||
this._msgHandler = (msg) => {
|
||||
@@ -531,7 +750,9 @@ Page({
|
||||
orderId: order.dingdan_id,
|
||||
jieshao: order.jieshao,
|
||||
jine: order.jine,
|
||||
beizhu: order.beizhu
|
||||
beizhu: order.beizhu,
|
||||
zhuangtai: order.zhuangtai,
|
||||
nicheng: order.nicheng,
|
||||
};
|
||||
sendGroupMessage({
|
||||
msgData: {
|
||||
@@ -555,6 +776,10 @@ Page({
|
||||
},
|
||||
onSuccess: (messageId, status) => {
|
||||
that.updateMsg(messageId, status);
|
||||
that.closeOrderSender();
|
||||
if (status === 'success') {
|
||||
wx.showToast({ title: '订单已发送', icon: 'success' });
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -566,5 +791,24 @@ Page({
|
||||
this.setData({ detailText: text, showDetailModal: true });
|
||||
},
|
||||
|
||||
onKeyboardHeightChange(e) { this.setData({ keyboardHeight: e.detail.height }); }
|
||||
onKeyboardHeightChange(e) { this.setData({ keyboardHeight: e.detail.height }); },
|
||||
|
||||
onAvatarError(e) {
|
||||
const def = getDefaultAvatarUrl(app);
|
||||
const idx = e.currentTarget.dataset.index;
|
||||
if (idx != null && idx !== '') {
|
||||
this.setData({ [`messages[${idx}].senderData.avatar`]: def });
|
||||
}
|
||||
},
|
||||
|
||||
onSelfAvatarError() {
|
||||
const def = getDefaultAvatarUrl(app);
|
||||
if (this.data.currentUser) {
|
||||
this.setData({ 'currentUser.avatar': def });
|
||||
}
|
||||
},
|
||||
|
||||
tapOrderBar() {
|
||||
this.openOrderSender();
|
||||
},
|
||||
});
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"navigationBarTitleText": "群聊",
|
||||
"usingComponents": {
|
||||
"order-card": "/components/order-card/order-card"
|
||||
"order-card": "/components/order-card/order-card",
|
||||
"order-sender": "/components/order-sender/order-sender"
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,28 @@
|
||||
<view class="chat-page">
|
||||
<view class="order-status-bar" wx:if="{{orderId}}" bindtap="tapOrderBar">
|
||||
<view class="order-status-main">
|
||||
<view class="order-status-left">
|
||||
<text class="order-status-id">订单 {{orderId}}</text>
|
||||
<text class="order-status-price" wx:if="{{orderJine}}">¥{{orderJine}}</text>
|
||||
</view>
|
||||
<text class="order-status-tag" wx:if="{{orderZhuangtaiText}}">{{orderZhuangtaiText}}</text>
|
||||
</view>
|
||||
<text class="order-status-desc" wx:if="{{orderJieshao}}">{{orderJieshao}}</text>
|
||||
<text class="order-status-hint">点击查看历史订单并发送</text>
|
||||
</view>
|
||||
<scroll-view class="chat-msg-list" scroll-y="true"
|
||||
scroll-into-view="{{scrollToView}}"
|
||||
refresher-enabled="{{true}}"
|
||||
refresher-triggered="{{isRefreshing}}"
|
||||
bindrefresherrefresh="onPullDownRefresh"
|
||||
style="top: 20rpx; bottom: calc({{bottomSafeHeight}}rpx + {{keyboardHeight}}px + env(safe-area-inset-bottom) + 20rpx);">
|
||||
style="top: {{orderId ? '120rpx' : '20rpx'}}; bottom: calc({{bottomSafeHeight}}rpx + {{keyboardHeight}}px + env(safe-area-inset-bottom) + 24rpx);">
|
||||
<view class="chat-loading-more" wx:if="{{loadingHistory}}">加载更早消息...</view>
|
||||
<block wx:for="{{messages}}" wx:key="messageId">
|
||||
<block wx:for="{{messages}}" wx:key="messageId" wx:for-index="msgIdx">
|
||||
<view class="chat-msg-wrapper" data-messageid="{{item.messageId}}" bindlongpress="showAction">
|
||||
<view class="chat-time-tag" wx:if="{{item.showTime}}">{{item.formattedTime}}</view>
|
||||
<view class="chat-msg-row {{item.senderId === currentUser.id ? 'chat-msg-row--right' : 'chat-msg-row--left'}}">
|
||||
<!-- 对方头像及昵称 -->
|
||||
<view wx:if="{{item.senderId !== currentUser.id}}" class="sender-info">
|
||||
<image class="chat-avatar" src="{{item.senderData.avatar || '/images/default-avatar.png'}}" mode="aspectFill" />
|
||||
<image class="chat-avatar" src="{{item.senderData.avatar || defaultAvatarUrl}}" mode="aspectFill" binderror="onAvatarError" data-index="{{msgIdx}}" />
|
||||
<text class="sender-name">{{item.senderData.name || item.senderId}}</text>
|
||||
</view>
|
||||
<view class="chat-bubble {{item.senderId === currentUser.id ? 'chat-bubble--right' : 'chat-bubble--left'}}"
|
||||
@@ -27,15 +37,15 @@
|
||||
<text class="chat-order-info">ID: {{item.payload.orderId}}</text>
|
||||
<text class="chat-order-info">内容: {{item.payload.jieshao}}</text>
|
||||
<text class="chat-order-info">金额: ¥{{item.payload.jine}}</text>
|
||||
<text class="chat-order-info" wx:if="{{item.payload.beizhu}}">备注: {{item.payload.beizhu}}</text>
|
||||
<view class="chat-order-info" style="color:#007aff;margin-top:8rpx">点击查看详情</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 自己的头像 -->
|
||||
<image wx:if="{{item.senderId === currentUser.id}}" class="chat-avatar" src="{{currentUser.avatar}}" mode="aspectFill" />
|
||||
<image wx:if="{{item.senderId === currentUser.id}}" class="chat-avatar" src="{{currentUser.avatar || defaultAvatarUrl}}" mode="aspectFill" binderror="onSelfAvatarError" />
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
<view id="msg-bottom" style="height:20rpx;"></view>
|
||||
<view id="msg-bottom" style="height:56rpx;"></view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="chat-input-area" style="bottom: {{keyboardHeight}}px; padding-bottom: calc(10rpx + env(safe-area-inset-bottom));">
|
||||
@@ -88,5 +98,5 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<order-sender visible="{{showOrderSender}}" bind:send="onSendOrder" bind:close="closeOrderSender" />
|
||||
<order-sender visible="{{showOrderSender}}" group-id="{{groupId}}" order-id="{{orderId}}" bind:send="onSendOrder" bind:close="closeOrderSender" />
|
||||
</view>
|
||||
|
||||
@@ -1,5 +1,67 @@
|
||||
/* 使用全局 chat-* 样式 */
|
||||
|
||||
.order-status-bar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 11;
|
||||
background: #fff;
|
||||
padding: 16rpx 24rpx;
|
||||
border-bottom: 1rpx solid #e8e8e8;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
.order-status-main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.order-status-id {
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.order-status-tag {
|
||||
font-size: 22rpx;
|
||||
color: #07c160;
|
||||
background: #e8f8ee;
|
||||
padding: 4rpx 16rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.order-status-left {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.order-status-price {
|
||||
font-size: 24rpx;
|
||||
color: #ff6b00;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
|
||||
.order-status-hint {
|
||||
font-size: 22rpx;
|
||||
color: #007aff;
|
||||
margin-top: 6rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.order-status-desc {
|
||||
font-size: 24rpx;
|
||||
color: #888;
|
||||
margin-top: 8rpx;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* 发送者昵称样式(群聊特有) */
|
||||
.sender-info {
|
||||
display: flex;
|
||||
|
||||
Reference in New Issue
Block a user