fxl преди 2 месеца
родител
ревизия
9bf8721f6f

+ 6 - 16
pages/edit/edit.vue

@@ -8,8 +8,6 @@ fxl
 张甜甜
 添加了触发联系人更新事件确保拨号页面联系人匹配列表实时更新。  uni.$emit('contactsUpdated');
 24.9.8
-传参
-24.9.28
  
  -->
 
@@ -111,7 +109,7 @@ export default {
 	},
 	gotoindex(){
 		uni.navigateBack({
-		  delta: 1 // 返回上一页
+		  delta: 2 // 返回上一页
 		});
 	},
     addPhone() {
@@ -296,19 +294,11 @@ export default {
 				uni.showToast({
 					title: '联系人保存成功'
 				});
-				
-				// 发出保存成功的事件
-			uni.$emit('contactSaved', this.contact); // 发送保存的联系人信息
-				     // 将联系人信息传递到下一IComponent(JSON.stringify(validPhones));
-			
-			const phoneNumbers=JSON.stringify(newContact.phoneNumbers);
-			 uni.navigateTo({
-			   url: `/pages/ContactDetails/ContactDetails?name=${encodeURIComponent(this.contact.name)}&phoneNumbers=${encodeURIComponent(phoneNumbers)}&count=${validPhones.length}`
-			 });
-			// uni.navigateBack({
-			//   delta: 1 // 返回上一页
-			// });
-			
+				setTimeout(()=>{
+					uni.navigateBack({
+					  delta: 2 // 返回上一页
+					});
+				},800);
 			}, e => {
 			  uni.showToast({
 				title: '保存联系人失败',

+ 273 - 241
pages/history/history.vue

@@ -19,13 +19,24 @@
     <view class="text-area">
       <view v-if="telephoneLog.length" v-for="(log, index) in limitedItems" :key="index">
         <view class="name-btn">
-          <view v-if="isLoudVisible" class="loud" @click="play(getContactName(log.number).name||getContactName(log.number).phoneNumbers[0].value)">
-            <image style="width: 80%;height: 40%;margin-left: 35rpx" src="../../static/pics/laba.png"></image>
-          </view>
-          <view class="con-mes" @click="goToDetails(getContactName(log.number))">
-			<text v-if="!getContactName(log.number).name" :style="{color:getLogDateColor(log.type)}">{{ formatPhoneNumber(getContactName(log.number).phoneNumbers[0].value) }}</text>
-			<text v-else :style="{color:getLogDateColor(log.type)}">{{ truncate(getContactName(log.number).name) }}</text>
+			
+          <view v-if="switchStatus" style="display: flex;flex-direction: row; ">
+          	<view class="loud" @click="play(getContactName(log.number).name||getContactName(log.number).phoneNumbers[0].value)">
+          	  <image style="width: 80%;height: 40%;margin-left: 35rpx" src="../../static/pics/laba.png"></image>
+          	</view>
+          	<view class="con-mes" @click="goToDetails(getContactName(log.number))">
+          				<text v-if="!getContactName(log.number).name" :style="{color:getLogDateColor(log.type)}">{{ formatPhoneNumber(getContactName(log.number).phoneNumbers[0].value) }}</text>
+          				<text v-else :style="{color:getLogDateColor(log.type)}">{{ truncate(getContactName(log.number).name) }}</text>
+          	</view>
           </view>
+		  
+		  <view v-else>
+		  	<view class="con-mes-null" @click="goToDetails(getContactName(log.number))">
+				<text v-if="!getContactName(log.number).name" :style="{color:getLogDateColor(log.type)}">{{ formatPhoneNumber(getContactName(log.number).phoneNumbers[0].value) }}</text>
+				<text v-else :style="{color:getLogDateColor(log.type)}">{{ truncate(getContactName(log.number).name) }}</text>
+		  	</view>
+		  </view>
+		  
           <view class="btn" @click="CallPhone(log.number)">
             <image class="Call" src="../../static/pics/call-out.png"></image>
           </view>
@@ -48,15 +59,16 @@ export default {
       contacts: [], // 存储联系人数据
       searchActive: true,
       hasPermission: false, // 用于存储权限状态
-	  
+	  switchStatus:false,
 	  isLoudVisible: true, // 初始状态为显示
     };
   },
   mounted() {
-	this.init();
     this.requestPermissions(); // 请求权限
   },
   onShow() {
+	this.init();
+	this.getM();
   	this.handleGetCallLogs();
   },
   computed: {
@@ -64,242 +76,256 @@ export default {
         return this.telephoneLog.slice(0, 100); // 只获取前 200 个项目
       }//记得v-for的数组改了
   },
-  methods: {
+  
+    methods: {
 	
-	goToDetails(item){
-		console.error('item',item)
-		const phoneNumbers=item.phoneNumbers
-		const name=item.name;
-		const phoneNumbersString=JSON.stringify(phoneNumbers)
-		const phoenNumberCount=item.phoneNumbers.length;
-		console.error("通话记录中的姓名",name)
-		console.error("phonenumber",phoneNumbers)
-		console.error("phoenNumberCount",phoenNumberCount)
-		uni.navigateTo({
-		    url: `/pages/ContactDetails/ContactDetails?name=${encodeURIComponent(name)}&phoneNumbers=${encodeURIComponent(phoneNumbersString)}&count=${phoenNumberCount}`
-		});
-	},
-	// 格式化电话号码
-	formatPhoneNumber(value) {
-	  // 移除所有非数字字符
-	  value = value.replace(/\D/g, '');
-	  
-	  if (value.length === 11) {
-	    // 如果长度为11, 在第4和第9位插入空格
-	    return value.replace(/(\d{3})(\d{4})(\d{4})/, '$1 $2 $3');
-	  } else {
-	    // 如果长度不为11,每4个字符插入一个空格
-	    return value.replace(/(\d{4})(?=\d)/g, '$1 ');
-	  }
-	},
-	truncate(value) {
-	  if (value.length > 9) {
-	    return value.slice(0, 5) + '\n' + value.substring(5, 9) + '...';
-	  }
-	  else{
-		return value.slice(0, 5) + '\n' + value.substring(5, 9)
-	  }
-	  return value;
-	},
-    init(){
-    	FvvUniTTS.init((callback) => {
-    		console.log(callback);
-    	},"com.iflytek.speechcloud");
-    	
-    	FvvUniTTS.onStart((res) => {
-    		console.log("onStart:" + res)
-    	});
-    	
-    	FvvUniTTS.onDone((res) => {
-    		console.log("onDone:" + res)
-    	});
-    	
-    	FvvUniTTS.onError((res) => {
-    		console.log("onError:" + res)
-    	});
-    	FvvUniTTS.getInstallTTS(res => {
-    	    console.log(res) 
-    	})
-    },
-    play(e){
-    	FvvUniTTS.speak({
-    		text:e,
-    		id:2,
-    	});
-    	
-    	FvvUniTTS.getInstallTTS(res => {
-    	    console.log(res+"11") 
-    	})
-    },
-    setLanguage(){
-    	console.log("set lang : " + FvvUniTTS.setLanguage("CHINESE"));
-    },
-    setEngines(){
-    	let setEngine = "com.iflytek.speechcloud"
-    	
-    	//获取已安装的引擎
-    	FvvUniTTS.getInstallTTS(res => {
-    		if(res == null || res.length <= 0){
-    			return
-    		}
-    		console.log(res)
-    		if(JSON.stringify(res).indexOf(setEngine) < 0){
-    			console.log("未安装该语音引擎")
-    			return
-    		}
-    		console.log("set engine : " + FvvUniTTS.setEngine(setEngine));
-    		FvvUniTTS.speak({
-    			text:"设置成功",
-    			id:2,
-    		});
-    	})
-    },
-    saveFile(){
-    	FvvUniTTS.saveAudioFile({
-    		text:"hello",
-    		id:3,
-    		path:"/sdcard/test/1.wav"
-    	})
-    },
-    setVoice(){
-    	FvvUniTTS.setPitch(100)
-    	FvvUniTTS.setSpeechRate(100)
-    },
-    showBar() {
-      this.searchActive = !this.searchActive;
-    },
-    requestPermissions() {
-		console.log("start")
-      if (plus.android && plus.android.runtimeMainActivity()) {
-        const activity = plus.android.runtimeMainActivity();
-        const ContextCompat = plus.android.importClass("androidx.core.content.ContextCompat");
-        const ActivityCompat = plus.android.importClass("androidx.core.app.ActivityCompat");
-        const PERMISSIONS = [plus.android.importClass("android.Manifest$permission").READ_CALL_LOG];
-        const PackageManager = plus.android.importClass("android.content.pm.PackageManager");
-    console.log("end")
-        const checkPermissions = () => {
-          // 检查是否已经授予权限
-          if (PERMISSIONS.every(permission => ContextCompat.checkSelfPermission(activity, permission) === PackageManager.PERMISSION_GRANTED)) {
-            console.log("权限已授予");
-            clearInterval(permissionCheckInterval); // 停止重复检查
-            this.handleGetCallLogs(); // 获取通话记录
-            this.getContacts(); // 获取通讯录
-          } else {
-            console.log("权限未授予,继续请求权限");
-            ActivityCompat.requestPermissions(activity, PERMISSIONS, 1);
-          }
-        };
-    
-	
-        // 设置一个重复定时器,每2秒检查一次权限
-        const permissionCheckInterval = setInterval(checkPermissions, 1000);
-    
-        // 回调函数处理权限请求结果
-        activity.onRequestPermissionsResult = (requestCode, permissions, grantResults) => {
-          if (requestCode === 1) {
-            if (grantResults.length > 0 && grantResults[0] === PackageManager.PERMISSION_GRANTED) {
-              console.log("权限已成功授予");
-            } else {
-              console.error("权限被拒绝");
-            }
-          }
-        };
-    
-        // 立即检查一次权限
-        checkPermissions();
-      }
-    },
-    handleGetCallLogs() {
-      if (plus.android) {
-        try {
-          const MainActivity = plus.android.runtimeMainActivity();
-          const CallLogHelper = plus.android.importClass("com.example.mylibrary.CallLogHelper");
-    
-          if (CallLogHelper) {
-            const logsJson = CallLogHelper.getCallLogs(MainActivity);
-            console.log("Raw logsJson:", logsJson); // 打印原始数据
-    
-            const logsArray = JSON.parse(logsJson);
-            console.log("Parsed logsArray:", logsArray); // 打印解析后的数据
-    
-            if (Array.isArray(logsArray)) {
-              this.telephoneLog = logsArray;
-            } else {
-              console.error("解析后的数据不是数组");
-            }
-          } else {
-            console.error("CallLogHelper 类未加载");
-          }
-        } catch (e) {
-          console.error("获取通话记录失败:", e);
-        }
-      } else {
-        console.error("Android 环境未准备好");
-      }
-    },
-    getContacts() {
-      const that = this;
-      plus.contacts.getAddressBook(plus.contacts.ADDRESSBOOK_PHONE, function(addressbook) {
-        addressbook.find(
-          ["displayName", "phoneNumbers"],
-          function(contacts) {
-            that.contacts = contacts.map(contact => ({
-              id: contact.id,
-              name: contact.displayName,
-              phoneNumbers: contact.phoneNumbers.map(phone => phone.value)
-            }));
-            console.log("获取到的联系人数据:", that.contacts);
-          },
-          function(error) {
-            console.error("获取通讯录失败: " + error.message);
-          },
-          { multiple: true }
-        );
-      });
-    },
-    getContactName(number) {
-        // 清理电话号码,移除所有非数字字符
-        const cleanedNumber = number.replace(/\D/g, '');
-        
-        // 查找匹配的联系人
-        const contact = this.contacts.find(contact =>
-          contact.phoneNumbers.some(phone => phone.replace(/\D/g, '') === cleanedNumber)
-        );
-		
-		// 判断是否找到联系人并设置 phoneNumbersArray
-		let phoneNumbersArray = contact === undefined ?[number]: contact.phoneNumbers ;
+		goToDetails(item){
+			console.error('item',item)
+			const phoneNumbers=item.phoneNumbers
+			const name=item.name;
+			const phoneNumbersString=JSON.stringify(phoneNumbers)
+			const phoenNumberCount=item.phoneNumbers.length;
+			console.error("通话记录中的姓名",name)
+			console.error("phonenumber",phoneNumbers)
+			console.error("phoenNumberCount",phoenNumberCount)
+			uni.navigateTo({
+				url: `/pages/ContactDetails/ContactDetails?name=${encodeURIComponent(name)}&phoneNumbers=${encodeURIComponent(phoneNumbersString)}&count=${phoenNumberCount}`
+			});
+		},
+		// 格式化电话号码
+		formatPhoneNumber(value) {
+		  // 移除所有非数字字符
+		  value = value.replace(/\D/g, '');
 		  
-		phoneNumbersArray = phoneNumbersArray.map(number => ({
-		    "value": number
-		}));
+		  if (value.length === 11) {
+			// 如果长度为11, 在第4和第9位插入空格
+			return value.replace(/(\d{3})(\d{4})(\d{4})/, '$1 $2 $3');
+		  } else {
+			// 如果长度不为11,每4个字符插入一个空格
+			return value.replace(/(\d{4})(?=\d)/g, '$1 ');
+		  }
+		},
+		truncate(value) {
+		  if (value.length > 9) {
+			return value.slice(0, 5) + '\n' + value.substring(5, 9) + '...';
+		  }
+		  else{
+			return value.slice(0, 5) + '\n' + value.substring(5, 9)
+		  }
+		  return value;
+		},
+		getM(){//获取本地语音开关信息
+			// 从本地存储中读取开关状态
+			const storedSwitchStatus = uni.getStorageSync('voiceBroadcastSwitch');
+			console.log("读取的本地存储状态1:", storedSwitchStatus);
+			
+			if (typeof storedSwitchStatus === 'boolean') {
+				this.switchStatus = storedSwitchStatus;
+			}
+		},
+		init(){
+			
+			FvvUniTTS.init((callback) => {
+				console.log(callback);
+			},"com.iflytek.speechcloud");
+			
+			FvvUniTTS.onStart((res) => {
+				console.log("onStart:" + res)
+			});
+			
+			FvvUniTTS.onDone((res) => {
+				console.log("onDone:" + res)
+			});
+			
+			FvvUniTTS.onError((res) => {
+				console.log("onError:" + res)
+			});
+			FvvUniTTS.getInstallTTS(res => {
+				console.log(res) 
+			})
+		},
+		play(e){
+			console.log("播放",e)
+			FvvUniTTS.speak({
+				text:e,
+				id:2,
+			});
+			
+			FvvUniTTS.getInstallTTS(res => {
+				console.log(res+"11") 
+			})
+		},
+		setLanguage(){
+			console.log("set lang : " + FvvUniTTS.setLanguage("CHINESE"));
+		},
+		setEngines(){
+			let setEngine = "com.iflytek.speechcloud"
+			
+			//获取已安装的引擎
+			FvvUniTTS.getInstallTTS(res => {
+				if(res == null || res.length <= 0){
+					return
+				}
+				console.log(res)
+				if(JSON.stringify(res).indexOf(setEngine) < 0){
+					console.log("未安装该语音引擎")
+					return
+				}
+				console.log("set engine : " + FvvUniTTS.setEngine(setEngine));
+				FvvUniTTS.speak({
+					text:"设置成功",
+					id:2,
+				});
+			})
+		},
+		saveFile(){
+			FvvUniTTS.saveAudioFile({
+				text:"hello",
+				id:3,
+				path:"/sdcard/test/1.wav"
+			})
+		},
+		setVoice(){
+			FvvUniTTS.setPitch(100)
+			FvvUniTTS.setSpeechRate(100)
+		},
+		showBar() {
+		  this.searchActive = !this.searchActive;
+		},
+		requestPermissions() {
+			console.log("start")
+		  if (plus.android && plus.android.runtimeMainActivity()) {
+			const activity = plus.android.runtimeMainActivity();
+			const ContextCompat = plus.android.importClass("androidx.core.content.ContextCompat");
+			const ActivityCompat = plus.android.importClass("androidx.core.app.ActivityCompat");
+			const PERMISSIONS = [plus.android.importClass("android.Manifest$permission").READ_CALL_LOG];
+			const PackageManager = plus.android.importClass("android.content.pm.PackageManager");
+		console.log("end")
+			const checkPermissions = () => {
+			  // 检查是否已经授予权限
+			  if (PERMISSIONS.every(permission => ContextCompat.checkSelfPermission(activity, permission) === PackageManager.PERMISSION_GRANTED)) {
+				console.log("权限已授予");
+				clearInterval(permissionCheckInterval); // 停止重复检查
+				this.handleGetCallLogs(); // 获取通话记录
+				this.getContacts(); // 获取通讯录
+			  } else {
+				console.log("权限未授予,继续请求权限");
+				ActivityCompat.requestPermissions(activity, PERMISSIONS, 1);
+			  }
+			};
+		
+		
+			// 设置一个重复定时器,每2秒检查一次权限
+			const permissionCheckInterval = setInterval(checkPermissions, 1000);
+		
+			// 回调函数处理权限请求结果
+			activity.onRequestPermissionsResult = (requestCode, permissions, grantResults) => {
+			  if (requestCode === 1) {
+				if (grantResults.length > 0 && grantResults[0] === PackageManager.PERMISSION_GRANTED) {
+				  console.log("权限已成功授予");
+				} else {
+				  console.error("权限被拒绝");
+				}
+			  }
+			};
+		
+			// 立即检查一次权限
+			checkPermissions();
+		  }
+		},
+		handleGetCallLogs() {
+		  if (plus.android) {
+			try {
+			  const MainActivity = plus.android.runtimeMainActivity();
+			  const CallLogHelper = plus.android.importClass("com.example.mylibrary.CallLogHelper");
+		
+			  if (CallLogHelper) {
+				const logsJson = CallLogHelper.getCallLogs(MainActivity);
+				console.log("Raw logsJson:", logsJson); // 打印原始数据
+		
+				const logsArray = JSON.parse(logsJson);
+				console.log("Parsed logsArray:", logsArray); // 打印解析后的数据
+		
+				if (Array.isArray(logsArray)) {
+				  this.telephoneLog = logsArray;
+				} else {
+				  console.error("解析后的数据不是数组");
+				}
+			  } else {
+				console.error("CallLogHelper 类未加载");
+			  }
+			} catch (e) {
+			  console.error("获取通话记录失败:", e);
+			}
+		  } else {
+			console.error("Android 环境未准备好");
+		  }
+		},
+		getContacts() {
+		  const that = this;
+		  plus.contacts.getAddressBook(plus.contacts.ADDRESSBOOK_PHONE, function(addressbook) {
+			addressbook.find(
+			  ["displayName", "phoneNumbers"],
+			  function(contacts) {
+				that.contacts = contacts.map(contact => ({
+				  id: contact.id,
+				  name: contact.displayName,
+				  phoneNumbers: contact.phoneNumbers.map(phone => phone.value)
+				}));
+				console.log("获取到的联系人数据:", that.contacts);
+			  },
+			  function(error) {
+				console.error("获取通讯录失败: " + error.message);
+			  },
+			  { multiple: true }
+			);
+		  });
+		},
+		getContactName(number) {
+			// 清理电话号码,移除所有非数字字符
+			const cleanedNumber = number.replace(/\D/g, '');
+			
+			// 查找匹配的联系人
+			const contact = this.contacts.find(contact =>
+			  contact.phoneNumbers.some(phone => phone.replace(/\D/g, '') === cleanedNumber)
+			);
+			
+			// 判断是否找到联系人并设置 phoneNumbersArray
+			let phoneNumbersArray = contact === undefined ?[number]: contact.phoneNumbers ;
+			  
+			phoneNumbersArray = phoneNumbersArray.map(number => ({
+				"value": number
+			}));
 
-	
-		// 返回包含姓名和电话号码的对象,其中电话号码是 JSON 格式的字符串
-		return {
-		  name: contact && contact.name ? contact.name : null,
-		  phoneNumbers:  phoneNumbersArray
-		};
-      },
-    CallPhone(number) {
-      plus.device.dial(number, false);
-	// 延迟刷新通话记录
-	  setTimeout(() => {
-	    this.handleGetCallLogs();
-	  }, 2000); // 等待 2 秒,确保通话记录有时间更新
-    },
-	getLogDateColor(callType){
-		return callType==3 ? '#ff0000' : '#000000'	
+		
+			// 返回包含姓名和电话号码的对象,其中电话号码是 JSON 格式的字符串
+			return {
+			  name: contact && contact.name ? contact.name : null,
+			  phoneNumbers:  phoneNumbersArray
+			};
+		  },
+		CallPhone(number) {
+		  plus.device.dial(number, false);
+		// 延迟刷新通话记录
+		  setTimeout(() => {
+			this.handleGetCallLogs();
+		  }, 2000); // 等待 2 秒,确保通话记录有时间更新
+		},
+		getLogDateColor(callType){
+			return callType==3 ? '#ff0000' : '#000000'	
+		},
+		filterContacts() {
+		  // 实现模糊查找逻辑
+		  const searchText = this.searchText.toLowerCase();
+		  this.filteredContacts = this.contacts.filter(contact => {
+			return (contact.name || '').toLowerCase().includes(searchText) ||
+			  contact.phoneNumbers.some(phone => phone.toLowerCase().includes(searchText));
+		  });
+		}
 	},
-    filterContacts() {
-      // 实现模糊查找逻辑
-      const searchText = this.searchText.toLowerCase();
-      this.filteredContacts = this.contacts.filter(contact => {
-        return (contact.name || '').toLowerCase().includes(searchText) ||
-          contact.phoneNumbers.some(phone => phone.toLowerCase().includes(searchText));
-      });
-    }
-	
-  }
+	mounted() {
+	  this.getM();
+	}
 }
 </script>
 
@@ -397,7 +423,7 @@ hr{
   background-color: #f0efef;
 }
 
-.con-mes {
+.con-mes,.con-mes-null {
   line-height: 1.1; 
   font-size: 35px;
   font-weight: 700;
@@ -413,6 +439,12 @@ hr{
   background-color: white;
 }
 
+.con-mes-null{
+	border-radius: 20rpx 0rpx 0rpx 20rpx;
+	width: 510rpx;
+	height: 200rpx;
+}
+
 .name-btn {
   display: flex;
   align-items: center;

+ 162 - 133
pages/index/index.vue

@@ -40,12 +40,22 @@
     <view class="text-area">
       <view v-if="filteredContacts.length" v-for="(item, id) in filteredContacts" :key="id">
         <view class="name-btn">
-          <view v-if="isLoudVisible" class="loud" @click="play(item.displayName || item.phoneNumbers[0].value)">
-            <image style="width: 80%;height: 40%; margin-left: 35rpx;" src="../../static/pics/laba.png"></image>
+			
+          <view v-if="switchStatus" style="display: flex;flex-direction: row; ">
+          	<view class="loud" @click="play(item.displayName || item.phoneNumbers[0].value)">
+          	  <image style="width: 80%;height: 40%; margin-left: 35rpx;" src="../../static/pics/laba.png"></image>
+          	</view>
+          	<view class="con-mes" @click="goToDetails(item)">
+          	  <text v-if="!item.displayName">{{ formatPhoneNumber(item.phoneNumbers[0].value) }}</text>
+          	  <text v-else>{{ truncate(item.displayName) }}</text>
+          	</view>
           </view>
-          <view class="con-mes" @click="goToDetails(item)">
-		    <text v-if="!item.displayName">{{ formatPhoneNumber(item.phoneNumbers[0].value) }}</text>
-		    <text v-else>{{ truncate(item.displayName) }}</text>
+		  
+		  <view v-else>
+		  	<view class="con-mes-null" @click="goToDetails(item)">
+		  	  <text v-if="!item.displayName">{{ formatPhoneNumber(item.phoneNumbers[0].value) }}</text>
+		  	  <text v-else>{{ truncate(item.displayName) }}</text>
+		  	</view>
 		  </view>
 		  
 		  <NumbersChoose class="phonenumber-choose-component"
@@ -114,17 +124,18 @@
 		    searchActive: true,
 			showModal:false,//选择对方号码部件显示判断
 			phoneNumbersCount:'',
+			switchStatus:false,
 			isChooseNumberVisible:{},
 			isActive: false,//点击对方号码,背景加深判断
-			
 		};
 	  },
 	  onShow() {
 		// 页面显示时直接调用
 		this.ToGetMessage();
 		/* this.ToGetHis(); */
-		this.init();
 		this.setLanguage();
+		this.init();
+	    this.getM();
 	  },
 	  beforeCreate() {
 			const domModule = uni.requireNativePlugin('dom')
@@ -187,12 +198,10 @@
 			  }
 		      return value;
 		    },
-		    onChange: function(e) {
-		    	this.old.x = e.detail.x
-		    	this.old.y = e.detail.y
-		    },
+		    
 		    
 			init(){
+				
 				FvvUniTTS.init((callback) => {
 					console.log(callback);
 				},"com.iflytek.speechcloud");
@@ -209,7 +218,7 @@
 					console.log("onError:" + res)
 				});
 				FvvUniTTS.getInstallTTS(res => {
-				    console.log(res) 
+				    console.log(res+"11") 
 				})
 			},
 			play(e){
@@ -276,129 +285,141 @@
 				}
 			},
 		  
