HarmonyOS 用@ohos.data.rdb 用DBHelper.ets 共用调用SQLite 库,进行DAL,Model,BLL,Interface,Factory 框架模式,表为

CREATE TABLE IF NOT EXISTS signInRecord (
id INTEGER PRIMARY KEY AUTOINCREMENT,
employeeId TEXT NOT NULL,
employeeName TEXT NOT NULL,
signInTime TEXT NOT NULL
)

项目结构 :
UtilitieDB
--DBHelper.ets
DAL
--signIn.ets
Model
--signIn.ets
BLL
----signIn.ets
Interface
----IsignIn.ets
Factory
--AbstractFactory.ets

/*
# encoding: utf-8
# 版权所有  2025 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : DevEco Studio 5.1.1 HarmonyOS
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2025/7/22 19:11
# User      :  geovindu
# Product   : DevEco Studio
# Project   : MyApplication
# File      : signIn.ets
*/export interface SignInRecordDbObject {id?: number;employeeId: string;employeeName: string;signInTime: string;
}export class SignInRecord {id: number | null;employeeId: string;employeeName: string;signInTime: string;constructor(employeeId: string,employeeName: string,signInTime: string,id: number | null = null) {this.id = id;this.employeeId = employeeId;this.employeeName = employeeName;this.signInTime = signInTime;}// 转换为数据库存储的对象格式(类型安全版本)toDbObject(): SignInRecordDbObject {const dbObject: SignInRecordDbObject = {employeeId: this.employeeId,employeeName: this.employeeName,signInTime: this.signInTime};if (this.id !== null) {dbObject.id = this.id;}return dbObject;}// 从数据库对象创建模型实例(类型安全版本)static fromDbObject(dbObject: SignInRecordDbObject): SignInRecord {return new SignInRecord(dbObject.employeeId,dbObject.employeeName,dbObject.signInTime,dbObject.id !== undefined ? dbObject.id : null);}
}/*
# encoding: utf-8
# 版权所有  2025 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : DevEco Studio 5.1.1 HarmonyOS
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2025/7/22 19:04
# User      :  geovindu
# Product   : DevEco Studio
# Project   : MyApplication
# File      : DBHelper.ets
*/import relationalStore from '@ohos.data.relationalStore';
import { BusinessError } from '@ohos.base';
import { Context } from '@ohos.abilityAccessCtrl';export class DBHelper {private static readonly DB_NAME: string = 'signInDB.db';private static readonly DB_VERSION: number = 1;private rdbStore: relationalStore.RdbStore | null = null;private static instance: DBHelper | null = null;private context: Context | null = null; // 新增上下文存储private constructor() {}/**** @returns*/public static getInstance(): DBHelper {if (!DBHelper.instance) {DBHelper.instance = new DBHelper();}if (!DBHelper.instance) {throw new Error('无法创建DBHelper实例,请检查实现');}return DBHelper.instance;}/*** 初始化数据库时保存上下文* @param context* @returns*/public async initDB(context: Context): Promise<relationalStore.RdbStore> {if (this.rdbStore) {return this.rdbStore;}/*** 保存上下文供后续使用*/this.context = context;const storeConfig: relationalStore.StoreConfig = {name: DBHelper.DB_NAME,securityLevel: relationalStore.SecurityLevel.S1};try {this.rdbStore = await relationalStore.getRdbStore(context, storeConfig);await this.createTables();return this.rdbStore;} catch (error) {const err = error as BusinessError;console.error(`初始化数据库失败: ${err.code} - ${err.message}`);throw new Error(`数据库初始化失败: ${err.message}`);}}/**** @returns*/private async createTables(): Promise<void> {if (!this.rdbStore) {throw new Error('数据库未初始化,请先调用initDB方法');}const createTableSql: string = `CREATE TABLE IF NOT EXISTS signInRecord (id INTEGER PRIMARY KEY AUTOINCREMENT,employeeId TEXT NOT NULL,employeeName TEXT NOT NULL,signInTime TEXT NOT NULL)`;try {await this.rdbStore.executeSql(createTableSql);console.log('签到记录表创建成功或已存在');} catch (error) {const err = error as BusinessError;console.error(`创建签到记录表失败: ${err.code} - ${err.message}`);throw new Error(`创建数据表失败: ${err.message}`);}}/**** @returns*/public getRdbStore(): relationalStore.RdbStore | null {if (!this.rdbStore) {console.warn('数据库尚未初始化,请先调用initDB方法');}return this.rdbStore;}/*** 修正关闭数据库的方法* @returns*/public async closeDB(): Promise<void> {if (this.rdbStore && this.context) {try {// 正确调用deleteRdbStore,需要传入上下文和数据库名称await relationalStore.deleteRdbStore(this.context, DBHelper.DB_NAME);this.rdbStore = null;this.context = null; // 清除上下文console.log('数据库已关闭并删除');} catch (error) {const err = error as BusinessError;console.error(`关闭数据库失败: ${err.code} - ${err.message}`);throw new Error(`关闭数据库失败: ${err.message}`);}} else {if (!this.context) {console.warn('上下文不存在,无法关闭数据库');} else {console.warn('数据库连接不存在,无需关闭');}}}
}/*
# encoding: utf-8
# 版权所有  2025 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : DevEco Studio 5.1.1 HarmonyOS
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2025/7/22 19:14
# User      :  geovindu
# Product   : DevEco Studio
# Project   : MyApplication
# File      : IsignIn.ets
*/import { SignInRecord } from '../model/signIn';export interface ISignIn {/*** 添加签到记录* @param record* @returns*/addSignInRecord(record: SignInRecord): Promise<number>;/*** 根据ID获取签到记录* @param id* @returns*/getSignInRecordById(id: number): Promise<SignInRecord | null>;/*** 获取所有签到记录* @returns*/getAllSignInRecords(): Promise<SignInRecord[]>;/*** 根据员工ID获取签到记录* @param employeeId* @returns*/getSignInRecordsByEmployeeId(employeeId: string): Promise<SignInRecord[]>;/*** 更新签到记录* @param record* @returns*/updateSignInRecord(record: SignInRecord): Promise<number>;/*** 删除签到记录* @param id* @returns*/deleteSignInRecord(id: number): Promise<number>;
}/*
# encoding: utf-8
# 版权所有  2025 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : DevEco Studio 5.1.1 HarmonyOS
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2025/7/22 19:16
# User      :  geovindu
# Product   : DevEco Studio
# Project   : MyApplication
# File      : AbstractFactory.ets
*/
import { ISignIn } from '../Interface/IsignIn';
import { SignInDAL } from '../DAL/signIn';
import { SignInBLL } from '../BLL/signIn';/*** 抽象工厂类*/
export abstract class AbstractFactory {// 创建数据访问层实例public abstract createSignInDAL(): ISignIn;// 创建业务逻辑层实例public abstract createSignInBLL(): ISignIn;
}/*** 签到记录工厂类*/
export class SignInFactory extends AbstractFactory {// 创建签到记录数据访问层实例public createSignInDAL(): ISignIn {return new SignInDAL();}/*** 创建签到记录业务逻辑层实例* @returns*/public createSignInBLL(): ISignIn {// 可以在这里注入不同的DAL实现,方便测试或切换数据源const dal = this.createSignInDAL();return new SignInBLL(dal);}
}/*
# encoding: utf-8
# 版权所有  2025 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : DevEco Studio 5.1.1 HarmonyOS
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2025/7/22 19:17
# User      :  geovindu
# Product   : DevEco Studio
# Project   : MyApplication
# File      : signIn.ets
*/
import relationalStore from '@ohos.data.relationalStore';
import { DBHelper } from '../UtilitieDB/DBHelper';
import { SignInRecord, SignInRecordDbObject } from '../model/signIn';
import { ISignIn } from '../Interface/IsignIn';
import { BusinessError } from '@ohos.base';// 定义与数据库字段对应的类型映射
type SignInColumn = 'id' | 'employeeId' | 'employeeName' | 'signInTime';export class SignInDAL implements ISignIn {private getRdbStore() {const rdbStore = DBHelper.getInstance().getRdbStore();if (!rdbStore) {throw new Error('数据库未初始化,请先调用initDB方法');}return rdbStore;}/*** 添加签到记录* @param record* @returns*/async addSignInRecord(record: SignInRecord): Promise<number> {try {const dbObject = record.toDbObject();// 构建符合要求的ValuesBucketconst valuesBucket: relationalStore.ValuesBucket = {'employeeId': dbObject.employeeId,'employeeName': dbObject.employeeName,'signInTime': dbObject.signInTime};const rowId = await this.getRdbStore().insert('signInRecord', valuesBucket);return rowId;} catch (error) {const err = error as BusinessError;console.error(`添加签到记录失败: ${err.code} - ${err.message}`);throw new Error(`添加签到记录失败: ${err.message}`);}}/*** 根据ID获取签到记录* @param id* @returns*/async getSignInRecordById(id: number): Promise<SignInRecord | null> {try {const predicates = new relationalStore.RdbPredicates('signInRecord');predicates.equalTo('id', id);const resultSet = await this.getRdbStore().query(predicates, ['*']);let record: SignInRecord | null = null;if (await resultSet.goToFirstRow()) {const dbObject: SignInRecordDbObject = {id: resultSet.getLong(resultSet.getColumnIndex('id')),employeeId: resultSet.getString(resultSet.getColumnIndex('employeeId')),employeeName: resultSet.getString(resultSet.getColumnIndex('employeeName')),signInTime: resultSet.getString(resultSet.getColumnIndex('signInTime'))};record = SignInRecord.fromDbObject(dbObject);}await resultSet.close();return record;} catch (error) {const err = error as BusinessError;console.error(`查询签到记录失败: ${err.code} - ${err.message}`);throw new Error(`查询签到记录失败: ${err.message}`);}}/*** 根据员工ID获取签到记录* @param employeeId* @returns*/async getSignInRecordsByEmployeeId(employeeId: string): Promise<SignInRecord[]> {try {const predicates = new relationalStore.RdbPredicates('signInRecord');predicates.equalTo('employeeId', employeeId).orderByDesc('signInTime');const resultSet = await this.getRdbStore().query(predicates, ['*']);const records: SignInRecord[] = [];while (await resultSet.goToNextRow()) {const dbObject: SignInRecordDbObject = {id: resultSet.getLong(resultSet.getColumnIndex('id')),employeeId: resultSet.getString(resultSet.getColumnIndex('employeeId')),employeeName: resultSet.getString(resultSet.getColumnIndex('employeeName')),signInTime: resultSet.getString(resultSet.getColumnIndex('signInTime'))};records.push(SignInRecord.fromDbObject(dbObject));}await resultSet.close();return records;} catch (error) {const err = error as BusinessError;console.error(`根据员工ID查询签到记录失败: ${err.code} - ${err.message}`);throw new Error(`根据员工ID查询签到记录失败: ${err.message}`);}}/*** 获取所有签到记录* @returns*/async getAllSignInRecords(): Promise<SignInRecord[]> {try {const predicates = new relationalStore.RdbPredicates('signInRecord');predicates.orderByDesc('signInTime');const resultSet = await this.getRdbStore().query(predicates, ['*']);const records: SignInRecord[] = [];while (await resultSet.goToNextRow()) {const dbObject: SignInRecordDbObject = {id: resultSet.getLong(resultSet.getColumnIndex('id')),employeeId: resultSet.getString(resultSet.getColumnIndex('employeeId')),employeeName: resultSet.getString(resultSet.getColumnIndex('employeeName')),signInTime: resultSet.getString(resultSet.getColumnIndex('signInTime'))};records.push(SignInRecord.fromDbObject(dbObject));}await resultSet.close();return records;} catch (error) {const err = error as BusinessError;console.error(`获取所有签到记录失败: ${err.code} - ${err.message}`);throw new Error(`获取所有签到记录失败: ${err.message}`);}}/*** 更新签到记录* @param record* @returns*/async updateSignInRecord(record: SignInRecord): Promise<number> {if (record.id === null) {throw new Error('更新失败,签到记录ID不能为空');}try {const dbObject = record.toDbObject();const predicates = new relationalStore.RdbPredicates('signInRecord');predicates.equalTo('id', record.id); // 这里已经指定了要更新的记录ID// 构建ValuesBucket,不包含id字段,因为不需要更新主键const valuesBucket: relationalStore.ValuesBucket = {'employeeId': dbObject.employeeId,'employeeName': dbObject.employeeName,'signInTime': dbObject.signInTime};// 执行更新操作const rowsUpdated = await this.getRdbStore().update(valuesBucket, predicates);return rowsUpdated;} catch (error) {const err = error as BusinessError;console.error(`更新签到记录失败: ${err.code} - ${err.message}`);throw new Error(`更新签到记录失败: ${err.message}`);}}/*** 删除签到记录* @param id* @returns*/async deleteSignInRecord(id: number): Promise<number> {try {const predicates = new relationalStore.RdbPredicates('signInRecord');predicates.equalTo('id', id);const rowsDeleted = await this.getRdbStore().delete(predicates);return rowsDeleted;} catch (error) {const err = error as BusinessError;console.error(`删除签到记录失败: ${err.code} - ${err.message}`);throw new Error(`删除签到记录失败: ${err.message}`);}}/*** 将结果集转换为签到记录数组* @param resultSet* @returns*/private convertResultSetToSignInRecords(resultSet: relationalStore.ResultSet): SignInRecord[] {const records: SignInRecord[] = [];resultSet.goToFirstRow();do {const record = this.convertResultSetToSignInRecord(resultSet);records.push(record);} while (resultSet.goToNextRow());return records;}/*** 结果集转换为单个签到记录* @param resultSet* @returns*/private convertResultSetToSignInRecord(resultSet: relationalStore.ResultSet): SignInRecord {return new SignInRecord(resultSet.getString(resultSet.getColumnIndex('employeeId')),resultSet.getString(resultSet.getColumnIndex('employeeName')),resultSet.getString(resultSet.getColumnIndex('signInTime')),resultSet.getLong(resultSet.getColumnIndex('id')));}}/*
# encoding: utf-8
# 版权所有  2025 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : DevEco Studio 5.1.1 HarmonyOS
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2025/7/22 18:18
# User      :  geovindu
# Product   : DevEco Studio
# Project   : MyApplication
# File      : signIn.ets
*/
import { ISignIn } from '../Interface/IsignIn';
import { SignInRecord } from '../model/signIn';
import { SignInDAL } from '../DAL/signIn';export class SignInBLL implements ISignIn {private signInDAL: ISignIn;constructor(signInDAL: ISignIn = new SignInDAL()) {this.signInDAL = signInDAL;}/*** 添加签到记录,包含业务逻辑验证* @param record* @returns*/async addSignInRecord(record: SignInRecord): Promise<number> {// 业务逻辑验证:检查必要字段if (!record.employeeId || record.employeeId.trim() === '') {throw new Error('员工ID不能为空');}if (!record.employeeName || record.employeeName.trim() === '') {throw new Error('员工姓名不能为空');}// 检查签到时间格式是否合法if (!this.isValidDateTime(record.signInTime)) {throw new Error('签到时间格式不正确');}// 调用数据访问层添加记录return this.signInDAL.addSignInRecord(record);}/*** 根据ID获取签到记录* @param id* @returns*/async getSignInRecordById(id: number): Promise<SignInRecord | null> {if (id <= 0) {throw new Error('无效的记录ID');}return this.signInDAL.getSignInRecordById(id);}/*** 获取所有签到记录* @returns*/async getAllSignInRecords(): Promise<SignInRecord[]> {return this.signInDAL.getAllSignInRecords();}/*** 根据员工ID获取签到记录* @param employeeId* @returns*/async getSignInRecordsByEmployeeId(employeeId: string): Promise<SignInRecord[]> {if (!employeeId || employeeId.trim() === '') {throw new Error('员工ID不能为空');}return this.signInDAL.getSignInRecordsByEmployeeId(employeeId);}/*** 更新签到记录* @param record* @returns*/async updateSignInRecord(record: SignInRecord): Promise<number> {if (!record.id) {throw new Error('签到记录ID不能为空');}/*** 验证更新的数据*/if (!record.employeeId || record.employeeId.trim() === '') {throw new Error('员工ID不能为空');}if (!this.isValidDateTime(record.signInTime)) {throw new Error('签到时间格式不正确');}return this.signInDAL.updateSignInRecord(record);}/*** 删除签到记录* @param id* @returns*/async deleteSignInRecord(id: number): Promise<number> {if (id <= 0) {throw new Error('无效的记录ID');}return this.signInDAL.deleteSignInRecord(id);}// 验证日期时间格式 (YYYY-MM-DD HH:MM:SS)private isValidDateTime(dateTime: string): boolean {const regex = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;return regex.test(dateTime);}
}/*
# encoding: utf-8
# 版权所有  2025 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : DevEco Studio 5.1.1 HarmonyOS
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2025/7/22 18:56
# User      :  geovindu
# Product   : DevEco Studio
# Project   : MyApplication
# File      : SignInExample.ets
*/
import { Context } from '@ohos.abilityAccessCtrl';
import { SignInFactory } from '../Factory/AbstractFactory';
import { DBHelper } from '../UtilitieDB/DBHelper';
import { SignInRecord } from '../model/signIn';
import { ISignIn } from '../Interface/IsignIn';export class SignInExample {private signInBLL: ISignIn;constructor(context: Context) {// 初始化数据库this.initDatabase(context);// 通过工厂获取BLL实例const factory = new SignInFactory();this.signInBLL = factory.createSignInBLL();}/*** 初始化数据库* @param context*/private async initDatabase(context: Context) {try {await DBHelper.getInstance().initDB(context);console.log('数据库初始化成功');} catch (error) {console.error('数据库初始化失败:', error);}}/*** 添加签到记录示例* @returns*/async addSignInRecordExample() {try {// 创建签到记录对象const now = new Date();const signInTime = `${now.getFullYear()}-${(now.getMonth() + 1).toString().padStart(2, '0')}-${now.getDate().toString().padStart(2, '0')} ${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`;const record = new SignInRecord('EMP001',       // employeeId'张三',          // employeeNamesignInTime       // signInTime);// 调用BLL层添加记录const rowId = await this.signInBLL.addSignInRecord(record);console.log(`添加签到记录成功,ID: ${rowId}`);return rowId;} catch (error) {console.error('添加签到记录失败:', error);return null;}}/*** 查询签到记录示例*/async querySignInRecordsExample() {try {// 1. 查询所有签到记录const allRecords = await this.signInBLL.getAllSignInRecords();console.log(`所有签到记录(${allRecords.length}条):`, allRecords);// 2. 根据ID查询记录(假设我们知道一个存在的ID)if (allRecords.length > 0) {const firstRecordId = allRecords[0].id;if (firstRecordId !== null) {const singleRecord = await this.signInBLL.getSignInRecordById(firstRecordId);console.log(`ID为${firstRecordId}的签到记录:`, singleRecord);}}// 3. 根据员工ID查询记录const empRecords = await this.signInBLL.getSignInRecordsByEmployeeId('EMP001');console.log(`员工EMP001的签到记录(${empRecords.length}条):`, empRecords);return allRecords;} catch (error) {console.error('查询签到记录失败:', error);return null;}}/**** @param id* @returns*/async querySignInRecordsExampleId(id:string) {try {// 1. 查询所有签到记录const allRecords = await this.signInBLL.getSignInRecordsByEmployeeId(id);console.log(`所有签到记录(${allRecords.length}条):`, allRecords);// 2. 根据ID查询记录(假设我们知道一个存在的ID)if (allRecords.length > 0) {const firstRecordId = allRecords[0].id;if (firstRecordId !== null) {const singleRecord = await this.signInBLL.getSignInRecordById(firstRecordId);console.log(`ID为${firstRecordId}的签到记录:`, singleRecord);}}// 3. 根据员工ID查询记录const empRecords = await this.signInBLL.getSignInRecordsByEmployeeId('EMP001');console.log(`员工EMP001的签到记录(${empRecords.length}条):`, empRecords);return allRecords;} catch (error) {console.error('查询签到记录失败:', error);return null;}}/*** 更新签到记录示例* @param recordId*/async updateSignInRecordExample(recordId: number) {try {// 先查询要更新的记录const record = await this.signInBLL.getSignInRecordById(recordId);if (!record) {console.log(`未找到ID为${recordId}的签到记录`);return -1;}// 修改记录内容record.employeeName = '张三(更新)'; // 修改员工姓名// 调用BLL层更新记录const rowsUpdated = await this.signInBLL.updateSignInRecord(record);console.log(`更新成功,影响行数: ${rowsUpdated}`);// 验证更新结果const updatedRecord = await this.signInBLL.getSignInRecordById(recordId);console.log('更新后的记录:', updatedRecord);return 1;} catch (error) {console.error('更新签到记录失败:', error);return -1;}}/*** 删除签到记录示例* @param recordId*/async deleteSignInRecordExample(recordId: number) {try {// 调用BLL层删除记录const rowsDeleted = await this.signInBLL.deleteSignInRecord(recordId);console.log(`删除成功,影响行数: ${rowsDeleted}`);// 验证删除结果const deletedRecord = await this.signInBLL.getSignInRecordById(recordId);if (!deletedRecord) {console.log(`ID为${recordId}的签到记录已成功删除`);}return 1;} catch (error) {console.error('删除签到记录失败:', error);return -1;}}/*** 完整操作流程示例*/async completeOperationFlow() {// 1. 添加一条新记录const newRecordId = await this.addSignInRecordExample();if (newRecordId) {// 2. 查询记录await this.querySignInRecordsExample();// 3. 更新记录await this.updateSignInRecordExample(newRecordId);// 4. 删除记录await this.deleteSignInRecordExample(newRecordId);}// 关闭数据库(通常在应用退出时调用)// await DBHelper.getInstance().closeDB();}
}// 在Ability中使用示例
// export default class SignInAbility extends Ability {
//   onWindowStageCreate(windowStage: window.WindowStage) {
//     // 初始化示例并执行操作
//     const signInExample = new SignInExample(this.context);
//     signInExample.completeOperationFlow();
//   }
// }

调用:

/**# encoding: utf-8# 版权所有 2024 ©涂聚文有限公司# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎# 描述:# Author    : geovindu,Geovin Du 涂聚文.# IDE       : DevEco Studio 5.1.1# OS        : windows 10# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j# Datetime  : 2025/7/22 19:33# User      : geovindu# Product   : MyApplicatin# Project   : MyApplicatin# File      : Register.ets* */import router from '@ohos.router'
import promptAction from '@ohos.promptAction'
import { SignInExample } from '../Controller/SignInExample';
import { SignInRecord } from '../model/signIn';
import { Context } from '@ohos.abilityAccessCtrl';@Entry
@Component
struct Register {@State message: string = '注册用户';// 页面数据@State allRecords: SignInRecord[] = [];@State employeeId: string = 'EMP001';@State employeeName: string = '张三';@State currentRecordId: number | null = null;// 页面上下文(用于数据库初始化)private context: Context = getContext(this) as Context;// 签到业务实例private signInExample: SignInExample = new SignInExample(this.context);// 页面加载时初始化数据async aboutToAppear() {await this.loadAllRecords(); // 加载所有签到记录}// 加载所有签到记录// 修正后的加载所有签到记录方法async loadAllRecords() {try {// 调用查询方法并获取结果const result = await this.signInExample.querySignInRecordsExample();// 空值判断:如果结果为null,设置为空数组if (result === null) {this.allRecords = [];promptAction.showToast({ message: '没有查询到签到记录' });return;}// 类型判断:确保返回的是数组if (!Array.isArray(result)) {this.allRecords = [];promptAction.showToast({ message: '数据格式错误' });console.error('查询签到记录返回非数组类型:', result);return;}// 正常赋值this.allRecords = result;// 空数组提示if (this.allRecords.length === 0) {promptAction.showToast({ message: '当前没有签到记录' });}} catch (error) {// 错误处理:统一捕获并处理所有可能的异常this.allRecords = []; // 出错时清空列表const errorMsg = error instanceof Error ? error.message : String(error);promptAction.showToast({ message: `加载失败: ${errorMsg}` });console.error('加载签到记录失败:', error);}}/*** 添加签到记录(绑定按钮点击事件)*/async handleAdd() {if (!this.employeeId || !this.employeeName) {promptAction.showToast({ message: '请输入员工ID和姓名' });return;}try {// 生成当前时间(格式:yyyy-MM-dd HH:mm:ss)const now = new Date();const signInTime = `${now.getFullYear()}-${(now.getMonth() + 1).toString().padStart(2, '0')}-${now.getDate().toString().padStart(2, '0')} ${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`;// 创建记录并添加const record = new SignInRecord(this.employeeId, this.employeeName, signInTime);const newId = await this.signInExample.addSignInRecordExample(); //recordpromptAction.showToast({ message: `添加成功,ID: ${newId}` });// 刷新列表await this.loadAllRecords();} catch (error) {promptAction.showToast({ message: `添加失败: ${error.message}` });}}/*** 更新签到记录(绑定按钮点击事件)* @param record*/async handleUpdate(record: SignInRecord) {if (!record.id) {promptAction.showToast({ message: '记录ID不存在' });return;}try {// 修改记录(示例:在姓名后加"[已更新]")const updatedRecord = new SignInRecord(record.employeeId,`${record.employeeName}[已更新]`,record.signInTime,record.id);// 执行更新const rows = await this.signInExample.updateSignInRecordExample(1) //(updatedRecord);if (rows > 0) {promptAction.showToast({ message: '更新成功' });await this.loadAllRecords(); // 刷新列表}} catch (error) {promptAction.showToast({ message: `更新失败: ${error.message}` });}}/*** 删除签到记录(绑定按钮点击事件)* @param id*/async handleDelete(id: number) {try {const rows = await this.signInExample.deleteSignInRecordExample(id);if (rows > 0) {promptAction.showToast({ message: '删除成功' });await this.loadAllRecords(); // 刷新列表}} catch (error) {promptAction.showToast({ message: `删除失败: ${error.message}` });}}/*** 根据员工ID查询(绑定按钮点击事件)*/async handleQueryByEmpId() {// 验证员工ID输入if (!this.employeeId || this.employeeId.trim() === '') {promptAction.showToast({ message: '请输入有效的员工ID' });return;}try {// 调用BLL层方法查询(修正方法名和调用方式)const result = await this.signInExample.querySignInRecordsExampleId(this.employeeId.trim());// 空值判断if (result === null) {this.allRecords = [];promptAction.showToast({ message: '未查询到相关记录' });return;}// 类型验证if (!Array.isArray(result)) {this.allRecords = [];promptAction.showToast({ message: '查询数据格式错误' });console.error('员工签到记录查询返回非数组类型:', result);return;}// 赋值并提示结果this.allRecords = result;// 根据结果数量显示不同提示if (this.allRecords.length === 0) {promptAction.showToast({ message: `未查询到员工${this.employeeId}的签到记录` });} else {promptAction.showToast({ message: `查询到${this.allRecords.length}条记录` });}} catch (error) {// 错误处理this.allRecords = [];const errorMsg = error instanceof Error ? error.message : String(error);promptAction.showToast({ message: `查询失败: ${errorMsg}` });console.error(`查询员工${this.employeeId}的签到记录失败:`, error);}}// 界面渲染build() {Column() {// 操作区域Column() {Text('签到管理').fontSize(20).fontWeight(FontWeight.Bold).margin(10);// 输入区域Row() {Button('添加签到').onClick(() => this.handleAdd()).backgroundColor('#007DFF');Button('查询该员工').onClick(() => this.handleQueryByEmpId()).backgroundColor('#00B42A');Button('查询所有').onClick(() => this.loadAllRecords()).backgroundColor('#F53F3F');Button('返回').onClick(() => {router.back();}).backgroundColor('#F53F3F');}.margin(10);// 记录列表Scroll() {List() {ForEach(this.allRecords, (record: SignInRecord) => {ListItem() {Row() {Column() {Text(`ID: ${record.id}`).fontSize(12);Text(`员工: ${record.employeeName}(${record.employeeId})`).fontSize(14);Text(`签到时间: ${record.signInTime}`).fontSize(12);}.width('70%');Column() {Button('修改').onClick(() => this.handleUpdate(record)).width(80).margin(5).backgroundColor('#FF7D00');Button('删除').onClick(() => this.handleDelete(record.id!)).width(80).margin(5).backgroundColor('#F53F3F');}}.padding(10);}})}}.width('100%').flexGrow(1);}.width('100%').height('100%');}.width('100%').height('100%');}
}

输出:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/92458.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/92458.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/92458.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL JSON 数据类型用法及与传统JSON字符串的对比 JSON数据类型简介

文章目录前言1. 基本用法JSON数据类型 vs 传统JSON字符串1. 存储方式2. 查询方式对比3. 索引支持JSON存储对象和数组的性能考虑1. 存储对象2. 存储数组性能对比总结最佳实践建议前言 MySQL从 5.7 版本开始引入了 JSON 数据类型&#xff0c;专门用于存储 JSON 格式的数据。与传…

C++:list(1)list的使用

list的使用一.list基本的结构1.环状双向链表2.哨兵节点3.迭代器4.节点结构5.链表遍历6.迭代器失效二.list的基本使用1.test01函数&#xff1a;主要测试std::list的初始化方式及遍历2.test02函数&#xff1a;主要测试std::list的常用成员函数操作3.测试结果如下三.list的其他操作…

ArcGIS地形起伏度计算

地形起伏度计算地形起伏度步骤1&#xff1a;计算最大值。步骤2&#xff1a;计算最小值。步骤3&#xff1a;计算地形起伏度。地形起伏度、地形粗糙度、地表切割深度和高程变异系数均为坡面复杂度因子&#xff0c;是一种宏观的地形信息因子&#xff0c;反映的是较大的区域内地表坡…

llama factory新手初步运行完整版

1、新建conda环境名称为llama_factory&#xff0c;并激活 conda create -n llama_factory python3.10 conda activate llama_factory2、激活后可检查内部包是否纯净&#xff0c;要确保环境内包较纯净&#xff0c;不然后续安装对应包会出现一系列水土不服的问题&#xff0c;导致…

Tomcat与JDK版本对照全解析:避坑指南与生产环境选型最佳实践

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 持续学习&#xff0c;不断…

短视频矩阵的未来前景:机遇无限,挑战并存

在当今数字化信息飞速传播的时代&#xff0c;短视频以其独特的魅力迅速席卷全球&#xff0c;成为人们获取信息、娱乐消遣的重要方式之一。短视频矩阵作为一种高效的内容传播与运营模式&#xff0c;正逐渐展现出其强大的影响力和潜力。本文将深入探讨短视频矩阵的未来前景&#…

【数据结构】哈希——位图与布隆过滤器

目录 位图&#xff1a; 引入 位图实现&#xff1a; 位图的结构 插入数据(标记数据) 删除数据(重置数据) 查找数据 位图完整代码&#xff1a; 位图的优缺点&#xff1a; 布隆过滤器&#xff1a; 引入 布隆过滤器实现&#xff1a; 布隆过滤器的结构&#xff1a; 插入…

本地运行C++版StableDiffusion!开源应用StableVerce发布

本地运行C版StableDiffusion&#xff01;开源应用StableVerce发布 StableVerse是一个用C开发的本地运行的图形工具。适合初学者快速入门&#xff1b;适用于办公室工作人员的文本和图像制作的小规模计算能力场景。 开源地址&#xff1a;https://github.com/kelvin-luo/StableVer…

OpenLayers 快速入门(七)矢量数据

看过的知识不等于学会。唯有用心总结、系统记录&#xff0c;并通过温故知新反复实践&#xff0c;才能真正掌握一二 作为一名摸爬滚打三年的前端开发&#xff0c;开源社区给了我饭碗&#xff0c;我也将所学的知识体系回馈给大家&#xff0c;助你少走弯路&#xff01; OpenLayers…

【PTA数据结构 | C语言版】关于堆的判断

本专栏持续输出数据结构题目集&#xff0c;欢迎订阅。 文章目录题目代码题目 将一系列给定数字顺序插入一个初始为空的最小堆。随后判断一系列相关命题是否为真。命题分下列几种&#xff1a; x is the root&#xff1a;x是根结点&#xff1b;x and y are siblings&#xff1a…

[CH582M入门第十步]蓝牙从机

前言 学习目标: 1、初步了解BLE协议 2、BLE从机代码解析 3、使用手机蓝牙软件控制CH582M从机LED亮灭一、蓝牙介绍 蓝牙(Bluetooth)是一种短距离无线通信技术,主要用于设备之间的数据传输和通信。它由爱立信(Ericsson)于1994年提出,现由蓝牙技术联盟(Bluetooth SIG)维…

力扣(LeetCode) ——轮转数组(C语言)

题目&#xff1a;轮转数组 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 示例1&#xff1a; 输入&#xff1a; nums [1,2,3,4,5,6,7]&#xff0c;k 3 输出&#xff1a; [5,6,7,1,2,3,4] 解释&#xff1a; 向右轮转 1 步:…

Rocky9部署Zabbix7(小白的“升级打怪”成长之路)

目录 一、关闭防火墙和SElinux和配置安装源 二、zabbxi服务器配置 1、安装Zabbix server&#xff0c;Web前端&#xff0c;agent &#xff0c;mysql-server 2、配置mysql数据库 3、为Zabbix server配置数据库 4、启动对应服务 三、登录zabbix 四、客户端部署 五、解决中…

python安装package和pycharm更改环境变量

安装numpy包 1、找到对应python版本的numpy包的版本 NumPy - News确认适配python版本的numpy&#xff0c;我安装 的python是3.11所以安装的numpy是2.2.0 2、修改pip安装的镜像源 1、全局修改&#xff1a; pip config set global.index-url https://pypi.tuna.tsinghua.edu.c…

Redis中的setnx命令为什么是原子性的

Redis的SETNX命令是一个原子性操作&#xff0c;这得益于其单线程架构的特性。Redis采用单线程模型&#xff0c;所有命令都在主线程中顺序执行&#xff0c;确保每个操作都具有原子性。执行SETNX时&#xff0c;Redis会首先检查指定key是否存在&#xff1a;若不存在则设置值并返回…

深入解析Hadoop中的EditLog与FsImage持久化设计及Checkpoint机制

HDFS元数据管理概述在HDFS&#xff08;Hadoop Distributed File System&#xff09;的架构中&#xff0c;元数据管理是保证系统可靠性和性能的核心环节。NameNode作为HDFS的主节点&#xff0c;负责维护整个文件系统的命名空间和文件到数据块的映射关系。这些元数据的高效管理直…

MFC类Qt的自动布局框架

由于作者习惯使用Qt&#xff0c;习惯了其框架下的水平和垂直布局。但在使用MFC时&#xff0c;却发现并没有十分好用的布局框架&#xff0c;检索了部分资料&#xff0c;发现要么不提供源码&#xff0c;要么方案不理想。搜索了很多资料&#xff0c;最终发现一个可用方案&#xff…

认识Transformer架构

一.前言前面我们介绍了RNN相关系列的模型&#xff0c;在当今大模型时代大家认识一下就好了&#xff0c;而本章节我们是要来介绍一下重中之重的Transformer模型&#xff0c;本章节就来介绍一下他的架构&#xff0c;了解Transformer模型的作⽤以及了解Transformer总体架构图中各个…

Python学习之存数据

在得到了对应的数据之后可以考虑用文件或者数据库的方式把内容持久化下来方便之后的分析&#xff0c;此时可以使用pymongo库&#xff0c;寥寥几行代码&#xff0c;数据就已经很好地存储下来。&#xff08;此处可参考我们之前发的文章)在 Python 中引入&#xff1a;import pymon…

PointLLM - ECCV 2024 Best Paper Candidate

https://github.com/OpenRobotLab/PointLLM PointLLM: Empowering Large Language Models to Understand Point Clouds 核心问题 对比两种让大型语言模型&#xff08;LLM&#xff09;“看懂”三维世界的方法 间接方法&#xff1a;通过2D图像进行猜测。 这是目前比较常见但充…