Merge branch 'Branch_1' of https://git.u8t.cn/tangxinyue/alipay-emulator into Branch_1

# Conflicts:
#	main.js
This commit is contained in:
小李 2026-03-18 11:14:13 +08:00
commit 7856f31273
9 changed files with 440 additions and 45 deletions

View File

@ -9,7 +9,7 @@
<view class="left flex-align-center">
<image @click="util.goBack()" :src="`/static/image/phone-message/${phone}/back.png`">
</image>
<view v-if="phone == 'iphone'" class="number-box">256</view>
<view v-if="phone == 'iphone' && number > 0" class="number-box">{{ number }}</view>
</view>
<view class="center">
<image v-if="phone == 'iphone' || phone == 'huawei'" class="img shrink-0"
@ -49,7 +49,8 @@
<slot></slot>
</scroll-view>
</view>
<view class="bottom-box fixed-bottom-box" :style="{ bottom: data.keyboardHeight + 'px' }">
<view class="bottom-box fixed-bottom-box" :class="{ 'safe-area': $system == 'iOS' && data.keyboardHeight == 0 }"
:style="{ bottom: data.keyboardHeight + 'px' }">
<slot name="bottom">
<view class="bottom-container flex-align-center" v-show="!sortMode">
<image v-if="phone != 'huawei' && phone != 'vivo'" class="add-img shrink-0"
@ -63,9 +64,9 @@
src="/static/image/phone-message/huawei/down.png"></image>
<!-- <input class="input flex-1" :placeholder="showInfo.placeholder" v-model="content"
@input="onInput"></input> -->
<textarea class="input flex-1" :adjust-position="false" fixed auto-height
:placeholder="showInfo.placeholder" v-model="content" @input="onInput" @focus="onFocus"
@blur="onBlur"></textarea>
<textarea class="input flex-1" :adjust-position="false" fixed auto-height show-confirm-bar
auto-blur :placeholder="showInfo.placeholder" v-model="content" @input="onInput"
@focus="onFocus" @blur="onBlur"></textarea>
<!-- <editor class="input flex-1" :placeholder="showInfo.placeholder"></editor> -->
<image v-if="phone == 'iphone' && !isSend" class="right-icon"
src="/static/image/phone-message/iphone/mic.png"></image>
@ -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;

View File

