af-mobile-client-vue3 1.0.54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +38 -0
- package/.env +7 -0
- package/.env.development +4 -0
- package/.env.envoiceShow +7 -0
- package/.env.production +7 -0
- package/.husky/commit-msg +1 -0
- package/.husky/pre-commit +1 -0
- package/.vscode/extensions.json +7 -0
- package/.vscode/settings.json +61 -0
- package/LICENSE +21 -0
- package/README.md +181 -0
- package/af-example-mobile-vue-web.iml +9 -0
- package/build/vite/index.ts +91 -0
- package/build/vite/vconsole.ts +44 -0
- package/eslint.config.js +7 -0
- package/index.html +17 -0
- package/mock/data.ts +20 -0
- package/mock/index.ts +5 -0
- package/mock/modules/prose.mock.ts +16 -0
- package/mock/modules/user.mock.ts +152 -0
- package/netlify.toml +12 -0
- package/package.json +107 -0
- package/public/favicon-dark.svg +4 -0
- package/public/favicon.ico +0 -0
- package/public/favicon.svg +4 -0
- package/public/pwa-192x192.png +0 -0
- package/public/pwa-512x512.png +0 -0
- package/public/safari-pinned-tab.svg +32 -0
- package/scripts/verifyCommit.js +19 -0
- package/src/App.vue +43 -0
- package/src/api/mock/index.ts +30 -0
- package/src/api/user/index.ts +40 -0
- package/src/assets/common/default-user-profile.png +0 -0
- package/src/assets/img/apps/apply-web.png +0 -0
- package/src/assets/img/apps/example-web.png +0 -0
- package/src/assets/img/apps/iot-web.png +0 -0
- package/src/assets/img/apps/linepatrol-web.png +0 -0
- package/src/assets/img/apps/monitor-web.png +0 -0
- package/src/assets/img/apps/oa-web.png +0 -0
- package/src/assets/img/apps/revenue-web.png +0 -0
- package/src/assets/img/apps/safe-check-web.png +0 -0
- package/src/assets/img/component/logo.png +0 -0
- package/src/assets/img/home/banner1.png +0 -0
- package/src/assets/img/home/banner2.png +0 -0
- package/src/assets/img/home/banner3.png +0 -0
- package/src/assets/img/home/banner4.png +0 -0
- package/src/assets/img/home/notice/icon.png +0 -0
- package/src/assets/img/user/login/background-shadow-1.svg +20 -0
- package/src/assets/img/user/login/logo-background.svg +20 -0
- package/src/assets/img/user/login/logo.png +0 -0
- package/src/assets/img/user/my/exit-login.png +0 -0
- package/src/assets/img/user/my/setting-arrow.png +0 -0
- package/src/assets/img/user/my/setting.png +0 -0
- package/src/bootstrap.ts +32 -0
- package/src/components/core/App/MicroAppView.vue +59 -0
- package/src/components/core/BeautifulLoading/index.vue +47 -0
- package/src/components/core/NavBar/index.vue +12 -0
- package/src/components/core/SvgIcon/index.vue +61 -0
- package/src/components/core/Tabbar/index.vue +38 -0
- package/src/components/core/Uploader/index.vue +104 -0
- package/src/components/core/XMultiSelect/index.vue +196 -0
- package/src/components/core/XSelect/index.vue +130 -0
- package/src/components/data/XBadge/index.vue +85 -0
- package/src/components/data/XCellDetail/index.vue +106 -0
- package/src/components/data/XCellList/index.vue +358 -0
- package/src/components/data/XCellListFilter/index.vue +392 -0
- package/src/components/data/XForm/index.vue +127 -0
- package/src/components/data/XFormItem/index.vue +472 -0
- package/src/components/data/XReportForm/XReportFormJsonRender.vue +220 -0
- package/src/components/data/XReportForm/index.vue +1058 -0
- package/src/components/layout/NormalDataLayout/index.vue +70 -0
- package/src/components/layout/TabBarLayout/index.vue +40 -0
- package/src/components.d.ts +53 -0
- package/src/enums/requestEnum.ts +25 -0
- package/src/env.d.ts +16 -0
- package/src/font-style/PingFangSC-Regular.woff2 +0 -0
- package/src/font-style/font.css +4 -0
- package/src/hooks/useCommon.ts +9 -0
- package/src/hooks/useLogin.ts +97 -0
- package/src/icons/svg/bird.svg +1 -0
- package/src/icons/svg/check-in.svg +33 -0
- package/src/icons/svg/dark.svg +5 -0
- package/src/icons/svg/github.svg +5 -0
- package/src/icons/svg/light.svg +5 -0
- package/src/icons/svg/link.svg +5 -0
- package/src/icons/svg/loadError.svg +1 -0
- package/src/icons/svg/notFound.svg +1 -0
- package/src/icons/svgo.yml +22 -0
- package/src/layout/PageLayout.vue +51 -0
- package/src/layout/SingleLayout.vue +35 -0
- package/src/locales/en-US.json +25 -0
- package/src/locales/zh-CN.json +25 -0
- package/src/main.ts +48 -0
- package/src/plugins/AppData.ts +38 -0
- package/src/plugins/GetLoginInfoService.ts +10 -0
- package/src/plugins/index.ts +11 -0
- package/src/router/README.md +8 -0
- package/src/router/guards.ts +60 -0
- package/src/router/index.ts +60 -0
- package/src/router/invoiceRoutes.ts +33 -0
- package/src/router/routes.ts +84 -0
- package/src/services/api/Login.ts +6 -0
- package/src/services/api/common.ts +98 -0
- package/src/services/api/index.ts +7 -0
- package/src/services/api/manage.ts +8 -0
- package/src/services/restTools.ts +37 -0
- package/src/settings.ts +1 -0
- package/src/stores/index.ts +7 -0
- package/src/stores/modules/cachedView.ts +31 -0
- package/src/stores/modules/counter.ts +19 -0
- package/src/stores/modules/routeTransitionName.ts +26 -0
- package/src/stores/modules/setting.ts +28 -0
- package/src/stores/modules/user.ts +180 -0
- package/src/stores/mutation-type.ts +7 -0
- package/src/styles/app.less +67 -0
- package/src/styles/login.less +81 -0
- package/src/typing.ts +3 -0
- package/src/utils/Storage.ts +124 -0
- package/src/utils/authority-utils.ts +87 -0
- package/src/utils/common.ts +41 -0
- package/src/utils/crypto.ts +39 -0
- package/src/utils/dataUtil.ts +42 -0
- package/src/utils/dictUtil.ts +51 -0
- package/src/utils/http/index.ts +158 -0
- package/src/utils/i18n.ts +41 -0
- package/src/utils/indexedDB.ts +180 -0
- package/src/utils/local-storage.ts +9 -0
- package/src/utils/mobileUtil.ts +26 -0
- package/src/utils/progress.ts +19 -0
- package/src/utils/routerUtil.ts +271 -0
- package/src/utils/set-page-title.ts +7 -0
- package/src/utils/validate.ts +6 -0
- package/src/views/chat/index.vue +153 -0
- package/src/views/common/LoadError.vue +64 -0
- package/src/views/common/NotFound.vue +68 -0
- package/src/views/component/EvaluateRecordView/index.vue +40 -0
- package/src/views/component/XCellDetailView/index.vue +216 -0
- package/src/views/component/XCellListView/index.vue +36 -0
- package/src/views/component/XFormView/index.vue +478 -0
- package/src/views/component/XReportFormIframeView/index.vue +45 -0
- package/src/views/component/XReportFormView/index.vue +295 -0
- package/src/views/component/index.vue +111 -0
- package/src/views/component/menu.vue +117 -0
- package/src/views/component/notice.vue +46 -0
- package/src/views/component/topNav.vue +36 -0
- package/src/views/invoiceShow/index.vue +62 -0
- package/src/views/user/login/ForgetPasswordForm.vue +93 -0
- package/src/views/user/login/LoginForm.vue +145 -0
- package/src/views/user/login/LoginTitle.vue +68 -0
- package/src/views/user/login/LoginWave.vue +109 -0
- package/src/views/user/login/index.vue +22 -0
- package/src/views/user/my/index.vue +230 -0
- package/src/vue-router.d.ts +9 -0
- package/tsconfig.json +43 -0
- package/uno.config.ts +32 -0
- package/vite.config.ts +110 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 字典工具
|
|
3
|
+
*/
|
|
4
|
+
import { getConfigByName } from '@af-mobile-client-vue3/services/api/common'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 获取字典
|
|
8
|
+
* @param configName 配置名
|
|
9
|
+
* @param callback 获取到字典的回调
|
|
10
|
+
*/
|
|
11
|
+
export function getDict(configName: string, callback: Function) {
|
|
12
|
+
getConfigByName(configName, (result) => {
|
|
13
|
+
if (result != null && result.value) {
|
|
14
|
+
callback(result.value)
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
console.warn(`dict [${configName}] not found`)
|
|
18
|
+
callback(null)
|
|
19
|
+
}
|
|
20
|
+
})
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function getDictItemByValue(configName: string, value: string, callback: Function) {
|
|
24
|
+
getDict(configName, (result) => {
|
|
25
|
+
if (result != null) {
|
|
26
|
+
for (const item of result) {
|
|
27
|
+
if (item.value.toString() === value) {
|
|
28
|
+
callback(item)
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
console.warn(`dict [${configName}] 's value [${value}] not found`)
|
|
33
|
+
}
|
|
34
|
+
callback(null)
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function getDictItemByLabel(configName: string, label: string, callback: Function) {
|
|
39
|
+
getDict(configName, (result) => {
|
|
40
|
+
if (result != null) {
|
|
41
|
+
for (const item of result) {
|
|
42
|
+
if (item.label.toString() === label) {
|
|
43
|
+
callback(item)
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
console.warn(`dict [${configName}] 's label [${label}] not found`)
|
|
48
|
+
}
|
|
49
|
+
callback(null)
|
|
50
|
+
})
|
|
51
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import Axios, { type AxiosError, type AxiosInstance, type AxiosRequestConfig, type AxiosResponse } from 'axios'
|
|
2
|
+
import { showToast } from 'vant'
|
|
3
|
+
import { ContentTypeEnum, ResultEnum } from '@af-mobile-client-vue3/enums/requestEnum'
|
|
4
|
+
import { ACCESS_TOKEN } from '@af-mobile-client-vue3/stores/mutation-type'
|
|
5
|
+
import { useUserStore } from '@af-mobile-client-vue3/stores/modules/user'
|
|
6
|
+
|
|
7
|
+
// 默认 axios 实例请求配置
|
|
8
|
+
const configDefault = {
|
|
9
|
+
headers: {
|
|
10
|
+
'Content-Type': ContentTypeEnum.JSON,
|
|
11
|
+
},
|
|
12
|
+
// 请求超时时间
|
|
13
|
+
timeout: 20000,
|
|
14
|
+
// API 请求的默认前缀
|
|
15
|
+
baseURL: import.meta.env.VITE_APP_API_BASE_URL,
|
|
16
|
+
data: {},
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
class Http {
|
|
20
|
+
// 当前实例
|
|
21
|
+
private static axiosInstance: AxiosInstance
|
|
22
|
+
// 请求配置
|
|
23
|
+
private static axiosConfigDefault: AxiosRequestConfig
|
|
24
|
+
|
|
25
|
+
// 请求拦截
|
|
26
|
+
private httpInterceptorsRequest(): void {
|
|
27
|
+
Http.axiosInstance.interceptors.request.use(
|
|
28
|
+
(config) => {
|
|
29
|
+
// 发送请求前,可在此让每个请求携带自定义 token, 请根据实际情况修改
|
|
30
|
+
const savedToken = useUserStore().getToken()
|
|
31
|
+
// 如果 token 存在
|
|
32
|
+
if (savedToken)
|
|
33
|
+
config.headers[ACCESS_TOKEN] = savedToken
|
|
34
|
+
return config
|
|
35
|
+
},
|
|
36
|
+
(error: AxiosError) => {
|
|
37
|
+
showToast({
|
|
38
|
+
message: error.message,
|
|
39
|
+
position: 'bottom',
|
|
40
|
+
})
|
|
41
|
+
return Promise.reject(error)
|
|
42
|
+
},
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 响应拦截
|
|
47
|
+
private httpInterceptorsResponse(): void {
|
|
48
|
+
Http.axiosInstance.interceptors.response.use(
|
|
49
|
+
async (response: AxiosResponse) => {
|
|
50
|
+
const compatible = import.meta.env.VITE_APP_COMPATIBLE
|
|
51
|
+
if (compatible !== 'V4')
|
|
52
|
+
return response.data
|
|
53
|
+
// 与后端协定的返回字段
|
|
54
|
+
const { code, msg, data } = response.data
|
|
55
|
+
// 临时向v3请求上传服务,因为没有code,未来会改
|
|
56
|
+
if (code === undefined && response.data.id !== undefined)
|
|
57
|
+
return response.data
|
|
58
|
+
// 判断请求是否成功
|
|
59
|
+
const isSuccess
|
|
60
|
+
= code === ResultEnum.SUCCESS
|
|
61
|
+
if (isSuccess) {
|
|
62
|
+
return data
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
if (code === 401) {
|
|
66
|
+
showToast({
|
|
67
|
+
message: '登录态已失效,请重新登录',
|
|
68
|
+
position: 'bottom',
|
|
69
|
+
})
|
|
70
|
+
await useUserStore().logout()
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
showToast({
|
|
74
|
+
message: msg,
|
|
75
|
+
position: 'bottom',
|
|
76
|
+
})
|
|
77
|
+
console.error(`请求失败,返回结果:${msg}`)
|
|
78
|
+
}
|
|
79
|
+
return Promise.reject(response.data)
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
(error: AxiosError) => {
|
|
83
|
+
// 处理 HTTP 网络错误
|
|
84
|
+
let message: string = error.response?.data as string
|
|
85
|
+
if (!message) {
|
|
86
|
+
// HTTP 状态码
|
|
87
|
+
const status = error.response?.status
|
|
88
|
+
switch (status) {
|
|
89
|
+
case 400:
|
|
90
|
+
message = '请求错误'
|
|
91
|
+
break
|
|
92
|
+
case 401:
|
|
93
|
+
message = '未授权,请登录'
|
|
94
|
+
break
|
|
95
|
+
case 403:
|
|
96
|
+
message = '拒绝访问'
|
|
97
|
+
break
|
|
98
|
+
case 404:
|
|
99
|
+
message = `请求地址出错: ${error.response?.config?.url}`
|
|
100
|
+
break
|
|
101
|
+
case 408:
|
|
102
|
+
message = '请求超时'
|
|
103
|
+
break
|
|
104
|
+
case 500:
|
|
105
|
+
message = '服务器内部错误'
|
|
106
|
+
break
|
|
107
|
+
case 501:
|
|
108
|
+
message = '服务未实现'
|
|
109
|
+
break
|
|
110
|
+
case 502:
|
|
111
|
+
message = '网关错误'
|
|
112
|
+
break
|
|
113
|
+
case 503:
|
|
114
|
+
message = '服务不可用'
|
|
115
|
+
break
|
|
116
|
+
case 504:
|
|
117
|
+
message = '网关超时'
|
|
118
|
+
break
|
|
119
|
+
case 505:
|
|
120
|
+
message = 'HTTP版本不受支持'
|
|
121
|
+
break
|
|
122
|
+
default:
|
|
123
|
+
message = '网络连接故障'
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
showToast({
|
|
127
|
+
message,
|
|
128
|
+
position: 'bottom',
|
|
129
|
+
})
|
|
130
|
+
return Promise.reject(error)
|
|
131
|
+
},
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
constructor(config: AxiosRequestConfig) {
|
|
136
|
+
Http.axiosConfigDefault = config
|
|
137
|
+
Http.axiosInstance = Axios.create(config)
|
|
138
|
+
this.httpInterceptorsRequest()
|
|
139
|
+
this.httpInterceptorsResponse()
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// 通用请求函数
|
|
143
|
+
public request<T>(paramConfig: AxiosRequestConfig): Promise<T> {
|
|
144
|
+
const config = { ...Http.axiosConfigDefault, ...paramConfig }
|
|
145
|
+
return new Promise((resolve, reject) => {
|
|
146
|
+
Http.axiosInstance
|
|
147
|
+
.request(config)
|
|
148
|
+
.then((response: any) => {
|
|
149
|
+
resolve(response)
|
|
150
|
+
})
|
|
151
|
+
.catch((error) => {
|
|
152
|
+
reject(error)
|
|
153
|
+
})
|
|
154
|
+
})
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export const http = new Http(configDefault)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// // import { createI18n } from 'vue-i18n'
|
|
2
|
+
// import enUS from 'vant/es/locale/lang/en-US'
|
|
3
|
+
// import zhCN from 'vant/es/locale/lang/zh-CN'
|
|
4
|
+
//
|
|
5
|
+
// /**
|
|
6
|
+
// * All i18n resources specified in the plugin `include` option can be loaded
|
|
7
|
+
// * at once using the import syntax
|
|
8
|
+
// */
|
|
9
|
+
// // import messages from '@intlify/unplugin-vue-i18n/messages'
|
|
10
|
+
// import { Locale, type PickerColumn } from 'vant'
|
|
11
|
+
//
|
|
12
|
+
// // export const i18n = createI18n({
|
|
13
|
+
// // locale: localStorage.getItem('language') || navigator.language,
|
|
14
|
+
// // fallbackLocale: 'zhCN',
|
|
15
|
+
// // messages,
|
|
16
|
+
// // })
|
|
17
|
+
//
|
|
18
|
+
// /** 多语言 picker columns */
|
|
19
|
+
// export const languageColumns: PickerColumn = [
|
|
20
|
+
// { text: '简体中文', value: 'zh-CN' },
|
|
21
|
+
// { text: 'English', value: 'en-US' },
|
|
22
|
+
// ]
|
|
23
|
+
//
|
|
24
|
+
// /** 当前语言 */
|
|
25
|
+
// export const locale = computed({
|
|
26
|
+
// get() {
|
|
27
|
+
// return (i18n.global.locale as unknown as Ref<string>).value
|
|
28
|
+
// },
|
|
29
|
+
// set(language: string) {
|
|
30
|
+
// localStorage.setItem('language', language);
|
|
31
|
+
// (i18n.global.locale as unknown as Ref<string>).value = language
|
|
32
|
+
// Locale.use(language)
|
|
33
|
+
// },
|
|
34
|
+
// })
|
|
35
|
+
//
|
|
36
|
+
// // 载入 vant 语言包
|
|
37
|
+
// Locale.use('zh-CN', zhCN)
|
|
38
|
+
// Locale.use('en-US', enUS)
|
|
39
|
+
//
|
|
40
|
+
// // 根据当前语言切换 vant 语言包
|
|
41
|
+
// Locale.use(locale.value)
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
// indexDB 存储
|
|
2
|
+
import { post } from '@af-mobile-client-vue3/services/restTools'
|
|
3
|
+
|
|
4
|
+
// 避免重复请求相同配置key的锁
|
|
5
|
+
const locks: any = {}
|
|
6
|
+
|
|
7
|
+
export const indexedDB = {
|
|
8
|
+
db: undefined,
|
|
9
|
+
indexedDB: window.indexedDB,
|
|
10
|
+
IDBKeyRange: window.IDBKeyRange, // 键范围
|
|
11
|
+
openDB(callback: Function) {
|
|
12
|
+
// 建立或打开数据库,建立对象存储空间(ObjectStore)
|
|
13
|
+
if (this.db) {
|
|
14
|
+
callback(this.db)
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
const version = 1
|
|
18
|
+
const request = this.indexedDB.open('view', version)
|
|
19
|
+
|
|
20
|
+
request.onerror = function (e: any) {
|
|
21
|
+
console.error(`打开数据库失败:${e.currentTarget.error.message}`)
|
|
22
|
+
}
|
|
23
|
+
request.onsuccess = function (e: any) {
|
|
24
|
+
this.db = e.target.result
|
|
25
|
+
callback(this.db)
|
|
26
|
+
}
|
|
27
|
+
request.onupgradeneeded = function (e: any) {
|
|
28
|
+
const db = e.target.result
|
|
29
|
+
if (!db.objectStoreNames.contains('metaCache')) {
|
|
30
|
+
// 没有该对象空间时创建该对象空间
|
|
31
|
+
db.createObjectStore('metaCache', {
|
|
32
|
+
keyPath: 'key',
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
deleteDB(dbname: string) {
|
|
39
|
+
// 删除数据库
|
|
40
|
+
this.indexedDB.deleteDatabase(dbname)
|
|
41
|
+
},
|
|
42
|
+
closeDB() {
|
|
43
|
+
if (!this.db)
|
|
44
|
+
this.db.close()
|
|
45
|
+
},
|
|
46
|
+
add(key: string, data: any) {
|
|
47
|
+
// eslint-disable-next-line ts/no-this-alias
|
|
48
|
+
const self = this
|
|
49
|
+
self.openDB((res: IDBDatabase) => {
|
|
50
|
+
const request = res.transaction('metaCache', 'readwrite').objectStore('metaCache').add({
|
|
51
|
+
key,
|
|
52
|
+
data,
|
|
53
|
+
})
|
|
54
|
+
request.onerror = function () {
|
|
55
|
+
self.update(key, data)
|
|
56
|
+
}
|
|
57
|
+
request.onsuccess = function () {
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
},
|
|
61
|
+
update(key: string, data: any) {
|
|
62
|
+
this.openDB((res: IDBDatabase) => {
|
|
63
|
+
const request = res.transaction('metaCache', 'readwrite').objectStore('metaCache').put({
|
|
64
|
+
key,
|
|
65
|
+
data,
|
|
66
|
+
})
|
|
67
|
+
request.onerror = function () {
|
|
68
|
+
console.error('数据更新失败')
|
|
69
|
+
}
|
|
70
|
+
request.onsuccess = function () {
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
},
|
|
74
|
+
get(key: string, callback: Function) {
|
|
75
|
+
this.openDB((res: IDBDatabase) => {
|
|
76
|
+
// 根据存储空间的键找到对应数据
|
|
77
|
+
const store = res.transaction('metaCache', 'readwrite').objectStore('metaCache')
|
|
78
|
+
const request = store.get(key)
|
|
79
|
+
request.onerror = function () {
|
|
80
|
+
}
|
|
81
|
+
request.onsuccess = function (e: any) {
|
|
82
|
+
const result = e.target.result
|
|
83
|
+
if (typeof (callback) === 'function')
|
|
84
|
+
callback(result.data)
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
},
|
|
88
|
+
getByWeb(key: string, url: string, params: any, callback: Function, processFun: Function) {
|
|
89
|
+
// 如果这个键正在被使用,等待它完成
|
|
90
|
+
if (locks[key]) {
|
|
91
|
+
locks[key].then(() => {
|
|
92
|
+
this.getByWeb(key, url, params, callback, processFun)
|
|
93
|
+
})
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// 创建一个新的 Promise
|
|
98
|
+
locks[key] = new Promise<void>((resolve, reject) => {
|
|
99
|
+
// eslint-disable-next-line ts/no-this-alias
|
|
100
|
+
const self = this
|
|
101
|
+
self.openDB((res: IDBDatabase) => {
|
|
102
|
+
// 根据存储空间的键找到对应数据
|
|
103
|
+
const store = res.transaction('metaCache', 'readwrite').objectStore('metaCache')
|
|
104
|
+
const request = store.get(key)
|
|
105
|
+
request.onerror = function (e) {
|
|
106
|
+
reject(e)
|
|
107
|
+
}
|
|
108
|
+
request.onsuccess = function (e: any) {
|
|
109
|
+
const result = e.target.result
|
|
110
|
+
if (!result && url) {
|
|
111
|
+
post(url, params).then((res) => {
|
|
112
|
+
if (processFun)
|
|
113
|
+
res = processFun(res)
|
|
114
|
+
|
|
115
|
+
if (import.meta.env.NODE_ENV === 'production' || key !== 'webMobileConfig')
|
|
116
|
+
self.add(key, res)
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
callback(res)
|
|
120
|
+
}
|
|
121
|
+
catch (e) {
|
|
122
|
+
console.error(e)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// 解锁这个键
|
|
126
|
+
resolve()
|
|
127
|
+
}).catch(() => {
|
|
128
|
+
if (import.meta.env.NODE_ENV === 'production' || key !== 'webMobileConfig')
|
|
129
|
+
self.add(key, null)
|
|
130
|
+
callback(null)
|
|
131
|
+
|
|
132
|
+
// 解锁这个键
|
|
133
|
+
resolve()
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
callback(result.data)
|
|
138
|
+
|
|
139
|
+
// 解锁这个键
|
|
140
|
+
resolve()
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
})
|
|
144
|
+
}).finally(() => {
|
|
145
|
+
// 移除这个键的锁
|
|
146
|
+
delete locks[key]
|
|
147
|
+
})
|
|
148
|
+
},
|
|
149
|
+
delete(key: string) {
|
|
150
|
+
this.openDB((res: IDBDatabase) => {
|
|
151
|
+
// 删除某一条记录
|
|
152
|
+
const request = res.transaction('metaCache', 'readwrite').objectStore('metaCache').delete(key)
|
|
153
|
+
|
|
154
|
+
request.onerror = function () {
|
|
155
|
+
console.error('数据删除失败')
|
|
156
|
+
}
|
|
157
|
+
request.onsuccess = function () {
|
|
158
|
+
}
|
|
159
|
+
})
|
|
160
|
+
},
|
|
161
|
+
clear(callback?: Function) {
|
|
162
|
+
this.openDB((res: IDBDatabase) => {
|
|
163
|
+
// 删除存储空间全部记录
|
|
164
|
+
const request = res.transaction('metaCache', 'readwrite').objectStore('metaCache').clear()
|
|
165
|
+
|
|
166
|
+
request.onerror = function () {
|
|
167
|
+
console.error('数据删除失败')
|
|
168
|
+
}
|
|
169
|
+
request.onsuccess = function () {
|
|
170
|
+
if (typeof callback === 'function')
|
|
171
|
+
callback()
|
|
172
|
+
}
|
|
173
|
+
})
|
|
174
|
+
},
|
|
175
|
+
clearCache() {
|
|
176
|
+
indexedDB.clear(() => {
|
|
177
|
+
location.reload()
|
|
178
|
+
})
|
|
179
|
+
},
|
|
180
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
interface Param {
|
|
2
|
+
funcName: string// 注册列表中的对应函数的key
|
|
3
|
+
param: any// 入参json格式
|
|
4
|
+
callbackFunc: Function// 回调函数
|
|
5
|
+
callBackMethodName?: string// 随机回调函数名字-不用传
|
|
6
|
+
}
|
|
7
|
+
// js端调用flutter中工具函数
|
|
8
|
+
/*
|
|
9
|
+
* 例:mobileUtil.execute({
|
|
10
|
+
funcName:'getLocationResult',
|
|
11
|
+
param: {a: 1},
|
|
12
|
+
callbackFunc: (result) => {
|
|
13
|
+
console.log('回调了test111', JSON.stringify(result))
|
|
14
|
+
message.value = JSON.stringify(result)
|
|
15
|
+
return 222
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
* */
|
|
19
|
+
export class mobileUtil {
|
|
20
|
+
// 执行flutter端函数
|
|
21
|
+
static execute(locationParam: Param): any {
|
|
22
|
+
locationParam.callBackMethodName = `mobile_func_${Math.random().toString(36).substring(7)}`
|
|
23
|
+
window[locationParam.callBackMethodName] = locationParam.callbackFunc
|
|
24
|
+
window[locationParam.funcName].postMessage(JSON.stringify(locationParam))
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import NProgress from 'nprogress'
|
|
2
|
+
import 'nprogress/nprogress.css'
|
|
3
|
+
|
|
4
|
+
NProgress.configure({
|
|
5
|
+
// 动画方式
|
|
6
|
+
easing: 'ease',
|
|
7
|
+
// 递增进度条的速度
|
|
8
|
+
speed: 500,
|
|
9
|
+
// 是否显示加载ico
|
|
10
|
+
showSpinner: true,
|
|
11
|
+
// 自动递增间隔
|
|
12
|
+
trickleSpeed: 200,
|
|
13
|
+
// 初始化时的最小百分比
|
|
14
|
+
minimum: 0.3,
|
|
15
|
+
// 加载条的父元素
|
|
16
|
+
parent: '#system-app',
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
export default NProgress
|