From 2c7da360f4b980c2b0933431273f7edefe563b2d Mon Sep 17 00:00:00 2001
From: tangxinyue <524779910@qq.com>
Date: Wed, 18 Mar 2026 10:12:20 +0800
Subject: [PATCH 1/2] =?UTF-8?q?=E5=AE=8C=E6=88=90=E6=94=AF=E4=BB=98?=
=?UTF-8?q?=E5=AE=9D=E7=9F=AD=E4=BF=A1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
components/message/chat/chat-layout.vue | 114 ++++++++++--
components/message/chat/chat-list.vue | 18 +-
components/message/list/list.vue | 42 ++++-
components/message/list/message-nav-bar.vue | 10 +-
main.js | 2 +-
pages/message/chat-page/chat-page.vue | 104 +++++++++--
pages/message/list-index.vue | 181 +++++++++++++++++++-
static/image/phone-message/change.png | Bin 0 -> 934 bytes
static/image/phone-message/edit.png | Bin 0 -> 568 bytes
static/image/phone-message/sort.png | Bin 0 -> 740 bytes
10 files changed, 426 insertions(+), 45 deletions(-)
create mode 100644 static/image/phone-message/change.png
create mode 100644 static/image/phone-message/edit.png
create mode 100644 static/image/phone-message/sort.png
diff --git a/components/message/chat/chat-layout.vue b/components/message/chat/chat-layout.vue
index 4787ad1..3fa524d 100644
--- a/components/message/chat/chat-layout.vue
+++ b/components/message/chat/chat-layout.vue
@@ -9,7 +9,7 @@
- 256
+ {{ number }}
-
+
-
+
@@ -126,6 +127,10 @@ const props = defineProps({
sortMode: {
type: Boolean,
default: false
+ },
+ number: {
+ type: Number,
+ default: 0
}
})
@@ -296,6 +301,7 @@ onMounted(() => {
left: 0;
}
+
.fixed-top-box {
position: fixed;
width: 100%;
@@ -344,6 +350,7 @@ onMounted(() => {
.img {
width: 96rpx;
height: 96rpx;
+ border-radius: 50%;
}
}
@@ -357,6 +364,10 @@ onMounted(() => {
height: 20rpx;
.title {
+ text-align: center;
+ max-width: 400rpx;
+ overflow: hidden;
+ text-overflow: ellipsis;
font-size: 20rpx;
color: #1A1A1A;
left: 20rpx;
@@ -370,8 +381,19 @@ onMounted(() => {
}
+
+
+ .bottom-box {
+ padding-bottom: 10rpx;
+ }
+
+ .safe-area {
+ padding-bottom: calc(10rpx + constant(safe-area-inset-bottom));
+ padding-bottom: calc(10rpx + env(safe-area-inset-bottom));
+ }
+
.bottom-container {
- padding: 10rpx 28rpx;
+ padding: 10rpx 28rpx 0;
.add-img {
width: 66rpx;
@@ -431,7 +453,7 @@ onMounted(() => {
.top-box {
.top-container {
- padding: 0 52rpx;
+ padding: 0 20rpx 0 52rpx;
background-color: #F7F7F7;
height: 88rpx;
@@ -456,10 +478,21 @@ onMounted(() => {
}
.center {
+ flex: 1;
+ display: flex;
+ align-items: center;
+
.title {
+ flex: 1;
+ display: block;
font-size: 36rpx;
color: #1A1A1A;
font-weight: 500;
+ width: 20px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ margin-right: 10rpx;
}
}
@@ -488,8 +521,19 @@ onMounted(() => {
}
.bottom-box {
+ padding-bottom: 20rpx;
+ }
+
+ .safe-area {
+ padding-bottom: calc(20rpx + constant(safe-area-inset-bottom));
+ padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
+ }
+
+ .bottom-box {
+
.bottom-container {
- padding: 20rpx 28rpx;
+ padding: 20rpx 28rpx 0;
+
.add-img {
width: 72rpx;
@@ -573,6 +617,7 @@ onMounted(() => {
.center {
flex: 1;
+ width: 20%;
height: 100%;
margin: 0 18rpx;
display: flex;
@@ -580,10 +625,15 @@ onMounted(() => {
justify-content: center;
.title {
+ width: 100%;
font-size: 36rpx;
color: #1A1A1A;
font-weight: 500;
line-height: 36rpx;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ margin-right: 10rpx;
}
.second-text {
@@ -617,11 +667,21 @@ onMounted(() => {
}
+ .bottom-box {
+ padding-bottom: 10rpx;
+ }
+
+ .safe-area {
+ padding-bottom: calc(10rpx + constant(safe-area-inset-bottom));
+ padding-bottom: calc(10rpx + env(safe-area-inset-bottom));
+ }
+
+
.bottom-box {
background-color: #FAFAFA;
.bottom-container {
- padding: 16rpx 32rpx 50rpx;
+ padding: 16rpx 32rpx 0;
.add-img {
width: 84rpx;
@@ -704,16 +764,19 @@ onMounted(() => {
.center {
flex: 1;
+ width: 20%;
height: 100%;
margin: 0 16rpx;
display: flex;
align-items: center;
+ overflow: hidden;
.img {
width: 72rpx;
height: 72rpx;
flex-shrink: 0;
margin-right: 18rpx;
+ border-radius: 50%;
}
.title {
@@ -721,6 +784,10 @@ onMounted(() => {
color: #1A1A1A;
font-weight: 500;
line-height: 36rpx;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ margin-right: 10rpx;
}
.second-text {
@@ -754,11 +821,20 @@ onMounted(() => {
}
+ .bottom-box {
+ padding-bottom: 12rpx;
+ }
+
+ .safe-area {
+ padding-bottom: calc(12rpx + constant(safe-area-inset-bottom));
+ padding-bottom: calc(12rpx + env(safe-area-inset-bottom));
+ }
+
.bottom-box {
background-color: #FFFFFF;
.bottom-container {
- padding: 12rpx 32rpx;
+ padding: 12rpx 32rpx 0;
.add-img {
width: 44rpx;
@@ -842,17 +918,23 @@ onMounted(() => {
.center {
flex: 1;
+ width: 20%;
height: 100%;
margin: 0 18rpx;
display: flex;
flex-direction: column;
justify-content: center;
+ overflow: hidden;
.title {
font-size: 34rpx;
color: #1A1A1A;
font-weight: 500;
line-height: 34rpx;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ margin-right: 10rpx;
}
}
@@ -879,11 +961,21 @@ onMounted(() => {
}
+ .bottom-box {
+ padding-bottom: 20rpx;
+ }
+
+ .safe-area {
+ padding-bottom: 20rpx;
+ padding-bottom: calc(20rpx + constant(safe-area-inset-bottom));
+ padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
+ }
+
.bottom-box {
background-color: #fff;
.bottom-container {
- padding: 20rpx 48rpx;
+ padding: 20rpx 48rpx 0;
.search-box {
min-height: 64rpx;
diff --git a/components/message/chat/chat-list.vue b/components/message/chat/chat-list.vue
index 96d5d6b..44170a4 100644
--- a/components/message/chat/chat-list.vue
+++ b/components/message/chat/chat-list.vue
@@ -23,7 +23,8 @@
短信/彩信
{{ formatHuaweiTopTime(message.time) }}
{{ formatChatTime(message.time) }} 中国联通
+ v-if="(phone == 'oppo' || (phone == 'vivo' && message.isMe)) && message.simIndex">
+ {{ simInfo[`sim${message.simIndex}`] }}
{
+ try {
+ const cached = uni.getStorageSync(SIM_STORAGE_KEY)
+ simInfo.value = cached ? JSON.parse(cached) : { sim1: '中国电信', sim2: '中国移动' }
+ } catch (e) {
+ simInfo.value = { sim1: '中国电信', sim2: '中国移动' }
+ }
+})
+
// 排序模式下的本地唦本列表
// 不直接修改 props.messageList,排序完成后 emit 给父组件
const localSortList = ref([])
diff --git a/components/message/list/list.vue b/components/message/list/list.vue
index 5dab17f..d8bc06a 100644
--- a/components/message/list/list.vue
+++ b/components/message/list/list.vue
@@ -12,8 +12,8 @@
> 99
? '99+' : (item.unReadNumber || 1) }}
-
+
@@ -40,9 +40,8 @@
- 编辑
-
+
+
{
border-radius: 50%;
}
+
+
.edit {
background-color: #5855D6;
}
+.main-box {
+ .title-box {
+ margin-bottom: 6rpx;
+
+
+ .title {
+ width: 20px;
+ flex: 1;
+ color: #1A1A1A;
+ font-size: 32rpx;
+ line-height: 32rpx;
+ white-space: nowrap;
+ font-weight: 600;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ .time {
+ flex-shrink: 0;
+ margin-left: 20rpx;
+ }
+ }
+}
+
// 苹果样式
.iphone-style {
+ .circle {
+ border-radius: 50% !important;
+ }
+
+ .square {
+ border-radius: 16rpx !important;
+ }
.swipe-action {
margin-top: 28rpx;
diff --git a/components/message/list/message-nav-bar.vue b/components/message/list/message-nav-bar.vue
index 48ce810..dd4042d 100644
--- a/components/message/list/message-nav-bar.vue
+++ b/components/message/list/message-nav-bar.vue
@@ -71,7 +71,7 @@
-
+
@@ -83,7 +83,8 @@
-
+
@@ -117,6 +118,11 @@ const buttonGroup = [{
click: () => {
emit('add')
}
+}, {
+ name: "设置卡1卡2运营商",
+ click: () => {
+ emit('setSim')
+ }
}]
const props = defineProps({
diff --git a/main.js b/main.js
index 861e941..4cd958c 100644
--- a/main.js
+++ b/main.js
@@ -27,7 +27,7 @@ export function createApp() {
const systemInfo = uni.getStorageSync('systemInfo') || {}
app.config.globalProperties.$system = systemInfo.platform == 'ios' ? 'iOS' : 'Android'
app.config.globalProperties.$systemInfo = systemInfo
- uni.setStorageSync('version', '1.0.3.sp2')
+ uni.setStorageSync('version', '1.0.3.sp3')
app.config.globalProperties.$version = uni.getStorageSync('version')
app.use(globalMethods);
diff --git a/pages/message/chat-page/chat-page.vue b/pages/message/chat-page/chat-page.vue
index 634a966..f0e5634 100644
--- a/pages/message/chat-page/chat-page.vue
+++ b/pages/message/chat-page/chat-page.vue
@@ -1,6 +1,7 @@
-
+
-
+
排序
+
+
+ 切换发言人
+
删除
@@ -33,12 +38,14 @@
时间:
-
+
{{ editingDate || '选择日期' }}
-
+
{{ editingTimeOfDay || '选择时刻' }}
@@ -62,12 +69,12 @@
- 正文:
+ 内容:
@@ -108,6 +115,7 @@ import {
} from 'vue'
import {
onLoad,
+ onShow,
onPageScroll
} from "@dcloudio/uni-app";
import {
@@ -121,6 +129,8 @@ const defaultList = defaultData
const STORAGE_KEY = 'message_list'
let currentId = null // 当前会话的 id
+let isMe = ref(true)
+
const messageList = ref([])
const showActionPopup = ref(false)
const popupTop = ref(0)
@@ -216,7 +226,7 @@ const handleEdit = () => {
const parts = (selectedMessage.value.time || "").split(' ')
editingDate.value = parts[0] || ""
editingTimeOfDay.value = parts[1] || ""
- editingSimKa.value = selectedMessage.value.simKa !== undefined ? selectedMessage.value.simKa : "";
+ editingSimKa.value = selectedMessage.value.simIndex !== undefined ? selectedMessage.value.simIndex : "";
editingTimeMode.value = selectedMessage.value.timeMode || 'auto';
showEditPopup.value = true;
@@ -253,6 +263,14 @@ const onTimeOfDayChange = (e) => {
editingTime.value = `${editingDate.value} ${editingTimeOfDay.value}`.trim()
}
+/**
+ * 切换sim卡
+ * @param value
+ */
+const onSimKaChange = (value) => {
+ editingSimKa.value = value
+}
+
const confirmEdit = () => {
if (editingMessage.value && editorCtx) {
editorCtx.getContents({
@@ -270,9 +288,9 @@ const confirmEdit = () => {
// 兼容旧 hideTime 字段:一并清除
delete messageList.value[index].hideTime;
if (editingSimKa.value) {
- messageList.value[index].simKa = Number(editingSimKa.value);
+ messageList.value[index].simIndex = Number(editingSimKa.value);
} else {
- delete messageList.value[index].simKa;
+ delete messageList.value[index].simIndex;
}
}
closeEditPopup();
@@ -329,6 +347,23 @@ const confirmSort = () => {
saveChatList()
}
+
+const handleChangeSpeaker = () => {
+ isMe.value = !isMe.value
+ if (isMe.value) {
+ uni.showToast({
+ title: "现在是自己发言",
+ icon: "none"
+ })
+ } else {
+ uni.showToast({
+ title: "现在是对方发言",
+ icon: "none"
+ })
+ }
+ closeActionPopup();
+}
+
/**
* 删除消息
*/
@@ -341,7 +376,8 @@ const handleDelete = () => {
const data = reactive({
phone: "iphone",
- data: {}
+ data: {},
+ number: 0
})
onLoad((options) => {
console.log(options)
@@ -353,10 +389,23 @@ onLoad((options) => {
// 优先从缓存读取
try {
const cached = uni.getStorageSync(STORAGE_KEY)
- const list = cached ? JSON.parse(cached) : defaultList
+ let list = cached ? JSON.parse(cached) : defaultList
const found = list.find(item => item.id == options.id)
if (found) {
data.data = found
+ let number = 0
+ list.forEach(item => {
+ if (item.id == options.id) {
+ item.unRead = false
+ item.unReadNumber = 1
+ }
+ console.log(number + item.unRead ? item.unReadNumber : 0)
+ number = number + Number(item.unRead ? item.unReadNumber : 0)
+ })
+ data.number = number
+ console.log(data.data)
+ uni.setStorageSync(STORAGE_KEY, JSON.stringify(list))
+
messageList.value = found.chatList || []
return
}
@@ -367,9 +416,23 @@ onLoad((options) => {
}
})
+onShow(() => {
+ // #ifdef APP-PLUS
+ if (data.phone == 'oppo') {
+ util.setAndroidSystemBarColor('#FAFAFA')
+ } else {
+ util.setAndroidSystemBarColor('#ffffff')
+ }
+ setTimeout(() => {
+ plus.navigator.setStatusBarStyle("dark");
+ }, 500)
+ // #endif
+})
+
const handleSend = (params) => {
console.log(params)
params.id = stringUtil.uuid()
+ params.isMe = isMe.value
messageList.value.push(params)
saveChatList()
}
@@ -464,6 +527,7 @@ const handleSend = (params) => {
border-radius: 12rpx;
padding: 20rpx 30rpx;
display: flex;
+ justify-content: space-between;
transform: translateX(-50%);
width: 540rpx;
z-index: 10;
@@ -488,6 +552,10 @@ const handleSend = (params) => {
color: #FFFFFF;
font-size: 20rpx;
margin: 0 20rpx;
+
+ text {
+ white-space: nowrap;
+ }
}
.action-icon {
@@ -525,7 +593,6 @@ const handleSend = (params) => {
color: #333;
text-align: center;
padding: 30rpx 0;
- border-bottom: 1rpx solid #EEEEEE;
}
.edit-body {
@@ -549,7 +616,6 @@ const handleSend = (params) => {
.edit-footer {
display: flex;
- border-top: 1rpx solid #EEEEEE;
}
.edit-btn {
@@ -558,16 +624,22 @@ const handleSend = (params) => {
line-height: 90rpx;
text-align: center;
font-size: 32rpx;
+ border-radius: 12rpx;
+ margin: 32rpx 16rpx;
+ margin-top: 0;
}
.edit-btn.cancel {
- color: #666;
- border-right: 1rpx solid #EEEEEE;
+ color: #767676;
+ background-color: #F1F1F1;
+ margin-left: 30rpx;
}
.edit-btn.confirm {
- color: #007AFF;
+ color: #FFFFFF;
font-weight: bold;
+ background-color: #1777FF;
+ margin-right: 30rpx;
}
.edit-row {
diff --git a/pages/message/list-index.vue b/pages/message/list-index.vue
index af9f725..b8e656e 100644
--- a/pages/message/list-index.vue
+++ b/pages/message/list-index.vue
@@ -1,6 +1,6 @@
-
+
@@ -13,13 +13,19 @@
头像URL:
-
+
+
+
+
联系人
@@ -33,7 +39,8 @@
是否未读
-
+
未读数量
@@ -59,6 +66,27 @@
+
+
+
+
+
@@ -91,7 +119,16 @@ const data = reactive({
isScroll: false
})
+const shape = [{
+ text: '圆形',
+ value: 'circle'
+}, {
+ text: '方形',
+ value: 'square',
+}]
+
const STORAGE_KEY = 'message_list'
+const SIM_STORAGE_KEY = 'sim_info'
onLoad((options) => {
if (options.phone) {
@@ -101,6 +138,16 @@ onLoad((options) => {
})
onShow(() => {
+ // #ifdef APP-PLUS
+ if (data.phone == 'oppo') {
+ util.setAndroidSystemBarColor('#FAFAFA')
+ } else {
+ util.setAndroidSystemBarColor('#ffffff')
+ }
+ setTimeout(() => {
+ plus.navigator.setStatusBarStyle("dark");
+ }, 500)
+ // #endif
// 优先从缓存加载列表
try {
const cached = uni.getStorageSync(STORAGE_KEY)
@@ -119,6 +166,49 @@ onPageScroll((e) => {
}
})
+/**
+ * 将图片保存到本地持久化存储
+ * @param {string} tempFilePath 临时文件路径
+ * @returns {Promise} 持久化后的文件路径
+ */
+const saveImageToLocal = (tempFilePath) => {
+ return new Promise((resolve, reject) => {
+ // 如果是已经持久化的路径或是静态资源,直接返回
+ if (!tempFilePath || tempFilePath.startsWith('_doc') || tempFilePath.startsWith('/static')) {
+ return resolve(tempFilePath)
+ }
+ uni.saveFile({
+ tempFilePath: tempFilePath,
+ success: (res) => {
+ console.log('图片持久化成功:', res.savedFilePath)
+ resolve(res.savedFilePath)
+ },
+ fail: (err) => {
+ console.error('图片持久化失败:', err)
+ resolve(tempFilePath) // 失败则回退使用原路径,确保业务不中断
+ }
+ })
+ })
+}
+
+/**
+ * 删除本地持久化文件
+ * @param {string} filePath 文件路径
+ */
+const removeLocalFile = (filePath) => {
+ if (filePath && filePath.startsWith('_doc')) {
+ uni.removeSavedFile({
+ filePath: filePath,
+ success: () => {
+ console.log('本地文件删除成功:', filePath)
+ },
+ fail: (err) => {
+ console.warn('本地文件删除失败:', filePath, err)
+ }
+ })
+ }
+}
+
/**
* 删除元素
* @param item
@@ -129,8 +219,15 @@ const deleteItem = (item) => {
content: '确定要删除吗?',
success: (res) => {
if (res.confirm) {
- defaultList.value.splice(defaultList.value.findIndex(i => i.id === item.id), 1)
- uni.setStorageSync(STORAGE_KEY, JSON.stringify(defaultList.value))
+ const idx = defaultList.value.findIndex(i => i.id === item.id)
+ if (idx > -1) {
+ // 删除关联的本地图片文件
+ if (item.img) {
+ removeLocalFile(item.img)
+ }
+ defaultList.value.splice(idx, 1)
+ uni.setStorageSync(STORAGE_KEY, JSON.stringify(defaultList.value))
+ }
}
}
})
@@ -179,6 +276,7 @@ const openAddPopup = () => {
addForm.unReadNumber = 1
addForm.noNotice = false
addForm.chatList = []
+ addForm.imgShape = 'circle'
addForm.date = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`
addForm.timeOfDay = `${pad(now.getHours())}:${pad(now.getMinutes())}`
showAddPopup.value = true
@@ -206,32 +304,48 @@ const editItem = (item) => {
const parts = timeStr.split(' ')
addForm.title = item.title || ''
addForm.img = item.img || ''
+ addForm.imgShape = item.imgShape || 'circle'
addForm.content = ''
addForm.unRead = !!item.unRead
addForm.unReadNumber = item.unReadNumber || 0
+ addForm.noNotice = item.noNotice || false
addForm.date = parts[0] || ''
addForm.timeOfDay = parts[1] || ''
addForm.chatList = item.chatList || []
showAddPopup.value = true
}
-const confirmAdd = () => {
+const confirmAdd = async () => {
if (!addForm.title.trim()) {
uni.showToast({ title: '请输入联系人名称', icon: 'none' })
return
}
- console.log(addForm)
+
const time = `${addForm.date} ${addForm.timeOfDay}`.trim()
+ // 处理图片持久化
+ let finalImgPath = addForm.img
+ if (editingItem.value) {
+ // 编辑模式:如果图片发生了变化,保存新图并删除旧图
+ if (addForm.img !== editingItem.value.img) {
+ finalImgPath = await saveImageToLocal(addForm.img)
+ removeLocalFile(editingItem.value.img)
+ }
+ } else {
+ // 新增模式:直接持久化
+ finalImgPath = await saveImageToLocal(addForm.img)
+ }
+
if (editingItem.value) {
// ===== 编辑模式:更新已有条目 =====
const idx = defaultList.value.findIndex(i => i.id === editingItem.value.id)
if (idx > -1) {
defaultList.value[idx].title = addForm.title.trim()
- defaultList.value[idx].img = addForm.img.trim()
+ defaultList.value[idx].img = finalImgPath
defaultList.value[idx].unRead = addForm.unRead
defaultList.value[idx].unReadNumber = addForm.unReadNumber
defaultList.value[idx].noNotice = addForm.noNotice
+ defaultList.value[idx].imgShape = addForm.imgShape
defaultList.value[idx].time = time
}
} else {
@@ -241,8 +355,9 @@ const confirmAdd = () => {
unRead: addForm.unRead,
unReadNumber: addForm.unReadNumber,
noNotice: addForm.noNotice,
- img: addForm.img.trim(),
+ img: finalImgPath,
title: addForm.title.trim(),
+ imgShape: addForm.imgShape,
chatList: addForm.content.trim() ? [
{
id: stringUtil.uuid(),
@@ -268,6 +383,41 @@ const confirmAdd = () => {
closeAddPopup()
}
+// ===== 设置运营商弹窗 =====
+const showSimPopup = ref(false)
+const simForm = reactive({
+ sim1: '',
+ sim2: ''
+})
+
+const setSim = () => {
+ try {
+ const cached = uni.getStorageSync(SIM_STORAGE_KEY)
+ const simInfo = cached ? JSON.parse(cached) : { sim1: '中国电信', sim2: '中国移动' }
+ simForm.sim1 = simInfo.sim1
+ simForm.sim2 = simInfo.sim2
+ } catch (e) {
+ simForm.sim1 = '中国电信'
+ simForm.sim2 = '中国移动'
+ }
+ showSimPopup.value = true
+}
+
+const closeSimPopup = () => {
+ showSimPopup.value = false
+}
+
+const confirmSim = () => {
+ try {
+ uni.setStorageSync(SIM_STORAGE_KEY, JSON.stringify({
+ sim1: simForm.sim1.trim() || '联通',
+ sim2: simForm.sim2.trim() || '移动'
+ }))
+ uni.showToast({ title: '保存成功', icon: 'success' })
+ } catch (e) { }
+ closeSimPopup()
+}
+