diff --git a/backend/application/common/model/Messages.php b/backend/application/common/model/Messages.php
index f97ff8f..48f7533 100644
--- a/backend/application/common/model/Messages.php
+++ b/backend/application/common/model/Messages.php
@@ -36,9 +36,14 @@ class Messages extends Model
+ /**
+ * 消息类型:0=系统消息,1=公告消息,2=需求消息
+ * 此处直接返回中文而非 __() 语言包:该文案会随接口返回给小程序,
+ * 而 API 模块加载的语言包并不包含这些 key,__() 查不到会原样输出英文
+ */
public function getMessageTypeList()
{
- return ['0' => __('Message_type 0'), '1' => __('Message_type 1'), '2' => __('Message_type 2')];
+ return ['0' => '系统消息', '1' => '公告消息', '2' => '需求消息'];
}
diff --git a/backend/application/common/model/order/Ships.php b/backend/application/common/model/order/Ships.php
index cf9dd73..0e2f2b9 100644
--- a/backend/application/common/model/order/Ships.php
+++ b/backend/application/common/model/order/Ships.php
@@ -26,7 +26,8 @@ class Ships extends Model
// 追加属性
protected $append = [
'images_list',
- 'files_list'
+ 'files_list',
+ 'deliver_links_list'
];
/**
@@ -45,6 +46,14 @@ class Ships extends Model
return self::parseUrlList($data['files'] ?? '');
}
+ /**
+ * 交付链接列表([{url, name}]),供接口与后台直接使用
+ */
+ public function getDeliverLinksListAttr($value, $data)
+ {
+ return self::parseUrlList($data['deliver_links'] ?? '');
+ }
+
/**
* 解析多图/多文件字段:英文逗号分隔的 URL 字符串 -> [{url, name}]
* 例:http://a.com/1.jpg,http://a.com/2.pdf => [['url'=>'http://a.com/1.jpg','name'=>'1.jpg'], ...]
diff --git a/backend/application/common/service/DemandService.php b/backend/application/common/service/DemandService.php
index 753a800..db244db 100644
--- a/backend/application/common/service/DemandService.php
+++ b/backend/application/common/service/DemandService.php
@@ -438,6 +438,28 @@ class DemandService
}
}
+ /**
+ * 规范化交付链接(只允许 1 个)
+ * 支持数组或字符串,仅保留第一个 http(s) 开头的合法链接
+ * @param array|string $links
+ * @return array
+ */
+ public static function normalizeDeliverLinks($links): array
+ {
+ if (is_string($links)) {
+ $links = preg_split('/[,,\r\n]+/', $links) ?: [];
+ }
+ foreach ((array)$links as $item) {
+ $url = is_array($item) ? trim($item['url'] ?? '') : trim((string)$item);
+ if ($url && preg_match('/^https?:\/\//i', $url)) {
+ //只保留第一个合法链接
+ return [$url];
+ }
+ }
+
+ return [];
+ }
+
/**
* 开发者发货(交付开发成果)
* 凭证截图、交付附件与备注写入订单发货表,尾款订单转为已发货(待收货)
@@ -452,10 +474,13 @@ class DemandService
$demandId = $requestData['demandId'] ?? 0;
$images = array_values($requestData['images'] ?? []);
$files = array_values($requestData['files'] ?? []);
+ $links = self::normalizeDeliverLinks($requestData['links'] ?? '');
$remark = trim($requestData['remark'] ?? '');
Db::startTrans();
- if (!$images || !$files) {
- throw new \Exception('请上传开发完成的凭证截图和交付附件');
+ //源码一般在企业微信沟通群直接交付(无大小限制),平台只登记发货状态,
+ //故仅凭证截图必填,附件与交付链接均选填
+ if (!$images) {
+ throw new \Exception('请上传开发完成的凭证截图');
}
$demand = self::getOne(['id' => $demandId], ['winBidding']);
if (!$demand) {
@@ -477,7 +502,7 @@ class DemandService
}
//交付内容写入订单发货表
$spuId = $finalOrder->orderGoods[0]->spu_id ?? 0;
- OrderShipService::createDemandDelivery($finalOrder->order_no, $spuId, $demandId, $images, $files, $remark);
+ OrderShipService::createDemandDelivery($finalOrder->order_no, $spuId, $demandId, $images, $files, $remark, $links);
//尾款订单改为已发货(待收货)
$upRes = OrderService::where(['id' => $finalOrder->id])->update(['order_status' => OrderService::ORDER_STATUS_SHIPPED]);
if (!$upRes) {
diff --git a/backend/application/common/service/MessageService.php b/backend/application/common/service/MessageService.php
index 6b965d9..e8b9e42 100644
--- a/backend/application/common/service/MessageService.php
+++ b/backend/application/common/service/MessageService.php
@@ -75,8 +75,14 @@ class MessageService
$lines[] = $name . ':' . $values[$key];
}
}
- if (!empty($template['remark'])) {
- $lines[] = '备注:' . $template['remark'];
+ // 各发送点已把 remark 作为最后一个 value 传入(对应 valueNames 末位的「备注」字段),
+ // 此处仅在正文尚未包含 remark 时才追加,避免出现两行重复的「备注」
+ $remark = $template['remark'] ?? '';
+ if ($remark !== '') {
+ $content = implode("\n", $lines);
+ if (mb_strpos($content, $remark) === false) {
+ $lines[] = '备注:' . $remark;
+ }
}
$content = implode("\n", $lines);
diff --git a/backend/application/common/service/OrderShipService.php b/backend/application/common/service/OrderShipService.php
index ce9c8e4..0eb5607 100644
--- a/backend/application/common/service/OrderShipService.php
+++ b/backend/application/common/service/OrderShipService.php
@@ -37,24 +37,28 @@ class OrderShipService
}
/**
- * 需求交付发货单(开发者发货:凭证截图+交付附件+备注)
- * 多图/多文件统一存英文逗号分隔的 URL 字符串:
+ * 需求交付发货单(开发者发货:凭证截图 + 交付附件/链接 + 备注)
+ * 多图/多文件/多链接统一存英文逗号分隔的 URL 字符串:
* http://xxx/a.jpg,http://xxx/b.pdf
+ * 说明:源码通常在企业微信沟通群直接交付,平台只登记发货状态,
+ * 故附件与链接均为选填,仅凭证截图必填
* @param $order_no
* @param $order_goods_spu_id
* @param $demand_id
* @param array $images URL 数组
- * @param array $files URL 数组
+ * @param array $files URL 数组(选填)
* @param string $remark
+ * @param array $links 交付链接数组(选填:Git仓库/网盘等持久获取方式)
* @return mixed
* @throws \Exception
*/
- public static function createDemandDelivery($order_no, $order_goods_spu_id, $demand_id, array $images, array $files, $remark = '')
+ public static function createDemandDelivery($order_no, $order_goods_spu_id, $demand_id, array $images, array $files, $remark = '', array $links = [])
{
// 复用模型的规范化方法,统一为英文逗号分隔字符串
$imagesStr = OrderShips::toUrlString($images);
$filesStr = OrderShips::toUrlString($files);
- if (mb_strlen($imagesStr) > 1000 || mb_strlen($filesStr) > 1000) {
+ $linksStr = OrderShips::toUrlString($links);
+ if (mb_strlen($imagesStr) > 1000 || mb_strlen($filesStr) > 1000 || mb_strlen($linksStr) > 1000) {
exception('附件数量过多或链接过长,请精简后重新发货');
}
$data = [
@@ -63,6 +67,7 @@ class OrderShipService
'demand_id' => $demand_id,
'images' => $imagesStr,
'files' => $filesStr,
+ 'deliver_links' => $linksStr,
'remark' => $remark,
];
$res = self::create($data);
@@ -99,6 +104,7 @@ class OrderShipService
return [
'images' => $ship->images_list,
'files' => $ship->files_list,
+ 'links' => $ship->deliver_links_list,
'remark' => $ship->remark,
'delivery_time' => $ship->createtime,
];
diff --git a/frontend/miniapp/app.js b/frontend/miniapp/app.js
index d0544b7..859fd4f 100644
--- a/frontend/miniapp/app.js
+++ b/frontend/miniapp/app.js
@@ -25,12 +25,10 @@ App({
});
},
});
- //启动未读消息轮询(tabbar红点)
- this.startUnreadPolling();
},
onShow: function () {
updateManager();
- //从后台切回前台,立即刷新未读红点
+ //从后台切回前台时刷新一次未读红点(不使用定时轮询,避免请求堆积导致页面卡死)
this.refreshUnread();
},
onHide: function () {},
@@ -38,19 +36,6 @@ App({
unread: 0, //未读消息数(tabbar红点共享缓存)
},
- /**
- * 未读消息轮询:小程序前台每10s刷新一次底部tabbar红点
- * (切后台后JS执行会被系统挂起,定时器自然暂停,回前台由onShow立即补一次)
- */
- startUnreadPolling: function () {
- if (this.unreadTimer) {
- return;
- }
- this.unreadTimer = setInterval(() => {
- this.refreshUnread();
- }, 10000);
- },
-
/**
* 刷新当前 tab 页 tabbar 实例的红点(非tab页无tabbar实例,自动跳过)
*/
diff --git a/frontend/miniapp/custom-tab-bar/index.js b/frontend/miniapp/custom-tab-bar/index.js
index 37fc7a5..fab95c9 100644
--- a/frontend/miniapp/custom-tab-bar/index.js
+++ b/frontend/miniapp/custom-tab-bar/index.js
@@ -62,7 +62,15 @@ Component({
if (!force && now - (this._lastFetchAt || 0) < 5000) {
return;
}
+ //上一次请求尚未结束时不再发起,避免请求堆积占满并发导致页面假死
+ if (this._fetching) {
+ return;
+ }
this._lastFetchAt = now;
+ this._fetching = true;
+ const done = () => {
+ this._fetching = false;
+ };
fetchMessageUnreadCount().then((res) => {
if (res.code == 1) {
const unread = Number(res.data?.unread_count) || 0;
@@ -70,7 +78,7 @@ Component({
const app = getApp();
if (app) app.globalData.unread = unread;
}
- }).catch(() => {});
+ }).catch(() => {}).then(done, done);
},
/**
diff --git a/frontend/miniapp/pages/demand/deliver/index.js b/frontend/miniapp/pages/demand/deliver/index.js
index 691c3d1..02dec91 100644
--- a/frontend/miniapp/pages/demand/deliver/index.js
+++ b/frontend/miniapp/pages/demand/deliver/index.js
@@ -8,6 +8,8 @@ Page({
data: {
demandId: 0,
remark: '',
+ // 交付链接(Git仓库/网盘等持久获取方式),选填
+ deliverLinks: '',
// 开发完成凭证截图(软件成品展示图等)
imageFiles: [],
imageMax: 9,
@@ -43,6 +45,19 @@ Page({
this.setData({ remark: e.detail.value });
},
+ // 交付链接变更
+ onDeliverLinksChange(e) {
+ this.setData({ deliverLinks: e.detail.value });
+ },
+
+ // 交付链接(单个):只取第一行,避免粘贴时带入多余内容
+ getDeliverLinks() {
+ const link = String(this.data.deliverLinks || '')
+ .split(/[\r\n]+/)[0]
+ .trim();
+ return link ? [link] : [];
+ },
+
// 凭证截图选择成功
// 注意:t-upload 绑定了 files,success 事件返回的是完整文件列表(含已选的旧文件),
// 必须整体覆盖,不能往 imageFiles 里追加,否则已选图片会重复
@@ -209,7 +224,7 @@ Page({
}
},
- // 表单验证
+ // 表单验证:源码一般在沟通群交付,平台仅凭证截图必填,附件与链接选填
validateForm() {
const { imageFiles, attachFiles } = this.data;
if (!imageFiles.length) {
@@ -219,9 +234,17 @@ Page({
});
return false;
}
- if (!attachFiles.length) {
+ const links = this.getDeliverLinks();
+ if (links.length > 1) {
wx.showToast({
- title: '请上传源码或软件附件',
+ title: '只能填写1个交付链接',
+ icon: 'none'
+ });
+ return false;
+ }
+ if (links.some(item => !/^https?:\/\//i.test(item))) {
+ wx.showToast({
+ title: '交付链接需以 http:// 或 https:// 开头',
icon: 'none'
});
return false;
@@ -251,6 +274,7 @@ Page({
opType: 'deliverGoods',
images: imageFiles.map(file => file.fullUrl || file.url),
files: attachFiles.map(file => file.fullUrl || file.url),
+ links: this.getDeliverLinks(),
remark
};
demandOperate(params).then(
diff --git a/frontend/miniapp/pages/demand/deliver/index.json b/frontend/miniapp/pages/demand/deliver/index.json
index 3227b1d..9fcad4c 100644
--- a/frontend/miniapp/pages/demand/deliver/index.json
+++ b/frontend/miniapp/pages/demand/deliver/index.json
@@ -3,6 +3,7 @@
"usingComponents": {
"t-upload": "tdesign-miniprogram/upload/upload",
"t-tag": "tdesign-miniprogram/tag/tag",
- "t-textarea": "tdesign-miniprogram/textarea/textarea"
+ "t-textarea": "tdesign-miniprogram/textarea/textarea",
+ "t-input": "tdesign-miniprogram/input/input"
}
}
diff --git a/frontend/miniapp/pages/demand/deliver/index.wxml b/frontend/miniapp/pages/demand/deliver/index.wxml
index be42d43..6a85ec2 100644
--- a/frontend/miniapp/pages/demand/deliver/index.wxml
+++ b/frontend/miniapp/pages/demand/deliver/index.wxml
@@ -20,14 +20,23 @@
/>
+
+
+
+ 源码交付方式
+
+
+ 建议在企业微信沟通群中直接发送源码文件,或使用网盘地址。下方的附件与链接为选填补充。
+
+
+
交付附件(源码或软件成品)
- *
-
+
- 上传源码或软件成品文件,客户确认收货后可下载,从聊天记录选择文件
+ 小体积源码或软件成品可直接上传,大文件请在沟通群交付;从聊天记录选择文件
+
+
+
+ 交付链接
+
+
+ 填写一个网盘下载地址
+
+
+
@@ -74,7 +98,7 @@
-
+
确认发货
diff --git a/frontend/miniapp/pages/demand/deliver/index.wxss b/frontend/miniapp/pages/demand/deliver/index.wxss
index d7181ca..a1b9a60 100644
--- a/frontend/miniapp/pages/demand/deliver/index.wxss
+++ b/frontend/miniapp/pages/demand/deliver/index.wxss
@@ -47,6 +47,20 @@
color: var(--text-tertiary);
}
+/* 交付方式提示卡片 */
+.form-card--tip {
+ background: var(--brand-color-light, #fff3e8);
+}
+
+.form-card--tip .form-card__desc {
+ margin-bottom: 0;
+}
+
+.tip-strong {
+ color: var(--brand-color, #ff5f15);
+ font-weight: 500;
+}
+
/* ================= 附件标签 ================= */
.attach-list {
display: flex;
diff --git a/frontend/miniapp/pages/demand/detail/index.wxml b/frontend/miniapp/pages/demand/detail/index.wxml
index 6c80469..2633d8d 100644
--- a/frontend/miniapp/pages/demand/detail/index.wxml
+++ b/frontend/miniapp/pages/demand/detail/index.wxml
@@ -73,6 +73,13 @@
+
+ 交付链接
+
+ {{item.url}}
+
+
+
发货备注
diff --git a/frontend/miniapp/pages/demand/detail/index.wxss b/frontend/miniapp/pages/demand/detail/index.wxss
index de9da7e..4bd30ef 100644
--- a/frontend/miniapp/pages/demand/detail/index.wxss
+++ b/frontend/miniapp/pages/demand/detail/index.wxss
@@ -94,6 +94,24 @@ page {
background: var(--bg-grey);
}
+/* 交付链接:长链接换行展示 + 复制按钮 */
+.delivery-link {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 12rpx 0;
+}
+
+.delivery-link__url {
+ flex: 1;
+ min-width: 0;
+ margin-right: 16rpx;
+ font-size: 26rpx;
+ line-height: 38rpx;
+ color: var(--brand-color, #ff5f15);
+ word-break: break-all;
+}
+
.delivery-remark {
font-size: 26rpx;
line-height: 40rpx;
diff --git a/frontend/miniapp/pages/message/detail/index.js b/frontend/miniapp/pages/message/detail/index.js
index 6f3a562..62e4a33 100644
--- a/frontend/miniapp/pages/message/detail/index.js
+++ b/frontend/miniapp/pages/message/detail/index.js
@@ -1,176 +1,82 @@
// pages/message/detail/index.js
+import { fetchMessageDetail, messageSetRead } from '../../../services/message/fetchMessage';
+
+// tabBar 页面(与 app.json 的 tabBar.list 保持一致):
+// navigateTo 无法跳转 tab 页,必须用 switchTab;而 switchTab 不支持带参数
+const TAB_PAGES = [
+ 'pages/home/home',
+ 'pages/goods/list/index',
+ 'pages/message/list/index',
+ 'pages/usercenter/index',
+];
+
Page({
-
- /**
- * 页面的初始数据
- */
data: {
- // 客服信息
- serviceAvatar: '/assets/images/contact.png',
- serviceNickname: '在线客服',
- inputContent: '',
- // 消息列表
- messageList: [{
- id: 1,
- type: 'text',
- content: '您好,请问有什么可以帮您?',
- time: '12:30',
- avatar: '/assets/image/contact.png',
- isSelf: false
- },
- {
- id: 2,
- type: 'text',
- content: '我想咨询一下订单问题',
- time: '12:31',
- avatar: '/assets/image/default_avatar_big.png',
- isSelf: true
- },
- {
- id: 3,
- type: 'text',
- content: '好的,请问是哪个订单呢?',
- time: '12:31',
- avatar: '/assets/image/contact.png',
- isSelf: false
- }
- ],
- scrollToMessage: '', // 用于消息定位
-
- // 输入相关
- inputContent: '',
- showEmoji: false,
+ id: 0,
+ detail: null,
+ jumpPage: '',
+ loading: true,
},
- // 监听输入框内容变化
- onInput(e) {
- this.setData({
- inputContent: e.detail.value
+ onLoad(options) {
+ const id = options?.id || 0;
+ this.setData({ id });
+ // 页面标题用消息标题,onLoad 阶段先给默认值
+ wx.setNavigationBarTitle({
+ title: '消息详情'
});
+ this.loadDetail();
},
- // 发送消息
- sendMessage() {
- if (!this.data.inputContent.trim()) return;
-
- const newMessage = {
- id: Date.now(), // 使用时间戳作为临时ID
- type: 'text',
- content: this.data.inputContent,
- isSelf: true,
- avatar: '你的默认头像URL',
- time: this.formatTime(new Date())
- };
-
- this.setData({
- messageList: [...this.data.messageList, newMessage],
- inputContent: '', // 清空输入框
- scrollToMessage: `msg-${newMessage.id}` // 滚动到最新消息
- });
- },
-
- // 选择图片
- chooseImage() {
- wx.chooseMedia({
- count: 1,
- mediaType: ['image'],
- sourceType: ['album', 'camera'],
- success: (res) => {
- const tempFilePath = res.tempFiles[0].tempFilePath;
- const newMessage = {
- id: Date.now(),
- type: 'image',
- content: tempFilePath,
- isSelf: true,
- avatar: '你的默认头像URL',
- time: this.formatTime(new Date())
- };
-
- this.setData({
- messageList: [...this.data.messageList, newMessage],
- scrollToMessage: `msg-${newMessage.id}`
+ loadDetail() {
+ fetchMessageDetail(this.data.id).then((res) => {
+ const detail = res.data || null;
+ const jumpPage = String(detail?.extra_json?.page || '');
+ this.setData({
+ detail,
+ jumpPage,
+ loading: false
+ });
+ if (detail?.title) {
+ wx.setNavigationBarTitle({
+ title: detail.title
});
}
+ // 进入即标记已读
+ if (detail && !detail.is_read) {
+ messageSetRead({ id: this.data.id }).then(() => {
+ this.setData({ 'detail.is_read': 1 });
+ }).catch(() => {});
+ }
+ }).catch(() => {
+ this.setData({ loading: false });
});
},
- // 预览图片
- previewImage(e) {
- const current = e.currentTarget.dataset.src;
- const urls = this.data.messageList
- .filter(msg => msg.type === 'image')
- .map(msg => msg.content);
-
- wx.previewImage({
- current,
- urls
+ // 前往消息关联的业务页面
+ onJumpTap() {
+ const jumpPage = String(this.data.jumpPage || '').replace(/^\//, '');
+ if (!jumpPage) {
+ return;
+ }
+ const pathname = jumpPage.split('?')[0];
+ //tabBar 页只能 switchTab(不支持带参数),其余走 navigateTo
+ if (TAB_PAGES.indexOf(pathname) !== -1) {
+ wx.switchTab({
+ url: '/' + pathname,
+ fail: () => {
+ wx.showToast({ title: '页面跳转失败', icon: 'none' });
+ }
+ });
+ return;
+ }
+ wx.navigateTo({
+ url: '/' + jumpPage,
+ fail: () => {
+ wx.showToast({ title: '页面跳转失败', icon: 'none' });
+ }
});
},
- // 格式化时间
- formatTime(date) {
- const hour = date.getHours().toString().padStart(2, '0');
- const minute = date.getMinutes().toString().padStart(2, '0');
- return `${hour}:${minute}`;
- },
-
- /**
- * 生命周期函数--监听页面加载
- */
- onLoad(options) {
- // 设置页面标题为客服名称
- wx.setNavigationBarTitle({
- title: this.serviceNickname
- });
-
- },
-
- /**
- * 生命周期函数--监听页面初次渲染完成
- */
- onReady() {
-
- },
-
- /**
- * 生命周期函数--监听页面显示
- */
- onShow() {
-
- },
-
- /**
- * 生命周期函数--监听页面隐藏
- */
- onHide() {
-
- },
-
- /**
- * 生命周期函数--监听页面卸载
- */
- onUnload() {
-
- },
-
- /**
- * 页面相关事件处理函数--监听用户下拉动作
- */
- onPullDownRefresh() {
-
- },
-
- /**
- * 页面上拉触底事件的处理函数
- */
- onReachBottom() {
-
- },
-
- /**
- * 用户点击右上角分享
- */
- onShareAppMessage() {
-
- }
-})
\ No newline at end of file
+ onShareAppMessage() { }
+});
diff --git a/frontend/miniapp/pages/message/detail/index.json b/frontend/miniapp/pages/message/detail/index.json
index b99150b..cf21abf 100644
--- a/frontend/miniapp/pages/message/detail/index.json
+++ b/frontend/miniapp/pages/message/detail/index.json
@@ -1,5 +1,9 @@
{
+ "navigationBarTitleText": "消息详情",
"usingComponents": {
- "t-icon": "tdesign-miniprogram/icon/icon"
+ "t-tag": "tdesign-miniprogram/tag/tag",
+ "t-button": "tdesign-miniprogram/button/button",
+ "t-empty": "tdesign-miniprogram/empty/empty",
+ "t-loading": "tdesign-miniprogram/loading/loading"
}
-}
\ No newline at end of file
+}
diff --git a/frontend/miniapp/pages/message/detail/index.wxml b/frontend/miniapp/pages/message/detail/index.wxml
index fc5f449..723b403 100644
--- a/frontend/miniapp/pages/message/detail/index.wxml
+++ b/frontend/miniapp/pages/message/detail/index.wxml
@@ -1,29 +1,29 @@
+
-
-
-
-
-
-
- {{item.content}}
-
-
- {{item.time}}
-
-
-
-
-
-
-
-
-
-
-
- 发送
-
-
+
+
-
\ No newline at end of file
+
+
+
+
+ {{detail.createtime_text}}
+ {{detail.content}}
+
+
+
+
+ 前往查看
+
+
+
+
+
+
+
+
diff --git a/frontend/miniapp/pages/message/detail/index.wxs b/frontend/miniapp/pages/message/detail/index.wxs
new file mode 100644
index 0000000..73c0139
--- /dev/null
+++ b/frontend/miniapp/pages/message/detail/index.wxs
@@ -0,0 +1,12 @@
+// 消息类型对应的标签主题色:0=系统消息(蓝),1=公告消息(橙),2=需求消息(绿)
+function tagTheme(type) {
+ var map = {
+ '0': 'primary',
+ '1': 'warning',
+ '2': 'success'
+ };
+ return map[String(type)] || 'default';
+}
+module.exports = {
+ tagTheme: tagTheme
+}
diff --git a/frontend/miniapp/pages/message/detail/index.wxss b/frontend/miniapp/pages/message/detail/index.wxss
index 5ec6b14..8f420e2 100644
--- a/frontend/miniapp/pages/message/detail/index.wxss
+++ b/frontend/miniapp/pages/message/detail/index.wxss
@@ -1,145 +1,64 @@
/* pages/message/detail/index.wxss */
.message-detail {
- display: flex;
- flex-direction: column;
- height: 100vh;
+ min-height: 100vh;
+ padding: 24rpx;
+ box-sizing: border-box;
+ background: var(--bg-page);
}
-.service-info {
- padding: 20rpx;
+.detail-loading {
+ display: flex;
+ justify-content: center;
+ padding-top: 120rpx;
+}
+
+.detail-card {
+ background: var(--bg-card);
+ border-radius: var(--radius-lg);
+ padding: 32rpx;
+ box-shadow: var(--shadow-card);
+}
+
+.detail-header {
display: flex;
align-items: center;
- background: #fff;
- border-bottom: 1rpx solid #eee;
+ justify-content: space-between;
}
-.service-info .avatar {
- width: 80rpx;
- height: 80rpx;
- border-radius: 50%;
- margin-right: 20rpx;
-}
-
-.service-info .nickname {
- font-size: 32rpx;
+.detail-title {
+ flex: 1;
+ min-width: 0;
+ margin-right: 16rpx;
+ font-size: 34rpx;
+ font-weight: 600;
+ line-height: 48rpx;
color: var(--text-primary);
}
-.message-list {
- flex: 1;
- padding: 20rpx;
- background: var(--bg-page);
+.detail-time {
+ margin-top: 12rpx;
+ font-size: 24rpx;
+ line-height: 36rpx;
+ color: var(--text-tertiary);
}
-.message-item {
- display: flex;
- margin-bottom: 30rpx;
-}
-
-.message-item.self {
- flex-direction: row-reverse;
- padding-right: 20rpx;
-}
-
-.message-item .avatar {
- width: 80rpx;
- height: 80rpx;
- border-radius: 50%;
-}
-
-.message-item .content {
- max-width: 60%;
- margin: 0 20rpx;
-}
-
-.message-item .bubble {
- padding: 20rpx;
- border-radius: 10rpx;
- background: #fff;
+/* 正文:保留换行,长内容自然撑开页面滚动 */
+.detail-content {
+ margin-top: 24rpx;
+ padding-top: 24rpx;
+ border-top: 1rpx solid var(--component-stroke, #eee);
+ font-size: 28rpx;
+ line-height: 44rpx;
+ color: var(--text-secondary);
+ white-space: pre-wrap;
word-break: break-all;
}
-.message-item.self .bubble {
- background: #07c160;
- color: #fff;
+/* 底部操作区:仅在需要跳转时出现 */
+.detail-actions {
+ margin-top: 40rpx;
}
-.message-item .msg-image {
- max-width: 100%;
- border-radius: 10rpx;
+.detail-empty {
+ padding-top: 200rpx;
}
-
-.message-item .time {
- font-size: 24rpx;
- color: var(--text-tertiary);
- margin-top: 10rpx;
- display: block;
-}
-
-.input-area {
- background: #fff;
- border-top: 1rpx solid #eee;
- padding-bottom: env(safe-area-inset-bottom);
- position: fixed; bottom: 0; left: 0; right: 0;
-}
-
-.toolbar {
- display: flex;
- padding: 20rpx;
- border-bottom: 1rpx solid #eee;
-}
-
-.tool-item {
- margin-right: 15rpx;
-}
-
-.input-box {
- display: flex;
- padding: 20rpx;
- align-items: flex-end;
- justify-content: center; align-items: center;
-}
-
-.input {
- flex: 1;
- background: var(--bg-page);
- border-radius: 8rpx;
- padding: 20rpx;
- min-height: 40rpx;
- max-height: 120rpx;
- margin-right: 20rpx;
-}
-
-.send-btn {
- width: 120rpx;
- height: 64rpx;
- line-height: 64rpx;
- text-align: center;
- background: #ddd;
- color: #fff;
- border-radius: 8rpx;
-}
-
-.send-btn.active {
- background: #07c160;
-}
-
-.emoji-panel {
- height: 400rpx;
- background: #fff;
- padding: 20rpx;
-}
-
-.emoji-list {
- display: flex;
- flex-wrap: wrap;
-}
-
-.emoji-item {
- width: 64rpx;
- height: 64rpx;
- font-size: 40rpx;
- display: flex;
- align-items: center;
- justify-content: center;
-}
\ No newline at end of file
diff --git a/frontend/miniapp/pages/message/list/index.js b/frontend/miniapp/pages/message/list/index.js
index f6727dc..60ed512 100644
--- a/frontend/miniapp/pages/message/list/index.js
+++ b/frontend/miniapp/pages/message/list/index.js
@@ -9,15 +9,6 @@ const TYPE_TABS = [
{ key: '2', label: '需求消息' },
];
-// tabBar 页面(与 app.json 的 tabBar.list 保持一致):
-// navigateTo 无法跳转 tab 页,必须用 switchTab;而 switchTab 不支持带参数
-const TAB_PAGES = [
- 'pages/home/home',
- 'pages/goods/list/index',
- 'pages/message/list/index',
- 'pages/usercenter/index',
-];
-
Page({
data: {
tabs: TYPE_TABS,
@@ -30,10 +21,7 @@ Page({
pageSize: 10,
unreadCount: 0,
hasMore: true,
- loading: false,
- showTextAndTitle: false,
- currentMessage: {},
- confirmBtn: '关闭'
+ loading: false
},
onLoad() {
@@ -94,61 +82,11 @@ Page({
this.loadList(true);
},
- showDialog(e) {
+ // 点击消息进入详情页(关闭交给小程序的返回:左上角/右滑手势/物理返回键)
+ onMessageTap(e) {
const id = e.currentTarget.dataset.id;
- const item = this.data.list.find(msg => msg.id == id);
- const jumpPage = item?.extra_json?.page || '';
- this.setData({
- showTextAndTitle: true,
- currentMessage: item || {},
- //携带跳转页面时提供「前往查看」
- confirmBtn: jumpPage ? '前往查看' : '关闭'
- });
- messageSetRead({ id: id }).then(() => {
- if (!item) {
- return;
- }
- const idx = this.data.list.findIndex(msg => msg.id == id);
- if (idx === -1) {
- return;
- }
- //原来未读的消息:本地未读数-1并同步tabbar红点
- if (!this.data.list[idx].is_read) {
- const typeKey = String(item.message_type);
- const unreadMap = { ...this.data.unreadMap };
- unreadMap[typeKey] = Math.max(Number(unreadMap[typeKey] || 0) - 1, 0);
- const totalUnread = Math.max(this.data.totalUnread - 1, 0);
- this.setData({ unreadMap, totalUnread });
- this.syncTabBarUnread(totalUnread);
- }
- this.setData({ [`list[${idx}].is_read`]: 1 });
- });
- },
-
- //弹窗确认:有跳转页面则前往,否则仅关闭
- onDialogConfirm() {
- const jumpPage = String(this.data.currentMessage?.extra_json?.page || '').replace(/^\//, '');
- this.setData({ showTextAndTitle: false });
- if (!jumpPage) {
- return;
- }
- const pathname = jumpPage.split('?')[0];
- //tabBar 页只能 switchTab(不支持带参数),其余走 navigateTo
- if (TAB_PAGES.indexOf(pathname) !== -1) {
- wx.switchTab({
- url: '/' + pathname,
- fail: () => {
- wx.showToast({ title: '页面跳转失败', icon: 'none' });
- }
- });
- return;
- }
wx.navigateTo({
- url: '/' + jumpPage,
- fail: () => {
- //页面路径不存在或超出页面栈时降级提示
- wx.showToast({ title: '页面跳转失败', icon: 'none' });
- }
+ url: `/pages/message/detail/index?id=${id}`
});
},
@@ -169,13 +107,6 @@ Page({
});
},
- onMessageTap(e) {
- const { type, id } = e.currentTarget.dataset;
- wx.navigateTo({
- url: `/pages/message/detail/index?type=${type}&id=${id}`
- });
- },
-
onShow() {
this.loadList(true);
},
diff --git a/frontend/miniapp/pages/message/list/index.json b/frontend/miniapp/pages/message/list/index.json
index de8f570..23cc1ff 100644
--- a/frontend/miniapp/pages/message/list/index.json
+++ b/frontend/miniapp/pages/message/list/index.json
@@ -4,14 +4,9 @@
"t-tab-panel": "tdesign-miniprogram/tab-panel/tab-panel",
"t-cell": "tdesign-miniprogram/cell/cell",
"t-icon": "tdesign-miniprogram/icon/icon",
- "t-row": "tdesign-miniprogram/row/row",
- "t-col": "tdesign-miniprogram/col/col",
"t-avatar": "tdesign-miniprogram/avatar/avatar",
- "t-badge": "tdesign-miniprogram/badge/badge",
- "t-dialog": "tdesign-miniprogram/dialog/dialog",
"t-empty": "tdesign-miniprogram/empty/empty",
- "t-tag": "tdesign-miniprogram/tag/tag",
- "t-divider": "tdesign-miniprogram/divider/divider"
+ "t-tag": "tdesign-miniprogram/tag/tag"
},
"navigationBarTitleText": "消息列表"
}
\ No newline at end of file
diff --git a/frontend/miniapp/pages/message/list/index.wxml b/frontend/miniapp/pages/message/list/index.wxml
index a499b3d..b890e86 100644
--- a/frontend/miniapp/pages/message/list/index.wxml
+++ b/frontend/miniapp/pages/message/list/index.wxml
@@ -1,15 +1,12 @@
-
-
-
-
-
-
-
-
-
+
+
@@ -24,11 +21,11 @@
-
+
{{item.title}}
- {{item.message_type_text}}
+ {{item.message_type_text}}
{{_index.ellipsis(item.content, 22)}}
{{item.createtime_text}}
@@ -40,12 +37,3 @@
-
-
-
-
- {{currentMessage.message_type_text}}
- {{currentMessage.content}}
-
-
-
diff --git a/frontend/miniapp/pages/message/list/index.wxs b/frontend/miniapp/pages/message/list/index.wxs
index bc34488..0641e43 100644
--- a/frontend/miniapp/pages/message/list/index.wxs
+++ b/frontend/miniapp/pages/message/list/index.wxs
@@ -1,6 +1,17 @@
function ellipsis(str, len) {
return str.length > len ? str.slice(0, len) + '...' : str;
}
+
+// 消息类型对应的标签主题色:0=系统消息(蓝),1=公告消息(橙),2=需求消息(绿)
+function tagTheme(type) {
+ var map = {
+ '0': 'primary',
+ '1': 'warning',
+ '2': 'success'
+ };
+ return map[String(type)] || 'default';
+}
module.exports = {
- ellipsis: ellipsis
-}
\ No newline at end of file
+ ellipsis: ellipsis,
+ tagTheme: tagTheme
+}
diff --git a/frontend/miniapp/pages/message/list/index.wxss b/frontend/miniapp/pages/message/list/index.wxss
index 06c225a..ef8be14 100644
--- a/frontend/miniapp/pages/message/list/index.wxss
+++ b/frontend/miniapp/pages/message/list/index.wxss
@@ -3,6 +3,28 @@
padding: 20rpx 0rpx;
}
+/* 顶部标题行:标题与清除按钮同一水平线,整体与下方分类 tabs 留出间距 */
+.message-header {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-between;
+ padding: 0 32rpx 12rpx;
+}
+
+.site-message-title {
+ font-size: 32rpx;
+ font-weight: bold;
+ line-height: 48rpx;
+ color: var(--text-primary);
+}
+
+/* 清除按钮:与文字垂直居中对齐 */
+.message-clear {
+ display: flex;
+ align-items: center;
+}
+
.clear-icon {
width: 40rpx;
height: 40rpx;
@@ -36,10 +58,6 @@
max-width: 420rpx;
}
-.site-message-title {
- font-weight: bold;
-}
-
.empty-container {
min-height: 100vh;
padding-top: 50%;