11 changed files with 238 additions and 32 deletions
@ -0,0 +1,81 @@
@@ -0,0 +1,81 @@
|
||||
import { deepCopy } from './caller'; |
||||
|
||||
const db_name = 'transmigration_game'; |
||||
export const store_name_archive = 'archive'; |
||||
export const key_name_archive = 'version'; |
||||
|
||||
const version = 1; |
||||
let db; |
||||
/** |
||||
* 打开数据库 |
||||
* @param {object} dbName 数据库的名字 |
||||
* @param {string} version 数据库的版本 |
||||
* @return {object} 该函数会返回一个数据库实例 |
||||
*/ |
||||
function openDB() { |
||||
return new Promise((resolve, reject) => { |
||||
// 兼容浏览器
|
||||
var indexedDB = window.indexedDB; |
||||
|
||||
// 打开数据库,若没有则会创建
|
||||
const request = indexedDB.open(db_name, version); |
||||
// 数据库打开成功回调
|
||||
request.onsuccess = function (e) { |
||||
db = request.result; // 数据库对象
|
||||
console.log('数据库打开成功'); |
||||
resolve(db); |
||||
}; |
||||
// 数据库打开失败的回调
|
||||
request.onerror = function (e) { |
||||
console.log('数据库打开报错'); |
||||
}; |
||||
// 数据库有更新时候的回调
|
||||
request.onupgradeneeded = function (e) { |
||||
// 数据库创建或升级的时候会触发
|
||||
console.log('onupgradeneeded'); |
||||
db = request.result; // 数据库对象
|
||||
createArchiveStore(); |
||||
}; |
||||
}); |
||||
} |
||||
|
||||
const createArchiveStore = () => { |
||||
if (!db.objectStoreNames.contains(store_name_archive)) { |
||||
const objectStore = db.createObjectStore(store_name_archive, { keyPath: key_name_archive }); |
||||
// 创建索引,在后面查询数据的时候可以根据索引查
|
||||
// objectStore.createIndex(index_name_equip, index_name_equip, { unique: false });
|
||||
} |
||||
}; |
||||
|
||||
await openDB(); |
||||
|
||||
export const insertToStore = (storeName, data) => { |
||||
data = deepCopy(data); |
||||
return new Promise<boolean>((resolve, reject) => { |
||||
const request = db |
||||
.transaction([storeName], 'readwrite') // 事务对象 指定表格名称和操作模式("只读"或"读写")
|
||||
.objectStore(storeName) // 仓库对象
|
||||
.put(data); |
||||
|
||||
request.onsuccess = function (event) { |
||||
resolve(true); |
||||
}; |
||||
|
||||
request.onerror = function (event) { |
||||
resolve(false); |
||||
}; |
||||
}); |
||||
}; |
||||
|
||||
export const getFromStore = (storeName, id) => { |
||||
return new Promise((resolve, reject) => { |
||||
const store = db.transaction([storeName], 'readonly').objectStore(storeName); |
||||
const request = store.get(id); |
||||
request.onsuccess = (e) => { |
||||
resolve(request.result); |
||||
}; |
||||
request.onerror = (e) => { |
||||
resolve([]); |
||||
}; |
||||
}); |
||||
}; |
@ -0,0 +1,75 @@
@@ -0,0 +1,75 @@
|
||||
import { Equip, Player, RebornPoints } from '@/config'; |
||||
import { getFromStore, insertToStore, store_name_archive } from './IndexedDB'; |
||||
import { uuid } from './random'; |
||||
import { version } from 'vue'; |
||||
const archive_version = '1.0'; |
||||
const archive_version_strengthen = '1.0_flag'; |
||||
|
||||
export class GameArchive { |
||||
version: String; |
||||
equips: Equip[]; |
||||
lv: number; |
||||
coins: number; |
||||
grid: any[]; |
||||
autoSell: string[]; |
||||
shop: any[]; |
||||
reborn: RebornPoints; |
||||
|
||||
constructor(player: Player, grid: any[], autoSell: any[], shop: any[], reboren: RebornPoints) { |
||||
this.version = archive_version; |
||||
this.equips = [player.weapon, player.armor, player.ring, player.neck, player.jewelry, player.pants, player.shoes, player.bracers]; |
||||
this.lv = player.lv; |
||||
this.coins = player.coins; |
||||
this.grid = grid; |
||||
this.autoSell = autoSell; |
||||
this.shop = shop; |
||||
this.reborn = reboren; |
||||
} |
||||
} |
||||
|
||||
export const saveArchive = (state) => { |
||||
const archive = new GameArchive(state.playerAttribute, state.grid, state.autoSell, state.shop, state.rebornPoints); |
||||
getFromStore(store_name_archive, archive_version_strengthen).then((flag: any) => { |
||||
const time = new Date().getTime(); |
||||
if (!flag || !flag.time || flag.time + 10 * 60 * 1000 < time) { |
||||
flag = { version: archive_version_strengthen, time: time }; |
||||
} |
||||
const equips = new Array(); |
||||
Array.prototype.push.apply(equips, archive.equips); |
||||
Array.prototype.push.apply(equips, archive.grid); |
||||
equips.forEach((equip) => { |
||||
if (!equip) return; |
||||
|
||||
if (equip.strengthenLv > 0 && !equip.id) { |
||||
equip.id = uuid(); |
||||
} |
||||
if (equip.id) { |
||||
flag[equip.id] = equip.strengthenLv; |
||||
} |
||||
}); |
||||
insertToStore(store_name_archive, archive); |
||||
insertToStore(store_name_archive, flag); |
||||
}); |
||||
}; |
||||
|
||||
export const checkImportArchive = async (data): Promise<void> => { |
||||
getFromStore(store_name_archive, archive_version_strengthen).then((rsp: any) => { |
||||
if (!rsp) return; |
||||
const equips = new Array(); |
||||
Array.prototype.push.apply(equips, data.equips); |
||||
Array.prototype.push.apply(equips, data.grid); |
||||
equips.forEach((equip) => { |
||||
if (!equip || !equip.id) return; |
||||
const slv = rsp[equip.id]; |
||||
slv && (equip.strengthenLv = slv); |
||||
}); |
||||
}); |
||||
}; |
||||
|
||||
export const getArchive = () => { |
||||
return new Promise((resolve, reject) => { |
||||
getFromStore(store_name_archive, archive_version).then((rsp: any) => { |
||||
resolve(rsp); |
||||
}); |
||||
}); |
||||
}; |
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
import CryptoJS from 'crypto-js'; |
||||
/** |
||||
* AES-256-CBC对称加密 |
||||
* @param text {string} 要加密的明文 |
||||
* @param secretKey {string} 密钥,43位随机大小写与数字 |
||||
* @returns {string} 加密后的密文,Base64格式 |
||||
*/ |
||||
export const AES_CBC_ENCRYPT = (text, secretKey) => { |
||||
var keyHex = CryptoJS.enc.Base64.parse(secretKey); |
||||
var ivHex = keyHex.clone(); |
||||
// 前16字节作为向量
|
||||
ivHex.sigBytes = 16; |
||||
ivHex.words.splice(4); |
||||
var messageHex = CryptoJS.enc.Utf8.parse(text); |
||||
var encrypted = CryptoJS.AES.encrypt(messageHex, keyHex, { |
||||
iv: ivHex, |
||||
mode: CryptoJS.mode.CBC, |
||||
padding: CryptoJS.pad.Pkcs7, |
||||
}); |
||||
return encrypted.toString(); |
||||
}; |
||||
|
||||
/** |
||||
* AES-256-CBC对称解密 |
||||
* @param textBase64 {string} 要解密的密文,Base64格式 |
||||
* @param secretKey {string} 密钥,43位随机大小写与数字 |
||||
* @returns {string} 解密后的明文 |
||||
*/ |
||||
export const AES_CBC_DECRYPT = (textBase64, secretKey) => { |
||||
var keyHex = CryptoJS.enc.Base64.parse(secretKey); |
||||
var ivHex = keyHex.clone(); |
||||
// 前16字节作为向量
|
||||
ivHex.sigBytes = 16; |
||||
ivHex.words.splice(4); |
||||
var decrypt = CryptoJS.AES.decrypt(textBase64, keyHex, { |
||||
iv: ivHex, |
||||
mode: CryptoJS.mode.CBC, |
||||
padding: CryptoJS.pad.Pkcs7, |
||||
}); |
||||
return CryptoJS.enc.Utf8.stringify(decrypt); |
||||
}; |
Loading…
Reference in new issue