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> | ... | ... |