@ -23,7 +23,8 @@
<view class="top-text" v-if="phone == 'huawei' && index == 0">短信/彩信</view>
<text v-if="phone == 'huawei'">{{ formatHuaweiTopTime(message.time) }}</text>
<text v-else>{{ formatChatTime(message.time) }} <text
v-if="(phone == 'oppo' || (phone == 'vivo' && message.isMe)) && message.simIndex"> 中国联通
v-if="(phone == 'oppo' || (phone == 'vivo' && message.isMe)) && message.simIndex">
{{ simInfo[`sim${message.simIndex}`] }}
</text></text>
<image style="width: 20rpx;height: 24rpx;margin-left: 8rpx; "
@ -74,8 +75,23 @@ const props = defineProps({
}
})
const SIM_STORAGE_KEY = 'sim_info'
const emit = defineEmits(['onMessageLongPress', 'sort'])
const simInfo = ref({
sim1: '中国电信',
sim2: '中国移动'
})
onMounted(() => {
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([])

View File

@ -12,8 +12,8 @@
> 99
? '99+' : (item.unReadNumber || 1) }}</text>
</view>
<image class="img avatar shrink-0"
:src="item.img || `/static/image/phone-message/${phone}/default.png`">
<image class="img avatar shrink-0" :class="item.imgShape"
:src="item.img || `/static/image/phone-message/${phone}/default.png`" mode="aspectFill">
</image>
</view>
<view class="border-box m-l-24 flex-1 flex flex-align-start">
@ -40,9 +40,8 @@
<view class="flex flex-align-center" style="margin-left: 1px;">
<view class="btn flex-center flex-align-center edit" style="color: #fff;"
@click="editItem(item)">
编辑
<!-- <image :src="`/static/image/phone-message/iphone/delete.png`">
</image> -->
<image :src="`/static/image/phone-message/edit.png`">
</image>
</view>
<view class="btn flex-center flex-align-center delete" @click="deleteItem(item)">
<image
@ -158,12 +157,45 @@ const editItem = (item) => {
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;

View File

@ -71,7 +71,7 @@
<view v-if="showInfo.placeholder" class="search-box flex flex-align-center">
<image class="icon" :src="`/static/image/phone-message/${props.phone}/search.png`">
</image>
<input class="input flex-1" :placeholder="showInfo.placeholder" type="text">
<input class="input flex-1" :placeholder="showInfo.placeholder" type="text" disabled>
<image v-if="phone != 'mi'" class="icon"
:src="`/static/image/phone-message/${props.phone}/mic.png`">
</image>
@ -83,7 +83,8 @@
<view class="bottom-placeholder"></view>
<!-- 底部样式 -->
<template v-if="phone == 'mi' || phone == 'oppo'">
<image class="add-message" :src="`/static/image/phone-message/${props.phone}/add-message.png`"></image>
<image class="add-message" @click="emit('add')"
:src="`/static/image/phone-message/${props.phone}/add-message.png`"></image>
<view class="bottom-box flex">
<view class="item flex-1 h100">
<image class="icon" :src="`/static/image/phone-message/${props.phone}/bottom-left.png`"></image>
@ -117,6 +118,11 @@ const buttonGroup = [{
click: () => {
emit('add')
}
}, {
name: "设置卡1卡2运营商",
click: () => {
emit('setSim')
}
}]
const props = defineProps({

View File

@ -1,6 +1,14 @@
<template>
<!-- 水印 -->
<view v-if="$isVip()">
<watermark :dark="data.dark" />
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark')">
<c-lottie ref="cLottieRef" :src='$watermark()' width="94px" height='74px' :loop="true"></c-lottie>
</liu-drag-button>
</view>
<view :class="`${data.phone}-style`">
<ChatLayout :phone="data.phone" :chatInfo="data.data" :sortMode="isSortMode" @send="handleSend">
<ChatLayout :phone="data.phone" :chatInfo="data.data" :sortMode="isSortMode" @send="handleSend"
:number="data.number">
<!-- 弹出操作层及遮罩 -->
<view v-if="showActionPopup" class="action-mask" @tap="closeActionPopup">
<view class="action-popup" :style="{ top: popupTop + 'px', left: popupLeft + 'px' }">
@ -13,9 +21,13 @@
<text>消息互换</text>
</view>
<view class="action-item" @tap.stop="handleSort">
<image class="action-icon" src="/static/image/phone-message/bianji.png"></image>
<image class="action-icon" src="/static/image/phone-message/sort.png"></image>
<text>排序</text>
</view>
<view class="action-item" @tap.stop="handleChangeSpeaker">
<image class="action-icon" src="/static/image/phone-message/change.png"></image>
<text>切换发言人</text>
</view>
<view class="action-item" @tap.stop="handleDelete">
<image class="action-icon" src="/static/image/phone-message/shanchu.png"></image>
<text>删除</text>
@ -33,12 +45,14 @@
<view class="edit-row">
<text class="edit-label">时间</text>
<view class="time-picker-group">
<picker mode="date" :value="editingDate" @change="onDateChange">
<picker mode="date" :fields="$system == 'Android' ? 'day' : ''" :value="editingDate"
@change="onDateChange">
<view class="time-picker-item">
<text>{{ editingDate || '选择日期' }}</text>
</view>
</picker>
<picker mode="time" :value="editingTimeOfDay" @change="onTimeOfDayChange">
<picker mode="time" :fields="$system == 'Android' ? 'minute' : ''"
:value="editingTimeOfDay" @change="onTimeOfDayChange">
<view class="time-picker-item">
<text>{{ editingTimeOfDay || '选择时刻' }}</text>
</view>
@ -62,12 +76,12 @@
<view class="edit-input"
style="padding: 0; background: transparent; display: flex; align-items: center; border-radius: 8rpx; height: 70rpx;">
<uni-data-select v-model="editingSimKa" :localdata="simList" :clear="false"
placeholder="请选择卡号"
placeholder="请选择卡号" @change="onSimKaChange"
style="flex: 1; border: none !important; width: 100%;"></uni-data-select>
</view>
</view>
<view class="edit-row">
<text class="edit-label">正文</text>
<text class="edit-label">内容</text>
</view>
<editor id="editor" class="edit-textarea" placeholder="请输入消息内容..." @ready="onEditorReady">
</editor>
@ -108,6 +122,7 @@ import {
} from 'vue'
import {
onLoad,
onShow,
onPageScroll
} from "@dcloudio/uni-app";
import {
@ -121,6 +136,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 +233,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 +270,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 +295,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 +354,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 +383,8 @@ const handleDelete = () => {
const data = reactive({
phone: "iphone",
data: {}
data: {},
number: 0
})
onLoad((options) => {
console.log(options)
@ -353,10 +396,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 +423,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 +534,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 +559,10 @@ const handleSend = (params) => {
color: #FFFFFF;
font-size: 20rpx;
margin: 0 20rpx;
text {
white-space: nowrap;
}
}
.action-icon {
@ -504,7 +579,7 @@ const handleSend = (params) => {
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 10;
z-index: 99;
display: flex;
justify-content: center;
align-items: center;
@ -525,7 +600,6 @@ const handleSend = (params) => {
color: #333;
text-align: center;
padding: 30rpx 0;
border-bottom: 1rpx solid #EEEEEE;
}
.edit-body {
@ -549,7 +623,6 @@ const handleSend = (params) => {
.edit-footer {
display: flex;
border-top: 1rpx solid #EEEEEE;
}
.edit-btn {
@ -558,16 +631,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 {

View File

@ -1,6 +1,13 @@
<template>
<!-- 水印 -->
<view v-if="$isVip()">
<watermark :dark="data.dark" />
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark')">
<c-lottie ref="cLottieRef" :src='$watermark()' width="94px" height='74px' :loop="true"></c-lottie>
</liu-drag-button>
</view>
<view>
<MessageNavBar :phone="data.phone" :isScroll="data.isScroll" @add="openAddPopup">
<MessageNavBar :phone="data.phone" :isScroll="data.isScroll" @add="openAddPopup" @setSim="setSim">
<MessageList :phone="data.phone" :list="defaultList" @item-click="itemClick" @delete-item="deleteItem"
@edit-item="editItem">
</MessageList>
@ -13,13 +20,19 @@
<view class="add-body">
<view class="add-row">
<text class="add-label">头像URL</text>
<view class="image-box" style="width: 84rpx;height: 84rpx;" @tap="selectImage">
<view class="image-box" :class="addForm.imgShape" style="width: 84rpx;height: 84rpx;"
@tap="selectImage">
<image v-if="addForm.img" class="image w100 h100" :src="addForm.img" mode="aspectFill">
</image>
<image v-else class="image w100 h100" src="/static/image/phone-message/add.png"
mode="aspectFill">
</image>
</view>
<view v-if="data.phone == 'iphone'"
style="flex: 1;display: flex;align-items: center;justify-content: flex-end;">
<uni-data-checkbox style="display: flex;justify-content: flex-end;"
v-model="addForm.imgShape" :localdata="shape"></uni-data-checkbox>
</view>
</view>
<view class="add-row">
<text class="add-label required">联系人</text>
@ -33,7 +46,8 @@
<text class="add-label">是否未读</text>
<switch :checked="addForm.unRead" @change="addForm.unRead = !addForm.unRead" />
</view>
<view class="add-row" v-if="addForm.unRead && data.phone == 'oppo' || data.phone == 'huawei'">
<view class="add-row"
v-if="addForm.unRead && (data.phone == 'oppo' || data.phone == 'huawei' || data.phone == 'iphone')">
<text class="add-label">未读数量</text>
<input class="add-input" type="number" v-model="addForm.unReadNumber" placeholder="请输入未读数量" />
</view>
@ -59,6 +73,27 @@
</view>
</view>
</view>
<!-- 设置运营商弹窗 -->
<view v-if="showSimPopup" class="add-mask" @tap="closeSimPopup">
<view class="add-popup" @tap.stop>
<view class="add-header">设置卡1卡2运营商</view>
<view class="add-body">
<view class="add-row">
<text class="add-label">卡1运营商</text>
<input class="add-input" v-model="simForm.sim1" placeholder="请输入卡1运营商名称" />
</view>
<view class="add-row">
<text class="add-label">卡2运营商</text>
<input class="add-input" v-model="simForm.sim2" placeholder="请输入卡2运营商名称" />
</view>
</view>
<view class="add-footer">
<view class="add-btn cancel" @tap="closeSimPopup">取消</view>
<view class="add-btn confirm" @tap="confirmSim">确定</view>
</view>
</view>
</view>
</view>
</template>
@ -91,7 +126,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 +145,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 +173,49 @@ onPageScroll((e) => {
}
})
/**
* 将图片保存到本地持久化存储
* @param {string} tempFilePath 临时文件路径
* @returns {Promise<string>} 持久化后的文件路径
*/
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,10 +226,17 @@ const deleteItem = (item) => {
content: '确定要删除吗?',
success: (res) => {
if (res.confirm) {
defaultList.value.splice(defaultList.value.findIndex(i => i.id === item.id), 1)
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 +283,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 +311,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 +362,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 +390,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()
}
</script>
<style>
@ -361,6 +518,19 @@ page {
align-items: center;
padding: 20rpx 32rpx;
gap: 16rpx;
.image-box {
border-radius: 50%;
overflow: hidden;
}
.circle {
border-radius: 50%;
}
.square {
border-radius: 16rpx;
}
}
.between {

Binary file not shown.

After

Width:  |  Height:  |  Size: 934 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 740 B