@liujitcn/kratos-uni-app-core 0.0.1
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/README.md +46 -0
- package/dist/module.mjs +84 -0
- package/dist/vite.mjs +405 -0
- package/package.json +58 -0
- package/src/api/base/config.ts +20 -0
- package/src/api/base/file.ts +79 -0
- package/src/api/base/login.ts +87 -0
- package/src/api/base/menu.ts +17 -0
- package/src/api/base/oauth.ts +149 -0
- package/src/api/system/auth.ts +54 -0
- package/src/api/system/base_area.ts +34 -0
- package/src/api/system/base_dict.ts +24 -0
- package/src/bootstrap.ts +23 -0
- package/src/components/BootstrapStatus.vue +39 -0
- package/src/components/KratosTabBar.vue +73 -0
- package/src/index.ts +6 -0
- package/src/module.ts +85 -0
- package/src/navigation-pattern.d.mts +2 -0
- package/src/navigation-pattern.mjs +29 -0
- package/src/navigation-tree.mjs +45 -0
- package/src/navigation.ts +330 -0
- package/src/pages.ts +26 -0
- package/src/rpc/base/v1/config.ts +34 -0
- package/src/rpc/base/v1/file.ts +66 -0
- package/src/rpc/base/v1/login.ts +128 -0
- package/src/rpc/base/v1/mcp.ts +20 -0
- package/src/rpc/base/v1/oauth.ts +199 -0
- package/src/rpc/base/v1/sse.ts +22 -0
- package/src/rpc/common/v1/common.ts +71 -0
- package/src/rpc/common/v1/enum.ts +71 -0
- package/src/rpc/common/v1/types.ts +77 -0
- package/src/rpc/google/protobuf/empty.ts +19 -0
- package/src/rpc/google/protobuf/wrappers.ts +124 -0
- package/src/rpc/system/app/v1/auth.ts +54 -0
- package/src/rpc/system/app/v1/base_area.ts +24 -0
- package/src/rpc/system/app/v1/base_dict.ts +37 -0
- package/src/rpc/system/app/v1/base_menu.ts +61 -0
- package/src/rpc/system/common/v1/enum.ts +80 -0
- package/src/static/images/avatar.png +0 -0
- package/src/static/images/center_bg.png +0 -0
- package/src/static/images/logo_icon.png +0 -0
- package/src/static/images/navigator_bg.png +0 -0
- package/src/static/tabs/home_default.png +0 -0
- package/src/static/tabs/home_selected.png +0 -0
- package/src/static/tabs/user_default.png +0 -0
- package/src/static/tabs/user_selected.png +0 -0
- package/src/stores/index.ts +14 -0
- package/src/stores/modules/setting.ts +56 -0
- package/src/stores/modules/user.ts +266 -0
- package/src/styles/base.scss +42 -0
- package/src/types/env.d.ts +24 -0
- package/src/types/go-captcha-uni.d.ts +7 -0
- package/src/types/uni-helper.d.ts +54 -0
- package/src/uni.scss +76 -0
- package/src/utils/auth.ts +67 -0
- package/src/utils/file.ts +95 -0
- package/src/utils/http.ts +430 -0
- package/src/utils/index.ts +79 -0
- package/src/utils/navigation.ts +81 -0
- package/src/utils/passwordCrypto.ts +275 -0
- package/src/views/pages/index/index.vue +227 -0
- package/src/views/pages/login/login.vue +1133 -0
- package/src/views/pages/login/protocal.vue +176 -0
- package/src/views/pages/status/index.vue +36 -0
- package/src/views/pages/webview/webview.vue +136 -0
- package/src/vite.ts +474 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
|
|
2
|
+
// versions:
|
|
3
|
+
// protoc-gen-ts_proto v2.11.8
|
|
4
|
+
// protoc unknown
|
|
5
|
+
// source: system/app/v1/base_menu.proto
|
|
6
|
+
|
|
7
|
+
/* eslint-disable */
|
|
8
|
+
|
|
9
|
+
/** 移动端菜单查询条件 */
|
|
10
|
+
export interface ListBaseMenuRequest {
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** 移动端菜单响应 */
|
|
14
|
+
export interface ListBaseMenuResponse {
|
|
15
|
+
/** 移动端扁平菜单 */
|
|
16
|
+
items: BaseMenu[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** 移动端菜单 */
|
|
20
|
+
export interface BaseMenu {
|
|
21
|
+
/** 菜单ID */
|
|
22
|
+
id: number;
|
|
23
|
+
/** 父级菜单ID */
|
|
24
|
+
parent_id: number;
|
|
25
|
+
/** 逻辑路由地址 */
|
|
26
|
+
path: string;
|
|
27
|
+
/** 逻辑路由名称 */
|
|
28
|
+
name: string;
|
|
29
|
+
/** 移动端菜单元信息 */
|
|
30
|
+
meta: BaseMenuMeta | undefined;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** 移动端菜单元信息 */
|
|
34
|
+
export interface BaseMenuMeta {
|
|
35
|
+
/** 菜单标题 */
|
|
36
|
+
title: string;
|
|
37
|
+
/** 菜单图标 */
|
|
38
|
+
icon?:
|
|
39
|
+
| string
|
|
40
|
+
| undefined;
|
|
41
|
+
/** 移动端页面配置 */
|
|
42
|
+
app: BaseMenuAppMeta | undefined;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** 移动端页面配置 */
|
|
46
|
+
export interface BaseMenuAppMeta {
|
|
47
|
+
/** 已注册的稳定视图键 */
|
|
48
|
+
view_key: string;
|
|
49
|
+
/** 页面访问模式 */
|
|
50
|
+
access: string;
|
|
51
|
+
/** 是否显示在自绘标签栏 */
|
|
52
|
+
in_tab_bar: boolean;
|
|
53
|
+
/** 标签栏选中图标 */
|
|
54
|
+
selected_icon?: string | undefined;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** App菜单服务 */
|
|
58
|
+
export interface BaseMenuService {
|
|
59
|
+
/** 查询移动端菜单 */
|
|
60
|
+
ListBaseMenu(request: ListBaseMenuRequest): Promise<ListBaseMenuResponse>;
|
|
61
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
|
|
2
|
+
// versions:
|
|
3
|
+
// protoc-gen-ts_proto v2.11.8
|
|
4
|
+
// protoc unknown
|
|
5
|
+
// source: system/common/v1/enum.proto
|
|
6
|
+
|
|
7
|
+
/* eslint-disable */
|
|
8
|
+
|
|
9
|
+
/** 系统配置类型 */
|
|
10
|
+
export enum BaseConfigType {
|
|
11
|
+
UNKNOWN_BCT = 0,
|
|
12
|
+
/** TEXT - 文本 */
|
|
13
|
+
TEXT = 1,
|
|
14
|
+
/** IMAGE - 图片 */
|
|
15
|
+
IMAGE = 2,
|
|
16
|
+
/** RICH_TEXT - 富文本 */
|
|
17
|
+
RICH_TEXT = 3,
|
|
18
|
+
/** DICT - 字典 */
|
|
19
|
+
DICT = 4,
|
|
20
|
+
/** BOOLEAN - 布尔 */
|
|
21
|
+
BOOLEAN = 5,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** 定时任务日志状态 */
|
|
25
|
+
export enum BaseJobLogStatus {
|
|
26
|
+
UNKNOWN_BJLS = 0,
|
|
27
|
+
/** SUCCESS - 成功 */
|
|
28
|
+
SUCCESS = 1,
|
|
29
|
+
/** FAIL - 失败 */
|
|
30
|
+
FAIL = 2,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** 菜单类型 */
|
|
34
|
+
export enum BaseMenuType {
|
|
35
|
+
UNKNOWN_MT = 0,
|
|
36
|
+
/** FOLDER - 目录 */
|
|
37
|
+
FOLDER = 1,
|
|
38
|
+
/** MENU - 菜单 */
|
|
39
|
+
MENU = 2,
|
|
40
|
+
/** BUTTON - 按钮 */
|
|
41
|
+
BUTTON = 3,
|
|
42
|
+
/** EXT_LINK - 外部链接 */
|
|
43
|
+
EXT_LINK = 4,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** 角色数据范围 */
|
|
47
|
+
export enum BaseRoleDataScope {
|
|
48
|
+
UNKNOWN_RDS = 0,
|
|
49
|
+
/** ALL - 全部数据 */
|
|
50
|
+
ALL = 1,
|
|
51
|
+
/** DEPT_AND_CHILDREN - 部门及子部门数据 */
|
|
52
|
+
DEPT_AND_CHILDREN = 2,
|
|
53
|
+
/** SELF_DEPT - 本部门数据 */
|
|
54
|
+
SELF_DEPT = 3,
|
|
55
|
+
/** SELF_USER - 本人数据 */
|
|
56
|
+
SELF_USER = 4,
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** 用户性别 */
|
|
60
|
+
export enum BaseUserGender {
|
|
61
|
+
UNKNOWN_BUG = 0,
|
|
62
|
+
/** SECRET - 保密 */
|
|
63
|
+
SECRET = 1,
|
|
64
|
+
/** BOY - 男 */
|
|
65
|
+
BOY = 2,
|
|
66
|
+
/** GIRL - 禁用 */
|
|
67
|
+
GIRL = 3,
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** 代码生成表状态 */
|
|
71
|
+
export enum CodeGenTableStatus {
|
|
72
|
+
/** UNKNOWN_CGTS - 未指定 */
|
|
73
|
+
UNKNOWN_CGTS = 0,
|
|
74
|
+
/** DRAFT_CGTS - 草稿 */
|
|
75
|
+
DRAFT_CGTS = 1,
|
|
76
|
+
/** GENERATED_CGTS - 已生成 */
|
|
77
|
+
GENERATED_CGTS = 2,
|
|
78
|
+
/** DISABLED_CGTS - 停用 */
|
|
79
|
+
DISABLED_CGTS = 3,
|
|
80
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createPinia } from 'pinia'
|
|
2
|
+
import persist from 'pinia-plugin-persistedstate'
|
|
3
|
+
|
|
4
|
+
// 创建 pinia 实例
|
|
5
|
+
const pinia = createPinia()
|
|
6
|
+
// 使用持久化存储插件
|
|
7
|
+
pinia.use(persist)
|
|
8
|
+
|
|
9
|
+
// 默认导出,给 main.ts 使用
|
|
10
|
+
export default pinia
|
|
11
|
+
|
|
12
|
+
// 模块统一导出
|
|
13
|
+
export * from './modules/user'
|
|
14
|
+
export * from './modules/setting'
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { defConfigService } from '../../api/base/config'
|
|
2
|
+
import { defineStore } from 'pinia'
|
|
3
|
+
import { ref } from 'vue'
|
|
4
|
+
import { BaseConfigSite } from '../../rpc/common/v1/enum'
|
|
5
|
+
|
|
6
|
+
const REQUIRED_APP_CONFIGS = [
|
|
7
|
+
{ key: 'serviceProtocol', name: '服务条款' },
|
|
8
|
+
{ key: 'privacyProtocol', name: '隐私协议' },
|
|
9
|
+
{ key: 'captchaType', name: '登录验证码类型' },
|
|
10
|
+
] as const
|
|
11
|
+
|
|
12
|
+
export const useSettingStore = defineStore('setting', () => {
|
|
13
|
+
const data = ref<Map<string, string>>()
|
|
14
|
+
let loading: Promise<void> | undefined
|
|
15
|
+
|
|
16
|
+
/** 读取移动端配置项。 */
|
|
17
|
+
const getData = (key: string): string | undefined => {
|
|
18
|
+
return data.value?.get(key)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** 加载并校验移动端必需配置。 */
|
|
22
|
+
const loadData = async () => {
|
|
23
|
+
if (loading) {
|
|
24
|
+
return loading
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const request = (async () => {
|
|
28
|
+
const res = await defConfigService.GetConfig({
|
|
29
|
+
site: BaseConfigSite.APP,
|
|
30
|
+
})
|
|
31
|
+
const nextData = new Map<string, string>()
|
|
32
|
+
res.configs.forEach((item) => {
|
|
33
|
+
nextData.set(item.key, item.value)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
const missingConfigs = REQUIRED_APP_CONFIGS.filter(({ key }) => !nextData.get(key))
|
|
37
|
+
if (missingConfigs.length) {
|
|
38
|
+
throw new Error(`移动端配置缺失:${missingConfigs.map(({ name }) => name).join('、')}`)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
data.value = nextData
|
|
42
|
+
})()
|
|
43
|
+
loading = request
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
await request
|
|
47
|
+
} finally {
|
|
48
|
+
loading = undefined
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
getData,
|
|
54
|
+
loadData,
|
|
55
|
+
}
|
|
56
|
+
})
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import type { UserProfileForm } from '../../rpc/system/app/v1/auth'
|
|
2
|
+
import type {
|
|
3
|
+
BindOauthSessionRequest,
|
|
4
|
+
CreateOauthSessionRequest,
|
|
5
|
+
CreateOauthSessionResponse,
|
|
6
|
+
} from '../../rpc/base/v1/oauth'
|
|
7
|
+
import type { LoginRequest, LoginResponse } from '../../rpc/base/v1/login'
|
|
8
|
+
import { defAuthService } from '../../api/system/auth'
|
|
9
|
+
import { defLoginService } from '../../api/base/login'
|
|
10
|
+
import { defOauthService } from '../../api/base/oauth'
|
|
11
|
+
import { defineStore } from 'pinia'
|
|
12
|
+
import { ref } from 'vue'
|
|
13
|
+
import {
|
|
14
|
+
setToken,
|
|
15
|
+
setRefreshToken,
|
|
16
|
+
getRefreshToken,
|
|
17
|
+
clearToken,
|
|
18
|
+
setTokenExpiresIn,
|
|
19
|
+
hasValidToken,
|
|
20
|
+
} from '../../utils/auth'
|
|
21
|
+
|
|
22
|
+
const AUTH_SILENT_LOGOUT_EVENT = 'auth:silent-logout'
|
|
23
|
+
let silentLogoutEventHandler: (() => void) | undefined
|
|
24
|
+
|
|
25
|
+
/** 用户状态扩展生命周期处理器。 */
|
|
26
|
+
export interface UserStoreExtension {
|
|
27
|
+
/** 登录令牌保存完成后执行。 */
|
|
28
|
+
onLogin?: () => void | Promise<void>
|
|
29
|
+
/** 用户主动登出并清理本地状态后执行。 */
|
|
30
|
+
onLogout?: () => void | Promise<void>
|
|
31
|
+
/** 令牌失效并静默清理本地状态后执行。 */
|
|
32
|
+
onSilentLogout?: () => void | Promise<void>
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const userStoreExtensions = new Set<UserStoreExtension>()
|
|
36
|
+
|
|
37
|
+
/** 注册用户 Store 的业务扩展,返回值用于注销本次注册。 */
|
|
38
|
+
export function registerUserStoreExtension(extension: UserStoreExtension) {
|
|
39
|
+
userStoreExtensions.add(extension)
|
|
40
|
+
return () => userStoreExtensions.delete(extension)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function runUserStoreExtensions(event: keyof UserStoreExtension) {
|
|
44
|
+
for (const extension of userStoreExtensions) {
|
|
45
|
+
const handler = extension[event]
|
|
46
|
+
if (!handler) {
|
|
47
|
+
continue
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
await handler()
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.warn(`user store ${event} extension failed`, error)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// 定义 Store
|
|
58
|
+
export const useUserStore = defineStore(
|
|
59
|
+
'user',
|
|
60
|
+
() => {
|
|
61
|
+
// 会员信息
|
|
62
|
+
const userInfo = ref<UserProfileForm>()
|
|
63
|
+
|
|
64
|
+
/** 判断当前本地登录态是否仍然可用。 */
|
|
65
|
+
function isAuthenticated() {
|
|
66
|
+
return Boolean(userInfo.value && hasValidToken())
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** 保存登录接口返回的认证令牌,并通知已注册的业务扩展。 */
|
|
70
|
+
async function applyLoginToken(data: LoginResponse | CreateOauthSessionResponse) {
|
|
71
|
+
const { token_type, access_token, refresh_token, expires_in } = data
|
|
72
|
+
setToken(token_type + ' ' + access_token)
|
|
73
|
+
setRefreshToken(refresh_token)
|
|
74
|
+
setTokenExpiresIn(expires_in)
|
|
75
|
+
await runUserStoreExtensions('onLogin')
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* 登录
|
|
80
|
+
*
|
|
81
|
+
* @param request
|
|
82
|
+
* @returns
|
|
83
|
+
*/
|
|
84
|
+
function login(request: LoginRequest) {
|
|
85
|
+
return new Promise<void>((resolve, reject) => {
|
|
86
|
+
defLoginService
|
|
87
|
+
.Login(request)
|
|
88
|
+
.then(async (data) => {
|
|
89
|
+
await applyLoginToken(data)
|
|
90
|
+
resolve()
|
|
91
|
+
})
|
|
92
|
+
.catch((error) => {
|
|
93
|
+
reject(error)
|
|
94
|
+
})
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* 创建三方登录会话
|
|
100
|
+
*
|
|
101
|
+
* @param request
|
|
102
|
+
* @returns
|
|
103
|
+
*/
|
|
104
|
+
function createOauthSession(request: CreateOauthSessionRequest) {
|
|
105
|
+
return new Promise<CreateOauthSessionResponse>((resolve, reject) => {
|
|
106
|
+
defOauthService
|
|
107
|
+
.CreateOauthSession(request)
|
|
108
|
+
.then(async (data) => {
|
|
109
|
+
if (data.binding_required) {
|
|
110
|
+
resolve(data)
|
|
111
|
+
return
|
|
112
|
+
}
|
|
113
|
+
await applyLoginToken(data)
|
|
114
|
+
resolve(data)
|
|
115
|
+
})
|
|
116
|
+
.catch((error) => {
|
|
117
|
+
reject(error)
|
|
118
|
+
})
|
|
119
|
+
})
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** 绑定已有账号并创建三方登录会话。 */
|
|
123
|
+
function bindOauthSession(request: BindOauthSessionRequest) {
|
|
124
|
+
return new Promise<void>((resolve, reject) => {
|
|
125
|
+
defOauthService
|
|
126
|
+
.BindOauthSession(request)
|
|
127
|
+
.then(async (data) => {
|
|
128
|
+
await applyLoginToken(data)
|
|
129
|
+
resolve()
|
|
130
|
+
})
|
|
131
|
+
.catch((error) => {
|
|
132
|
+
reject(error)
|
|
133
|
+
})
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* 获取用户资料
|
|
139
|
+
*/
|
|
140
|
+
function getUserProfile() {
|
|
141
|
+
return new Promise<UserProfileForm>((resolve, reject) => {
|
|
142
|
+
defAuthService
|
|
143
|
+
.GetUserProfile({})
|
|
144
|
+
.then((data) => {
|
|
145
|
+
if (!data) {
|
|
146
|
+
reject('Verification failed, please Login again.')
|
|
147
|
+
return
|
|
148
|
+
}
|
|
149
|
+
userInfo.value = data
|
|
150
|
+
resolve(data)
|
|
151
|
+
})
|
|
152
|
+
.catch((error) => {
|
|
153
|
+
reject(error)
|
|
154
|
+
})
|
|
155
|
+
})
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* 登出
|
|
160
|
+
*/
|
|
161
|
+
function logout() {
|
|
162
|
+
return new Promise<void>((resolve, reject) => {
|
|
163
|
+
defLoginService
|
|
164
|
+
.Logout({})
|
|
165
|
+
.then(() => {
|
|
166
|
+
clearUserData().then(() => {
|
|
167
|
+
resolve()
|
|
168
|
+
})
|
|
169
|
+
})
|
|
170
|
+
.catch((error) => {
|
|
171
|
+
reject(error)
|
|
172
|
+
})
|
|
173
|
+
})
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* 刷新 token
|
|
178
|
+
*/
|
|
179
|
+
function refreshToken() {
|
|
180
|
+
const refreshToken = getRefreshToken()
|
|
181
|
+
return new Promise<void>((resolve, reject) => {
|
|
182
|
+
defLoginService
|
|
183
|
+
.RefreshToken({
|
|
184
|
+
refresh_token: refreshToken,
|
|
185
|
+
})
|
|
186
|
+
.then((data) => {
|
|
187
|
+
const { token_type, access_token, refresh_token, expires_in } = data
|
|
188
|
+
setToken(token_type + ' ' + access_token)
|
|
189
|
+
setRefreshToken(refresh_token)
|
|
190
|
+
setTokenExpiresIn(expires_in)
|
|
191
|
+
resolve()
|
|
192
|
+
})
|
|
193
|
+
.catch((error) => {
|
|
194
|
+
console.log(' refreshToken 刷新失败', error)
|
|
195
|
+
reject(error)
|
|
196
|
+
})
|
|
197
|
+
})
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* 清理用户数据
|
|
202
|
+
*
|
|
203
|
+
* @returns
|
|
204
|
+
*/
|
|
205
|
+
async function clearUserData() {
|
|
206
|
+
clearToken()
|
|
207
|
+
userInfo.value = undefined
|
|
208
|
+
await runUserStoreExtensions('onLogout')
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** 静默清理登录态,用于 token 失效后降级为游客,不主动跳登录页。 */
|
|
212
|
+
function silentLogout() {
|
|
213
|
+
clearToken()
|
|
214
|
+
userInfo.value = undefined
|
|
215
|
+
uni.removeStorageSync('user')
|
|
216
|
+
void runUserStoreExtensions('onSilentLogout')
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/** 确认必须登录的操作是否可继续,不可继续时交给调用方跳登录。 */
|
|
220
|
+
function ensureAuthenticated() {
|
|
221
|
+
if (isAuthenticated()) {
|
|
222
|
+
return true
|
|
223
|
+
}
|
|
224
|
+
silentLogout()
|
|
225
|
+
return false
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (silentLogoutEventHandler) {
|
|
229
|
+
uni.$off(AUTH_SILENT_LOGOUT_EVENT, silentLogoutEventHandler)
|
|
230
|
+
}
|
|
231
|
+
silentLogoutEventHandler = () => {
|
|
232
|
+
userInfo.value = undefined
|
|
233
|
+
void runUserStoreExtensions('onSilentLogout')
|
|
234
|
+
}
|
|
235
|
+
uni.$on(AUTH_SILENT_LOGOUT_EVENT, silentLogoutEventHandler)
|
|
236
|
+
|
|
237
|
+
return {
|
|
238
|
+
userInfo,
|
|
239
|
+
isAuthenticated,
|
|
240
|
+
getUserProfile,
|
|
241
|
+
login,
|
|
242
|
+
createOauthSession,
|
|
243
|
+
bindOauthSession,
|
|
244
|
+
logout,
|
|
245
|
+
clearUserData,
|
|
246
|
+
silentLogout,
|
|
247
|
+
ensureAuthenticated,
|
|
248
|
+
refreshToken,
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
// 网页端配置
|
|
253
|
+
// persist: true,
|
|
254
|
+
// 小程序端配置
|
|
255
|
+
persist: {
|
|
256
|
+
storage: {
|
|
257
|
+
getItem(key) {
|
|
258
|
+
return uni.getStorageSync(key)
|
|
259
|
+
},
|
|
260
|
+
setItem(key, value) {
|
|
261
|
+
uni.setStorageSync(key, value)
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
view,
|
|
2
|
+
navigator,
|
|
3
|
+
input,
|
|
4
|
+
scroll-view {
|
|
5
|
+
box-sizing: border-box;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
button::after {
|
|
9
|
+
border: none;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
swiper,
|
|
13
|
+
scroll-view {
|
|
14
|
+
flex: 1;
|
|
15
|
+
height: 100%;
|
|
16
|
+
overflow: hidden;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.uni-data-tree .selected-area,
|
|
20
|
+
.uni-data-pickerview .selected-area {
|
|
21
|
+
flex: 0 1 auto;
|
|
22
|
+
height: auto;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
image {
|
|
26
|
+
width: 100%;
|
|
27
|
+
height: 100%;
|
|
28
|
+
vertical-align: middle;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// 两行省略
|
|
32
|
+
.ellipsis {
|
|
33
|
+
overflow: hidden;
|
|
34
|
+
text-overflow: ellipsis;
|
|
35
|
+
display: -webkit-box;
|
|
36
|
+
-webkit-line-clamp: 2;
|
|
37
|
+
-webkit-box-orient: vertical;
|
|
38
|
+
}
|
|
39
|
+
.is-required {
|
|
40
|
+
color: #dd524d;
|
|
41
|
+
margin-right: 8rpx;
|
|
42
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
|
2
|
+
|
|
3
|
+
interface ImportMetaEnv {
|
|
4
|
+
/** H5 开发服务端口 */
|
|
5
|
+
readonly VITE_APP_PORT: string
|
|
6
|
+
/** 接口基础路径 */
|
|
7
|
+
readonly VITE_APP_BASE_API: string
|
|
8
|
+
/** 页面实际请求使用的接口地址 */
|
|
9
|
+
readonly VITE_APP_API_URL: string
|
|
10
|
+
/** 静态资源基础路径 */
|
|
11
|
+
readonly VITE_APP_STATIC_API: string
|
|
12
|
+
/** 页面实际请求使用的静态资源地址 */
|
|
13
|
+
readonly VITE_APP_STATIC_URL: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface ImportMeta {
|
|
17
|
+
readonly env: ImportMetaEnv
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
declare module '*.vue' {
|
|
21
|
+
import { DefineComponent } from 'vue'
|
|
22
|
+
const component: DefineComponent<{}, {}, any>
|
|
23
|
+
export default component
|
|
24
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
declare namespace UniHelper {
|
|
2
|
+
type UniPopupType =
|
|
3
|
+
| 'top'
|
|
4
|
+
| 'right'
|
|
5
|
+
| 'bottom'
|
|
6
|
+
| 'left'
|
|
7
|
+
| 'center'
|
|
8
|
+
| 'message'
|
|
9
|
+
| 'dialog'
|
|
10
|
+
| 'share'
|
|
11
|
+
|
|
12
|
+
interface SwiperOnChangeEvent {
|
|
13
|
+
detail: {
|
|
14
|
+
current: number
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type SwiperOnChange = (ev: SwiperOnChangeEvent) => void
|
|
19
|
+
type SelectorPickerOnChange = (ev: { detail: { value: number } }) => void
|
|
20
|
+
type RadioGroupOnChange = (ev: { detail: { value: string } }) => void
|
|
21
|
+
type SwitchOnChange = (ev: any) => void
|
|
22
|
+
type RegionPickerOnChange = (ev: { detail: { value: string[]; code: string[] } }) => void
|
|
23
|
+
type UniDataPickerOnChange = (ev: {
|
|
24
|
+
detail: {
|
|
25
|
+
value: Array<{ text?: string; value: string }>
|
|
26
|
+
}
|
|
27
|
+
}) => void
|
|
28
|
+
type ButtonOnGetphonenumber = (ev: {
|
|
29
|
+
detail: {
|
|
30
|
+
errMsg?: string
|
|
31
|
+
code?: string
|
|
32
|
+
}
|
|
33
|
+
}) => void | Promise<void>
|
|
34
|
+
|
|
35
|
+
interface UniFormsRuleItem {
|
|
36
|
+
rules?: Array<Record<string, unknown>>
|
|
37
|
+
validateTrigger?: 'bind' | 'submit' | string
|
|
38
|
+
errorMessage?: string
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
type UniFormsRules = Record<string, UniFormsRuleItem>
|
|
42
|
+
|
|
43
|
+
interface UniFormsInstance {
|
|
44
|
+
validate: () => Promise<unknown>
|
|
45
|
+
validateField?: (props: string | string[]) => Promise<unknown>
|
|
46
|
+
clearValidate?: (props?: string | string[]) => void
|
|
47
|
+
setRules?: (rules: UniFormsRules) => void
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
interface UniPopupInstance {
|
|
51
|
+
open: (type?: UniPopupType) => void
|
|
52
|
+
close: () => void
|
|
53
|
+
}
|
|
54
|
+
}
|
package/src/uni.scss
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 这里是uni-app内置的常用样式变量
|
|
3
|
+
*
|
|
4
|
+
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
|
|
5
|
+
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
|
|
11
|
+
*
|
|
12
|
+
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/* 颜色变量 */
|
|
16
|
+
|
|
17
|
+
/* 行为相关颜色 */
|
|
18
|
+
$uni-color-primary: #007aff;
|
|
19
|
+
$uni-color-success: #4cd964;
|
|
20
|
+
$uni-color-warning: #f0ad4e;
|
|
21
|
+
$uni-color-error: #dd524d;
|
|
22
|
+
|
|
23
|
+
/* 文字基本颜色 */
|
|
24
|
+
$uni-text-color: #333; // 基本色
|
|
25
|
+
$uni-text-color-inverse: #fff; // 反色
|
|
26
|
+
$uni-text-color-grey: #999; // 辅助灰色,如加载更多的提示信息
|
|
27
|
+
$uni-text-color-placeholder: #808080;
|
|
28
|
+
$uni-text-color-disable: #c0c0c0;
|
|
29
|
+
|
|
30
|
+
/* 背景颜色 */
|
|
31
|
+
$uni-bg-color: #fff;
|
|
32
|
+
$uni-bg-color-grey: #f8f8f8;
|
|
33
|
+
$uni-bg-color-hover: #f1f1f1; // 点击状态颜色
|
|
34
|
+
$uni-bg-color-mask: rgba(0, 0, 0, 0.4); // 遮罩颜色
|
|
35
|
+
|
|
36
|
+
/* 边框颜色 */
|
|
37
|
+
$uni-border-color: #c8c7cc;
|
|
38
|
+
|
|
39
|
+
/* 尺寸变量 */
|
|
40
|
+
|
|
41
|
+
/* 文字尺寸 */
|
|
42
|
+
$uni-font-size-sm: 12px;
|
|
43
|
+
$uni-font-size-base: 14px;
|
|
44
|
+
$uni-font-size-lg: 16;
|
|
45
|
+
|
|
46
|
+
/* 图片尺寸 */
|
|
47
|
+
$uni-img-size-sm: 20px;
|
|
48
|
+
$uni-img-size-base: 26px;
|
|
49
|
+
$uni-img-size-lg: 40px;
|
|
50
|
+
|
|
51
|
+
/* Border Radius */
|
|
52
|
+
$uni-border-radius-sm: 2px;
|
|
53
|
+
$uni-border-radius-base: 3px;
|
|
54
|
+
$uni-border-radius-lg: 6px;
|
|
55
|
+
$uni-border-radius-circle: 50%;
|
|
56
|
+
|
|
57
|
+
/* 水平间距 */
|
|
58
|
+
$uni-spacing-row-sm: 5px;
|
|
59
|
+
$uni-spacing-row-base: 10px;
|
|
60
|
+
$uni-spacing-row-lg: 15px;
|
|
61
|
+
|
|
62
|
+
/* 垂直间距 */
|
|
63
|
+
$uni-spacing-col-sm: 4px;
|
|
64
|
+
$uni-spacing-col-base: 8px;
|
|
65
|
+
$uni-spacing-col-lg: 12px;
|
|
66
|
+
|
|
67
|
+
/* 透明度 */
|
|
68
|
+
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
|
|
69
|
+
|
|
70
|
+
/* 文章场景相关 */
|
|
71
|
+
$uni-color-title: #2c405a; // 文章标题颜色
|
|
72
|
+
$uni-font-size-title: 20px;
|
|
73
|
+
$uni-color-subtitle: #555; // 二级标题颜色
|
|
74
|
+
$uni-font-size-subtitle: 18px;
|
|
75
|
+
$uni-color-paragraph: #3f536e; // 文章段落颜色
|
|
76
|
+
$uni-font-size-paragraph: 15px;
|