feat 配置SQlite
This commit is contained in:
@@ -20,7 +20,9 @@ export default defineManifestConfig({
|
|||||||
},
|
},
|
||||||
screenOrientation: ['landscape-primary'],
|
screenOrientation: ['landscape-primary'],
|
||||||
/* 模块配置 */
|
/* 模块配置 */
|
||||||
modules: {},
|
modules: {
|
||||||
|
SQLite: {},
|
||||||
|
},
|
||||||
/* 应用发布信息 */
|
/* 应用发布信息 */
|
||||||
distribute: {
|
distribute: {
|
||||||
/* android打包配置 */
|
/* android打包配置 */
|
||||||
|
|||||||
14
src/auto-imports.d.ts
vendored
14
src/auto-imports.d.ts
vendored
@@ -9,6 +9,7 @@ declare global {
|
|||||||
const EffectScope: typeof import('vue')['EffectScope']
|
const EffectScope: typeof import('vue')['EffectScope']
|
||||||
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
|
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
|
||||||
const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
|
const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
|
||||||
|
const closeDatabase: typeof import('./utils/sqlite')['closeDatabase']
|
||||||
const computed: typeof import('vue')['computed']
|
const computed: typeof import('vue')['computed']
|
||||||
const computedAsync: typeof import('@vueuse/core')['computedAsync']
|
const computedAsync: typeof import('@vueuse/core')['computedAsync']
|
||||||
const computedEager: typeof import('@vueuse/core')['computedEager']
|
const computedEager: typeof import('@vueuse/core')['computedEager']
|
||||||
@@ -33,11 +34,13 @@ declare global {
|
|||||||
const defineComponent: typeof import('vue')['defineComponent']
|
const defineComponent: typeof import('vue')['defineComponent']
|
||||||
const eagerComputed: typeof import('@vueuse/core')['eagerComputed']
|
const eagerComputed: typeof import('@vueuse/core')['eagerComputed']
|
||||||
const effectScope: typeof import('vue')['effectScope']
|
const effectScope: typeof import('vue')['effectScope']
|
||||||
|
const executeSql: typeof import('./utils/sqlite')['executeSql']
|
||||||
const extendRef: typeof import('@vueuse/core')['extendRef']
|
const extendRef: typeof import('@vueuse/core')['extendRef']
|
||||||
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
|
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
|
||||||
const getCurrentScope: typeof import('vue')['getCurrentScope']
|
const getCurrentScope: typeof import('vue')['getCurrentScope']
|
||||||
const h: typeof import('vue')['h']
|
const h: typeof import('vue')['h']
|
||||||
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
|
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
|
||||||
|
const initTables: typeof import('./utils/sqlite')['initTables']
|
||||||
const inject: typeof import('vue')['inject']
|
const inject: typeof import('vue')['inject']
|
||||||
const injectLocal: typeof import('@vueuse/core')['injectLocal']
|
const injectLocal: typeof import('@vueuse/core')['injectLocal']
|
||||||
const isDefined: typeof import('@vueuse/core')['isDefined']
|
const isDefined: typeof import('@vueuse/core')['isDefined']
|
||||||
@@ -91,6 +94,7 @@ declare global {
|
|||||||
const onUnmounted: typeof import('vue')['onUnmounted']
|
const onUnmounted: typeof import('vue')['onUnmounted']
|
||||||
const onUpdated: typeof import('vue')['onUpdated']
|
const onUpdated: typeof import('vue')['onUpdated']
|
||||||
const onWatcherCleanup: typeof import('vue')['onWatcherCleanup']
|
const onWatcherCleanup: typeof import('vue')['onWatcherCleanup']
|
||||||
|
const openDatabase: typeof import('./utils/sqlite')['openDatabase']
|
||||||
const pausableWatch: typeof import('@vueuse/core')['pausableWatch']
|
const pausableWatch: typeof import('@vueuse/core')['pausableWatch']
|
||||||
const provide: typeof import('vue')['provide']
|
const provide: typeof import('vue')['provide']
|
||||||
const provideLocal: typeof import('@vueuse/core')['provideLocal']
|
const provideLocal: typeof import('@vueuse/core')['provideLocal']
|
||||||
@@ -110,9 +114,11 @@ declare global {
|
|||||||
const resolveComponent: typeof import('vue')['resolveComponent']
|
const resolveComponent: typeof import('vue')['resolveComponent']
|
||||||
const resolveRef: typeof import('@vueuse/core')['resolveRef']
|
const resolveRef: typeof import('@vueuse/core')['resolveRef']
|
||||||
const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
|
const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
|
||||||
|
const selectSql: typeof import('./utils/sqlite')['selectSql']
|
||||||
const shallowReactive: typeof import('vue')['shallowReactive']
|
const shallowReactive: typeof import('vue')['shallowReactive']
|
||||||
const shallowReadonly: typeof import('vue')['shallowReadonly']
|
const shallowReadonly: typeof import('vue')['shallowReadonly']
|
||||||
const shallowRef: typeof import('vue')['shallowRef']
|
const shallowRef: typeof import('vue')['shallowRef']
|
||||||
|
const sqlite: typeof import('./utils/sqlite')['default']
|
||||||
const storage: typeof import('./utils/storage')['default']
|
const storage: typeof import('./utils/storage')['default']
|
||||||
const syncRef: typeof import('@vueuse/core')['syncRef']
|
const syncRef: typeof import('@vueuse/core')['syncRef']
|
||||||
const syncRefs: typeof import('@vueuse/core')['syncRefs']
|
const syncRefs: typeof import('@vueuse/core')['syncRefs']
|
||||||
@@ -124,6 +130,7 @@ declare global {
|
|||||||
const toRef: typeof import('vue')['toRef']
|
const toRef: typeof import('vue')['toRef']
|
||||||
const toRefs: typeof import('vue')['toRefs']
|
const toRefs: typeof import('vue')['toRefs']
|
||||||
const toValue: typeof import('vue')['toValue']
|
const toValue: typeof import('vue')['toValue']
|
||||||
|
const transaction: typeof import('./utils/sqlite')['transaction']
|
||||||
const triggerRef: typeof import('vue')['triggerRef']
|
const triggerRef: typeof import('vue')['triggerRef']
|
||||||
const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount']
|
const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount']
|
||||||
const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount']
|
const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount']
|
||||||
@@ -331,6 +338,7 @@ declare module 'vue' {
|
|||||||
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
|
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
|
||||||
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
|
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
|
||||||
readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']>
|
readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']>
|
||||||
|
readonly closeDatabase: UnwrapRef<typeof import('./utils/sqlite')['closeDatabase']>
|
||||||
readonly computed: UnwrapRef<typeof import('vue')['computed']>
|
readonly computed: UnwrapRef<typeof import('vue')['computed']>
|
||||||
readonly computedAsync: UnwrapRef<typeof import('@vueuse/core')['computedAsync']>
|
readonly computedAsync: UnwrapRef<typeof import('@vueuse/core')['computedAsync']>
|
||||||
readonly computedEager: UnwrapRef<typeof import('@vueuse/core')['computedEager']>
|
readonly computedEager: UnwrapRef<typeof import('@vueuse/core')['computedEager']>
|
||||||
@@ -355,11 +363,13 @@ declare module 'vue' {
|
|||||||
readonly defineComponent: UnwrapRef<typeof import('vue')['defineComponent']>
|
readonly defineComponent: UnwrapRef<typeof import('vue')['defineComponent']>
|
||||||
readonly eagerComputed: UnwrapRef<typeof import('@vueuse/core')['eagerComputed']>
|
readonly eagerComputed: UnwrapRef<typeof import('@vueuse/core')['eagerComputed']>
|
||||||
readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
|
readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
|
||||||
|
readonly executeSql: UnwrapRef<typeof import('./utils/sqlite')['executeSql']>
|
||||||
readonly extendRef: UnwrapRef<typeof import('@vueuse/core')['extendRef']>
|
readonly extendRef: UnwrapRef<typeof import('@vueuse/core')['extendRef']>
|
||||||
readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
|
readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
|
||||||
readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
|
readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
|
||||||
readonly h: UnwrapRef<typeof import('vue')['h']>
|
readonly h: UnwrapRef<typeof import('vue')['h']>
|
||||||
readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']>
|
readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']>
|
||||||
|
readonly initTables: UnwrapRef<typeof import('./utils/sqlite')['initTables']>
|
||||||
readonly inject: UnwrapRef<typeof import('vue')['inject']>
|
readonly inject: UnwrapRef<typeof import('vue')['inject']>
|
||||||
readonly injectLocal: UnwrapRef<typeof import('@vueuse/core')['injectLocal']>
|
readonly injectLocal: UnwrapRef<typeof import('@vueuse/core')['injectLocal']>
|
||||||
readonly isDefined: UnwrapRef<typeof import('@vueuse/core')['isDefined']>
|
readonly isDefined: UnwrapRef<typeof import('@vueuse/core')['isDefined']>
|
||||||
@@ -413,6 +423,7 @@ declare module 'vue' {
|
|||||||
readonly onUnmounted: UnwrapRef<typeof import('vue')['onUnmounted']>
|
readonly onUnmounted: UnwrapRef<typeof import('vue')['onUnmounted']>
|
||||||
readonly onUpdated: UnwrapRef<typeof import('vue')['onUpdated']>
|
readonly onUpdated: UnwrapRef<typeof import('vue')['onUpdated']>
|
||||||
readonly onWatcherCleanup: UnwrapRef<typeof import('vue')['onWatcherCleanup']>
|
readonly onWatcherCleanup: UnwrapRef<typeof import('vue')['onWatcherCleanup']>
|
||||||
|
readonly openDatabase: UnwrapRef<typeof import('./utils/sqlite')['openDatabase']>
|
||||||
readonly pausableWatch: UnwrapRef<typeof import('@vueuse/core')['pausableWatch']>
|
readonly pausableWatch: UnwrapRef<typeof import('@vueuse/core')['pausableWatch']>
|
||||||
readonly provide: UnwrapRef<typeof import('vue')['provide']>
|
readonly provide: UnwrapRef<typeof import('vue')['provide']>
|
||||||
readonly provideLocal: UnwrapRef<typeof import('@vueuse/core')['provideLocal']>
|
readonly provideLocal: UnwrapRef<typeof import('@vueuse/core')['provideLocal']>
|
||||||
@@ -432,9 +443,11 @@ declare module 'vue' {
|
|||||||
readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']>
|
readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']>
|
||||||
readonly resolveRef: UnwrapRef<typeof import('@vueuse/core')['resolveRef']>
|
readonly resolveRef: UnwrapRef<typeof import('@vueuse/core')['resolveRef']>
|
||||||
readonly resolveUnref: UnwrapRef<typeof import('@vueuse/core')['resolveUnref']>
|
readonly resolveUnref: UnwrapRef<typeof import('@vueuse/core')['resolveUnref']>
|
||||||
|
readonly selectSql: UnwrapRef<typeof import('./utils/sqlite')['selectSql']>
|
||||||
readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
|
readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
|
||||||
readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
|
readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
|
||||||
readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
|
readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
|
||||||
|
readonly sqlite: UnwrapRef<typeof import('./utils/sqlite')['default']>
|
||||||
readonly storage: UnwrapRef<typeof import('./utils/storage')['default']>
|
readonly storage: UnwrapRef<typeof import('./utils/storage')['default']>
|
||||||
readonly syncRef: UnwrapRef<typeof import('@vueuse/core')['syncRef']>
|
readonly syncRef: UnwrapRef<typeof import('@vueuse/core')['syncRef']>
|
||||||
readonly syncRefs: UnwrapRef<typeof import('@vueuse/core')['syncRefs']>
|
readonly syncRefs: UnwrapRef<typeof import('@vueuse/core')['syncRefs']>
|
||||||
@@ -446,6 +459,7 @@ declare module 'vue' {
|
|||||||
readonly toRef: UnwrapRef<typeof import('vue')['toRef']>
|
readonly toRef: UnwrapRef<typeof import('vue')['toRef']>
|
||||||
readonly toRefs: UnwrapRef<typeof import('vue')['toRefs']>
|
readonly toRefs: UnwrapRef<typeof import('vue')['toRefs']>
|
||||||
readonly toValue: UnwrapRef<typeof import('vue')['toValue']>
|
readonly toValue: UnwrapRef<typeof import('vue')['toValue']>
|
||||||
|
readonly transaction: UnwrapRef<typeof import('./utils/sqlite')['transaction']>
|
||||||
readonly triggerRef: UnwrapRef<typeof import('vue')['triggerRef']>
|
readonly triggerRef: UnwrapRef<typeof import('vue')['triggerRef']>
|
||||||
readonly tryOnBeforeMount: UnwrapRef<typeof import('@vueuse/core')['tryOnBeforeMount']>
|
readonly tryOnBeforeMount: UnwrapRef<typeof import('@vueuse/core')['tryOnBeforeMount']>
|
||||||
readonly tryOnBeforeUnmount: UnwrapRef<typeof import('@vueuse/core')['tryOnBeforeUnmount']>
|
readonly tryOnBeforeUnmount: UnwrapRef<typeof import('@vueuse/core')['tryOnBeforeUnmount']>
|
||||||
|
|||||||
1
src/components.d.ts
vendored
1
src/components.d.ts
vendored
@@ -35,7 +35,6 @@ declare module 'vue' {
|
|||||||
SettingsSensorConfig: typeof import('./components/settings/sensorConfig.vue')['default']
|
SettingsSensorConfig: typeof import('./components/settings/sensorConfig.vue')['default']
|
||||||
SettingsWifiNetwork: typeof import('./components/settings/wifiNetwork.vue')['default']
|
SettingsWifiNetwork: typeof import('./components/settings/wifiNetwork.vue')['default']
|
||||||
SettingsWifiSettings: typeof import('./components/settings/wifiSettings.vue')['default']
|
SettingsWifiSettings: typeof import('./components/settings/wifiSettings.vue')['default']
|
||||||
ToggleFullscreen: typeof import('./components/toggleFullscreen.vue')['default']
|
|
||||||
WarningFilter: typeof import('./components/warning/filter.vue')['default']
|
WarningFilter: typeof import('./components/warning/filter.vue')['default']
|
||||||
WarningItem: typeof import('./components/warning/item.vue')['default']
|
WarningItem: typeof import('./components/warning/item.vue')['default']
|
||||||
WorkDashboard: typeof import('./components/work/dashboard.vue')['default']
|
WorkDashboard: typeof import('./components/work/dashboard.vue')['default']
|
||||||
|
|||||||
1
src/uni-pages.d.ts
vendored
1
src/uni-pages.d.ts
vendored
@@ -6,6 +6,7 @@
|
|||||||
type _LocationUrl =
|
type _LocationUrl =
|
||||||
"/pages/Ahome/index" |
|
"/pages/Ahome/index" |
|
||||||
"/pages/bluetooth/index" |
|
"/pages/bluetooth/index" |
|
||||||
|
"/pages/demo/sqlite" |
|
||||||
"/pages/heatmap/index" |
|
"/pages/heatmap/index" |
|
||||||
"/pages/message/index" |
|
"/pages/message/index" |
|
||||||
"/pages/project/index" |
|
"/pages/project/index" |
|
||||||
|
|||||||
469
src/utils/sqlite.ts
Normal file
469
src/utils/sqlite.ts
Normal file
@@ -0,0 +1,469 @@
|
|||||||
|
/**
|
||||||
|
* SQLite 数据库工具类
|
||||||
|
* 用于 uni-app Android/iOS 本地数据库操作
|
||||||
|
*
|
||||||
|
* ======================== 使用说明 ========================
|
||||||
|
*
|
||||||
|
* ## 1. 导入
|
||||||
|
*
|
||||||
|
* ```typescript
|
||||||
|
* import DB, { initTables } from '@/utils/sqlite'
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ## 2. 初始化数据库表
|
||||||
|
*
|
||||||
|
* ```typescript
|
||||||
|
* // 首次使用或表结构变更时调用,仅需执行一次
|
||||||
|
* await initTables()
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ## 3. 插入数据(增)
|
||||||
|
*
|
||||||
|
* ```typescript
|
||||||
|
* // 方式一:使用 insert 方法(推荐,自动拼接 SQL)
|
||||||
|
* await DB.insert('device', {
|
||||||
|
* device_name: '徐工XS65H #01',
|
||||||
|
* device_type: '压路机',
|
||||||
|
* status: 'online',
|
||||||
|
* })
|
||||||
|
*
|
||||||
|
* // 方式二:使用原生 SQL
|
||||||
|
* await DB.executeSql(
|
||||||
|
* `INSERT INTO device (device_name, device_type, status)
|
||||||
|
* VALUES ('徐工XS65H #01', '压路机', 'online')`
|
||||||
|
* )
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ## 4. 删除数据(删)
|
||||||
|
*
|
||||||
|
* ```typescript
|
||||||
|
* // 按条件删除
|
||||||
|
* await DB.delete('device', "id = 1")
|
||||||
|
* // 删除所有
|
||||||
|
* await DB.delete('device')
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ## 5. 更新数据(改)
|
||||||
|
*
|
||||||
|
* ```typescript
|
||||||
|
* await DB.update('device',
|
||||||
|
* { status: 'offline', updated_at: new Date().toISOString() },
|
||||||
|
* "id = 1"
|
||||||
|
* )
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ## 6. 查询数据(查)
|
||||||
|
*
|
||||||
|
* ### 6.1 查询全部
|
||||||
|
* ```typescript
|
||||||
|
* const devices = await DB.select('device')
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ### 6.2 详细查询 —— 按 ID 查询单条
|
||||||
|
* ```typescript
|
||||||
|
* const device = await DB.selectById('device', 1)
|
||||||
|
* // 返回: { id: 1, device_name: '...', ... } 或 null
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ### 6.3 详细查询 —— 按字段精确匹配
|
||||||
|
* ```typescript
|
||||||
|
* const devices = await DB.selectByField('device', 'status', 'online')
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ### 6.4 模糊查询 —— LIKE 模糊匹配
|
||||||
|
* ```typescript
|
||||||
|
* // 按设备名称模糊查询
|
||||||
|
* const devices = await DB.selectLike('device', 'device_name', '徐工')
|
||||||
|
*
|
||||||
|
* // 指定返回字段的模糊查询
|
||||||
|
* const devices = await DB.selectLike('device', 'device_name', '徐工', 'id, device_name, status')
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ### 6.5 条件查询 —— 带排序和分页
|
||||||
|
* ```typescript
|
||||||
|
* const devices = await DB.select('device', '*', "status = 'online'", 'id DESC', 10)
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ### 6.6 计数查询
|
||||||
|
* ```typescript
|
||||||
|
* const count = await DB.count('device', "status = 'online'")
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ### 6.7 原生 SQL 查询(复杂查询时使用)
|
||||||
|
* ```typescript
|
||||||
|
* const result = await DB.selectSql('SELECT * FROM device WHERE status = "online"')
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ## 7. 事务操作
|
||||||
|
*
|
||||||
|
* ```typescript
|
||||||
|
* await DB.transaction([
|
||||||
|
* "INSERT INTO device (device_name, device_type) VALUES ('设备A', '压路机')",
|
||||||
|
* "INSERT INTO work_record (device_id, speed) VALUES (1, 5.5)",
|
||||||
|
* ])
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ## 8. 其他
|
||||||
|
*
|
||||||
|
* ```typescript
|
||||||
|
* // 手动打开数据库
|
||||||
|
* await DB.open()
|
||||||
|
* // 手动关闭数据库
|
||||||
|
* await DB.close()
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
|
||||||
|
const DB_NAME = 'road_roller'
|
||||||
|
const DB_PATH = '_doc/road_roller.db'
|
||||||
|
|
||||||
|
let isOpen = false
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转义 SQL 字符串值,防止单引号注入
|
||||||
|
*/
|
||||||
|
function escapeValue(value: any): string {
|
||||||
|
if (value === null || value === undefined)
|
||||||
|
return 'NULL'
|
||||||
|
if (typeof value === 'number')
|
||||||
|
return String(value)
|
||||||
|
if (typeof value === 'boolean')
|
||||||
|
return value ? '1' : '0'
|
||||||
|
return `'${String(value).replace(/'/g, '\'\'')}'`
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据库操作类
|
||||||
|
*/
|
||||||
|
class DB {
|
||||||
|
/**
|
||||||
|
* 打开数据库
|
||||||
|
*/
|
||||||
|
static open(): Promise<void> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (isOpen) {
|
||||||
|
resolve()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
plus.sqlite.openDatabase({
|
||||||
|
name: DB_NAME,
|
||||||
|
path: DB_PATH,
|
||||||
|
success() {
|
||||||
|
console.log('数据库打开成功')
|
||||||
|
isOpen = true
|
||||||
|
resolve()
|
||||||
|
},
|
||||||
|
fail(err: any) {
|
||||||
|
console.error('数据库打开失败:', err)
|
||||||
|
reject(err)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭数据库
|
||||||
|
*/
|
||||||
|
static close(): Promise<void> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!isOpen) {
|
||||||
|
resolve()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
plus.sqlite.closeDatabase({
|
||||||
|
name: DB_NAME,
|
||||||
|
success() {
|
||||||
|
console.log('数据库关闭成功')
|
||||||
|
isOpen = false
|
||||||
|
resolve()
|
||||||
|
},
|
||||||
|
fail(err: any) {
|
||||||
|
console.error('数据库关闭失败:', err)
|
||||||
|
reject(err)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行 SQL 语句(增、删、改)
|
||||||
|
*/
|
||||||
|
static executeSql(sql: string | string[]): Promise<any> {
|
||||||
|
return DB.open().then(() => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
plus.sqlite.executeSql({
|
||||||
|
name: DB_NAME,
|
||||||
|
sql,
|
||||||
|
success(res: any) {
|
||||||
|
resolve(res)
|
||||||
|
},
|
||||||
|
fail(err: any) {
|
||||||
|
console.error('执行SQL失败:', err)
|
||||||
|
reject(err)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询 SQL 语句
|
||||||
|
*/
|
||||||
|
static selectSql(sql: string): Promise<any[]> {
|
||||||
|
return DB.open().then(() => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
plus.sqlite.selectSql({
|
||||||
|
name: DB_NAME,
|
||||||
|
sql,
|
||||||
|
success(res: any) {
|
||||||
|
resolve(res)
|
||||||
|
},
|
||||||
|
fail(err: any) {
|
||||||
|
console.error('查询SQL失败:', err)
|
||||||
|
reject(err)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行事务
|
||||||
|
*/
|
||||||
|
static transaction(sqls: string[]): Promise<void> {
|
||||||
|
return DB.open().then(() => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
plus.sqlite.transaction({
|
||||||
|
name: DB_NAME,
|
||||||
|
sql: sqls,
|
||||||
|
success() {
|
||||||
|
console.log('事务执行成功')
|
||||||
|
resolve()
|
||||||
|
},
|
||||||
|
fail(err: any) {
|
||||||
|
console.error('事务执行失败:', err)
|
||||||
|
reject(err)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ======================== CRUD 封装方法 ========================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插入一条记录
|
||||||
|
* @param table 表名
|
||||||
|
* @param data 键值对数据对象
|
||||||
|
* @example
|
||||||
|
* await DB.insert('device', { device_name: '设备A', device_type: '压路机', status: 'online' })
|
||||||
|
*/
|
||||||
|
static async insert(table: string, data: Record<string, any>): Promise<any> {
|
||||||
|
const keys = Object.keys(data)
|
||||||
|
const values = keys.map(k => escapeValue(data[k]))
|
||||||
|
const sql = `INSERT INTO ${table} (${keys.join(', ')}) VALUES (${values.join(', ')})`
|
||||||
|
return DB.executeSql(sql)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新记录
|
||||||
|
* @param table 表名
|
||||||
|
* @param data 要更新的键值对
|
||||||
|
* @param where 条件子句(不含 WHERE 关键字),为空则更新全部
|
||||||
|
* @example
|
||||||
|
* await DB.update('device', { status: 'offline' }, "id = 1")
|
||||||
|
*/
|
||||||
|
static async update(table: string, data: Record<string, any>, where?: string): Promise<any> {
|
||||||
|
const sets = Object.keys(data).map(k => `${k} = ${escapeValue(data[k])}`)
|
||||||
|
let sql = `UPDATE ${table} SET ${sets.join(', ')}`
|
||||||
|
if (where)
|
||||||
|
sql += ` WHERE ${where}`
|
||||||
|
return DB.executeSql(sql)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除记录
|
||||||
|
* @param table 表名
|
||||||
|
* @param where 条件子句(不含 WHERE 关键字),为空则删除全部
|
||||||
|
* @example
|
||||||
|
* await DB.delete('device', "id = 1")
|
||||||
|
*/
|
||||||
|
static async delete(table: string, where?: string): Promise<any> {
|
||||||
|
let sql = `DELETE FROM ${table}`
|
||||||
|
if (where)
|
||||||
|
sql += ` WHERE ${where}`
|
||||||
|
return DB.executeSql(sql)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询记录
|
||||||
|
* @param table 表名
|
||||||
|
* @param columns 返回字段,默认 '*'
|
||||||
|
* @param where 条件子句(不含 WHERE 关键字),可选
|
||||||
|
* @param orderBy 排序子句(不含 ORDER BY 关键字),可选
|
||||||
|
* @param limit 返回条数限制,可选
|
||||||
|
* @example
|
||||||
|
* const list = await DB.select('device', '*', "status = 'online'", 'id DESC', 10)
|
||||||
|
*/
|
||||||
|
static async select(
|
||||||
|
table: string,
|
||||||
|
columns: string = '*',
|
||||||
|
where?: string,
|
||||||
|
orderBy?: string,
|
||||||
|
limit?: number,
|
||||||
|
): Promise<any[]> {
|
||||||
|
let sql = `SELECT ${columns} FROM ${table}`
|
||||||
|
if (where)
|
||||||
|
sql += ` WHERE ${where}`
|
||||||
|
if (orderBy)
|
||||||
|
sql += ` ORDER BY ${orderBy}`
|
||||||
|
if (limit)
|
||||||
|
sql += ` LIMIT ${limit}`
|
||||||
|
return DB.selectSql(sql)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按 ID 查询单条记录(详细查询)
|
||||||
|
* @param table 表名
|
||||||
|
* @param id 主键值
|
||||||
|
* @returns 记录对象或 null
|
||||||
|
* @example
|
||||||
|
* const device = await DB.selectById('device', 1)
|
||||||
|
*/
|
||||||
|
static async selectById(table: string, id: number | string): Promise<any> {
|
||||||
|
const result = await DB.select(
|
||||||
|
table,
|
||||||
|
'*',
|
||||||
|
`id = ${typeof id === 'string' ? escapeValue(id) : id}`,
|
||||||
|
)
|
||||||
|
return result?.[0] || null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按字段精确匹配查询(详细查询)
|
||||||
|
* @param table 表名
|
||||||
|
* @param field 字段名
|
||||||
|
* @param value 匹配值
|
||||||
|
* @param columns 返回字段,默认 '*'
|
||||||
|
* @example
|
||||||
|
* const devices = await DB.selectByField('device', 'status', 'online')
|
||||||
|
*/
|
||||||
|
static async selectByField(
|
||||||
|
table: string,
|
||||||
|
field: string,
|
||||||
|
value: any,
|
||||||
|
columns: string = '*',
|
||||||
|
): Promise<any[]> {
|
||||||
|
return DB.select(table, columns, `${field} = ${escapeValue(value)}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模糊查询(LIKE %keyword%)
|
||||||
|
* @param table 表名
|
||||||
|
* @param field 要模糊匹配的字段名
|
||||||
|
* @param keyword 关键词
|
||||||
|
* @param columns 返回字段,默认 '*'
|
||||||
|
* @example
|
||||||
|
* // 按设备名称模糊查询
|
||||||
|
* const devices = await DB.selectLike('device', 'device_name', '徐工')
|
||||||
|
* // 指定返回字段
|
||||||
|
* const devices = await DB.selectLike('device', 'device_name', '徐工', 'id, device_name')
|
||||||
|
*/
|
||||||
|
static async selectLike(
|
||||||
|
table: string,
|
||||||
|
field: string,
|
||||||
|
keyword: string,
|
||||||
|
columns: string = '*',
|
||||||
|
): Promise<any[]> {
|
||||||
|
const escapedKeyword = keyword.replace(/'/g, '\'\'')
|
||||||
|
return DB.select(table, columns, `${field} LIKE '%${escapedKeyword}%'`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计数查询
|
||||||
|
* @param table 表名
|
||||||
|
* @param where 条件子句(不含 WHERE 关键字),可选
|
||||||
|
* @returns 记录数量
|
||||||
|
* @example
|
||||||
|
* const count = await DB.count('device', "status = 'online'")
|
||||||
|
*/
|
||||||
|
static async count(table: string, where?: string): Promise<number> {
|
||||||
|
const result = await DB.select(table, 'COUNT(*) as total', where)
|
||||||
|
return result?.[0]?.total || 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化数据库表
|
||||||
|
*/
|
||||||
|
export async function initTables() {
|
||||||
|
const sqls = [
|
||||||
|
// 设备信息表
|
||||||
|
`CREATE TABLE IF NOT EXISTS device (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
device_name TEXT NOT NULL,
|
||||||
|
device_type TEXT,
|
||||||
|
status TEXT DEFAULT 'offline',
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
|
)`,
|
||||||
|
// 作业记录表
|
||||||
|
`CREATE TABLE IF NOT EXISTS work_record (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
device_id INTEGER,
|
||||||
|
start_time DATETIME,
|
||||||
|
end_time DATETIME,
|
||||||
|
speed REAL,
|
||||||
|
frequency REAL,
|
||||||
|
amplitude REAL,
|
||||||
|
compaction_value REAL,
|
||||||
|
gps_lat REAL,
|
||||||
|
gps_lng REAL,
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (device_id) REFERENCES device(id)
|
||||||
|
)`,
|
||||||
|
// RTK 轨迹数据表
|
||||||
|
`CREATE TABLE IF NOT EXISTS rtk_track (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
work_record_id INTEGER,
|
||||||
|
timestamp DATETIME,
|
||||||
|
latitude REAL,
|
||||||
|
longitude REAL,
|
||||||
|
altitude REAL,
|
||||||
|
speed REAL,
|
||||||
|
heading REAL,
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (work_record_id) REFERENCES work_record(id)
|
||||||
|
)`,
|
||||||
|
// 告警记录表
|
||||||
|
`CREATE TABLE IF NOT EXISTS warning_record (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
device_id INTEGER,
|
||||||
|
warning_type TEXT,
|
||||||
|
warning_level TEXT,
|
||||||
|
message TEXT,
|
||||||
|
is_read INTEGER DEFAULT 0,
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (device_id) REFERENCES device(id)
|
||||||
|
)`,
|
||||||
|
]
|
||||||
|
|
||||||
|
try {
|
||||||
|
await DB.transaction(sqls)
|
||||||
|
console.log('数据库表初始化成功')
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
console.error('数据库表初始化失败:', err)
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 兼容旧版按需导出
|
||||||
|
export const openDatabase = DB.open
|
||||||
|
export const closeDatabase = DB.close
|
||||||
|
export const executeSql = DB.executeSql
|
||||||
|
export const selectSql = DB.selectSql
|
||||||
|
export const transaction = DB.transaction
|
||||||
|
|
||||||
|
export default DB
|
||||||
Reference in New Issue
Block a user