Commit 931d73b7929f28758bdfe56306f5af088a86c7dc

Authored by xp.Huang
2 parents 90872f02 2d795708

Merge branch 'ww' into 'main_dev'

feat(share): 新增分享页面

See merge request yunteng/thingskit-view!31
@@ -84,8 +84,13 @@ const transformBodyValue = (body: RequestParams['Body'], requestParamsBodyType: @@ -84,8 +84,13 @@ const transformBodyValue = (body: RequestParams['Body'], requestParamsBodyType:
84 return value 84 return value
85 } 85 }
86 86
  87 +const extraValue = (object: Recordable) => {
  88 + return Object.keys(object).reduce((prev, next) => {
  89 + return {...prev, ...(object[next] ? {[next]: object[next]} : {} )}
  90 + }, {})
  91 +}
  92 +
87 export const customRequest = async (request: RequestConfigType) => { 93 export const customRequest = async (request: RequestConfigType) => {
88 - console.log(request)  
89 const { requestHttpType, requestParams, requestParamsBodyType, requestOriginUrl } = request as ExtraRequestConfigType 94 const { requestHttpType, requestParams, requestParamsBodyType, requestOriginUrl } = request as ExtraRequestConfigType
90 let { requestUrl } = request as ExtraRequestConfigType 95 let { requestUrl } = request as ExtraRequestConfigType
91 const { Header, Body } = requestParams 96 const { Header, Body } = requestParams
@@ -98,7 +103,6 @@ export const customRequest = async (request: RequestConfigType) => { @@ -98,7 +103,6 @@ export const customRequest = async (request: RequestConfigType) => {
98 } 103 }
99 104
100 const body = transformBodyValue(Body, requestParamsBodyType) 105 const body = transformBodyValue(Body, requestParamsBodyType)
101 - console.log({ body, requestParamsBodyType, Params })  
102 106
103 return defHttp.request<any>({ 107 return defHttp.request<any>({
104 url: requestUrl, 108 url: requestUrl,
@@ -106,7 +110,7 @@ export const customRequest = async (request: RequestConfigType) => { @@ -106,7 +110,7 @@ export const customRequest = async (request: RequestConfigType) => {
106 method: requestHttpType, 110 method: requestHttpType,
107 params: Params, 111 params: Params,
108 data: body, 112 data: body,
109 - headers: Header 113 + headers: extraValue(Header)
110 }, { 114 }, {
111 joinPrefix: false, 115 joinPrefix: false,
112 apiUrl: '' 116 apiUrl: ''
  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 + const { accessCredentials } = options
  39 + return defHttp.get<{ data: any }>({
  40 + url: `${Api.SHARE_CONTENT}/${ViewTypeEnum.LARGE_SCREEN}/share_data/${options.id}`,
  41 + params: accessCredentials ? { accessCredentials } : {}
  42 + })
  43 +}
@@ -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 }
  1 +export enum ViewTypeEnum {
  2 + DATA_BOARD = 'DATA_BOARD',
  3 + LARGE_SCREEN = 'LARGE_SCREEN',
  4 + SCADA = 'SCADA'
  5 +}
@@ -18,6 +18,7 @@ export const useFetchTargetData = () => { @@ -18,6 +18,7 @@ export const useFetchTargetData = () => {
18 const res = isSocketType 18 const res = isSocketType
19 ? await sendMessage(unref(targetData) as CreateComponentType) 19 ? await sendMessage(unref(targetData) as CreateComponentType)
20 : await customRequest(toRaw(targetData.value.request)) 20 : await customRequest(toRaw(targetData.value.request))
  21 +
21 if (res) { 22 if (res) {
22 return res 23 return res
23 } 24 }
@@ -21,8 +21,10 @@ const size = computed(() => { @@ -21,8 +21,10 @@ const size = computed(() => {
21 </script> 21 </script>
22 22
23 <template> 23 <template>
24 - <SvgBorder :option="chartConfig.option">  
25 - <SvgIcon :style="{ color: chartConfig.option.iconColor }" :size="size" :name="chartConfig.option.icon!"  
26 - prefix="iconfont" />  
27 - </SvgBorder> 24 + <section>
  25 + <SvgBorder :option="chartConfig.option">
  26 + <SvgIcon :style="{ color: chartConfig.option.iconColor }" :size="size" :name="chartConfig.option.icon!"
  27 + prefix="iconfont" />
  28 + </SvgBorder>
  29 + </section>
28 </template> 30 </template>
@@ -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) {
  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>
  1 +<template>
  2 + <section>
  3 + <preview v-if="!allowLoadPreviewPage" :key="key"></preview>
  4 + <NModal :show="showModal" :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 showModal = ref(false)
  35 +const ROUTE = useRoute()
  36 +const accessCredentials = ref('')
  37 +const loading = ref(false)
  38 +const userStore = useUserStore()
  39 +const chartEditStore = useChartEditStore()
  40 +
  41 +const getToken = async () => {
  42 + const { params } = ROUTE
  43 + const { publicId } = params as Record<'id' | 'publicId', string>
  44 + const { token, refreshToken } = await getPublicToken(publicId)
  45 + userStore.storeToken(token, refreshToken)
  46 +}
  47 +
  48 +const checkNeedAccessToken = async () => {
  49 + const { params } = ROUTE
  50 + const { id } = params as Record<'id' | 'publicId', string>
  51 + const res = await checkSharePageNeedAccessToken(id)
  52 + return res.data
  53 +}
  54 +
  55 +const sharePageHandlerProcess = async () => {
  56 + await getToken()
  57 + const flag = await checkNeedAccessToken()
  58 + if (flag) {
  59 + showModal.value = true
  60 + } else {
  61 + allowLoadPreviewPage.value = false
  62 + await getSharePageContentData()
  63 + }
  64 +}
  65 +
  66 +const getSharePageContentData = async () => {
  67 + try {
  68 + const { params } = ROUTE
  69 + const { id } = params as Record<'id' | 'publicId', string>
  70 + loading.value = true
  71 + const res = await getShareContentData({ id, accessCredentials: unref(accessCredentials) })
  72 + const { dataViewContent, dataViewName, dataViewId } = res.data
  73 + const content = JSONParse(dataViewContent.content) as ChartEditStorageType
  74 + if (content) {
  75 + const { editCanvasConfig, requestGlobalConfig, componentList } = content
  76 + chartEditStore.editCanvasConfig = editCanvasConfig
  77 + chartEditStore.requestGlobalConfig = requestGlobalConfig
  78 + chartEditStore.componentList = componentList
  79 + }
  80 + showModal.value = false
  81 + allowLoadPreviewPage.value = false
  82 + } catch (error) {
  83 + console.log(error)
  84 + } finally {
  85 + loading.value = false
  86 + }
  87 +
  88 +}
  89 +
  90 +const handleSubmit = () => {
  91 + getSharePageContentData()
  92 +}
  93 +
  94 +onMounted(() => {
  95 + sharePageHandlerProcess()
  96 +})
  97 +
  98 +let key = ref(Date.now())
  99 +
  100 + // 数据变更 -> 组件销毁重建
  101 + ;[SavePageEnum.JSON, SavePageEnum.CHART].forEach((saveEvent: string) => {
  102 + if (!window.opener) return
  103 + window.opener.addEventListener(saveEvent, async (e: any) => {
  104 + const localStorageInfo: ChartEditStorageType = await getSessionStorageInfo() as unknown as ChartEditStorageType
  105 + setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, [{ ...e.detail, id: localStorageInfo.id }])
  106 + key.value = Date.now()
  107 + })
  108 + })
  109 +</script>