项目结构:
/**
# 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/21 20:48
# User : geovindu
# Product : DevEco Studio
# Project : MyApplication
# File : DBHelper.ets
**/
import relationalStore from '@ohos.data.relationalStore'
import dataRdb from '@ohos.data.relationalStore'
import { ValuesBucket } from '@kit.ArkData'
import { Context } from '@kit.AbilityKit'
import data_rdb from '@ohos.data.rdb';
// 数据库名称 文件地址问题 src/main/resources/rawfile/
const DB_NAME ='geovindu'
// 数据库配置
const STORE_CONFIG : relationalStore.StoreConfig= {
name: DB_NAME,
securityLevel: relationalStore.SecurityLevel.S1
};
// 表名
const TABLE_NAME = 'signInRecord'
// 图书馆表名称
const TAB_LIBRARY = "signInRecord";
// 书籍表名称
const TAB_BOOK = "book";
// 创建图书馆表的SQL语句
const CREATE_TABLE_LIBRARY = `
CREATE TABLE IF NOT EXISTS ${TAB_LIBRARY} (
id INTEGER PRIMARY KEY AUTOINCREMENT,
employeeId TEXT NOT NULL,
signInTime TEXT NOT NULL
)`;
// 创建书籍表的SQL语句
const CREATE_TABLE_BOOK = `
CREATE TABLE IF NOT EXISTS ${TAB_BOOK} (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT,
author TEXT,
libraryId INTEGER,
FOREIGN KEY (libraryId) REFERENCES ${TAB_LIBRARY}(id)
)`;
export class DBHelper {
private rdbStore: relationalStore.RdbStore | null = null
/**
* 创建数据库表
* @param {Object} context - 上下文对象
*/
createTable(context: Context) {
data_rdb.getRdbStore(context, STORE_CONFIG, 1, (err, rdbStore) => {
if (err) {
console.error('创建数据库失败:', err);
return;
}
rdbStore.executeSql(CREATE_TABLE_LIBRARY);
rdbStore.executeSql(CREATE_TABLE_BOOK);
console.info('表创建完成.');
});
}
// 初始化数据库
async initDB(context: Context) {
try {
const storeConfig: relationalStore.StoreConfig = {
name: DB_NAME,
securityLevel: relationalStore.SecurityLevel.S1
}
this.rdbStore = await relationalStore.getRdbStore(context, storeConfig)
// 创建表
const createTableSql = `
CREATE TABLE IF NOT EXISTS ${TABLE_NAME} (
id INTEGER PRIMARY KEY AUTOINCREMENT,
employeeId TEXT NOT NULL,
signInTime TEXT NOT NULL
)
`
await this.rdbStore.executeSql(createTableSql)
console.info(`初始化数据库成功:`)
}
catch (e) {
console.error(`初始化数据库失败:${e}`)
console.info(`初始化数据库失败:${e}`)
}
}
// 插入签到记录
async insertSignIn(employeeId: string, signInTime: string) {
if (!this.rdbStore) return false
const valuesBucket: ValuesBucket = {
'employeeId': employeeId,
'signInTime': signInTime
}
const rowId = await this.rdbStore.insert(TABLE_NAME, valuesBucket)
return rowId > 0
}
// 查询所有签到记录
async queryAllSignIn(): Promise<relationalStore.ResultSet | null> {
if (!this.rdbStore) return null
const querySql = `SELECT * FROM ${TABLE_NAME} ORDER BY signInTime DESC`
return await this.rdbStore.querySql(querySql)
}
}
/**
# 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/21 21:04
# User : geovindu
# Product : DevEco Studio
# Project : MyApplication
# File : SignInPage.ets
**/
import { DBHelper } from '../utils/DBHelper'
import { common } from '@kit.AbilityKit'
import router from '@ohos.router'
import prompt from '@ohos.prompt'
import promptAction from '@ohos.promptAction'
@Entry
@Component
struct SignInPage {
@State employeeId: string = '' // 员工ID输入
@State signInResult: string = '' // 签到结果提示
@State signInTime:string = new Date().toLocaleString()
// 在结构体中添加数据库实例
private dbHelper: DBHelper = new DBHelper()
private context = getContext(this) as common.UIAbilityContext
// 在页面加载时初始化数据库
aboutToAppear() {
this.dbHelper.initDB(this.context)
//this.dbHelper.createTable(this.context)
}
build() {
Column() {
Text('员工签到')
.fontSize(25)
.margin(20)
// 员工ID输入框
TextInput({ placeholder: '请输入员工ID' })
.width(300)
.height(50)
.border({ width: 1 })
.margin(10)
.onChange((value) => {
this.employeeId = value
})
// 模拟指纹识别按钮
Button('指纹签到')
.width(150)
.height(50)
.margin(20)
.onClick(() => {
if (this.employeeId === '') {
this.signInResult = '请先输入员工ID'
return
}
// 模拟指纹识别成功
this.signInResult = '签到成功!时间:' + new Date().toLocaleString()
this.signInTime = new Date().toLocaleString()
// 后续步骤添加数据保存逻辑
this.aboutToAppear()
// 保存数据到数据库
this.dbHelper.insertSignIn(this.employeeId, this.signInTime).then((success) => {
this.signInResult = success ?
`签到成功!时间:${this.signInTime}` :
'签到失败,请重试'
})
})
// 显示签到结果
Text(this.signInResult)
.fontSize(16)
.margin(10)
.fontColor('#FF0000')
Button('返回')
.onClick(() => {
router.pushUrl({ url: 'pages/Index' }).then(() => {
console.info('跳转成功')
promptAction.showToast({ message: '跳转成功' })
}).catch(() => {
promptAction.showToast({ message: '跳转失败' })
console.info('跳转失败')
});
}
)
}
.width('100%')
.height('100%')
}
}
/**
# 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/21 21:13
# User : geovindu
# Product : DevEco Studio
# Project : MyApplication
# File : HistoryPage.ets
**/
import { DBHelper } from '../utils/DBHelper'
import { common } from '@kit.AbilityKit'
import { Employee } from '../models/Employee'
import router from '@ohos.router'
import prompt from '@ohos.prompt'
import promptAction from '@ohos.promptAction'
@Entry
@Component
struct HistoryPage {
@State records: Array<Employee> = []
private dbHelper: DBHelper = new DBHelper()
private context = getContext(this) as common.UIAbilityContext
async aboutToAppear() {
await this.dbHelper.initDB(this.context)
this.queryRecords()
}
// 查询记录
async queryRecords() {
const resultSet = await this.dbHelper.queryAllSignIn()
if (!resultSet) return
this.records = []
while (resultSet.goToNextRow()) {
this.records.push(new Employee(resultSet.getLong(resultSet.getColumnIndex('id')),
resultSet.getString(resultSet.getColumnIndex('employeeId')),
resultSet.getString(resultSet.getColumnIndex('signInTime'))
))
}
resultSet.close()
}
build() {
Column() {
Text('签到历史记录')
.fontSize(25)
.margin(20)
// 列表展示记录
List({ space: 10 }) {
ForEach(this.records, (item:Employee) => {
ListItem() {
Row() {
Text(`员工ID:${item.employeeId}`)
.flexGrow(1)
Text(`时间:${item.signInTime}`)
.flexGrow(2)
}
.padding(10)
.backgroundColor('#FFFFFF')
.borderRadius(5)
}
})
}
.padding(10)
Button('返回')
.onClick(() => {
router.pushUrl({ url: 'pages/Index' }).then(() => {
console.info('跳转成功')
promptAction.showToast({ message: '跳转成功' })
}).catch(() => {
promptAction.showToast({ message: '跳转失败' })
console.info('跳转失败')
});
}
)
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
}
}
/**
# 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/21 21:14
# User : geovindu
# Product : DevEco Studio
# Project : MyApplication
# File : ExportPage.ets
**/
import { DBHelper } from '../utils/DBHelper'
import { common } from '@kit.AbilityKit'
import router from '@ohos.router'
import prompt from '@ohos.prompt'
import promptAction from '@ohos.promptAction'
@Entry
@Component
struct ExportPage {
@State exportText: string = '导出的签到数据将显示在这里...'
private dbHelper: DBHelper = new DBHelper()
private context = getContext(this) as common.UIAbilityContext
async exportData() {
await this.dbHelper.initDB(this.context)
const resultSet = await this.dbHelper.queryAllSignIn()
if (!resultSet) {
this.exportText = '无数据可导出'
return
}
let text = '签到记录导出:\n'
while (resultSet.goToNextRow()) {
text += `ID: ${resultSet.getString(resultSet.getColumnIndex('employeeId'))} 时间: ${resultSet.getString(resultSet.getColumnIndex('signInTime'))}\n`
}
resultSet.close()
this.exportText = text
}
build() {
Column() {
Text('数据导出')
.fontSize(25)
.margin(20)
Button('导出记录')
.width(150)
.height(50)
.margin(10)
.onClick(() => {
this.exportData()
})
Button('返回')
.onClick(() => {
router.pushUrl({ url: 'pages/Index' }).then(() => {
console.info('跳转成功')
promptAction.showToast({ message: '跳转成功' })
}).catch(() => {
promptAction.showToast({ message: '跳转失败' })
console.info('跳转失败')
});
}
)
TextArea({ text: this.exportText })
.width('90%')
.height(300)
.margin(10)
.border({ width: 1 })
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
}
}
/**
# 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/20 10:23
# User : geovindu
# Product : DevEco Studio
# Project : MyApplication
# File : index.ets
**/
import router from '@ohos.router'
import prompt from '@ohos.prompt'
import promptAction from '@ohos.promptAction'
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
build() {
Column() {
// 页面标题
Text('办公签到系统')
.fontSize(30)
.margin(20)
// 功能按钮区域
Column() {
Button('员工签到')
.width(200)
.height(60)
.fontSize(18)
.margin(10)
.onClick(() => {
// 后续步骤添加跳转逻辑
router.pushUrl({ url: 'pages/SignInPage' }).then(() => {
console.info('跳转成功')
promptAction.showToast({ message: '跳转成功' })
}).catch(() => {
promptAction.showToast({ message: '跳转失败' })
console.info('跳转失败')
});
})
Button('历史记录')
.onClick(() => {
router.pushUrl({ url: 'pages/HistoryPage' }).then(() => {
console.info('跳转成功')
promptAction.showToast({ message: '跳转成功' })
}).catch(() => {
console.info('跳转失败')
promptAction.showToast({ message: '跳转失败' })
});
})
.width(200)
.height(60)
.fontSize(18)
.margin(10)
Button('数据导出')
.onClick(() => {
router.pushUrl({ url: 'pages/ExportPage' }).then(() => {
console.info('跳转成功')
promptAction.showToast({ message: '跳转成功' })
}).catch(() => {
promptAction.showToast({ message: '跳转失败' })
console.info('跳转失败')
});
})
.width(200)
.height(60)
.fontSize(18)
.margin(10)
}
.margin(30)
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
}
}
输出: