添加注册功能测试,修改登录逻辑,添加记住密码功能测试

This commit is contained in:
cc 2025-04-15 19:28:40 +08:00
parent 21230d5a0d
commit b431789d3a
18 changed files with 271 additions and 40 deletions

View File

@ -1,6 +1,5 @@
/**
* Copyright (c) 2025 TDCAT.CN
* Author: CC
*/
// 初始化应用

View File

@ -1,6 +1,5 @@
/**
* Copyright (c) 2025 TDCAT.CN
* Author: CC
*/
import { hilog } from '@kit.PerformanceAnalysisKit';
@ -430,8 +429,25 @@ export class ClassRoomService {
// 检查当前用户是否为教师
public checkIsTeacher(): boolean {
const currentAccount = settingsService.getCurrentAccount();
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `检查用户 ${currentAccount} 是否为教师`);
const category = this.dbService.getUserCategory(currentAccount);
this.isTeacher = category === 'teacher';
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `用户类别: ${category}`);
// 首先通过数据库类别判断
if (category === 'teacher') {
this.isTeacher = true;
} else if (category === 'student') {
this.isTeacher = false;
} else {
// 如果类别不明确,通过账号判断(备用)
hilog.warn(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `用户类别不明确,尝试通过账号号码判断`);
this.isTeacher = currentAccount.includes('0');
hilog.info(TIAN_CHANNEL_DOMAIN_ID, TIAN_CHANNEL_TAG, `通过账号判断用户身份为${this.isTeacher ? '教师' : '学生'}`);
}
logManager.info(LogCategory.USER, LogEventType.SYSTEM_INFO,
`用户 ${currentAccount} 的角色为: ${this.isTeacher ? '教师' : '学生'}`);
return this.isTeacher;
}

View File

@ -1,6 +1,5 @@
/**
* Copyright (c) 2025 TDCAT.CN
* Author: CC
*/
import { hilog } from '@kit.PerformanceAnalysisKit';
@ -197,11 +196,11 @@ export class DatabaseService {
}
// 降级逻辑 - 当API不可用时
/* if (account.includes('2')) {
if (account.includes('2')) {
return 'student';
} else if (account.includes('0')) {
return 'teacher';
}*/
}
return '';
}
@ -215,9 +214,9 @@ export class DatabaseService {
}
// 默认值 - 仅用于开发/测试
/* if (account === '2') return '张三';
if (account === '2') return '张三';
if (account === '9222') return '李华';
if (account === '0') return '教师demo';*/
if (account === '0') return '教师demo';
return '';
}

View File

@ -1,6 +1,5 @@
/**
* Copyright (c) 2025 TDCAT.CN
* Author: CC
*/
import { hilog } from '@kit.PerformanceAnalysisKit';
@ -167,6 +166,7 @@ export class LogManager {
new VersionLogItem("1.2.0 beta1.0","2025-4-3",["测试消息发送","修复已知问题"]),
new VersionLogItem("1.2.0 beta1.1","2025-4-4",["更新说明文档","添加日志输出"]),
new VersionLogItem("1.2.0 beta1.2","2025-4-8",["修改首页","添加网页"]),
new VersionLogItem("1.2.0 beta2.0","2025-4-15",["修改登录逻辑","修复上课逻辑","添加注册功能测试","添加记住密码功能测试"]),
];
}

View File