-		showBar() {
-		  this.searchActive = !this.searchActive;
-		  this.ToGetMessage();
-		},
-		// 获取联系人信息
-	   ToGetMessage() {
-		 var that = this;
-		 // 获取通讯录对象
-		 plus.contacts.getAddressBook(plus.contacts.ADDRESSBOOK_PHONE, function(addressbook) {
-		   addressbook.find(["displayName", "phoneNumbers"], function(contacts) {
-			 that.list = contacts;
-			 console.log(that.list)
-	   
-			 // 将联系人按自定义规则排序
-			 that.list.sort(function(a, b) {
-			   // 检查是否为汉字、英文、数字或符号
-			   const isChinese = (str) => /^[\u4e00-\u9fa5]+$/.test(str);
-			   const isEnglish = (str) => /^[A-Za-z]+$/.test(str);
-			   const isNumber = (str) => /^[0-9]+$/.test(str);
-	   
-			   // 获取首字母,如果 displayName 是空,则使用 phoneNumbers 的第一个号码
-			   let firstCharA = a.displayName ? a.displayName.trim()[0] : a.phoneNumbers[0].value;
-			   let firstCharB = b.displayName ? b.displayName.trim()[0] : b.phoneNumbers[0].value;
-	   
-			   // 将汉字转换为拼音以便比较
-			   if (isChinese(firstCharA)) {
-				 firstCharA = pinyin(firstCharA, { style: pinyin.STYLE_FIRST_LETTER })[0][0];
-			   }
-			   if (isChinese(firstCharB)) {
-				 firstCharB = pinyin(firstCharB, { style: pinyin.STYLE_FIRST_LETTER })[0][0];
-			   }
-	   
-			   // 确定排序的优先级
-			   if (isEnglish(firstCharA) && isEnglish(firstCharB)) {
-				 // 如果都是英文,按字母顺序排序
-				 return firstCharA.localeCompare(firstCharB);
-			   } else if (isChinese(firstCharA) && isChinese(firstCharB)) {
-				 // 如果都是汉字(已经转换为拼音首字母),按拼音排序
-				 return firstCharA.localeCompare(firstCharB);
-			   } else if ((isEnglish(firstCharA) || isChinese(firstCharA)) && (isNumber(firstCharB) || !isEnglish(firstCharB))) {
-				 // 如果 A 是英文或汉字,而 B 是数字或其他符号,则 A 在前
-				 return -1;
-			   } else if ((isNumber(firstCharA) || !isEnglish(firstCharA)) && (isEnglish(firstCharB) || isChinese(firstCharB))) {
-				 // 如果 A 是数字或其他符号,而 B 是英文或汉字,则 B 在前
-				 return 1;
-			   } else {
-				 // 若是其他情况(如两个字符都为数字或符号),按字符顺序排序
-				 return firstCharA.localeCompare(firstCharB);
-			   }
-			 });
-	   
-			 // 更新过滤后的联系人列表
-			 console.log("list",that.list);
-			 that.filteredContacts = that.list;
-			 console.error("更新过滤后的联系人列表",that.filteredContacts)
-		   }, function() {
-			 uni.showToast({
-			   title: '获取联系人失败',
-			   duration: 2000 // 在屏幕上显示的时间长度
+			showBar() {
+				this.searchActive = !this.searchActive;
+				this.ToGetMessage();
+			},
+			// 获取联系人信息
+		    ToGetMessage() {
+			 var that = this;
+			 // 获取通讯录对象
+			 plus.contacts.getAddressBook(plus.contacts.ADDRESSBOOK_PHONE, function(addressbook) {
+			   addressbook.find(["displayName", "phoneNumbers"], function(contacts) {
+				 that.list = contacts;
+				 console.log(that.list)
+		   
+				 // 将联系人按自定义规则排序
+				 that.list.sort(function(a, b) {
+				   // 检查是否为汉字、英文、数字或符号
+				   const isChinese = (str) => /^[\u4e00-\u9fa5]+$/.test(str);
+				   const isEnglish = (str) => /^[A-Za-z]+$/.test(str);
+				   const isNumber = (str) => /^[0-9]+$/.test(str);
+		   
+				   // 获取首字母,如果 displayName 是空,则使用 phoneNumbers 的第一个号码
+				   let firstCharA = a.displayName ? a.displayName.trim()[0] : a.phoneNumbers[0].value;
+				   let firstCharB = b.displayName ? b.displayName.trim()[0] : b.phoneNumbers[0].value;
+		   
+				   // 将汉字转换为拼音以便比较
+				   if (isChinese(firstCharA)) {
+					 firstCharA = pinyin(firstCharA, { style: pinyin.STYLE_FIRST_LETTER })[0][0];
+				   }
+				   if (isChinese(firstCharB)) {
+					 firstCharB = pinyin(firstCharB, { style: pinyin.STYLE_FIRST_LETTER })[0][0];
+				   }
+		   
+				   // 确定排序的优先级
+				   if (isEnglish(firstCharA) && isEnglish(firstCharB)) {
+					 // 如果都是英文,按字母顺序排序
+					 return firstCharA.localeCompare(firstCharB);
+				   } else if (isChinese(firstCharA) && isChinese(firstCharB)) {
+					 // 如果都是汉字(已经转换为拼音首字母),按拼音排序
+					 return firstCharA.localeCompare(firstCharB);
+				   } else if ((isEnglish(firstCharA) || isChinese(firstCharA)) && (isNumber(firstCharB) || !isEnglish(firstCharB))) {
+					 // 如果 A 是英文或汉字,而 B 是数字或其他符号,则 A 在前
+					 return -1;
+				   } else if ((isNumber(firstCharA) || !isEnglish(firstCharA)) && (isEnglish(firstCharB) || isChinese(firstCharB))) {
+					 // 如果 A 是数字或其他符号,而 B 是英文或汉字,则 B 在前
+					 return 1;
+				   } else {
+					 // 若是其他情况(如两个字符都为数字或符号),按字符顺序排序
+					 return firstCharA.localeCompare(firstCharB);
+				   }
+				 });
+		   
+				 // 更新过滤后的联系人列表
+				 console.log("list",that.list);
+				 that.filteredContacts = that.list;
+				 console.error("更新过滤后的联系人列表",that.filteredContacts)
+			   }, function() {
+				 uni.showToast({
+				   title: '获取联系人失败',
+				   duration: 2000 // 在屏幕上显示的时间长度
+				 });
+			   }, { multiple: true }); // 应该检索多个联系人
+			 }, function(e) {
+			   uni.showToast({
+				 title: '获取通讯录对象失败:' + e.message,
+				 duration: 2000
+			   });
 			 });
-		   }, { multiple: true }); // 应该检索多个联系人
-		 }, function(e) {
-		   uni.showToast({
-			 title: '获取通讯录对象失败:' + e.message,
-			 duration: 2000
-		   });
-		 });
-	   },
-		// 拨打电话
-		CallPhone(item,e) {
-		  // 重置所有isChooseNumberVisible状态
-		  Object.keys(this.isChooseNumberVisible).forEach(key=>{
-		  			 this.$set(this.isChooseNumberVisible,key,false); 
-		  });
-		  console.log("ischooseNumber",this.isChooseNumberVisible)
-		  // 调用HTML5 Plus框架提供的接口
-		  plus.device.dial(e, false);
-		  Object.keys(this.isChooseNumberVisible).forEach(key=>{
-		  			 this.$set(this.isChooseNumberVisible,key,false); 
-		  });
-		},
-		filterContacts() {
-		  // 获取用户输入的文本,转换为小写
-		  const searchText = this.searchText.toLowerCase();
-		  console.log("输入内容",searchText)
-		  if (!searchText) {
-		    // 如果用户没有输入,显示所有联系人
-			console.log("kong")
-		    this.filteredContacts = this.list;
+		   },
+			// 拨打电话
+			CallPhone(item,e) {
+			  // 重置所有isChooseNumberVisible状态
+			  Object.keys(this.isChooseNumberVisible).forEach(key=>{
+						 this.$set(this.isChooseNumberVisible,key,false); 
+			  });
+			  console.log("ischooseNumber",this.isChooseNumberVisible)
+			  // 调用HTML5 Plus框架提供的接口
+			  plus.device.dial(e, false);
+			  Object.keys(this.isChooseNumberVisible).forEach(key=>{
+						 this.$set(this.isChooseNumberVisible,key,false); 
+			  });
+			},
+			filterContacts() {
+			  // 获取用户输入的文本,转换为小写
+			  const searchText = this.searchText.toLowerCase();
+			  console.log("输入内容",searchText)
+			  if (!searchText) {
+				// 如果用户没有输入,显示所有联系人
+				console.log("kong")
+				this.filteredContacts = this.list;
+				
+			  } else {
+				// 过滤出匹配用户输入的联系人
+				this.filteredContacts = this.list.filter(contact => {
+				  // 模糊查找逻辑:检查 displayName 或 phoneNumbers 是否包含用户输入的文本
+				  const isFuzzyMatch = (contact.displayName || '').toLowerCase().includes(searchText) ||
+									   contact.phoneNumbers.some(phone => phone.value.toLowerCase().includes(searchText));
 			
-		  } else {
-		    // 过滤出匹配用户输入的联系人
-		    this.filteredContacts = this.list.filter(contact => {
-		      // 模糊查找逻辑:检查 displayName 或 phoneNumbers 是否包含用户输入的文本
-		      const isFuzzyMatch = (contact.displayName || '').toLowerCase().includes(searchText) ||
-		                           contact.phoneNumbers.some(phone => phone.value.toLowerCase().includes(searchText));
-		
-		      // 拼音首字母查找逻辑:检查拼音首字母序列是否包含用户输入的序列
-		      const displayNameFirstLetters = getInitials(contact.displayName || '');
-		      const isInitialsMatch = displayNameFirstLetters.includes(searchText);
-		
-		      // 返回匹配结果,只有当模糊查找或拼音首字母查找任一条件满足时,才包含该联系人
-		      return isFuzzyMatch || isInitialsMatch;
-		    });
-		  }
-		},
-		
-		search() {
-		  // 可以在这里添加更复杂的搜索逻辑
-		  this.filterContacts();
-		},
-  		//进行页面跳转到联系人详情
-		goToDetails(item){
-			console.error('item',item)
-			const phoneNumbers=item.phoneNumbers
-			const phoneNumbersString=JSON.stringify(phoneNumbers)
-			const phoenNumberCount=item.phoneNumbers.length;
-			console.error("phonenumber",phoneNumbers)
-			console.error("phoenNumberCount",phoenNumberCount)
-			uni.navigateTo({
-			    url: `/pages/ContactDetails/ContactDetails?name=${encodeURIComponent(item.displayName)}&phoneNumbers=${encodeURIComponent(phoneNumbersString)}&count=${phoenNumberCount}`
-			});
+				  // 拼音首字母查找逻辑:检查拼音首字母序列是否包含用户输入的序列
+				  const displayNameFirstLetters = getInitials(contact.displayName || '');
+				  const isInitialsMatch = displayNameFirstLetters.includes(searchText);
+			
+				  // 返回匹配结果,只有当模糊查找或拼音首字母查找任一条件满足时,才包含该联系人
+				  return isFuzzyMatch || isInitialsMatch;
+				});
+			  }
+			},
+			
+			search() {
+			  // 可以在这里添加更复杂的搜索逻辑
+			  this.filterContacts();
+			},
+			//进行页面跳转到联系人详情
+			goToDetails(item){
+				console.error('item',item)
+				const phoneNumbers=item.phoneNumbers
+				const phoneNumbersString=JSON.stringify(phoneNumbers)
+				const phoenNumberCount=item.phoneNumbers.length;
+				console.error("phonenumber",phoneNumbers)
+				console.error("phoenNumberCount",phoenNumberCount)
+				uni.navigateTo({
+					url: `/pages/ContactDetails/ContactDetails?name=${encodeURIComponent(item.displayName)}&phoneNumbers=${encodeURIComponent(phoneNumbersString)}&count=${phoenNumberCount}`
+				});
+			},
+			getM(){//获取本地语音开关信息
+				// 从本地存储中读取开关状态
+				const storedSwitchStatus = uni.getStorageSync('voiceBroadcastSwitch');
+				console.log("读取的本地存储状态1:", storedSwitchStatus);
+				
+				if (typeof storedSwitchStatus === 'boolean') {
+				    this.switchStatus = storedSwitchStatus;
+				}
+			}
 		},
+	  mounted() {
+	    this.getM();
 	  }
 	}
 </script>
@@ -491,7 +512,7 @@
   background-color: #f0efef;
 }
 
