Harmonyos应用实例50. 数字编码:身份证的秘密
·
10. 数字编码:身份证的秘密
知识点:数字编码的意义(教材中的实践活动)。
功能:输入身份证号码,系统解析并高亮显示地址码、出生日期码、顺序码,让学生理解数字编码的规范性。
// IdCodeDecoder.ets
// IdCodeDecoder.ets
interface IdCardInfo {
addressCode: string;
addressInfo: string;
birthYear: string;
birthMonth: string;
birthDay: string;
orderCode: string;
gender: string;
checkCode: string;
age: number;
isValid: boolean;
validationMessage: string;
}
@Entry
@Component
struct IdCodeDecoder {
@State idInput: string = '110101201203020066'
@State analysis: string[] = []
@State idCardInfo: IdCardInfo | null = null
@State showHelp: boolean = false
private provinceCodes = new Map<string, string>([
['11', '北京市'], ['12', '天津市'], ['13', '河北省'], ['14', '山西省'], ['15', '内蒙古自治区'],
['21', '辽宁省'], ['22', '吉林省'], ['23', '黑龙江省'], ['31', '上海市'], ['32', '江苏省'],
['33', '浙江省'], ['34', '安徽省'], ['35', '福建省'], ['36', '江西省'], ['37', '山东省'],
['41', '河南省'], ['42', '湖北省'], ['43', '湖南省'], ['44', '广东省'], ['45', '广西壮族自治区'],
['46', '海南省'], ['50', '重庆市'], ['51', '四川省'], ['52', '贵州省'], ['53', '云南省'],
['54', '西藏自治区'], ['61', '陕西省'], ['62', '甘肃省'], ['63', '青海省'], ['64', '宁夏回族自治区'],
['65', '新疆维吾尔自治区'], ['71', '台湾省'], ['81', '香港特别行政区'], ['82', '澳门特别行政区']
])
build() {
Scroll() {
Column({ space: 20 }) {
// 标题栏
Row() {
Text('🆔 数字编码:身份证的秘密')
.fontSize(28)
.fontWeight(FontWeight.Bold)
.fontColor('#2C3E50')
Blank()
Button('帮助')
.fontSize(14)
.width(60)
.height(35)
.backgroundColor('#95A5A6')
.onClick(() => {
this.showHelp = !this.showHelp;
})
}
.width('95%')
.padding(15)
.backgroundColor('#ECF0F1')
.borderRadius(15)
// 帮助信息
if (this.showHelp) {
Column({ space: 10 }) {
Text('💡 身份证号码结构说明')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#2C3E50')
.width('100%')
.textAlign(TextAlign.Start)
Text('1. 前6位:地址码(省、市、区)')
.fontSize(16)
.fontColor('#34495E')
Text('2. 第7-14位:出生日期码(年、月、日)')
.fontSize(16)
.fontColor('#34495E')
Text('3. 第15-17位:顺序码(奇数为男,偶数为女)')
.fontSize(16)
.fontColor('#34495E')
Text('4. 第18位:校验码(0-9或X)')
.fontSize(16)
.fontColor('#34495E')
}
.padding(15)
.backgroundColor('#FFF9E6')
.borderRadius(10)
.width('95%')
}
// 输入区域
Column({ space: 15 }) {
Text('📝 请输入身份证号码')
.fontSize(20)
.fontColor('#2C3E50')
.fontWeight(FontWeight.Bold)
.width('100%')
.textAlign(TextAlign.Start)
Row() {
TextInput({
placeholder: '请输入18位身份证号',
text: this.idInput
})
.maxLength(18)
.type(InputType.Number)
.width('100%')
.height(50)
.border({ width: 2, color: '#3498DB' })
.borderRadius(10)
.padding(15)
}
.width('95%')
Row({ space: 10 }) {
Button('解析')
.fontSize(16)
.width('30%')
.height(40)
.backgroundColor('#3498DB')
.onClick(() => this.decode())
Button('示例')
.fontSize(16)
.width('30%')
.height(40)
.backgroundColor('#27AE60')
.onClick(() => {
this.idInput = '110101201203020066';
this.decode();
})
Button('清空')
.fontSize(16)
.width('30%')
.height(40)
.backgroundColor('#E74C3C')
.onClick(() => {
this.idInput = '';
this.analysis = [];
this.idCardInfo = null;
})
}
.width('95%')
.justifyContent(FlexAlign.SpaceBetween)
}
// 解析结果
if (this.idCardInfo) {
Column({ space: 20 }) {
Text('📊 解析结果')
.fontSize(22)
.fontWeight(FontWeight.Bold)
.fontColor('#2C3E50')
.width('100%')
.textAlign(TextAlign.Start)
// 基本信息卡片
Column({ space: 15 }) {
// 身份证号码信息
Row() {
Text('身份证号:')
.fontSize(16)
.fontColor('#7F8C8D')
.fontWeight(FontWeight.Bold)
Text(this.idInput)
.fontSize(16)
.fontColor('#2C3E50')
.fontWeight(FontWeight.Bold)
.layoutWeight(1)
.textAlign(TextAlign.End)
}
.width('100%')
// 地址信息
Row() {
Text('📍 地址:')
.fontSize(16)
.fontColor('#7F8C8D')
.fontWeight(FontWeight.Bold)
Text(this.idCardInfo.addressInfo)
.fontSize(16)
.fontColor('#2C3E50')
.layoutWeight(1)
.textAlign(TextAlign.End)
}
.width('100%')
// 出生日期
Row() {
Text('🎂 出生日期:')
.fontSize(16)
.fontColor('#7F8C8D')
.fontWeight(FontWeight.Bold)
Text(`${this.idCardInfo.birthYear}年${this.idCardInfo.birthMonth}月${this.idCardInfo.birthDay}日`)
.fontSize(16)
.fontColor('#2C3E50')
.layoutWeight(1)
.textAlign(TextAlign.End)
}
.width('100%')
// 年龄
Row() {
Text('🎈 年龄:')
.fontSize(16)
.fontColor('#7F8C8D')
.fontWeight(FontWeight.Bold)
Text(`${this.idCardInfo.age}岁`)
.fontSize(16)
.fontColor('#2C3E50')
.layoutWeight(1)
.textAlign(TextAlign.End)
}
.width('100%')
// 性别
Row() {
Text('👤 性别:')
.fontSize(16)
.fontColor('#7F8C8D')
.fontWeight(FontWeight.Bold)
Text(this.idCardInfo.gender)
.fontSize(16)
.fontColor('#2C3E50')
.layoutWeight(1)
.textAlign(TextAlign.End)
}
.width('100%')
// 校验码
Row() {
Text('🔍 校验码:')
.fontSize(16)
.fontColor('#7F8C8D')
.fontWeight(FontWeight.Bold)
Text(this.idCardInfo.checkCode)
.fontSize(16)
.fontColor('#2C3E50')
.layoutWeight(1)
.textAlign(TextAlign.End)
}
.width('100%')
// 验证结果
Row() {
Text('✅ 验证结果:')
.fontSize(16)
.fontColor('#7F8C8D')
.fontWeight(FontWeight.Bold)
Text(this.idCardInfo.isValid ? '有效' : '无效')
.fontSize(16)
.fontColor(this.idCardInfo.isValid ? '#27AE60' : '#E74C3C')
.fontWeight(FontWeight.Bold)
.layoutWeight(1)
.textAlign(TextAlign.End)
}
.width('100%')
// 验证信息
if (!this.idCardInfo.isValid) {
Text(this.idCardInfo.validationMessage)
.fontSize(14)
.fontColor('#E74C3C')
.width('100%')
.textAlign(TextAlign.Start)
}
}
.padding(20)
.backgroundColor('#FFFFFF')
.borderRadius(15)
.width('95%')
.shadow({
radius: 5,
color: '#0000001A',
offsetX: 0,
offsetY: 2
})
// 编码规则说明
Column({ space: 15 }) {
Text('📚 编码规则')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor('#2C3E50')
.width('100%')
.textAlign(TextAlign.Start)
Flex({ direction: FlexDirection.Row, wrap: FlexWrap.Wrap, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Start }) {
this.CodeSection('1-6', '地址码', '#3498DB')
this.CodeSection('7-14', '出生日期码', '#27AE60')
this.CodeSection('15-17', '顺序码', '#F39C12')
this.CodeSection('18', '校验码', '#E74C3C')
}
.width('100%')
}
.padding(20)
.backgroundColor('#F8F9FA')
.borderRadius(15)
.width('95%')
}
}
// 历史记录
Column({ space: 15 }) {
Text('📋 解析记录')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor('#2C3E50')
.width('100%')
.textAlign(TextAlign.Start)
if (this.analysis.length > 0) {
List({ space: 10 }) {
ForEach(this.analysis, (item: string, index: number) => {
ListItem() {
Row({ space: 10 }) {
Text(`${index + 1}.`)
.fontSize(16)
.fontColor('#7F8C8D')
.fontWeight(FontWeight.Bold)
Text(item)
.fontSize(16)
.fontColor('#2C3E50')
.layoutWeight(1)
}
.width('100%')
.padding(15)
.backgroundColor('#FFFFFF')
.borderRadius(10)
.border({ width: 0, color: '#3498DB' })
.borderWidth(4)
.borderColor('#3498DB')
}
})
}
.width('100%')
.height(200)
} else {
Text('暂无解析记录')
.fontSize(16)
.fontColor('#95A5A6')
.width('100%')
.textAlign(TextAlign.Center)
.padding(20)
}
}
.padding(20)
.backgroundColor('#E8F4F8')
.borderRadius(15)
.width('95%')
}
.width('100%')
.padding(20)
.backgroundColor('#F5F6FA')
}
.width('100%')
.height('100%')
}
@Builder
CodeSection(range: string, name: string, color: string) {
Column({ space: 5 }) {
Text(range)
.fontSize(14)
.fontWeight(FontWeight.Bold)
.fontColor('#2C3E50')
Text(name)
.fontSize(12)
.fontColor('#7F8C8D')
}
.width('23%')
.height(80)
.padding(10)
.backgroundColor(color)
.borderRadius(10)
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
}
decode() {
if (this.idInput.length !== 18) {
this.analysis = ['请输入正确的18位身份证号码'];
return;
}
// 验证格式
if (!/^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[0-9Xx]$/.test(this.idInput)) {
this.analysis = ['身份证号码格式不正确'];
return;
}
// 解析各个部分
const addressCode = this.idInput.substring(0, 6);
const birthYear = this.idInput.substring(6, 10);
const birthMonth = this.idInput.substring(10, 12);
const birthDay = this.idInput.substring(12, 14);
const orderCode = this.idInput.substring(14, 17);
const checkCode = this.idInput.substring(17, 18).toUpperCase();
const gender = parseInt(orderCode) % 2 === 1 ? '男' : '女';
// 计算年龄
const now = new Date();
const birthDate = new Date(parseInt(birthYear), parseInt(birthMonth) - 1, parseInt(birthDay));
let age = now.getFullYear() - birthDate.getFullYear();
const monthDiff = now.getMonth() - birthDate.getMonth();
if (monthDiff < 0 || (monthDiff === 0 && now.getDate() < birthDate.getDate())) {
age--;
}
// 获取地址信息
const provinceCode = addressCode.substring(0, 2);
const provinceName = this.provinceCodes.get(provinceCode) || '未知地区';
const addressInfo = `${provinceName}(${addressCode})`;
// 验证校验码
const isValid = this.validateCheckCode(this.idInput);
const validationMessage = isValid ? '身份证号码有效' : '校验码错误,身份证号码无效';
// 构建信息
this.idCardInfo = {
addressCode,
addressInfo,
birthYear,
birthMonth,
birthDay,
orderCode,
gender,
checkCode,
age,
isValid,
validationMessage
};
// 添加到历史记录
const record = `${this.idInput} - ${birthYear}年${birthMonth}月${birthDay}日 - ${gender}`;
this.analysis.unshift(record);
if (this.analysis.length > 5) {
this.analysis.pop();
}
}
validateCheckCode(idCard: string): boolean {
const weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
const checkCodes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
let sum = 0;
for (let i = 0; i < 17; i++) {
sum += parseInt(idCard[i]) * weights[i];
}
const checkCodeIndex = sum % 11;
return idCard[17].toUpperCase() === checkCodes[checkCodeIndex];
}
}
更多推荐



所有评论(0)