Showing
12 changed files
with
219 additions
and
23 deletions
src/api/external/sys/share.ts
0 → 100644
1 | +import { ViewTypeEnum } from "@/enums/external/viewEnum" | |
2 | +import { defHttp } from "@/utils/external/http/axios" | |
3 | + | |
4 | +enum Api { | |
5 | + TOKEN = '/auth/login/public', | |
6 | + | |
7 | + CHECK = '/share/check', | |
8 | + | |
9 | + SHARE_CONTENT = '/share' | |
10 | +} | |
11 | + | |
12 | +/** | |
13 | + * @description 获取token | |
14 | + * @param publicId string | |
15 | + */ | |
16 | +export const getPublicToken = (publicId: string) => { | |
17 | + return defHttp.post<Record<'token' | 'refreshToken', string>>({ | |
18 | + url: Api.TOKEN, | |
19 | + data: { publicId } | |
20 | + }, { joinPrefix: false }) | |
21 | +} | |
22 | + | |
23 | +/** | |
24 | + * @description 检查时候需要访问令牌 | |
25 | + * @param id string | |
26 | + */ | |
27 | +export const checkSharePageNeedAccessToken = (id: string) => { | |
28 | + return defHttp.get<{data: boolean}>({ | |
29 | + url: `${Api.CHECK}/${ViewTypeEnum.LARGE_SCREEN}/${id}` | |
30 | + }) | |
31 | +} | |
32 | + | |
33 | +/** | |
34 | + * @description 获取分享的数据内容 | |
35 | + * @param options | |
36 | + */ | |
37 | +export const getShareContentData = (options: Record<'id' | 'accessCredentials', string>) => { | |
38 | + return defHttp.get<{ data: any }>({ | |
39 | + url: `${Api.SHARE_CONTENT}/${ViewTypeEnum.LARGE_SCREEN}/share_data/${options.id}`, | |
40 | + params: { accessCredentials: options.accessCredentials } | |
41 | + }) | |
42 | +} | ... | ... |
... | ... | @@ -9,4 +9,10 @@ export enum PageEnum { |
9 | 9 | // 未发布 |
10 | 10 | REDIRECT_UN_PUBLISH = '/redirect/unPublish', |
11 | 11 | REDIRECT_UN_PUBLISH_NAME = 'redirect-un-publish', |
12 | + | |
13 | +} | |
14 | + | |
15 | +export enum ShareEnum { | |
16 | + SHARE_PATH = '/share/preview/:id/:publicId', | |
17 | + SHARE_PATH_NAME = 'ChartSharePreview' | |
12 | 18 | } | ... | ... |
src/enums/external/viewEnum.ts
0 → 100644
... | ... | @@ -2,7 +2,6 @@ import { Router } from "vue-router" |
2 | 2 | import { createErrorGuard } from "./errorGuard" |
3 | 3 | import { createLoadingGuard } from "./loadingGuard" |
4 | 4 | import { createPermissionGuard } from "./permissionGuard" |
5 | - | |
6 | 5 | export const setupRouterGuard = (router: Router) => { |
7 | 6 | createPermissionGuard(router) |
8 | 7 | createErrorGuard(router) | ... | ... |
1 | 1 | import { ProjectRuntimeEnvEnum } from "@/enums/external/envEnum"; |
2 | -import { PageEnum } from "@/enums/external/pageEnum"; | |
2 | +import { PageEnum, ShareEnum } from "@/enums/external/pageEnum"; | |
3 | 3 | import { useUserStoreWithOut } from "@/store/external/modules/user"; |
4 | 4 | import { NavigationGuardNext, NavigationGuardWithThis, RouteLocationNormalized, RouteLocationRaw, Router } from "vue-router"; |
5 | 5 | |
6 | 6 | |
7 | -const whitePathList: string[] = [PageEnum.BASE_LOGIN]; | |
7 | +const whitePathList: string[] = [PageEnum.BASE_LOGIN, ShareEnum.SHARE_PATH]; | |
8 | 8 | |
9 | 9 | const isAloneMode = [ProjectRuntimeEnvEnum.DEV_ALONE, ProjectRuntimeEnvEnum.PROD_ALONE].includes(import.meta.env.MODE as ProjectRuntimeEnvEnum) |
10 | 10 | |
11 | 11 | const toIotPlatformLogin = ({ to, from, next }: { to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext }) => { |
12 | 12 | const { origin, port } = window.location |
13 | + | |
13 | 14 | if (Number(port) === Number(import.meta.env.VITE_DEV_PORT)) { |
14 | - if (whitePathList.includes(to.path)) { | |
15 | + if (to.matched.find(item => whitePathList.includes(item.path))) { | |
15 | 16 | next() |
16 | 17 | return |
17 | 18 | } else { |
... | ... | @@ -36,8 +37,9 @@ export function createPermissionGuard(router: Router) { |
36 | 37 | } |
37 | 38 | |
38 | 39 | const token = userStore.getJwtToken |
40 | + console.log(token) | |
39 | 41 | |
40 | - if (whitePathList.includes(to.path)) { | |
42 | + if (to.matched.find(item => whitePathList.includes(item.path))) { | |
41 | 43 | if (to.path === PageEnum.BASE_LOGIN && token) { |
42 | 44 | const isSessionTimeout = userStore.getSessionTimeout |
43 | 45 | try { |
... | ... | @@ -47,6 +49,9 @@ export function createPermissionGuard(router: Router) { |
47 | 49 | } catch (error) { |
48 | 50 | console.error(error) |
49 | 51 | } |
52 | + } else if (to.matched.find(item => ShareEnum.SHARE_PATH)) { | |
53 | + next() | |
54 | + return | |
50 | 55 | } |
51 | 56 | else { |
52 | 57 | if (!isAloneMode) { | ... | ... |
src/router/external/share.route.ts
0 → 100644
1 | +import { RouteRecordRaw } from 'vue-router' | |
2 | +import { ShareEnum } from '@/enums/external/pageEnum' | |
3 | + | |
4 | +// 引入路径 | |
5 | +const importPath = { | |
6 | + [ShareEnum.SHARE_PATH_NAME]: () => import('@/views/share/index.vue') | |
7 | +} | |
8 | + | |
9 | +export const shareRoutes: RouteRecordRaw = { | |
10 | + path: ShareEnum.SHARE_PATH, | |
11 | + name: ShareEnum.SHARE_PATH_NAME, | |
12 | + component: importPath[ShareEnum.SHARE_PATH_NAME], | |
13 | + meta: { | |
14 | + title: '分享', | |
15 | + isRoot: true | |
16 | + } | |
17 | +} | |
18 | + | |
\ No newline at end of file | ... | ... |
... | ... | @@ -7,7 +7,10 @@ import { HttpErrorPage, LoginRoute, ReloadRoute } from '@/router/base' |
7 | 7 | import { Layout } from '@/router/constant' |
8 | 8 | |
9 | 9 | import modules from '@/router/modules' |
10 | +// THINGS_KIT 重写路由拦截逻辑 | |
10 | 11 | import { setupRouterGuard } from './external/guard' |
12 | +// THINGS_KIT 新增分享路由 | |
13 | +import { shareRoutes } from './external/share.route' | |
11 | 14 | |
12 | 15 | const RootRoute: Array<RouteRecordRaw> = [ |
13 | 16 | { |
... | ... | @@ -23,7 +26,9 @@ const RootRoute: Array<RouteRecordRaw> = [ |
23 | 26 | modules.projectRoutes, |
24 | 27 | modules.chartRoutes, |
25 | 28 | modules.previewRoutes, |
26 | - modules.editRoutes | |
29 | + modules.editRoutes, | |
30 | + // THINGS_KIT 新增分享路由 | |
31 | + shareRoutes | |
27 | 32 | ] |
28 | 33 | } |
29 | 34 | ] | ... | ... |
... | ... | @@ -5,7 +5,8 @@ import { DateViewConfigurationInfoType } from '@/api/external/contentSave/model/ |
5 | 5 | export enum ProjectInfoEnum { |
6 | 6 | INFO = 'info', |
7 | 7 | SAVE_STATUS = 'saveStatus', |
8 | - DATA_VIEW_NAME = 'dataViewName' | |
8 | + DATA_VIEW_NAME = 'dataViewName', | |
9 | + ACCESS_CREDENTIALS = 'accessCredentials' | |
9 | 10 | } |
10 | 11 | |
11 | 12 | export enum EEditCanvasTypeEnum { |
... | ... | @@ -17,4 +18,6 @@ export interface ProjectInfoStoreType { |
17 | 18 | [ProjectInfoEnum.INFO]: DateViewConfigurationInfoType |
18 | 19 | |
19 | 20 | [ProjectInfoEnum.SAVE_STATUS]: SyncEnum |
21 | + | |
22 | + [ProjectInfoEnum.ACCESS_CREDENTIALS]: string | |
20 | 23 | } | ... | ... |
... | ... | @@ -6,10 +6,10 @@ import { SyncEnum } from "@/enums/external/editPageEnum"; |
6 | 6 | export const useProjectInfoStore = defineStore({ |
7 | 7 | id: 'useProjectInfoStore', |
8 | 8 | state: (): ProjectInfoStoreType => ({ |
9 | - info: { | |
9 | + info: { | |
10 | 10 | } as ProjectInfoStoreType['info'], |
11 | - | |
12 | - saveStatus: SyncEnum.FAILURE | |
11 | + saveStatus: SyncEnum.FAILURE, | |
12 | + accessCredentials: '' | |
13 | 13 | }), |
14 | 14 | getters: { |
15 | 15 | getProjectInfo(): ProjectInfoStoreType[ProjectInfoEnum.INFO] { |
... | ... | @@ -28,6 +28,9 @@ export const useProjectInfoStore = defineStore({ |
28 | 28 | }, |
29 | 29 | setSaveStatus(status: SyncEnum) { |
30 | 30 | this[ProjectInfoEnum.SAVE_STATUS] = status |
31 | + }, | |
32 | + setAccessCredentials(string: string) { | |
33 | + this[ProjectInfoEnum.ACCESS_CREDENTIALS] = string | |
31 | 34 | } |
32 | 35 | } |
33 | 36 | }) | ... | ... |
... | ... | @@ -2,13 +2,22 @@ import { fetchRouteParamsLocation, JSONParse, } from '@/utils' |
2 | 2 | import { getDataView } from '@/api/external/contentSave/content' |
3 | 3 | import { ChartEditStorageType } from '..' |
4 | 4 | import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' |
5 | +import { useRoute } from 'vue-router' | |
6 | +import { ShareEnum } from '@/enums/external/pageEnum' | |
7 | + | |
8 | + | |
9 | +const isSharePageMode = () => { | |
10 | + const ROUTE = useRoute() | |
11 | + return ROUTE.matched.find(item => item.path === ShareEnum.SHARE_PATH) | |
12 | +} | |
5 | 13 | |
6 | 14 | export const getSessionStorageInfo = async () => { |
15 | + if (isSharePageMode()) return | |
7 | 16 | const id = fetchRouteParamsLocation() |
8 | 17 | const chartEditStore = useChartEditStore() |
9 | 18 | const res = await getDataView(id) |
10 | 19 | if (res) { |
11 | - const { dataViewContent, dataViewName, dataViewId } = res | |
20 | + const { dataViewContent } = res | |
12 | 21 | const content = JSONParse(dataViewContent.content) as ChartEditStorageType |
13 | 22 | if (content) { |
14 | 23 | const { editCanvasConfig, requestGlobalConfig, componentList } = content | ... | ... |
1 | 1 | <template> |
2 | - <!-- THINGS_KIT 预览时需要异步请求接口 改为异步加载组件 --> | |
3 | - <Suspense> | |
4 | - <preview :key="key"></preview> | |
5 | - </Suspense> | |
2 | + <preview :key="key"></preview> | |
6 | 3 | </template> |
7 | 4 | |
8 | 5 | <script setup lang="ts"> |
... | ... | @@ -16,13 +13,13 @@ import Preview from './index.vue' |
16 | 13 | |
17 | 14 | let key = ref(Date.now()) |
18 | 15 | |
19 | -// 数据变更 -> 组件销毁重建 | |
20 | -;[SavePageEnum.JSON, SavePageEnum.CHART].forEach((saveEvent: string) => { | |
21 | - if (!window.opener) return | |
22 | - window.opener.addEventListener(saveEvent, async (e: any) => { | |
23 | - const localStorageInfo: ChartEditStorageType = await getSessionStorageInfo() as unknown as ChartEditStorageType | |
24 | - setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, [{ ...e.detail, id: localStorageInfo.id }]) | |
25 | - key.value = Date.now() | |
16 | + // 数据变更 -> 组件销毁重建 | |
17 | + ;[SavePageEnum.JSON, SavePageEnum.CHART].forEach((saveEvent: string) => { | |
18 | + if (!window.opener) return | |
19 | + window.opener.addEventListener(saveEvent, async (e: any) => { | |
20 | + const localStorageInfo: ChartEditStorageType = await getSessionStorageInfo() as unknown as ChartEditStorageType | |
21 | + setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, [{ ...e.detail, id: localStorageInfo.id }]) | |
22 | + key.value = Date.now() | |
23 | + }) | |
26 | 24 | }) |
27 | -}) | |
28 | 25 | </script> | ... | ... |
src/views/share/index.vue
0 → 100644
1 | +<template> | |
2 | + <section> | |
3 | + <preview v-if="!allowLoadPreviewPage" :key="key"></preview> | |
4 | + <NModal :show="allowLoadPreviewPage" :maskClosable="false" :closable="false" style="width: 300px;"> | |
5 | + <NCard> | |
6 | + <NForm @keyup.enter="handleSubmit"> | |
7 | + <NFormItem label="访问令牌"> | |
8 | + <NInput v-model:value="accessCredentials" type="password" /> | |
9 | + </NFormItem> | |
10 | + <NFormItem :showLabel="false"> | |
11 | + <NButton :loading="loading" type="primary" style="width: 100%;" @click="handleSubmit">访问</NButton> | |
12 | + </NFormItem> | |
13 | + </NForm> | |
14 | + </NCard> | |
15 | + </NModal> | |
16 | + </section> | |
17 | +</template> | |
18 | + | |
19 | +<script setup lang="ts"> | |
20 | +import { NModal, NCard, NForm, NFormItem, NInput, NButton, } from 'naive-ui' | |
21 | +import { getSessionStorageInfo } from '../preview/utils' | |
22 | +import type { ChartEditStorageType } from '../preview/index.d' | |
23 | +import { SavePageEnum } from '@/enums/editPageEnum' | |
24 | +import { JSONParse, setSessionStorage } from '@/utils' | |
25 | +import { StorageEnum } from '@/enums/storageEnum' | |
26 | +import { onMounted, ref, unref } from 'vue' | |
27 | +import Preview from '../preview/index.vue' | |
28 | +import { useRoute } from 'vue-router' | |
29 | +import { useUserStore } from '@/store/external/modules/user' | |
30 | +import { checkSharePageNeedAccessToken, getPublicToken, getShareContentData } from '@/api/external/sys/share' | |
31 | +import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' | |
32 | + | |
33 | +const allowLoadPreviewPage = ref(true) | |
34 | +const ROUTE = useRoute() | |
35 | +const accessCredentials = ref('') | |
36 | +const loading = ref(false) | |
37 | +const userStore = useUserStore() | |
38 | +const chartEditStore = useChartEditStore() | |
39 | + | |
40 | +const getToken = async () => { | |
41 | + const { params } = ROUTE | |
42 | + const { publicId } = params as Record<'id' | 'publicId', string> | |
43 | + const { token, refreshToken } = await getPublicToken(publicId) | |
44 | + userStore.storeToken(token, refreshToken) | |
45 | +} | |
46 | + | |
47 | +const checkNeedAccessToken = async () => { | |
48 | + const { params } = ROUTE | |
49 | + const { id } = params as Record<'id' | 'publicId', string> | |
50 | + const res = await checkSharePageNeedAccessToken(id) | |
51 | + return res.data | |
52 | +} | |
53 | + | |
54 | +const sharePageHandlerProcess = async () => { | |
55 | + await getToken() | |
56 | + const flag = await checkNeedAccessToken() | |
57 | + if (!flag) { | |
58 | + allowLoadPreviewPage.value = false | |
59 | + } | |
60 | +} | |
61 | + | |
62 | +const getSharePageContentData = async () => { | |
63 | + try { | |
64 | + const { params } = ROUTE | |
65 | + const { id } = params as Record<'id' | 'publicId', string> | |
66 | + loading.value = true | |
67 | + const res = await getShareContentData({ id, accessCredentials: unref(accessCredentials) }) | |
68 | + const { dataViewContent, dataViewName, dataViewId } = res.data | |
69 | + const content = JSONParse(dataViewContent.content) as ChartEditStorageType | |
70 | + if (content) { | |
71 | + const { editCanvasConfig, requestGlobalConfig, componentList } = content | |
72 | + chartEditStore.editCanvasConfig = editCanvasConfig | |
73 | + chartEditStore.requestGlobalConfig = requestGlobalConfig | |
74 | + chartEditStore.componentList = componentList | |
75 | + } | |
76 | + allowLoadPreviewPage.value = false | |
77 | + } catch (error) { | |
78 | + console.log(error) | |
79 | + } finally { | |
80 | + loading.value = false | |
81 | + } | |
82 | + | |
83 | +} | |
84 | + | |
85 | +const handleSubmit = () => { | |
86 | + getSharePageContentData() | |
87 | +} | |
88 | + | |
89 | +onMounted(() => { | |
90 | + sharePageHandlerProcess() | |
91 | +}) | |
92 | + | |
93 | +let key = ref(Date.now()) | |
94 | + | |
95 | + // 数据变更 -> 组件销毁重建 | |
96 | + ;[SavePageEnum.JSON, SavePageEnum.CHART].forEach((saveEvent: string) => { | |
97 | + if (!window.opener) return | |
98 | + window.opener.addEventListener(saveEvent, async (e: any) => { | |
99 | + const localStorageInfo: ChartEditStorageType = await getSessionStorageInfo() as unknown as ChartEditStorageType | |
100 | + setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, [{ ...e.detail, id: localStorageInfo.id }]) | |
101 | + key.value = Date.now() | |
102 | + }) | |
103 | + }) | |
104 | +</script> | ... | ... |