-.con-mes {
+.con-mes,.con-mes-null {
   font-family: 'FangSong', '仿宋_GB2312', serif;
   font-size: 35px;
   font-weight: 700;
@@ -507,6 +528,14 @@
   background-color: white;
 }
 
+.con-mes-null{
+	border-radius: 20rpx 0rpx 0rpx 20rpx;
+	width: 510rpx;
+	height: 200rpx;
+}
+
+
+
 .name-btn {
   display: flex;
   align-items: center;

+ 522 - 15
pages/test/test.vue

@@ -1,29 +1,536 @@
+<!-- 
+ 联系人主页,获取通讯录信息
+ 
+ zzh 24.8.26 修改 name-btn边框宽度
+ 方新力 24.8.28 修改字体大小,满6字换行,号码满7字换
+ -->
+
 <template>
-	<view>
-		<button @click="get(number)">按钮</button>
-		<hint></hint>
-	</view>
+    <!-- <movable-area class="floating-button" scale-area @change="updateFloatingButton">
+      <movable-view class="floating-button-view" direction="all">
+        可滚动的字母列表
+        <scroll-view class="alphabet-scroll" scroll-y>
+          <view v-for="letter in alphabet" :key="letter" class="alphabet-item"
+            :data-letter="letter" :class="{ active: currentLetter === letter }"
+            @touchstart="scrollToLetter(letter)">
+            {{ letter }}
+          </view>
+        </scroll-view>
+      </movable-view>
+    </movable-area> -->
+
+  <view class="content">
+    <view v-if="searchActive" class="navbar" style="padding-bottom: 20px;">
+      <image @click="showBar()" class="icon" src="../../static/pics/search.png"></image>
+      <image @click="navigateToPage('add')" class="icon" src="../../static/pics/add.png"></image>
+      <image @click="navigateToPage('setting')" class="icon" src="../../static/pics/setting.png"></image>
+	  
+    </view>
+    <view class="navbar" v-else>
+      <view class="uni-column">
+        <view class="search-input">
+          <input type="text" focus confirm-type="search" v-model="searchText" placeholder="输入号码或名字" @input="filterContacts" />
+        </view>
+        <view class="search-img" @click="showBar()">
+          取消
+        </view>
+      </view>
+    </view>
+    <view class="text-area">
+      <view v-if="filteredContacts.length" v-for="(item, id) in filteredContacts" :key="id">
+        <view class="name-btn">
+          <view v-if="isLoudVisible" class="loud" @click="play(item.displayName || item.phoneNumbers[0].value)">
+            <image style="width: 80%;height: 40%; margin-left: 35rpx;" src="../../static/pics/laba.png"></image>
+          </view>
+          <view class="con-mes" @click="goToDetails(item)">
+		    <text v-if="!item.displayName">{{ formatPhoneNumber(item.phoneNumbers[0].value) }}</text>
+		    <text v-else>{{ truncate(item.displayName) }}</text>
+		  </view>
+          <view class="btn" @click="CallPhone(item.phoneNumbers[0].value)">
+            <image class="Call" src="../../static/pics/call-out.png"></image>
+          </view>
+        </view>
+      </view>
+      <view v-else class="notFind">
+        该号码或联系人不存在
+      </view>
+    </view>
+  </view>
 </template>
 
 <script>
-	import hint from "../../components/hint.vue"
+	// 辅助函数,用于获取字符串的所有拼音首字母
+	function getInitials(str) {
+	  // 将字符串转换为拼音数组,每个汉字转换为对应的拼音首字母
+	  const initialsArray = pinyin(str, {
+	    style: pinyin.STYLE_FIRST_LETTER
+	  });
+	  
+	  // 映射每个拼音首字母数组,只取每个数组的第一个字符(即首字母)
+	  const firstLettersOnly = initialsArray.map(initial => initial[0]);
+	  
+	  // 使用 join 方法将所有首字母拼接成一个字符串
+	  return firstLettersOnly.join('');
+	}
+	const FvvUniTTS=uni.requireNativePlugin('Fvv-UniTTS');
+	import pinyin from "pinyin"; // 假设你使用了一个 pinyin 库,例如 pinyin
 	export default {
-		components:{
-			hint
+	  data() {
+		return {
+		    searchText: '', // 用户输入的搜索文本
+		    list: [], // 原始联系人列表
+		    filteredContacts: [], // 过滤后的联系人列表
+			num: '',
+			isLoudVisible: true, // 初始状态为显示
+		    searchActive: true,
+			
+		};
+	  },
+	  onShow() {
+		// 页面显示时直接调用
+		this.ToGetMessage();
+		/* this.ToGetHis(); */
+		this.init();
+		this.setLanguage();
+	  },
+	  beforeCreate() {
+			const domModule = uni.requireNativePlugin('dom')
+			domModule.addRule('fontFace', {
+				'fontFamily': "myIconfont",
+				'src': "url('../assets/typeface/almmdfdk.ttf')"
+			});
+	  },
+	  methods: {
+		    toNum(e){
+				console.log("num",e);
+				this.num=e;
+			},
+		    // 格式化电话号码
+		    formatPhoneNumber(value) {
+		      // 移除所有非数字字符
+		      value = value.replace(/\D/g, '');
+		      
+		      if (value.length === 11) {
+		        // 如果长度为11, 在第4和第9位插入空格
+		        return value.replace(/(\d{3})(\d{4})(\d{4})/, '$1 $2 $3');
+		      } else {
+		        // 如果长度不为11,每4个字符插入一个空格
+		        return value.replace(/(\d{4})(?=\d)/g, '$1 ');
+		      }
+		    },
+  			truncate(value) {
+		      if (value.length > 9) {
+		        return value.slice(0, 5) + '\n' + value.substring(5, 9) + '...';
+		      }
+			  else{
+				return value.slice(0, 5) + '\n' + value.substring(5, 9)
+			  }
+		      return value;
+		    },
+		    onChange: function(e) {
+		    	this.old.x = e.detail.x
+		    	this.old.y = e.detail.y
+		    },
+		    
+			init(){
+				FvvUniTTS.init((callback) => {
+					console.log(callback);
+				},"com.iflytek.speechcloud");
+				
+				FvvUniTTS.onStart((res) => {
+					console.log("onStart:" + res)
+				});
+				
+				FvvUniTTS.onDone((res) => {
+					console.log("onDone:" + res)
+				});
+				
+				FvvUniTTS.onError((res) => {
+					console.log("onError:" + res)
+				});
+				FvvUniTTS.getInstallTTS(res => {
+				    console.log(res) 
+				})
+			},
+			play(e){
+				console.log("xinxi",e)
+				FvvUniTTS.speak({
+					text:e,
+					id:2,
+				});
+				
+				FvvUniTTS.getInstallTTS(res => {
+				    console.log(res+"11") 
+				})
+			},
+			setLanguage(){
+				console.log("set lang : " + FvvUniTTS.setLanguage("CHINESE"));
+			},
+			setEngines(){
+				let setEngine = "com.iflytek.speechcloud"
+				
+				//获取已安装的引擎
+				FvvUniTTS.getInstallTTS(res => {
+					if(res == null || res.length <= 0){
+						return
+					}
+					console.log(res)
+					if(JSON.stringify(res).indexOf(setEngine) < 0){
+						console.log("未安装该语音引擎")
+						return
+					}
+					console.log("set engine : " + FvvUniTTS.setEngine(setEngine));
+					FvvUniTTS.speak({
+						text:"设置成功",
+						id:2,
+					});
+				})
+			},
+			saveFile(){
+				FvvUniTTS.saveAudioFile({
+					text:"hello",
+					id:3,
+					path:"/sdcard/test/1.wav"
+				})
+			},
+			setVoice(){
+				FvvUniTTS.setPitch(100)
+				FvvUniTTS.setSpeechRate(100)
+			},
+			navigateToPage(page) {
+				switch (page) {
+				  case 'add':
+					// 导航到添加页面
+					uni.navigateTo({
+					  url: '/pages/add/add'
+					});
+					break;
+				  case 'setting':
+					// 导航到设置页面
+					uni.navigateTo({
+					  url: '/pages/setting/setting'
+					});
+					break;
+					default:
+					break;
+				}
+			},
+		  
+		showBar() {
+		  this.searchActive = !this.searchActive;
+		  this.ToGetMessage();
 		},
-		data() {
-			return{
-				num:''
-			}
+		// 获取联系人信息
+	   ToGetMessage() {
+		 var that = this;
+		 // 获取通讯录对象
+		 plus.contacts.getAddressBook(plus.contacts.ADDRESSBOOK_PHONE, function(addressbook) {
+		   addressbook.find(["displayName", "phoneNumbers"], function(contacts) {
+			 that.list = contacts;
+			 console.log(that.list)
+	   
+			 // 将联系人按自定义规则排序
+			 that.list.sort(function(a, b) {
+			   // 检查是否为汉字、英文、数字或符号
+			   const isChinese = (str) => /^[\u4e00-\u9fa5]+$/.test(str);
+			   const isEnglish = (str) => /^[A-Za-z]+$/.test(str);
+			   const isNumber = (str) => /^[0-9]+$/.test(str);
+	   
+			   // 获取首字母,如果 displayName 是空,则使用 phoneNumbers 的第一个号码
+			   let firstCharA = a.displayName ? a.displayName.trim()[0] : a.phoneNumbers[0].value;
+			   let firstCharB = b.displayName ? b.displayName.trim()[0] : b.phoneNumbers[0].value;
+	   
+			   // 将汉字转换为拼音以便比较
+			   if (isChinese(firstCharA)) {
+				 firstCharA = pinyin(firstCharA, { style: pinyin.STYLE_FIRST_LETTER })[0][0];
+			   }
+			   if (isChinese(firstCharB)) {
+				 firstCharB = pinyin(firstCharB, { style: pinyin.STYLE_FIRST_LETTER })[0][0];
+			   }
+	   
+			   // 确定排序的优先级
+			   if (isEnglish(firstCharA) && isEnglish(firstCharB)) {
+				 // 如果都是英文,按字母顺序排序
+				 return firstCharA.localeCompare(firstCharB);
+			   } else if (isChinese(firstCharA) && isChinese(firstCharB)) {
+				 // 如果都是汉字(已经转换为拼音首字母),按拼音排序
+				 return firstCharA.localeCompare(firstCharB);
+			   } else if ((isEnglish(firstCharA) || isChinese(firstCharA)) && (isNumber(firstCharB) || !isEnglish(firstCharB))) {
+				 // 如果 A 是英文或汉字,而 B 是数字或其他符号,则 A 在前
+				 return -1;
+			   } else if ((isNumber(firstCharA) || !isEnglish(firstCharA)) && (isEnglish(firstCharB) || isChinese(firstCharB))) {
+				 // 如果 A 是数字或其他符号,而 B 是英文或汉字,则 B 在前
+				 return 1;
+			   } else {
+				 // 若是其他情况(如两个字符都为数字或符号),按字符顺序排序
+				 return firstCharA.localeCompare(firstCharB);
+			   }
+			 });
+	   
+			 // 更新过滤后的联系人列表
+			 console.log("list",that.list);
+			 that.filteredContacts = that.list;
+			 console.error("更新过滤后的联系人列表",that.filteredContacts)
+		   }, function() {
+			 uni.showToast({
+			   title: '获取联系人失败',
+			   duration: 2000 // 在屏幕上显示的时间长度
+			 });
+		   }, { multiple: true }); // 应该检索多个联系人
+		 }, function(e) {
+		   uni.showToast({
+			 title: '获取通讯录对象失败:' + e.message,
+			 duration: 2000
+		   });
+		 });
+	   },
+		// 拨打电话
+		CallPhone(e) {
+		  // 调用HTML5 Plus框架提供的接口
+		  plus.device.dial(e, false);
 		},
-		methods: {
+		filterContacts() {
+		  // 获取用户输入的文本,转换为小写
+		  const searchText = this.searchText.toLowerCase();
+		  console.log("输入内容",searchText)
+		  if (!searchText) {
+		    // 如果用户没有输入,显示所有联系人
+			console.log("kong")
+		    this.filteredContacts = this.list;
 			
-			
-			
-		}
+		  } else {
+		    // 过滤出匹配用户输入的联系人
+		    this.filteredContacts = this.list.filter(contact => {
+		      // 模糊查找逻辑:检查 displayName 或 phoneNumbers 是否包含用户输入的文本
+		      const isFuzzyMatch = (contact.displayName || '').toLowerCase().includes(searchText) ||
+		                           contact.phoneNumbers.some(phone => phone.value.toLowerCase().includes(searchText));
+		
+		      // 拼音首字母查找逻辑:检查拼音首字母序列是否包含用户输入的序列
+		      const displayNameFirstLetters = getInitials(contact.displayName || '');
+		      const isInitialsMatch = displayNameFirstLetters.includes(searchText);
+		
+		      // 返回匹配结果,只有当模糊查找或拼音首字母查找任一条件满足时,才包含该联系人
+		      return isFuzzyMatch || isInitialsMatch;
+		    });
+		  }
+		},
+		
+		search() {
+		  // 可以在这里添加更复杂的搜索逻辑
+		  this.filterContacts();
+		},
+  		//进行页面跳转到联系人详情
+		goToDetails(item){
+			console.error('item',item)
+			const phoneNumbers=item.phoneNumbers
+			const phoneNumbersString=JSON.stringify(phoneNumbers)
+			const phoenNumberCount=item.phoneNumbers.length;
+			console.error("phonenumber",phoneNumbers)
+			console.error("phoenNumberCount",phoenNumberCount)
+			uni.navigateTo({
+			    url: `/pages/ContactDetails/ContactDetails?name=${encodeURIComponent(item.displayName)}&phoneNumbers=${encodeURIComponent(phoneNumbersString)}&count=${phoenNumberCount}`
+			});
+		},
+	  }
 	}
 </script>
 
 <style>
+.floating-button {
+  width: 50px; /* 根据需要调整尺寸 */
+  height: 300px; /* 根据需要调整尺寸,确保字母列表可以容纳 */
+  border-radius: 25px;
+  background-color: rgba(0, 0, 0, 0.5);
+  position: fixed;
+  right: 20px;
+  bottom: 20px;
+  overflow: hidden; /* 确保内容在按钮范围内 */
+  z-index: 1000; /* 一个较高的z-index值,确保它在最上层 */
+}
+
+.alphabet-scroll {
+  width: 100%;
+  height: 100%;
+  background-color: #fff; /* 根据需要调整背景色 */
+}
+
+.alphabet-item {
+  padding: 5px 10px;
+  text-align: center;
+  cursor: pointer;
+}
+
+.alphabet-item.active {
+  background-color: #007AFF; /* 高亮颜色 */
+  color: #fff;
+}
+
+	
+.notFind{
+	font-size: 50rpx;
+}
+	
+.null {}
+
+/* 其他样式保持不变 */
+.uni-column {
+  width: 690rpx;
+  height: 140rpx;
+  border: 1px solid black;
+  margin-top: 18rpx;
+  border-radius: 20rpx;
+  font-size: 50rpx;
+  display: flex; /* 使用flex布局 */
+  justify-content: space-between; /* 左右分布 */
+  /* 其他样式保持不变 */
+}
+
+.search-input {
+  width: 75%;
+  /* 可以根据需要调整以下样式 */
+  display: flex;
+  align-items: center;
+}
+
+.search-img {
+  width: 25%;
+  /* 可以根据需要调整以下样式 */
+  display: flex;
+  border-left: 1px solid black;
+  justify-content: center;
+  align-items: center;
+}
+
+.search-input input {
+  /* 根据需要调整输入框大小 */
+  width: 90%; /* 例如90% */
+  height: 90%; /* 例如80% */
+  font-size: 50rpx;
+  padding: 10px; /* 根据需要调整内边距 */
+}
+
+.search-img image {
+  width: 50%; /* 例如30% */
+  height: 50%; /* 保持与输入框一致的高度 */
+  font-size: 50rpx;
+}
+
+.content {
+  min-height: 100%;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  background-color: #f0efef;
+}
+
+.con-mes {
+  line-height: 1.05; /* 行高为字体大小的0.2倍 */
+  font-family: 'FangSong', '仿宋_GB2312', serif;
+  font-size: 35px;
+  font-weight: 700;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  text-align: center;
+  white-space: pre-line; /* 保证换行符有效 */
+  word-wrap: break-word; /* 确保长单词换行 */
+  width: 410rpx;
+  height: 200rpx;
+  border: none;
+  background-color: white;
+}
+
+.name-btn {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  width: 690rpx;
+  height: 200rpx;
+  border: 0.5px solid black;
+  margin-top: 8rpx;
+  margin-bottom: 10rpx;
+  border-radius: 20rpx;
+  font-size: 50rpx;
+}
+
+.text-area {
+  padding-top: 145px;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+
+.loud {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  width: 100rpx;
+  height: 200rpx;
+  border-radius: 20rpx 0rpx 0rpx 20rpx;
+  background-color: white;
+}
+
+.btn {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  width: 180rpx;
+  height: 200rpx;
+  background-color: #ecfff3;
+  border-radius: 0rpx 20rpx 20rpx 0rpx;
+}
+
+.Call {
+  width: 100rpx;
+  height: 100rpx;
+  object-fit: contain;
+}
+
+.navbar {
+  display: flex;
+  justify-content: space-around;
+  align-items: flex-end;
+  width: 100%;
+  background-color: #f0efef;
+  min-height: 120px;
+  padding-bottom: 20px;
+  position: fixed; /* 设置为固定定位 */
+  top: 0; /* 与页面顶部的距离为0 */
+  z-index: 999;
+}
+
+.icon {
+  justify-content: space-around;
+  width: 100rpx;
+  height: 100rpx;
+}
+
+.uni-tabbar__iconfont {
+	  font-size: 50px; /* 自定义字体大小 */
+	  width: 80px;
+	  height: 80px;
+	}
+	
+/* 悬浮框css */
+movable-view {
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	height: 150rpx;
+	width: 150rpx;
+	background-color: #007AFF;
+	color: #fff;
+}
+
+movable-area {
+	height: 300rpx;
+	width: 100%;
+	background-color: #D8D8D8;
+	overflow: hidden;
+}
 
+.max {
+	width:500rpx;
+	height: 500rpx;
+}
 </style>

Файловите разлики са ограничени, защото са твърде много
+ 544 - 164
unpackage/dist/dev/app-plus/app-service.js


+ 6 - 1
unpackage/dist/dev/app-plus/pages/history/history.css

@@ -85,7 +85,7 @@ hr{
   justify-content: center;
   background-color: #f0efef;
 }
-.con-mes {
+.con-mes,.con-mes-null {
   line-height: 1.1; 
   font-size: 35px;
   font-weight: 700;
@@ -100,6 +100,11 @@ hr{
   border: none;
   background-color: white;
 }
+.con-mes-null{
+	border-radius: 0.625rem 0 0 0.625rem;
+	width: 15.9375rem;
+	height: 6.25rem;
+}
 .name-btn {
   display: flex;
   align-items: center;

+ 160 - 3
unpackage/dist/dev/app-plus/pages/index/index.css

@@ -1,4 +1,137 @@
 
+.modal-container[data-v-2ccb2f06] {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  z-index: 1000;
+  border-radius: 40px;
+}
+/* 遮盖罩样式 */
+.modal-overlay[data-v-2ccb2f06] {
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background-color: rgba(0, 0, 0, 0.5);
+  z-index: 999; /* 确保遮罩在内容下层 */
+}
+.modal-content[data-v-2ccb2f06] {
+  padding: 20px;
+  border-radius: 8px;
+  width: 300px;
+  max-width: 90%;
+  background: #ffffff;
+  z-index: 1000; /* 确保遮罩在内容上层 */
+}
+.modal-title[data-v-2ccb2f06] {
+  font-size: 40px;
+  font-weight: bold;
+  margin-bottom: 15px;
+}
+.modal-body[data-v-2ccb2f06] {
+  font-size: 30px;
+  margin-bottom: 20px;
+}
+.modal-buttons[data-v-2ccb2f06] {
+  display: flex;
+  justify-content: space-between;
+}
+.confirm-btn[data-v-2ccb2f06], .cancel-btn[data-v-2ccb2f06] {
+  flex: 1;
+  padding: 2px;
+  margin: 8px;
+  background: transparent; /* 背景透明 */
+  font-size: 36px;
+  border: 2px solid #dbdada;
+}
+.confirm-btn[data-v-2ccb2f06] {
+  border-radius: 20px;
+  color: #eb9d9a;
+}
+.cancel-btn[data-v-2ccb2f06] {
+  border-radius: 20px;
+  color: #9ee493;
+}
+
+
+.modal-container[data-v-7e794c10] {
+	position: fixed;
+	top: 0;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	z-index: 10000;
+}
+/* 遮盖罩样式 */
+.modal-overlay[data-v-7e794c10] {
+	position: absolute;
+	top: 0;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	background-color: rgba(0, 0, 0, 0.5);
+	z-index: 9990; /* 确保遮罩在内容下层 */
+}
+.modal-content[data-v-7e794c10] {
+	position: fixed;
+	bottom: 0%;
+    padding: 20px;
+    border-radius: 8px;
+    width: 100%;
+    max-width: 90%;
+    background: #ffffff;
+    z-index: 9999; /* 确保遮罩在内容上层 */
+}
+.modal-title[data-v-7e794c10] {
+	display: flex;
+	align-items: center;
+    justify-content: center;
+    font-size: 2.1875rem;
+    font-weight: bold;
+    margin-bottom: 0.15625rem;
+}
+.modal-body[data-v-7e794c10] {
+	display: flex;
+	flex-direction: column;/*按列排布*/
+	align-items: center;
+	justify-content: center;
+	font-size: 2.1875rem;
+	padding: 0.15625rem;
+	margin: 0.15625rem;
+}
+.modal-buttons[data-v-7e794c10] {
+	display: flex;
+	justify-content: space-between;
+}
+.confirm-btn[data-v-7e794c10], .cancel-btn[data-v-7e794c10] {
+	flex: 1;
+	padding: 2px;
+	margin: 8px;
+	background: transparent; /* 背景透明 */
+	border-radius: 4px;
+	font-size: 36px;
+}
+.confirm-btn[data-v-7e794c10] {
+	outline: none;
+	border: none;
+	color: red;
+}
+.cancel-btn[data-v-7e794c10] {
+	border: none;
+	outline: none;
+	color: blue;
+}
+
+
 .floating-button {
   width: 50px; /* 根据需要调整尺寸 */
   height: 300px; /* 根据需要调整尺寸,确保字母列表可以容纳 */
@@ -74,8 +207,7 @@
   justify-content: center;
   background-color: #f0efef;
 }
-.con-mes {
-  line-height: 1.05; /* 行高为字体大小的0.2倍 */
+.con-mes,.con-mes-null {
   font-family: 'FangSong', '仿宋_GB2312', serif;
   font-size: 35px;
   font-weight: 700;
@@ -90,6 +222,11 @@
   border: none;
   background-color: white;
 }
+.con-mes-null{
+	border-radius: 0.625rem 0 0 0.625rem;
+	width: 15.9375rem;
+	height: 6.25rem;
+}
 .name-btn {
   display: flex;
   align-items: center;
@@ -153,7 +290,27 @@
 	  width: 80px;
 	  height: 80px;
 }
-	
+.phonenumber-choose-component{
+	position: fixed;
+	bottom: 0;
+	left: 0;
+	right: 0;
+}
+.choose-phonenumber{
+	flex-direction: column;
+	font-size: 2.5rem;
+	transition: background-color 0.3s;
+}
+.choose-phonenumber.active {
+	background-color: #b0b0b0; /* 点击后颜色 */
+}
+.line{
+	/*分隔线,宽度、height参数为分隔线的粗细、颜色、上下间隔*/
+	width: 100%;
+	height: 0.0625rem;
+	background-color: #dbdbdb;
+	margin: 0.28125rem 0;
+}
 /* 悬浮框css */
 uni-movable-view {
 	display: flex;

+ 2 - 26
unpackage/dist/dev/app-plus/pages/tel/tel.css

@@ -111,8 +111,8 @@
 }
 .single-sim {
   width: 100%; /* 占满整个 .action 容器的宽度 */
-  height: 100px; /* 高度与双卡按钮相同 */
-  background-color: #ecfff3; /* 与双卡按钮相同的背景颜色 */
+  height: 100px; /* 设置按钮高度 */
+  background-color: #ecfff3; /* 按钮背景颜色 */
   color: #A9A9A9;
   font-size: 36px;
   display: flex;
@@ -121,30 +121,6 @@
   z-index: 4;
   position: relative;
 }
-.dual-sim-container {
-  display: flex;
-  width: 100%; /* 确保容器占满 .action 的宽度 */
-}
-.dual-sim {
-  flex: 1; /* 每个按钮占据 .dual-sim-container 容器的 50% 宽度 */
-  height: 100px;
-  background-color: #ecfff3;
-  color: #A9A9A9;
-  font-size: 36px;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  z-index: 4;
-  padding-top: 0.625rem;
-  position: relative; /* 允许内部元素使用相对定位 */
-}
-.dual-sim span {
-  position: absolute;
-  right: 33px;
-  top: -20px; /* 向上移动数字 */
-  font-size: 36px; /* 调整数字的大小 */
-  color: #A9A9A9; /* 数字颜色 */
-}
 .scale {
   /* 切换按钮的样式,背景色为浅绿色,内容居中对齐 */
   width: 100%;

+ 176 - 0
unpackage/dist/dev/app-plus/pages/test/test.css

@@ -0,0 +1,176 @@
+
+.floating-button {
+  width: 50px; /* 根据需要调整尺寸 */
+  height: 300px; /* 根据需要调整尺寸,确保字母列表可以容纳 */
+  border-radius: 25px;
+  background-color: rgba(0, 0, 0, 0.5);
+  position: fixed;
+  right: 20px;
+  bottom: 20px;
+  overflow: hidden; /* 确保内容在按钮范围内 */
+  z-index: 1000; /* 一个较高的z-index值,确保它在最上层 */
+}
+.alphabet-scroll {
+  width: 100%;
+  height: 100%;
+  background-color: #fff; /* 根据需要调整背景色 */
+}
+.alphabet-item {
+  padding: 5px 10px;
+  text-align: center;
+  cursor: pointer;
+}
+.alphabet-item.active {
+  background-color: #007AFF; /* 高亮颜色 */
+  color: #fff;
+}
+.notFind{
+	font-size: 1.5625rem;
+}
+.null {}
+
+/* 其他样式保持不变 */
+.uni-column {
+  width: 21.5625rem;
+  height: 4.375rem;
+  border: 1px solid black;
+  margin-top: 0.5625rem;
+  border-radius: 0.625rem;
+  font-size: 1.5625rem;
+  display: flex; /* 使用flex布局 */
+  justify-content: space-between; /* 左右分布 */
+  /* 其他样式保持不变 */
+}
+.search-input {
+  width: 75%;
+  /* 可以根据需要调整以下样式 */
+  display: flex;
+  align-items: center;
+}
+.search-img {
+  width: 25%;
+  /* 可以根据需要调整以下样式 */
+  display: flex;
+  border-left: 1px solid black;
+  justify-content: center;
+  align-items: center;
+}
+.search-input uni-input {
+  /* 根据需要调整输入框大小 */
+  width: 90%; /* 例如90% */
+  height: 90%; /* 例如80% */
+  font-size: 1.5625rem;
+  padding: 10px; /* 根据需要调整内边距 */
+}
+.search-img uni-image {
+  width: 50%; /* 例如30% */
+  height: 50%; /* 保持与输入框一致的高度 */
+  font-size: 1.5625rem;
+}
+.content {
+  min-height: 100%;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  background-color: #f0efef;
+}
+.con-mes {
+  line-height: 1.05; /* 行高为字体大小的0.2倍 */
+  font-family: 'FangSong', '仿宋_GB2312', serif;
+  font-size: 35px;
+  font-weight: 700;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  text-align: center;
+  white-space: pre-line; /* 保证换行符有效 */
+  word-wrap: break-word; /* 确保长单词换行 */
+  width: 12.8125rem;
+  height: 6.25rem;
+  border: none;
+  background-color: white;
+}
+.name-btn {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  width: 21.5625rem;
+  height: 6.25rem;
+  border: 0.5px solid black;
+  margin-top: 0.25rem;
+  margin-bottom: 0.3125rem;
+  border-radius: 0.625rem;
+  font-size: 1.5625rem;
+}
+.text-area {
+  padding-top: 145px;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+.loud {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  width: 3.125rem;
+  height: 6.25rem;
+  border-radius: 0.625rem 0 0 0.625rem;
+  background-color: white;
+}
+.btn {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  width: 5.625rem;
+  height: 6.25rem;
+  background-color: #ecfff3;
+  border-radius: 0 0.625rem 0.625rem 0;
+}
+.Call {
+  width: 3.125rem;
+  height: 3.125rem;
+  object-fit: contain;
+}
+.navbar {
+  display: flex;
+  justify-content: space-around;
+  align-items: flex-end;
+  width: 100%;
+  background-color: #f0efef;
+  min-height: 120px;
+  padding-bottom: 20px;
+  position: fixed; /* 设置为固定定位 */
+  top: 0; /* 与页面顶部的距离为0 */
+  z-index: 999;
+}
+.icon {
+  justify-content: space-around;
+  width: 3.125rem;
+  height: 3.125rem;
+}
+.uni-tabbar__iconfont {
+	  font-size: 50px; /* 自定义字体大小 */
+	  width: 80px;
+	  height: 80px;
+}
+	
+/* 悬浮框css */
+uni-movable-view {
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	height: 4.6875rem;
+	width: 4.6875rem;
+	background-color: #007AFF;
+	color: #fff;
+}
+uni-movable-area {
+	height: 9.375rem;
+	width: 100%;
+	background-color: #D8D8D8;
+	overflow: hidden;
+}
+.max {
+	width:15.625rem;
+	height: 15.625rem;
+}

Някои файлове не бяха показани, защото твърде много файлове са промени