网站死链怎么解决,免费室内设计师,重庆网络策划推广公司,ppt免费模板100个项目有个需求#xff0c;需要生成app和小程序#xff0c;app支持离线数据库#xff0c;如果当前没有网络提醒用户开启离线模式#xff0c;所以就随便搞了下#xff0c;具体的思路就是#xff1a; 一个接口和多个实现类#xff08;类似后端的模板设计模式#xff09;需要生成app和小程序app支持离线数据库如果当前没有网络提醒用户开启离线模式所以就随便搞了下具体的思路就是 一个接口和多个实现类类似后端的模板设计模式例如sqlite实现类indexedDB实现类等等根据环境动态选用具体的实现类 indexedDB有些方法没有改sqlite没有测试此处就是提供一个思路只是用来学习和研究着玩了
目录 class类
BaseApi
import type LocalDB from /class/DbClass
import { tableConfig } from /enums/DbEnums
import { CallBackFunType } from /utils/request
class BaseApi {public localDB: LocalDB;public table: string;public hasTable: boolean;constructor(table: string, localDB: LocalDB){this.table tablethis.hasTable falsethis.localDB localDBif(this.localDB.Db().isOpen()){this.localDB.Db().hasTable(table).then((res:any) {this.hasTable res}).catch((res: any) {console.log(构造初始化失败 table: this.table)})}}public getTable(): string{return this.table;}public getHasTable(): boolean{return this.hasTable;}public setHasTable(hasTable:boolean){this.hasTable hasTable;}/*** 验证是否存在表信息*/public async verifyTable(init: boolean false): PromiseCallBackFunTypeany{if(!this.getHasTable() init){const res await this.init();if(!res){return new CallBackFunType({}).fail(初始化数据库失败)}else {return new CallBackFunType({}).success(初始化数据库成功);}}return new CallBackFunType({}).success(存在数据库);}/*** 初始化*/public async init(): Promiseboolean{// 浏览器不能直接新建需要适配const res await this.localDB.Db().createTable(this.table, tableConfig[this.table])return res;}
}export default BaseApi;DbClass
import type SqlAbapter from /plugins/db/SqlAbapter// 根据平台选择适配器
class LocalDB {private db : SqlAbapter;public name : string;public isSupport: boolean;constructor(db:SqlAbapter , name: string, isSupport: boolean){this.db db;this.name namethis.isSupport isSupport}/*** 批量初始化表*/public initDb(tables: Recordstring, Recordstring, any): void{// 验证当前是否开启了离线缓存验证当前是否支持离线缓存if(!this.isSupport){console.log(当前不支持离线缓存)return;}this.db.open(tables).then((res: boolean) {if(res){console.log(数据库打开成功)}else {console.log(数据库打开失败)}})}// 验证是否public Db():SqlAbapter{// 验证当前是否开启了离线缓存验证当前是否支持离线缓存if(!this.isSupport){console.log(当前不支持离线缓存)}return this.db;}
}export default LocalDB;方法抽象
抽象模版 SqlAbapter.ts interface SqlAbapter {/*** 数据库是否开启*/isOpen: () boolean;/*** 开启数据库*/open: (tables: Recordstring, Recordstring, any) Promiseboolean;/*** 关闭数据库*/close: () Promiseboolean;/*** 是否存在表*/hasTable: (dbTable: string) Promiseboolean;/*** 创建表*/createTable: (dbTable: string, data: string[]) Promiseboolean;/*** 删除表*/dropTable: (dbTable: string) Promiseboolean;/*** 新增数据 indexedDb 重读id会报错*/insertTableData: (dbTable: string, data:Recordstring,any) Promiseboolean;/*** 新增或修改*/insertOrReplaceData: (dbTable:string, data:Recordstring,any, condition:Recordstring,any) Promiseboolean;/*** 查询数据*/selectTableData: (dbTable:string, condition: Recordstring,any) Promiseany;/*** 删除数据*/deleteTableData: (dbTable:string, condition: Recordstring,any) Promiseboolean;/*** 更新数据*/updateTableData: (dbTable:string, data: Recordstring,any, condition: Recordstring,any) PromiseBoolean;/*** 分页查询*/pullSQL: (dbTable: string, id:string, current: number, size:number) Promiseany;}export default SqlAbapter;sqlite实现
import type SqlAbapter from /plugins/db/SqlAbapter
import { replace, keyValSql, isEmpty, whereSql, updateSetSql } from /plugins/utils;
class SqliteAdapter implements SqlAbapter {public dbName: string;public dbPath: string;constructor(dbName: string, dbPath:string){this.dbName dbName;this.dbPath dbPath;}// 判断数据库是否打开isOpen() {// 数据库打开了就返回 true,否则返回 falsevar open plus.sqlite.isOpenDatabase({name: this.dbName, // 数据库名称path: this.dbPath // 数据库地址})return open;}// 创建数据库 或 有该数据库就打开open(tables: Recordstring, Recordstring, any):Promiseboolean {return new Promise((resolve, reject) {// 打开数据库plus.sqlite.openDatabase({name: this.dbName,path: this.dbPath,success(e) {resolve(true); // 成功回调// 初始化表 todo: },fail(e) {reject(false); // 失败回调}})})}hasTable(dbTable: string): Promiseboolean {let sql select * from sqlite_master where type table and name ${dbTable}return new Promise((resolve, reject) {// 打开数据库plus.sqlite.executeSql({name: this.dbName,sql: [sql],success(res) {if (res.resultSet.length 0) {resolve(true); // 成功回调} else {resolve(false); // 失败回调}},fail(e) {reject(false); // 失败回调}})})}// 关闭数据库close(): Promiseboolean {return new Promise((resolve, reject) {plus.sqlite.closeDatabase({name: this.dbName,success(e) {resolve(e);},fail(e) {reject(e);}})})}// 数据库建表 sql:CREATE TABLE IF NOT EXISTS dbTable(id varchar(50),name TEXT) // 创建 CREATE TABLE IF NOT EXISTS 、 dbTable 是表名不能用数字开头、括号里是表格的表头createTable(dbTable: string, data: string[]): Promiseboolean {let keys ;if(!data || data.length 0){return new Promise((resolve, reject) { reject(创建失败,索引不能为空) })}data.forEach((key:string) {keys keys key ,;})keys replace(keys, ,)// todo: 增加表 属性 varchar等等let sql CREATE TABLE IF NOT EXISTS ${dbTable}(${keys})return new Promise((resolve, reject) {// executeSql: 执行增删改等操作的SQL语句plus.sqlite.executeSql({name: this.dbName,sql: [sql],success(e) {resolve(true);},fail(e) {reject(false);}})})}// 数据库删表 sql:DROP TABLE dbTabledropTable(dbTable: string): Promiseboolean {return new Promise((resolve, reject) {plus.sqlite.executeSql({name: this.dbName,sql: [DROP TABLE ${dbTable}],success(e) {resolve(true);},fail(e) {reject(false);}})})}// 向表格里添加数据 sql:INSERT INTO dbTable VALUES(x,x,x) 对应新增// 或者 sql:INSERT INTO dbTable (x,x,x) VALUES(x,x,x) 具体新增// 插入 INSERT INTO 、 dbTable 是表名、根据表头列名插入列值insertTableData(dbTable: string, data:Recordstring,any): Promiseboolean {// 判断有没有传参if (dbTable ! undefined data) {// 判断传的参是否有值if (!isEmpty(data)) {let res keyValSql(data)// 拼接sql执行插入var sql INSERT INTO ${dbTable} (${res.keySql}) VALUES(${res.valSql});// console.log(sql);return new Promise((resolve, reject) {// 表格添加数据plus.sqlite.executeSql({name: this.dbName,sql: [sql],success(e) {resolve(e);},fail(e) {reject(e);}})})} else {return new Promise((resolve, reject) { reject(错误添加) })}} else {return new Promise((resolve, reject) { reject(错误添加) })}}// 根据条件向表格里添加数据 有数据更新、无数据插入// (建表时需要设置主键) 例如 --- roomid varchar(50) PRIMARY KEYinsertOrReplaceData(dbTable: string, data: Recordstring,any):Promiseboolean {// 判断有没有传参if (dbTable ! undefined data) {if (!isEmpty(data)) {let res keyValSql(data)let sql INSERT OR REPLACE INTO ${dbTable} (${res.keySql}) VALUES(${res.valSql});// console.log(sql);return new Promise((resolve, reject) {// 表格添加数据plus.sqlite.executeSql({name: this.dbName,sql: [sql],success(e) {resolve(e);},fail(e) {reject(e);}})})}else {return new Promise((resolve, reject) { reject(错误添加) })}} else {return new Promise((resolve, reject) { reject(错误添加) })}}// 查询获取数据库里的数据 sql:SELECT * FROM dbTable WHERE lname lvalue// 查询 SELECT * FROM 、 dbTable 是表名、 WHERE 查找条件 lname,lvalue 是查询条件的列名和列值selectTableData(dbTable:string, condition: Recordstring,any): Promiseany {if (dbTable ! undefined) {// 第一个是表单名称后两个参数是列表名用来检索let where if(!isEmpty(condition)){where whereSql(condition)}// if (lname ! undefined cc ! undefined) {// // 两个检索条件// var sql SELECT * FROM ${dbTable} WHERE ${lname} ${lvalue} AND ${cc} ${dd};// }let sql SELECT * FROM ${dbTable};if(where){sql sql where where;}return new Promise((resolve, reject) {// 表格查询数据 执行查询的SQL语句plus.sqlite.selectSql({name: this.dbName,sql: sql,success(e) {resolve(e);},fail(e) {reject(e);}})})} else {return new Promise((resolve, reject) { reject(错误查询) });}}// 删除表里的数据 sql:DELETE FROM dbTable WHERE lname lvalue// 删除 DELETE FROM 、 dbTable 是表名、 WHERE 查找条件 lname,lvalue 是查询条件的列名和列值deleteTableData(dbTable:string, condition: Recordstring,any): Promiseboolean {if (dbTable ! undefined) {let where if(!isEmpty(condition)){where whereSql(condition)}var sql DELETE FROM ${dbTable};if(where){sql sql where where}return new Promise((resolve, reject) {// 删除表数据plus.sqlite.executeSql({name: this.dbName,sql: [sql],success(e) {resolve(e);},fail(e) {reject(e);}})})} else {return new Promise((resolve, reject) { reject(错误删除) });}}// 修改数据表里的数据 sql:UPDATE dbTable SET 列名 列值,列名 列值 WHERE lname lvalue// 修改 UPDATE 、 dbTable 是表名, data: 要修改的列名修改后列值, lname,lvalue 是查询条件的列名和列值updateTableData(dbTable:string, data: Recordstring,any, condition: Recordstring,any): Promiseboolean {if(!dbTable || isEmpty(data)){return new Promise((resolve, reject) { reject(修改错误) });}let res updateSetSql(data)var sql UPDATE ${dbTable} SET res;if(!isEmpty(condition)){let where whereSql(condition)if(where){sql sql where where}}// WHERE 前面是要修改的列名、列值后面是条件的列名、列值return new Promise((resolve, reject) {// 修改表数据plus.sqlite.executeSql({name: this.dbName,sql: [sql],success(e) {resolve(e);},fail(e) {reject(e);}})})}// 获取指定数据条数 sql:SELECT * FROM dbTable ORDER BY id DESC LIMIT 15 OFFSET num// dbTable 表名, ORDER BY 代表排序默认正序, id 是排序的条件 DESC 代表倒序从最后一条数据开始拿// LIMIT 15 OFFSET ${num},这句的意思是跳过 num 条拿 15 条数据, num 为跳过多少条数据是动态值// 例 初始num设为0就从最后的数据开始拿15条下次不拿刚获取的数据所以可以让num为15这样就能一步一步的拿完所有的数据pullSQL(dbTable: string, id:string, current: number, size:number): Promiseany {if(current 0){return new Promise((resolve, reject) { reject(分页查询错误页码必须从1开始) });}let num 0;if(current 0){num (current - 1) * size}return new Promise((resolve, reject) {plus.sqlite.selectSql({name: this.dbName,sql: SELECT * FROM ${dbTable} ORDER BY ${id} DESC LIMIT ${size} OFFSET ${num},success(e) {resolve(e);},fail(e) {reject(e);}})})}
}export default SqliteAdapter;indexedDb 实现
import type SqlAbapter from /plugins/db/SqlAbapter
import { keyValSql, isEmpty, whereSql, updateSetSql } from /plugins/utils;class IndexDbAdapter implements SqlAbapter {// 这个做法是因为 不同的浏览器获取indexedDB的方式不一样。// mozIndexedDB火狐浏览器内核webkitIndexedDBwebkit内核msIndexedDBIE内核。public indexedDB window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;public dbName: string;public dbPath: string;private request: IDBOpenDBRequest | undefined;private db: IDBDatabase | undefined;constructor(dbName: string, dbPath:string){this.dbName dbName;this.dbPath dbPath;// this.request this.indexedDB.open(this.dbName,1)}// 判断数据库是否打开isOpen() {// 数据库打开了就返回 true,否则返回 falseif(this.request null){return false;}else {return true;}}// 创建数据库 或 有该数据库就打开open(tables: Recordstring, Recordstring, any):Promiseboolean {return new Promise((resolve, reject) {this.request this.indexedDB.open(this.dbName,1)let _this this;this.request.onerror function(event) {console.error(Database error:, event.target?.errorCode);reject(数据库打开失败);};this.request.onupgradeneeded function(event) {console.log(onupgradeneeded , event)resolve(true);_this.db (event.target as IDBOpenDBRequest).result;// _this.createTable(ttt, [name, val])if(!isEmpty(tables)){let tabs Object.keys(tables)tabs.forEach((tab:string) {_this.hasTable(tab).then((res: boolean) {if(res){// 当前console.log(当前数据库: ${tab} 已存在不进行初始化)}else {// 初始化表_this.createTable(tab, Object.keys(tables[tab])).then((creRes:any) {if(creRes){console.log(当前数据库: ${tab} 初始化完成)}else {console.log(当前数据库: ${tab} 初始化失败)}})}})})}};this.request.onsuccess function(event) {_this.db (event.target as IDBOpenDBRequest).result;resolve(true);console.log(Database opened successfully);};})}hasTable(dbTable: string): Promiseboolean {let _this this;return new Promise((resolve, reject) {let res _this.db?.objectStoreNames.contains(dbTable) as booleanconsole.log(hasTable this.db? , this.db)console.log(hasTable , res)resolve(res);})}// 关闭数据库close(): Promiseboolean {let _this this;return new Promise((resolve, reject) {_this.db?.close();resolve(true);})}// 数据库建表 sql:CREATE TABLE IF NOT EXISTS dbTable(id varchar(50),name TEXT) // 创建 CREATE TABLE IF NOT EXISTS 、 dbTable 是表名不能用数字开头、括号里是表格的表头createTable(dbTable: string, data: string[]): Promiseboolean {if(!data || data.length 0){return new Promise((resolve, reject) { reject(创建失败,索引不能为空) })}let _this this;return new Promise((resolve, reject) {// executeSql: 创建表const objectStore _this.db?.createObjectStore(dbTable,{ keyPath: id });data.forEach((key:any) {objectStore?.createIndex(key, key, {unique: false})})resolve(true)})}// 数据库删表 sql:DROP TABLE dbTabledropTable(dbTable: string): Promiseboolean {return new Promise((resolve, reject) {reject(false);})}// 向表格里添加数据 sql:INSERT INTO dbTable VALUES(x,x,x) 对应新增// 或者 sql:INSERT INTO dbTable (x,x,x) VALUES(x,x,x) 具体新增// 插入 INSERT INTO 、 dbTable 是表名、根据表头列名插入列值insertTableData(dbTable: string, data:Recordstring,any): Promiseboolean {// 判断有没有传参if (dbTable ! undefined data) {// 判断传的参是否有值if (!isEmpty(data)) {let _this this;return new Promise((resolve, reject) {// 添加数据到对象存储空间let transaction _this.db?.transaction([dbTable], readwrite);const objectStore transaction?.objectStore(dbTable);let request objectStore?.add(data) as IDBRequest;// 写入数据的事件监听request.onsuccess function (event) {resolve(true)console.log(数据写入成功);};request.onerror function (event) {reject(数据写入失败: event?.target?.error?.message)console.log(数据写入失败 event 》 , event);}})} else {return new Promise((resolve, reject) { reject(错误添加) })}} else {return new Promise((resolve, reject) { reject(错误添加) })}}// 根据条件向表格里添加数据 有数据更新、无数据插入// (建表时需要设置主键) 例如 --- roomid varchar(50) PRIMARY KEYinsertOrReplaceData(dbTable: string, data: Recordstring,any):Promiseboolean {// 判断有没有传参if (dbTable ! undefined data) {if (!isEmpty(data)) {return new Promise((resolve, reject) {// 表格添加数据reject(false);})}else {return new Promise((resolve, reject) { reject(错误添加) })}} else {return new Promise((resolve, reject) { reject(错误添加) })}}// 查询获取数据库里的数据 sql:SELECT * FROM dbTable WHERE lname lvalue// 查询 SELECT * FROM 、 dbTable 是表名、 WHERE 查找条件 lname,lvalue 是查询条件的列名和列值selectTableData(dbTable:string, condition: Recordstring,any): Promiseany {if (dbTable ! undefined) {// 第一个是表单名称后两个参数是列表名用来检索return new Promise((resolve, reject) {reject(false);})} else {return new Promise((resolve, reject) { reject(错误查询) });}}// 删除表里的数据 sql:DELETE FROM dbTable WHERE lname lvalue// 删除 DELETE FROM 、 dbTable 是表名、 WHERE 查找条件 lname,lvalue 是查询条件的列名和列值deleteTableData(dbTable:string, condition: Recordstring,any): Promiseboolean {if (dbTable ! undefined) {return new Promise((resolve, reject) {reject(false);})} else {return new Promise((resolve, reject) { reject(错误删除) });}}// 修改数据表里的数据 sql:UPDATE dbTable SET 列名 列值,列名 列值 WHERE lname lvalue// 修改 UPDATE 、 dbTable 是表名, data: 要修改的列名修改后列值, lname,lvalue 是查询条件的列名和列值updateTableData(dbTable:string, data: Recordstring,any, condition: Recordstring,any): Promiseboolean {return new Promise((resolve, reject) {reject(false);})}// 获取指定数据条数 sql:SELECT * FROM dbTable ORDER BY id DESC LIMIT 15 OFFSET num// dbTable 表名, ORDER BY 代表排序默认正序, id 是排序的条件 DESC 代表倒序从最后一条数据开始拿// LIMIT 15 OFFSET ${num},这句的意思是跳过 num 条拿 15 条数据, num 为跳过多少条数据是动态值// 例 初始num设为0就从最后的数据开始拿15条下次不拿刚获取的数据所以可以让num为15这样就能一步一步的拿完所有的数据pullSQL(dbTable: string, id:string, current: number, size:number): Promiseany {return new Promise((resolve, reject) {reject(false);})}
}export default IndexDbAdapter;动态选取
db-plugins
import SqliteAdapter from ./db/sqlite/sqliteAdapter;
import IndexDbAdapter from ./db/indexedDb/indexedDbAdapter;
import { DbConfig, tableConfig } from /enums/DbEnums
import LocalDB from /class/DbClasslet localDB : LocalDB;
// #ifdef APP-PLUS
// App 环境使用 sqlite 适配器localDB new LocalDB(new SqliteAdapter(DbConfig.Name, DbConfig.Path), sqlite, true);
// #endif
// #ifdef MP-WEIXIN
// 小程序环境使用内存适配器,自定义实现// #endif
// #ifdef H5
// 浏览器 环境使用 indexeddb 适配器localDB new LocalDB(new IndexDbAdapter(DbConfig.Name, DbConfig.Path), indexedDb, true);
// #endifconsole.log(当前环境注册的本地数据库为,localDB.name)// 初始化表
localDB.initDb(tableConfig)
export default localDB;api应用
testService
import {request , CallBackFunType} from /utils/request
import { HttpPath } from /enums/constant
import localDB from /plugins/db-plugins
import type LocalDB from /class/DbClass
import { DbTable, DbConfig } from /enums/DbEnums
import BaseApi from /class/baseApiClassclass TestApi extends BaseApi{constructor(table: string, localDB:LocalDB){super(table, localDB)}public save(data: {id: string ,name: string, value: string}) {return request({url: HttpPath.App /dict/type,method: post,data}, async (requestConfig: any) {console.log(离线回调操作: , requestConfig)const res await this.verifyTable(true);return new PromiseCallBackFunTypeany((resolve, reject) {if(res.code ! 200){reject(res)}else{// 执行数据库操作this.localDB.Db().insertTableData(DbTable.Test, data).then((res) {if(res){resolve(new CallBackFunType({}).success())}else {reject(new CallBackFunType({}).fail())}}).catch((e:any) {reject(e)})}})})}
}export default new TestApi(DbTable.Test, localDB);
页面使用
templateview测试/view
/templatescript langts setupimport { onLoad } from dcloudio/uni-app;import TestApi from /api/testServiceonLoad(() {TestApi.save({id:1231,name: 2321, value: dasdas}).then((res:any) {console.log(res)})})
/scriptstyle langscss
/style执行效果 以浏览器(indexedDb)为例