@ -33,17 +33,14 @@ export default class EntryAbility extends UIAbility {
console.info('==========================================');
console.info(asciiArt);
console.info('Copyright (c) 2025 TDCAT.CN');
console.info('Author: CC');
console.info('==========================================');
hilog.info(DOMAIN, 'COPYRIGHT', '==========================================');
hilog.info(DOMAIN, 'COPYRIGHT', 'Copyright (c) 2025 TDCAT.CN');
hilog.info(DOMAIN, 'COPYRIGHT', 'Author: CC');
hilog.info(DOMAIN, 'COPYRIGHT', '==========================================');
hilog.info(DOMAIN, 'COPYRIGHT', '%{public}s', '==========================================');
hilog.info(DOMAIN, 'COPYRIGHT', '%{public}s', 'Copyright (c) 2025 TDCAT.CN');
hilog.info(DOMAIN, 'COPYRIGHT', '%{public}s', 'Author: CC');
hilog.info(DOMAIN, 'COPYRIGHT', '%{public}s', '==========================================');
copyrightDisplayed = true;

View File

@ -1,6 +1,5 @@
/**
* Copyright (c) 2025 TDCAT.CN
* Author: CC
*/
import { router } from '@kit.ArkUI';

View File

@ -1,6 +1,5 @@
/**
* Copyright (c) 2025 TDCAT.CN
* Author: CC
*/
import { router } from '@kit.ArkUI';

View File

@ -1,6 +1,5 @@
/**
* Copyright (c) 2025 TDCAT.CN
* Author: CC
*/
import { router } from '@kit.ArkUI';
@ -59,14 +58,29 @@ struct ClassPage {
// 检查用户角色
const currentAccount = settingsService.getCurrentAccount();
logManager.info(LogCategory.USER, LogEventType.SYSTEM_INFO, `当前用户账号: ${currentAccount}`);
const category = this.dbService.getUserCategory(currentAccount);
logManager.info(LogCategory.USER, LogEventType.SYSTEM_INFO, `用户类别: ${category}`);
if (category === 'student') {
this.userRole = UserRole.STUDENT;
logManager.info(LogCategory.USER, LogEventType.SYSTEM_INFO, '用户角色设置为学生');
} else if (category === 'teacher') {
this.userRole = UserRole.TEACHER;
logManager.info(LogCategory.USER, LogEventType.SYSTEM_INFO, '用户角色设置为教师');
} else {
this.userRole = UserRole.UNKNOWN;
logManager.warn(LogCategory.USER, '无法识别用户角色,设置为未知');
// 尝试使用账号号码进行识别(备用方案)
if (currentAccount.includes('2')) {
this.userRole = UserRole.STUDENT;
logManager.info(LogCategory.USER, LogEventType.SYSTEM_INFO, '通过账号号码识别为学生');
} else if (currentAccount.includes('0')) {
this.userRole = UserRole.TEACHER;
logManager.info(LogCategory.USER, LogEventType.SYSTEM_INFO, '通过账号号码识别为教师');
}
}
// 同步设置到课堂服务

View File

@ -1,6 +1,5 @@
/**
* Copyright (c) 2025 TDCAT.CN
* Author: CC
*/
import { router } from '@kit.ArkUI';

View File

@ -1,6 +1,5 @@
/**
* Copyright (c) 2025 TDCAT.CN
* Author: CC
*/
import { router } from '@kit.ArkUI';

View File

@ -1,6 +1,5 @@
/**
* Copyright (c) 2025 TDCAT.CN
* Author: CC
*/
import { router } from '@kit.ArkUI';

View File

@ -1,6 +1,5 @@
/**
* Copyright (c) 2025 TDCAT.CN
* Author: CC
*/
import { router } from '@kit.ArkUI';

View File

@ -1,6 +1,5 @@
/**
* Copyright (c) 2025 TDCAT.CN
* Author: CC
*/
import { router } from '@kit.ArkUI';

View File

@ -1,6 +1,5 @@
/**
* Copyright (c) 2025 TDCAT.CN
* Author: CC
*/
import { router } from '@kit.ArkUI';
@ -44,7 +43,7 @@ struct DataProcessingStatement {
.textAlign(TextAlign.Center)
.width('100%')
Text('最近更新日期2023年12月1日\n文件编号CMSDP-2023-001\n生效日期2023年12月15日')
Text('最近更新日期2023年12月1日\n文件编号CMSDP-2023-001\n生效日期2025年04月15日')
.fontSize(14)
.fontColor('#666666')
.margin({ bottom: 20 })
@ -76,7 +75,7 @@ struct DataProcessingStatement {
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
Text('2.1 数据控制者\n\n公司名称数据猫\n注册地址中国北京市海淀区科学园路XX号\n企业统一社会信用代码XXXXXXXXXXXXXXXXXXXX\n负责人数据保护官\n联系电话400-123-4567\n电子邮件support@tdcat.cn\n\n2.2 数据处理者\n\n在某些情况下我们会委托第三方服务提供商作为数据处理者处理部分个人数据。所有第三方处理者都必须遵守我们的数据保护标准和安全要求并且仅能根据我们明确的书面指示处理个人数据。我们仅选择能够提供足够保证的数据处理者这些保证应包括实施适当的技术和组织措施确保数据处理符合适用的数据保护法律要求并保护数据主体的权利。\n\n我们会与所有数据处理者签订符合法律要求的数据处理协议明确其数据处理义务和责任。')
Text('2.1 数据控制者\n\n公司名称数据猫\n注册地址重庆理工大学两江校区\n企业统一社会信用代码XXXXXXXXXXXXXXXXXXXX\n负责人数据保护官\n电子邮件support@tdcat.cn\n\n2.2 数据处理者\n\n在某些情况下我们会委托第三方服务提供商作为数据处理者处理部分个人数据。所有第三方处理者都必须遵守我们的数据保护标准和安全要求并且仅能根据我们明确的书面指示处理个人数据。我们仅选择能够提供足够保证的数据处理者这些保证应包括实施适当的技术和组织措施确保数据处理符合适用的数据保护法律要求并保护数据主体的权利。\n\n我们会与所有数据处理者签订符合法律要求的数据处理协议明确其数据处理义务和责任。')
.fontSize(14)
.margin({ bottom: 20 })
.textAlign(TextAlign.Start)
@ -156,7 +155,7 @@ struct DataProcessingStatement {
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
Text('如果您对我们的数据处理有任何疑问,或希望行使数据主体权利,请通过以下方式联系我们:\n\n数据保护官数据保护官\n数据保护团队个人信息保护办公室\n电子邮件support@tdcat.cn\n电话400-123-4567\n地址中国北京市海淀区科学园路XX号\n邮编100080\n\n我们将尽快处理您的请求通常会在收到请求后的30天内回复。如果由于特殊情况需要更长的处理时间我们会告知您延迟的原因及预计回复时间。\n\n如果您对我们的回复不满意您还可以向相关数据保护监管机构投诉或寻求司法救济。')
Text('如果您对我们的数据处理有任何疑问,或希望行使数据主体权利,请通过以下方式联系我们:\n\n数据保护官数据保护官\n数据保护团队个人信息保护办公室\n电子邮件support@tdcat.cn\n地址:重庆理工大学两江校区\n邮编100080\n\n我们将尽快处理您的请求通常会在收到请求后的30天内回复。如果由于特殊情况需要更长的处理时间我们会告知您延迟的原因及预计回复时间。\n\n如果您对我们的回复不满意您还可以向相关数据保护监管机构投诉或寻求司法救济。')
.fontSize(14)
.margin({ bottom: 30 })
.textAlign(TextAlign.Start)

View File

@ -1,6 +1,5 @@
/**
* Copyright (c) 2025 TDCAT.CN
* Author: CC
*/
import { router } from '@kit.ArkUI';
@ -44,7 +43,7 @@ struct PrivacyPolicy {
.textAlign(TextAlign.Center)
.width('100%')
Text('最近更新日期2023年12月1日\n文件编号CMSPP-2023-001\n生效日期2023年12月15日')
Text('最近更新日期2023年12月1日\n文件编号CMSPP-2023-001\n生效日期2025年04月15日')
.fontSize(14)
.fontColor('#666666')
.margin({ bottom: 20 })
@ -152,7 +151,7 @@ struct PrivacyPolicy {
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
Text('如果您对本隐私政策有任何疑问、意见或建议,或者想行使您的权利,请通过以下方式联系我们:\n\n个人信息保护负责人数据保护官\n联系部门个人信息保护办公室\n电子邮件support@tdcat.cn\n电话400-123-4567\n地址中国北京市海淀区科学园路XX号\n邮编100080\n\n一般情况下我们将在收到您的请求后30天内答复。如您不满意我们的回复特别是我们的个人信息处理行为损害了您的合法权益您还可以通过以下外部途径寻求解决方案向所在地的人民法院提起诉讼。')
Text('如果您对本隐私政策有任何疑问、意见或建议,或者想行使您的权利,请通过以下方式联系我们:\n\n个人信息保护负责人数据保护官\n联系部门个人信息保护办公室\n电子邮件support@tdcat.cn\n地址:重庆理工大学两江校区\n邮编100080\n\n一般情况下我们将在收到您的请求后30天内答复。如您不满意我们的回复特别是我们的个人信息处理行为损害了您的合法权益您还可以通过以下外部途径寻求解决方案向所在地的人民法院提起诉讼。')
.fontSize(14)
.margin({ bottom: 30 })
.textAlign(TextAlign.Start)

View File

@ -1,6 +1,5 @@
/**
* Copyright (c) 2025 TDCAT.CN
* Author: CC
*/
import { router } from '@kit.ArkUI';
@ -44,7 +43,7 @@ struct UserAgreement {
.textAlign(TextAlign.Center)
.width('100%')
Text('最近更新日期2023年12月1日\n文件编号CMSUSR-2023-001\n生效日期2023年12月15日')
Text('最近更新日期2023年12月1日\n文件编号CMSUSR-2023-001\n生效日期2025年04月15日')
.fontSize(14)
.fontColor('#666666')
.margin({ bottom: 20 })
@ -156,7 +155,7 @@ struct UserAgreement {
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
Text('如您对本协议或本系统服务有任何疑问,请通过以下方式与我们联系:\n\n名称数据猫\n电子邮件support@tdcat.cn\n电话400-123-4567\n地址中国北京市海淀区科学园路XX号\n邮编100080')
Text('如您对本协议或本系统服务有任何疑问,请通过以下方式与我们联系:\n\n名称数据猫\n电子邮件support@tdcat.cn\n地址:重庆理工大学两江校区\n邮编100080')
.fontSize(14)
.margin({ bottom: 30 })
.textAlign(TextAlign.Start)

View File

@ -1,6 +1,5 @@
/**
* Copyright (c) 2025 TDCAT.CN
* Author: CC
*/
import router from '@ohos.router';
@ -9,6 +8,7 @@ import settingsService from '../common/SettingsService';
import { DatabaseService } from '../common/DatabaseService';
import promptAction from '@ohos.promptAction';
import common from '@ohos.app.ability.common';
import fileIo from '@ohos.file.fs';
@Entry
@Component
@ -20,9 +20,11 @@ struct Login {
@State isLoading: boolean = false; // 加载状态
@State errorMessage: string = ''; // 错误信息
@State isAgreementChecked: boolean = false; // 是否同意条款
@State isRememberPassword: boolean = false; // 是否记住密码
// 获取数据库服务实例
private dbService: DatabaseService = DatabaseService.getInstance();
private userpassFilePath: string = '';
// 登录验证方法
private async handleLogin(): Promise<void> {
@ -58,6 +60,11 @@ struct Login {
// 设置当前用户
settingsService.setCurrentAccount(this.username);
// 如果勾选了记住密码,保存用户名密码到文件
if (this.isRememberPassword) {
this.saveUserCredentials();
}
// 记录登录日志
logManager.info(LogCategory.USER, LogEventType.USER_LOGIN, `User logged in: ${this.username}`);
@ -71,13 +78,164 @@ struct Login {
this.errorMessage = '账号或密码错误';
logManager.info(LogCategory.USER, LogEventType.USER_LOGIN_FAIL, `Login failed: ${this.username}`);
}
} catch (error) {
} catch {
this.errorMessage = '登录失败,请稍后重试';
logManager.info(LogCategory.USER, LogEventType.USER_LOGIN_FAIL, `Login error: ${error}`);
logManager.info(LogCategory.USER, LogEventType.USER_LOGIN_FAIL, '登录过程中出现错误');
} finally {
this.isLoading = false;
}
}
// 保存用户凭证到文件
private saveUserCredentials(): void {
try {
const credentials: string = JSON.stringify({
username: this.username,
password: this.password
});
// 写入文件前确保文件存在
this.ensureFileExists();
// 写入文件
try {
const file = fileIo.openSync(this.userpassFilePath, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);
// 将字符串转换为字节数组并写入
const buffer = new ArrayBuffer(credentials.length * 2);
const dataView = new DataView(buffer);
for (let i = 0; i < credentials.length; i++) {
dataView.setUint16(i * 2, credentials.charCodeAt(i), true);
}
fileIo.writeSync(file.fd, buffer);
fileIo.closeSync(file.fd);
logManager.info(LogCategory.SYSTEM, LogEventType.SYSTEM_INFO, "已保存用户凭证");
} catch {
logManager.error(LogCategory.SYSTEM, "写入凭证失败");
}
} catch {
logManager.error(LogCategory.SYSTEM, "保存凭证失败");
}
}
// 清除保存的用户凭证
private clearUserCredentials(): void {
try {
if (fileIo.accessSync(this.userpassFilePath)) {
try {
// 清空文件内容
const file = fileIo.openSync(this.userpassFilePath, fileIo.OpenMode.WRITE_ONLY | fileIo.OpenMode.TRUNC);
fileIo.closeSync(file.fd);
logManager.info(LogCategory.SYSTEM, LogEventType.SYSTEM_INFO, "已清除用户凭证");
} catch {
logManager.error(LogCategory.SYSTEM, "清除凭证失败");
}
}
} catch {
// 文件不存在,不需要清除
logManager.info(LogCategory.SYSTEM, LogEventType.SYSTEM_INFO, "没有需要清除的凭证文件");
}
}
// 读取用户凭证
private loadUserCredentials(): void {
try {
if (fileIo.accessSync(this.userpassFilePath)) {
try {
const file = fileIo.openSync(this.userpassFilePath, fileIo.OpenMode.READ_ONLY);
const fileSize = fileIo.statSync(this.userpassFilePath).size;
if (fileSize > 0) {
const buf = new ArrayBuffer(fileSize);
fileIo.readSync(file.fd, buf);
fileIo.closeSync(file.fd);
// 手动将字节数组转换为字符串
const dataView = new DataView(buf);
let content = '';
// 安全地读取字符
for (let i = 0; i < Math.floor(fileSize / 2); i++) {
content += String.fromCharCode(dataView.getUint16(i * 2, true));
}
if (content && content.length > 0) {
try {
// 解析JSON内容并添加显式类型标注
const jsonText: string = content;
// 使用Record<string, string>类型替代any
const parsed: Record<string, string> = JSON.parse(jsonText);
if (parsed && typeof parsed === 'object') {
// 直接访问并检查属性
if (parsed.username !== undefined && typeof parsed.username === 'string') {
this.username = parsed.username;
}
if (parsed.password !== undefined && typeof parsed.password === 'string') {
this.password = parsed.password;
}
this.isRememberPassword = true;
logManager.info(LogCategory.SYSTEM, LogEventType.SYSTEM_INFO, "已加载保存的凭证");
}
} catch {
logManager.error(LogCategory.SYSTEM, "解析凭证失败");
}
} else {
// 文件存在但内容为空
logManager.info(LogCategory.SYSTEM, LogEventType.SYSTEM_INFO, "凭证文件存在但为空");
}
} else {
fileIo.closeSync(file.fd);
logManager.info(LogCategory.SYSTEM, LogEventType.SYSTEM_INFO, "凭证文件为空");
}
} catch {
logManager.error(LogCategory.SYSTEM, "读取凭证文件失败");
}
} else {
// 文件不存在
logManager.info(LogCategory.SYSTEM, LogEventType.SYSTEM_INFO, "凭证文件不存在");
}
} catch {
// 文件不存在或无法访问
logManager.info(LogCategory.SYSTEM, LogEventType.SYSTEM_INFO, "未找到保存的凭证");
}
}
// 检查是否启用记住密码但没有凭据
private checkRememberPasswordStatus(): void {
// 当用户勾选记住密码但没有已保存的凭据时显示提示
if (this.isRememberPassword && (!this.username || !this.password)) {
promptAction.showToast({
message: '当前没有保存的密码',
duration: 2000
});
}
}
// 确保文件存在,不存在则创建
private ensureFileExists(): void {
try {
// 检查文件是否存在
if (!fileIo.accessSync(this.userpassFilePath)) {
// 创建空文件
const file = fileIo.openSync(this.userpassFilePath, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY);
fileIo.closeSync(file.fd);
logManager.info(LogCategory.SYSTEM, LogEventType.SYSTEM_INFO, "已创建凭证文件");
}
} catch {
// 文件不存在,创建新文件
try {
const file = fileIo.openSync(this.userpassFilePath, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY);
fileIo.closeSync(file.fd);
logManager.info(LogCategory.SYSTEM, LogEventType.SYSTEM_INFO, "已创建凭证文件");
} catch {
logManager.error(LogCategory.SYSTEM, "创建凭证文件失败");
}
}
}
build() {
Stack() {
@ -163,6 +321,49 @@ struct Login {
.width('100%')
}
// 记住密码选项
Row() {
Checkbox()
.select(this.isRememberPassword)
.selectedColor('#2196F3')
.width(20)
.height(20)
.margin({ right: 8 })
.onChange((value: boolean) => {
this.isRememberPassword = value;
if (value) {
this.checkRememberPasswordStatus();
} else if (this.username && this.password) {
// 用户取消勾选"记住密码"选项,询问是否清除已保存的密码
AlertDialog.show({
title: '提示',
message: '是否清除已保存的密码?',
primaryButton: {
value: '取消',
action: () => {
// 用户取消,恢复勾选状态
this.isRememberPassword = true;
}
},
secondaryButton: {
value: '确定',
action: () => {
// 用户确认,清除保存的密码
this.clearUserCredentials();
}
}
});
}
})
Text('记住密码')
.fontSize(14)
.fontColor('#666666')
}
.width('100%')
.margin({ bottom: 16 })
.alignItems(VerticalAlign.Center)
// 条款同意选项
Row() {
Checkbox()
@ -286,9 +487,9 @@ struct Login {
.width(24)
.height(24)
.margin({ right: 4 })
Text('测试')
/* Text('测试')
.fontSize(16)
.fontColor('#FFFFFF')
.fontColor('#FFFFFF')*/
}
}
.width(100)
@ -312,8 +513,9 @@ struct Login {
url: 'pages/HomePage'
});
}
}).catch((error: Error) => {
logManager.error(LogCategory.USER, `Test login failed: ${error.message}`);
}).catch(() => {
// 避免使用错误对象,直接记录测试登录失败
logManager.error(LogCategory.USER, '测试登录失败');
promptAction.showToast({
message: '测试登录失败',
duration: 2000
@ -353,6 +555,23 @@ struct Login {
aboutToAppear(): void {
this.Log_LoginEvent('aboutToAppear');
// 获取应用目录中的Userpass.txt文件路径 - 使用应用程序内部文件目录而非resources
const context = getContext(this) as common.UIAbilityContext;
this.userpassFilePath = context.filesDir + "/Userpass.txt";
// 加载保存的用户凭证
this.loadUserCredentials();
// 检查是否有保存的凭据
setTimeout(() => {
if (this.isRememberPassword && (!this.username || !this.password)) {
promptAction.showToast({
message: '当前没有保存的密码',
duration: 2000
});
}
}, 500); // 短暂延迟确保加载完成
}
aboutToDisappear(): void {
@ -382,8 +601,6 @@ struct Login {
logManager.info(LogCategory.USER, LogEventType.SYSTEM_INFO, `LoginPage: ${eventName}`);
}
}
}
export { Login }

View File

@ -1,6 +1,5 @@
/**
* Copyright (c) 2025 TDCAT.CN
* Author: CC
*/
import router from '@ohos.router';