diff --git a/package.json b/package.json index 73d55090858f7deecd8a6f5a8618128795af14f8..9b9a8c46af37e474029a1a27332e1a8dacdd4acd 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "node": ">=10.0.0" }, "devDependencies": { - "@dcloudio/types": "^2.2.11", + "@dcloudio/types": "^2.2.12", "@microsoft/api-extractor": "^7.13.2", "@rollup/plugin-alias": "^3.1.1", "@rollup/plugin-commonjs": "^17.0.0", diff --git a/packages/uni-app-plus/src/service/api/index.ts b/packages/uni-app-plus/src/service/api/index.ts index f803dba3df677ad4b3440500c659526c18029ea0..beaf7d062782976de4f2ffc2e6530ce9df3fb893 100644 --- a/packages/uni-app-plus/src/service/api/index.ts +++ b/packages/uni-app-plus/src/service/api/index.ts @@ -1,3 +1,4 @@ +export * from './storage/storage' export * from './file/getFileInfo' export * from './device/compass' diff --git a/packages/uni-app-plus/src/service/api/storage/storage.ts b/packages/uni-app-plus/src/service/api/storage/storage.ts new file mode 100644 index 0000000000000000000000000000000000000000..40d39e9d38abdd7c451c1b8e2518fee924a37a3a --- /dev/null +++ b/packages/uni-app-plus/src/service/api/storage/storage.ts @@ -0,0 +1,242 @@ +import { + defineSyncApi, + defineAsyncApi, + API_SET_STORAGE_SYNC, + API_TYPE_SET_STORAGE_SYNC, + API_SET_STORAGE, + API_TYPE_SET_STORAGE, + SetStorageProtocol, + SetStorageSyncProtocol, + API_GET_STORAGE_SYNC, + GetStorageSyncProtocol, + API_TYPE_GET_STORAGE_SYNC, + API_GET_STORAGE, + GetStorageProtocol, + API_TYPE_GET_STORAGE, + API_TYPE_REMOVE_STORAGE_SYNC, + API_REMOVE_STORAGE, + API_TYPE_REMOVE_STORAGE, + RemoveStorageSyncProtocol, + RemoveStorageProtocol, +} from '@dcloudio/uni-api' + +import { warpPlusErrorCallback } from '../../../helpers/plus' + +const STORAGE_DATA_TYPE = '__TYPE' +const STORAGE_KEYS = 'uni-storage-keys' + +function parseValue(value: any) { + const types = ['object', 'string', 'number', 'boolean', 'undefined'] + try { + const object = typeof value === 'string' ? JSON.parse(value) : value + const type = object.type + if (types.indexOf(type) >= 0) { + const keys = Object.keys(object) + if (keys.length === 2 && 'data' in object) { + // eslint-disable-next-line valid-typeof + if (typeof object.data === type) { + return object.data + } + // eslint-disable-next-line no-useless-escape + if ( + type === 'object' && + /^\d{4}-\d{2}-\d{2}T\d{2}\:\d{2}\:\d{2}\.\d{3}Z$/.test(object.data) + ) { + // ISO 8601 格式返回 Date + return new Date(object.data) + } + } else if (keys.length === 1) { + return '' + } + } + } catch (error) {} +} + +export const setStorageSync = defineSyncApi( + API_SET_STORAGE_SYNC, + (key, data) => { + const type = typeof data + const value = + type === 'string' + ? data + : JSON.stringify({ + type, + data: data, + }) + try { + if (type === 'string' && parseValue(value) !== undefined) { + plus.storage.setItem(key + STORAGE_DATA_TYPE, type) + } else { + plus.storage.removeItem(key + STORAGE_DATA_TYPE) + } + plus.storage.setItem(key, value) + } catch (error) {} + }, + SetStorageSyncProtocol +) + +export const setStorage = defineAsyncApi( + API_SET_STORAGE, + ({ key, data }, { resolve, reject }) => { + const type = typeof data + const value = + type === 'string' + ? data + : JSON.stringify({ + type, + data: data, + }) + try { + const storage = plus.storage + if (type === 'string' && parseValue(value) !== undefined) { + storage.setItemAsync(key + STORAGE_DATA_TYPE, type) + } else { + storage.removeItemAsync(key + STORAGE_DATA_TYPE) + } + storage.setItemAsync(key, value, resolve, warpPlusErrorCallback(reject)) + } catch (error) { + reject(error.message) + } + }, + SetStorageProtocol +) + +function parseGetStorage(type: string, value: string) { + let data: any = value + if ( + type !== 'string' || + (type === 'string' && value === '{"type":"undefined"}') + ) { + try { + // 兼容H5和V3初期历史格式 + let object = JSON.parse(value) + const result = parseValue(object) + if (result !== undefined) { + data = result + } else if (type) { + // 兼容App端历史格式 + data = object + if (typeof object === 'string') { + object = JSON.parse(object) + const objectType = typeof object + if (objectType === 'number' && type === 'date') { + data = new Date(object) + } else if ( + objectType === + (['null', 'array'].indexOf(type) < 0 ? type : 'object') + ) { + data = object + } + } + } + } catch (error) {} + } + return data +} + +export const getStorageSync = defineSyncApi( + API_GET_STORAGE_SYNC, + (key: string, t: boolean) => { + const value = plus.storage.getItem(key) + const typeOrigin = plus.storage.getItem(key + STORAGE_DATA_TYPE) || '' + const type = typeOrigin.toLowerCase() + if (typeof value !== 'string') { + return '' + } + return parseGetStorage(type, value) + }, + GetStorageSyncProtocol +) + +export const getStorage = defineAsyncApi( + API_GET_STORAGE, + ({ key }, { resolve, reject }) => { + const storage = plus.storage + storage.getItemAsync( + key, + function (res) { + storage.getItemAsync( + key + STORAGE_DATA_TYPE, + function (typeRes) { + const typeOrigin = typeRes.data || '' + const type = typeOrigin.toLowerCase() + resolve({ + data: parseGetStorage(type, res.data), + }) + }, + function () { + const type = '' + resolve({ + data: parseGetStorage(type, res.data), + }) + } + ) + }, + warpPlusErrorCallback(reject) + ) + }, + GetStorageProtocol +) + +export const removeStorageSync = defineSyncApi( + API_REMOVE_STORAGE, + (key) => { + plus.storage.removeItem(key + STORAGE_DATA_TYPE) + plus.storage.removeItem(key) + }, + RemoveStorageSyncProtocol +) + +export const removeStorage = defineAsyncApi( + API_REMOVE_STORAGE, + ({ key }, { resolve, reject }) => { + // 兼容App端历史格式 + plus.storage.removeItemAsync(key + STORAGE_DATA_TYPE) + plus.storage.removeItemAsync(key, resolve, warpPlusErrorCallback(reject)) + }, + RemoveStorageProtocol +) + +export const clearStorageSync = ( + defineSyncApi('clearStorageSync', () => { + plus.storage.clear() + }) +) + +export const clearStorage = ( + defineAsyncApi('clearStorage', (_, { resolve, reject }) => { + plus.storage.clearAsync(resolve, warpPlusErrorCallback(reject)) + }) +) + +export const getStorageInfoSync = ( + defineSyncApi('getStorageInfoSync', () => { + const length = plus.storage.getLength() || 0 + const keys: string[] = [] + let currentSize = 0 + for (let index = 0; index < length; index++) { + const key = plus.storage.key(index) + if ( + key !== STORAGE_KEYS && + (key.indexOf(STORAGE_DATA_TYPE) < 0 || + key.indexOf(STORAGE_DATA_TYPE) + STORAGE_DATA_TYPE.length !== + key.length) + ) { + const value = plus.storage.getItem(key) + currentSize += key.length + value.length + keys.push(key) + } + } + return { + keys, + currentSize: Math.ceil((currentSize * 2) / 1024), + limitSize: Number.MAX_VALUE, + } + }) +) + +export const getStorageInfo = ( + defineAsyncApi('getStorageInfo', (_, { resolve }) => { + resolve(getStorageInfoSync()) + }) +) diff --git a/yarn.lock b/yarn.lock index 653d0246bc3c52151c9894e191c2664c915a3389..622ad723195be412d75dcdfa8676bed74b2440ac 100644 --- a/yarn.lock +++ b/yarn.lock @@ -312,10 +312,9 @@ exec-sh "^0.3.2" minimist "^1.2.0" -"@dcloudio/types@^2.2.11": - version "2.2.11" - resolved "https://registry.nlark.com/@dcloudio/types/download/@dcloudio/types-2.2.11.tgz#241fed0bbe0da07b790edf766675db5b699c130e" - integrity sha1-JB/tC74NoHt5Dt92ZnXbW2mcEw4= +"@dcloudio/types@^2.2.12": + version "2.2.12" + resolved "https://registry.yarnpkg.com/@dcloudio/types/-/types-2.2.12.tgz#b65c33a84fa011d67a2af79b458abe060b2b98d4" "@eslint/eslintrc@^0.4.2": version "0.4.2" @@ -5626,7 +5625,6 @@ merge2@^1.2.3, merge2@^1.3.0: merge@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/merge/-/merge-2.1.1.tgz#59ef4bf7e0b3e879186436e8481c06a6c162ca98" - integrity sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w== methods@~1.1.2: version "1.1.2"