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,4 +9,10 @@ export enum PageEnum { | ||
9 | // 未发布 | 9 | // 未发布 |
10 | REDIRECT_UN_PUBLISH = '/redirect/unPublish', | 10 | REDIRECT_UN_PUBLISH = '/redirect/unPublish', |
11 | REDIRECT_UN_PUBLISH_NAME = 'redirect-un-publish', | 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,7 +2,6 @@ import { Router } from "vue-router" | ||
2 | import { createErrorGuard } from "./errorGuard" | 2 | import { createErrorGuard } from "./errorGuard" |
3 | import { createLoadingGuard } from "./loadingGuard" | 3 | import { createLoadingGuard } from "./loadingGuard" |
4 | import { createPermissionGuard } from "./permissionGuard" | 4 | import { createPermissionGuard } from "./permissionGuard" |
5 | - | ||
6 | export const setupRouterGuard = (router: Router) => { | 5 | export const setupRouterGuard = (router: Router) => { |
7 | createPermissionGuard(router) | 6 | createPermissionGuard(router) |
8 | createErrorGuard(router) | 7 | createErrorGuard(router) |
1 | import { ProjectRuntimeEnvEnum } from "@/enums/external/envEnum"; | 1 | import { ProjectRuntimeEnvEnum } from "@/enums/external/envEnum"; |
2 | -import { PageEnum } from "@/enums/external/pageEnum"; | 2 | +import { PageEnum, ShareEnum } from "@/enums/external/pageEnum"; |
3 | import { useUserStoreWithOut } from "@/store/external/modules/user"; | 3 | import { useUserStoreWithOut } from "@/store/external/modules/user"; |
4 | import { NavigationGuardNext, NavigationGuardWithThis, RouteLocationNormalized, RouteLocationRaw, Router } from "vue-router"; | 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 | const isAloneMode = [ProjectRuntimeEnvEnum.DEV_ALONE, ProjectRuntimeEnvEnum.PROD_ALONE].includes(import.meta.env.MODE as ProjectRuntimeEnvEnum) | 9 | const isAloneMode = [ProjectRuntimeEnvEnum.DEV_ALONE, ProjectRuntimeEnvEnum.PROD_ALONE].includes(import.meta.env.MODE as ProjectRuntimeEnvEnum) |
10 | 10 | ||
11 | const toIotPlatformLogin = ({ to, from, next }: { to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext }) => { | 11 | const toIotPlatformLogin = ({ to, from, next }: { to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext }) => { |
12 | const { origin, port } = window.location | 12 | const { origin, port } = window.location |
13 | + | ||
13 | if (Number(port) === Number(import.meta.env.VITE_DEV_PORT)) { | 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 | next() | 16 | next() |
16 | return | 17 | return |
17 | } else { | 18 | } else { |
@@ -36,8 +37,9 @@ export function createPermissionGuard(router: Router) { | @@ -36,8 +37,9 @@ export function createPermissionGuard(router: Router) { | ||
36 | } | 37 | } |
37 | 38 | ||
38 | const token = userStore.getJwtToken | 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 | if (to.path === PageEnum.BASE_LOGIN && token) { | 43 | if (to.path === PageEnum.BASE_LOGIN && token) { |
42 | const isSessionTimeout = userStore.getSessionTimeout | 44 | const isSessionTimeout = userStore.getSessionTimeout |
43 | try { | 45 | try { |
@@ -47,6 +49,9 @@ export function createPermissionGuard(router: Router) { | @@ -47,6 +49,9 @@ export function createPermissionGuard(router: Router) { | ||
47 | } catch (error) { | 49 | } catch (error) { |
48 | console.error(error) | 50 | console.error(error) |
49 | } | 51 | } |
52 | + } else if (to.matched.find(item => ShareEnum.SHARE_PATH)) { | ||
53 | + next() | ||
54 | + return | ||
50 | } | 55 | } |
51 | else { | 56 | else { |
52 | if (!isAloneMode) { | 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 | + |
@@ -7,7 +7,10 @@ import { HttpErrorPage, LoginRoute, ReloadRoute } from '@/router/base' | @@ -7,7 +7,10 @@ import { HttpErrorPage, LoginRoute, ReloadRoute } from '@/router/base' | ||
7 | import { Layout } from '@/router/constant' | 7 | import { Layout } from '@/router/constant' |
8 | 8 | ||
9 | import modules from '@/router/modules' | 9 | import modules from '@/router/modules' |
10 | +// THINGS_KIT 重写路由拦截逻辑 | ||
10 | import { setupRouterGuard } from './external/guard' | 11 | import { setupRouterGuard } from './external/guard' |
12 | +// THINGS_KIT 新增分享路由 | ||
13 | +import { shareRoutes } from './external/share.route' | ||
11 | 14 | ||
12 | const RootRoute: Array<RouteRecordRaw> = [ | 15 | const RootRoute: Array<RouteRecordRaw> = [ |
13 | { | 16 | { |
@@ -23,7 +26,9 @@ const RootRoute: Array<RouteRecordRaw> = [ | @@ -23,7 +26,9 @@ const RootRoute: Array<RouteRecordRaw> = [ | ||
23 | modules.projectRoutes, | 26 | modules.projectRoutes, |
24 | modules.chartRoutes, | 27 | modules.chartRoutes, |
25 | modules.previewRoutes, | 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,7 +5,8 @@ import { DateViewConfigurationInfoType } from '@/api/external/contentSave/model/ | ||
5 | export enum ProjectInfoEnum { | 5 | export enum ProjectInfoEnum { |
6 | INFO = 'info', | 6 | INFO = 'info', |
7 | SAVE_STATUS = 'saveStatus', | 7 | SAVE_STATUS = 'saveStatus', |
8 | - DATA_VIEW_NAME = 'dataViewName' | 8 | + DATA_VIEW_NAME = 'dataViewName', |
9 | + ACCESS_CREDENTIALS = 'accessCredentials' | ||
9 | } | 10 | } |
10 | 11 | ||
11 | export enum EEditCanvasTypeEnum { | 12 | export enum EEditCanvasTypeEnum { |
@@ -17,4 +18,6 @@ export interface ProjectInfoStoreType { | @@ -17,4 +18,6 @@ export interface ProjectInfoStoreType { | ||
17 | [ProjectInfoEnum.INFO]: DateViewConfigurationInfoType | 18 | [ProjectInfoEnum.INFO]: DateViewConfigurationInfoType |
18 | 19 | ||
19 | [ProjectInfoEnum.SAVE_STATUS]: SyncEnum | 20 | [ProjectInfoEnum.SAVE_STATUS]: SyncEnum |
21 | + | ||
22 | + [ProjectInfoEnum.ACCESS_CREDENTIALS]: string | ||
20 | } | 23 | } |
@@ -6,10 +6,10 @@ import { SyncEnum } from "@/enums/external/editPageEnum"; | @@ -6,10 +6,10 @@ import { SyncEnum } from "@/enums/external/editPageEnum"; | ||
6 | export const useProjectInfoStore = defineStore({ | 6 | export const useProjectInfoStore = defineStore({ |
7 | id: 'useProjectInfoStore', | 7 | id: 'useProjectInfoStore', |
8 | state: (): ProjectInfoStoreType => ({ | 8 | state: (): ProjectInfoStoreType => ({ |
9 | - info: { | 9 | + info: { |
10 | } as ProjectInfoStoreType['info'], | 10 | } as ProjectInfoStoreType['info'], |
11 | - | ||
12 | - saveStatus: SyncEnum.FAILURE | 11 | + saveStatus: SyncEnum.FAILURE, |
12 | + accessCredentials: '' | ||
13 | }), | 13 | }), |
14 | getters: { | 14 | getters: { |
15 | getProjectInfo(): ProjectInfoStoreType[ProjectInfoEnum.INFO] { | 15 | getProjectInfo(): ProjectInfoStoreType[ProjectInfoEnum.INFO] { |
@@ -28,6 +28,9 @@ export const useProjectInfoStore = defineStore({ | @@ -28,6 +28,9 @@ export const useProjectInfoStore = defineStore({ | ||
28 | }, | 28 | }, |
29 | setSaveStatus(status: SyncEnum) { | 29 | setSaveStatus(status: SyncEnum) { |
30 | this[ProjectInfoEnum.SAVE_STATUS] = status | 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,13 +2,22 @@ import { fetchRouteParamsLocation, JSONParse, } from '@/utils' | ||
2 | import { getDataView } from '@/api/external/contentSave/content' | 2 | import { getDataView } from '@/api/external/contentSave/content' |
3 | import { ChartEditStorageType } from '..' | 3 | import { ChartEditStorageType } from '..' |
4 | import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' | 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 | export const getSessionStorageInfo = async () => { | 14 | export const getSessionStorageInfo = async () => { |
15 | + if (isSharePageMode()) return | ||
7 | const id = fetchRouteParamsLocation() | 16 | const id = fetchRouteParamsLocation() |
8 | const chartEditStore = useChartEditStore() | 17 | const chartEditStore = useChartEditStore() |
9 | const res = await getDataView(id) | 18 | const res = await getDataView(id) |
10 | if (res) { | 19 | if (res) { |
11 | - const { dataViewContent, dataViewName, dataViewId } = res | 20 | + const { dataViewContent } = res |
12 | const content = JSONParse(dataViewContent.content) as ChartEditStorageType | 21 | const content = JSONParse(dataViewContent.content) as ChartEditStorageType |
13 | if (content) { | 22 | if (content) { |
14 | const { editCanvasConfig, requestGlobalConfig, componentList } = content | 23 | const { editCanvasConfig, requestGlobalConfig, componentList } = content |
1 | <template> | 1 | <template> |
2 | - <!-- THINGS_KIT 预览时需要异步请求接口 改为异步加载组件 --> | ||
3 | - <Suspense> | ||
4 | - <preview :key="key"></preview> | ||
5 | - </Suspense> | 2 | + <preview :key="key"></preview> |
6 | </template> | 3 | </template> |
7 | 4 | ||
8 | <script setup lang="ts"> | 5 | <script setup lang="ts"> |
@@ -16,13 +13,13 @@ import Preview from './index.vue' | @@ -16,13 +13,13 @@ import Preview from './index.vue' | ||
16 | 13 | ||
17 | let key = ref(Date.now()) | 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 | </script> | 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> |