文章目录
前言
需要实现一个通讯录的功能很简单,只需要在后端将用户名查询出来返回给前端展示就好,但是要按照A-Z排序就稍稍复杂了一点,要考虑用户名为中文、英文、数字等特殊字符的如何进行排序,仿照微信的话,数字以及特殊字符的归于‘#’类,排在最后。
提示:以下是本篇文章正文内容,下面案例可供参考
一、pinyin4j是什么?
是一个Java库,用于汉字转拼音,核心就是PinyinHelper类,感兴趣可以上官网研究pinyin4j, a Java library converting Chinese to pinyin
二、使用步骤
1.引入库
代码如下(示例):
<dependency>
<groupId>com.belerweb</groupId>
<artifactId>pinyin4j</artifactId>
<version>2.5.1</version>
</dependency>
2.后端代码
逻辑:输出A-Z,(char) (96 + i)
将数字i转换为对应的字符,其中96是字符'a'
的ASCII值。然后,String.valueOf()
将字符转换为字符串,并且.toUpperCase()
将字符串中的第一个字符转换为大写。循环遍历数据库查询出来的用户list集合,判断一下第一个字符是否为中文或者英文,获取对应字符的拼音,判断该用户是否在A-Z的范围中,将数据封装成一个json格式。
代码如下(示例):
/**
* 按用户拼音首字母分组
* @param list
* @return
* @throws BadHanyuPinyinOutputFormatCombination
*/
public static List<String> getUserCodeGroup(List<Member> list) throws BadHanyuPinyinOutputFormatCombination {
//输出26个字母
JSONObject jsonObj = new JSONObject();
List<String> jsonList= new ArrayList();
List<Member> otherLetter = new ArrayList<Member>();
for(int i=1;i<=26;i++){
String word = String.valueOf((char) (96 + i)). toUpperCase();
//循环找出首字母一样的数据
List<Member> letter = new ArrayList<Member>();
otherLetter = new ArrayList<Member>();
for (Member str : list) {
if(isChineseFrist(str.getName().charAt(0)) || isEnglishFrist(str.getName())) {//判断用户名的第一个字母是否为中文或者字母
String code = changeChinesePinyin(str.getName()).get("groupPinyin");
if (word.equals(code)) {
letter.add(str);
}
System.out.println(str);
}else{//非英文或中文的用户名 排最后
otherLetter.add(str);
}
}
//因前端需要json格式的数据进行遍历,所以此处我把数据封装成json格式
jsonObj.put("key",word);
jsonObj.put("list",letter);
jsonList.add(jsonObj.toString());
}
jsonObj.put("key","#");
jsonObj.put("list",otherLetter);
jsonList.add(jsonObj.toString());
return jsonList;
}
/**
*获取拼音的工具类
* 获取姓名全拼和首字母
* @param chinese 汉语名称
* @return fullPinyin : 全拼 simplePinyin : 首字母 groupPinyin:微信用户组第一个字母
* @throws BadHanyuPinyinOutputFormatCombination
*/
public static Map<String, String> changeChinesePinyin(String chinese) throws BadHanyuPinyinOutputFormatCombination {
Map<String, String> pinyin = new HashMap<String, String>();
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
format.setVCharType(HanyuPinyinVCharType.WITH_V);
StringBuffer fullPinyin = new StringBuffer();
StringBuffer simplePinyin = new StringBuffer();
StringBuffer firstPinyin = new StringBuffer();
char[] chineseChar = chinese.toCharArray();
//判断如果是英文就不需要去获取拼音直接返回英文就可以了
if(isEnglishFrist(chinese)){
fullPinyin = fullPinyin.append(chinese);
simplePinyin = simplePinyin.append(chinese);
firstPinyin=firstPinyin.append(chineseChar[0]);
}
//判断如果是中文就需要去获取拼音直接返回英文就可以了
if(isChineseFrist(chinese)){
for (int i = 0; i < chineseChar.length; i++) {
String[] str = null;
try {
str = PinyinHelper.toHanyuPinyinStringArray(chineseChar[i],
format);
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
}
if (str != null) {
fullPinyin = fullPinyin.append(str[0].toString());
simplePinyin = simplePinyin.append(str[0].charAt(0));
}
if (str == null) {
String regex = "^[0-9]*[a-zA-Z]*+$";
Pattern pattern = Pattern.compile(regex);
Matcher m = pattern.matcher(String.valueOf(chineseChar[i]));
if (m.find()) {
fullPinyin = fullPinyin.append(chineseChar[i]);
simplePinyin = simplePinyin.append(chineseChar[i]);
}
}
}
String[] name = PinyinHelper.toHanyuPinyinStringArray(chineseChar[0],format);
firstPinyin=firstPinyin.append(name[0].charAt(0));
}
pinyin.put("fullPinyin", fullPinyin.toString());
pinyin.put("simplePinyin", simplePinyin.toString().toUpperCase());
pinyin.put("groupPinyin", firstPinyin.toString().toUpperCase());
return pinyin;
}
/**
* 判断第一个是否为字母
* @param str
* @return
*/
public static boolean isEnglishFrist(String str){
for (int i = str.length();--i>=0;){
if (Character.isLetter(str.charAt(i))){
return true;
}
}
return false;
}
/**
* 判断第一个是否为中文
* @param str
* @return
*/
public static boolean isChineseFrist(char ch) {
return Character.UnicodeBlock.of(ch) == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
|| Character.UnicodeBlock.of(ch) == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS;
}
3.前端vue3+ts代码
<template>
<!-- 通讯录列表 -->
<div class="peoBox">
<!-- 字母检索 -->
<div class="letter">
<div v-for="(item, index) in navArray" :key="index" @click="scrollOn(item.key)">
{{ item.key }}
</div>
</div>
<div class="peo" ref="box">
<div v-for="item in peoArray" :key="item.key">
<p class="peoKey" :id="'peo' + item.key">{{ item.key }}</p>
<li class="peolist" v-for="ele in item.list" :key="ele.name" :id="ele.name"
@mousemove="handleMouseMove(ele.name)" @mouseleave="handleMouseLeave(ele.name)">
<a-avatar shape="square" :src=ele.avatar alt="用户头像">
<template #icon>
<UserOutlined />
</template>
</a-avatar>
{{ ele.name }}
</li>
</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, reactive } from 'vue';
import { getAddressBookList } from '@/api/system/addressBook'
const handleMouseMove = (name) => {
var addressList = document.getElementById(name);
if (null != addressList)
addressList.style.backgroundColor = '#e7e7e7'
}
const handleMouseLeave = (name) => {
var addressList = document.getElementById(name);
if (null != addressList)
addressList.style.backgroundColor = 'white'
}
const peoArray: any = reactive([])
const navArray: any = reactive([])
const initData = () => {
getAddressBookList().then(res => {
debugger
const data = res.data;
data.forEach((ele) => {
ele = JSON.parse(ele)
navArray.push(ele)
if (ele.list.length > 0) {
peoArray.push(ele)
}
});
})
}
initData()
const scrollOn = (key) => {
let target = document.getElementById("peo" + key); //获取每个字母通讯录对象
if (target){
target.scrollIntoView({
behavior: "smooth", // 定义动画过渡效果, "auto"或 "smooth" 之一。默认为 "auto"
});
}
}
export default defineComponent({
setup() {
return {
peoArray,
navArray,
handleMouseMove,
handleMouseLeave,
navBar: true,
navBarHeight: "50px", //导航栏高度
scrollOn,
};
},
});
</script>
<style scoped>
.peoBox {
position: relative;
background-color: white;
color: black;
}
.peoKey {
margin-bottom: -5px;
color: #909499;
}
.peolist {
height: 55px;
padding-top: 12px;
}
.peoHr {
border-bottom: 1px solid #f7f7f7f7;
}
/* 字母 */
.letter {
position: absolute;
right: 10px;
top: 25%;
z-index: 2;
}
</style>
效果图,点击右边的导航栏会调转到对应的用户列表。
总结
刚学vue3+ts,代码不规范的地方请谅解,也可以帮忙修改完善一下~
相互学习进步
参考文档:
封装一个类似微信通讯录带有字母检索功能的vue组件_vue 前端 通讯录-CSDN博客Java获取名字首字母拼音及用户按名字拼音分组工具_java中将名字首字符按26个字母分组-CSDN博客