Commit f9fa85751cb515c1a303022fb5e1b87622e3cb7c

Authored by xp.Huang
1 parent 32b3b0d0

feat:合并ThingsKit v1.2.0版本

1 import { defHttp } from '@/utils/external/http/axios' 1 import { defHttp } from '@/utils/external/http/axios'
2 -import { DictItem, OrganizationListItem, UploadResponse } from './model' 2 +import { ConfigurationItemType, DictItem, OrganizationListItem, UploadResponse } from './model'
  3 +import { PaginationResult } from '/#/external/axios'
3 4
4 enum Api { 5 enum Api {
5 GET_DICT = '/dict_item', 6 GET_DICT = '/dict_item',
@@ -54,7 +55,7 @@ export const getPlatformInfo = () => defHttp.get({ url: Api.PLATFORM }) @@ -54,7 +55,7 @@ export const getPlatformInfo = () => defHttp.get({ url: Api.PLATFORM })
54 55
55 //获取组态列表 56 //获取组态列表
56 export const getConfigurationList = (params: object) => { 57 export const getConfigurationList = (params: object) => {
57 - return defHttp.get({ url: `${Api.CONFIGURATION}`, params }) 58 + return defHttp.get<PaginationResult<ConfigurationItemType>>({ url: `${Api.CONFIGURATION}`, params })
58 } 59 }
59 60
60 //组态设置是否公开或私有 61 //组态设置是否公开或私有
@@ -145,4 +146,4 @@ export const getProfileAttrs = (params: { deviceProfileId: string; dataType?: st @@ -145,4 +146,4 @@ export const getProfileAttrs = (params: { deviceProfileId: string; dataType?: st
145 url: `${Api.DEVICE_ATTR}/${deviceProfileId}`, 146 url: `${Api.DEVICE_ATTR}/${deviceProfileId}`,
146 params: { dataType }, 147 params: { dataType },
147 }); 148 });
148 -};  
  149 +};
@@ -23,4 +23,34 @@ export interface OrganizationListItem { @@ -23,4 +23,34 @@ export interface OrganizationListItem {
23 name: string; 23 name: string;
24 parentId?: string; 24 parentId?: string;
25 remark: string; 25 remark: string;
26 -}  
  26 +}
  27 +
  28 +export interface ConfigurationItemType {
  29 + id: string
  30 + creator: string
  31 + createTime: string
  32 + name: string
  33 + enabled: boolean
  34 + tenantId: string
  35 + viewType: string
  36 + organizationId: string
  37 + platform: string
  38 + organizationDTO: OrganizationDto
  39 + publicId?: string
  40 + productAndDevice: ProductAndDevice[]
  41 +}
  42 +
  43 +export interface OrganizationDto {
  44 + name: string
  45 + enabled: boolean
  46 + sort: number
  47 + children: any[]
  48 +}
  49 +
  50 +export interface ProductAndDevice {
  51 + name: string
  52 + profileId: string
  53 + deviceList: any
  54 + deviceType: string
  55 + transportType: string
  56 +}
@@ -3,14 +3,19 @@ import {CreateComponentType} from '@/packages/index.d' @@ -3,14 +3,19 @@ import {CreateComponentType} from '@/packages/index.d'
3 import {chartInitConfig} from '@/settings/designSetting' 3 import {chartInitConfig} from '@/settings/designSetting'
4 import {OverrideILoadConfigurationframeConfig} from './index' 4 import {OverrideILoadConfigurationframeConfig} from './index'
5 import cloneDeep from 'lodash/cloneDeep' 5 import cloneDeep from 'lodash/cloneDeep'
  6 +import { Platform } from './help'
6 7
7 export const enum shareEnum { 8 export const enum shareEnum {
8 PRIVATE_VIEW = "PRIVATE_VIEW", 9 PRIVATE_VIEW = "PRIVATE_VIEW",
  10 + PUBLIC_VIEW = 'PUBLIC_VIEW'
9 } 11 }
10 12
11 export const option = { 13 export const option = {
12 // 网站路径 14 // 网站路径
13 dataset: '', 15 dataset: '',
  16 + organizationId: '',
  17 + platform: Platform.PC,
  18 + publicId: '' as (undefined | string),
14 // 圆角 19 // 圆角
15 borderRadius: 10, 20 borderRadius: 10,
16 pages: { 21 pages: {
@@ -3,24 +3,19 @@ @@ -3,24 +3,19 @@
3 <setting-item-box name="路径" :alone="true"> 3 <setting-item-box name="路径" :alone="true">
4 <setting-item name="请选择要加载的组态"> 4 <setting-item name="请选择要加载的组态">
5 <n-select label-in-value @change="handleUpdateValue" filterable size="small" v-model:value="optionData.dataset" 5 <n-select label-in-value @change="handleUpdateValue" filterable size="small" v-model:value="optionData.dataset"
6 - :options="configurationOptions"/> 6 + :options="configurationOptions" />
7 </setting-item> 7 </setting-item>
8 </setting-item-box> 8 </setting-item-box>
9 <setting-item-box name="是否公开"> 9 <setting-item-box name="是否公开">
10 <setting-item> 10 <setting-item>
11 <div style="display:flex"> 11 <div style="display:flex">
12 - <n-switch @change="handleChange" v-model:value="optionData.isShare" size="small"/> 12 + <n-switch @change="handleChange" v-model:value="optionData.isShare" size="small" />
13 </div> 13 </div>
14 </setting-item> 14 </setting-item>
15 </setting-item-box> 15 </setting-item-box>
16 <setting-item-box name="样式"> 16 <setting-item-box name="样式">
17 <setting-item name="圆角"> 17 <setting-item name="圆角">
18 - <n-input-number  
19 - v-model:value="optionData.borderRadius"  
20 - size="small"  
21 - :min="0"  
22 - placeholder="圆角"  
23 - ></n-input-number> 18 + <n-input-number v-model:value="optionData.borderRadius" size="small" :min="0" placeholder="圆角"></n-input-number>
24 </setting-item> 19 </setting-item>
25 </setting-item-box> 20 </setting-item-box>
26 <setting-item-box name="分页"> 21 <setting-item-box name="分页">
@@ -28,13 +23,8 @@ @@ -28,13 +23,8 @@
28 <n-input-number v-model:value="optionData.pages.page" size="small" :min="1" placeholder="页码"></n-input-number> 23 <n-input-number v-model:value="optionData.pages.page" size="small" :min="1" placeholder="页码"></n-input-number>
29 </setting-item> 24 </setting-item>
30 <setting-item name="页数"> 25 <setting-item name="页数">
31 - <n-input-number  
32 - disabled  
33 - v-model:value="optionData.pages.pageSize"  
34 - size="small"  
35 - :min="10"  
36 - placeholder="页数"  
37 - ></n-input-number> 26 + <n-input-number disabled v-model:value="optionData.pages.pageSize" size="small" :min="10"
  27 + placeholder="页数"></n-input-number>
38 </setting-item> 28 </setting-item>
39 </setting-item-box> 29 </setting-item-box>
40 <setting-item-box name="颜色" :alone="true"> 30 <setting-item-box name="颜色" :alone="true">
@@ -49,11 +39,12 @@ @@ -49,11 +39,12 @@
49 </template> 39 </template>
50 40
51 <script setup lang="ts"> 41 <script setup lang="ts">
52 -import {PropType, onMounted, ref, watch} from 'vue'  
53 -import {option, shareEnum} from './config'  
54 -import {CollapseItem, SettingItemBox, SettingItem} from '@/components/Pages/ChartItemSetting'  
55 -import {getConfigurationList, setConfigurationIsShare} from '@/api/external/common/index'  
56 -import {SelectOption} from 'naive-ui' 42 +import { PropType, onMounted, ref, watch } from 'vue'
  43 +import { option, shareEnum } from './config'
  44 +import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
  45 +import { getConfigurationList, setConfigurationIsShare } from '@/api/external/common/index'
  46 +import { ConfigurationItemType } from '@/api/external/common/model'
  47 +import { Platform } from './help'
57 48
58 const props = defineProps({ 49 const props = defineProps({
59 optionData: { 50 optionData: {
@@ -62,44 +53,40 @@ const props = defineProps({ @@ -62,44 +53,40 @@ const props = defineProps({
62 } 53 }
63 }) 54 })
64 55
65 -const configurationOptions = ref([]) 56 +const configurationOptions = ref<ConfigurationItemType[]>([])
66 57
67 const configurationId = ref('') 58 const configurationId = ref('')
68 59
69 const getConfigurationOptions = async (params: object) => { 60 const getConfigurationOptions = async (params: object) => {
70 - const {items} = await getConfigurationList(params) 61 + const { items } = await getConfigurationList(params)
71 if (items) { 62 if (items) {
72 - configurationOptions.value = items.map((item: SelectOption) => ({ 63 + configurationOptions.value = items.map((item) => ({
73 label: item.name, 64 label: item.name,
74 value: item.id, 65 value: item.id,
75 - viewType: item.viewType 66 + ...item
76 })) 67 }))
77 } 68 }
78 } 69 }
79 70
80 watch( 71 watch(
81 - () => props.optionData.pages,  
82 - (newData: any) => {  
83 - getConfigurationOptions({page: newData.page, pageSize: newData.pageSize})  
84 - },  
85 - {  
86 - deep: true,  
87 - immediate: true  
88 - } 72 + () => props.optionData.pages,
  73 + (newData: any) => {
  74 + getConfigurationOptions({ page: newData.page, pageSize: newData.pageSize })
  75 + },
  76 + {
  77 + deep: true,
  78 + immediate: true
  79 + }
89 ) 80 )
90 81
91 onMounted(() => { 82 onMounted(() => {
92 - getConfigurationOptions({page: props.optionData.pages.page, pageSize: props.optionData.pages.pageSize}) 83 + getConfigurationOptions({ page: props.optionData.pages.page, pageSize: props.optionData.pages.pageSize })
93 }) 84 })
94 85
95 -const handleUpdateValue = (value: string, options: SelectOption) => {  
96 - const {viewType} = options 86 +const handleUpdateValue = (value: string, options: ConfigurationItemType) => {
  87 + const { viewType, organizationId, publicId, platform } = options
97 configurationId.value = value 88 configurationId.value = value
98 - if (viewType === shareEnum.PRIVATE_VIEW) {  
99 - props.optionData.isShare = false  
100 - } else {  
101 - props.optionData.isShare = true  
102 - } 89 + Object.assign(props.optionData, { isShare: viewType === shareEnum.PUBLIC_VIEW, organizationId, platform, publicId } as typeof option)
103 } 90 }
104 91
105 const handleChange = async (value: boolean) => { 92 const handleChange = async (value: boolean) => {
@@ -108,7 +95,7 @@ const handleChange = async (value: boolean) => { @@ -108,7 +95,7 @@ const handleChange = async (value: boolean) => {
108 }) 95 })
109 if (res) { 96 if (res) {
110 window.$message.success('操作成功!') 97 window.$message.success('操作成功!')
111 - await getConfigurationOptions({page: props.optionData.pages.page, pageSize: props.optionData.pages.pageSize}) 98 + await getConfigurationOptions({ page: props.optionData.pages.page, pageSize: props.optionData.pages.pageSize })
112 } 99 }
113 } 100 }
114 </script> 101 </script>
  1 +
  2 +export enum ScadaModeEnum {
  3 + LIGHTBOX = 'lightbox',
  4 + DESIGN = 'design',
  5 + SHARE = 'share',
  6 +}
  7 +
  8 +export enum Platform {
  9 + PHONE = 'phone',
  10 + PC = 'pc',
  11 +}
  12 +
  13 +interface ScadaLinkParamsType {
  14 + configurationId: string;
  15 + organizationId: string;
  16 + mode: ScadaModeEnum;
  17 + platform: Platform;
  18 + publicId?: string;
  19 +}
  20 +
  21 +const getRandomString = () => Number(Math.random().toString().substring(2)).toString(36);
  22 +
  23 +export const encode = (record: Recordable) => {
  24 + let hash = JSON.stringify(record);
  25 + const mixinString = getRandomString()
  26 + .slice(0, 10)
  27 + .padEnd(10, getRandomString())
  28 + .split('')
  29 + .map((item) => (Math.random() > 0.5 ? item.toUpperCase() : item))
  30 + .join('');
  31 + hash = window.btoa(hash);
  32 + hash = hash.substring(0, 6) + mixinString + hash.substring(6);
  33 + hash = window.btoa(hash);
  34 + return hash;
  35 +};
  36 +
  37 +
  38 +export const createScadaPageLink = (
  39 + record: Partial<Record<'id' | 'organizationId' | 'platform' | 'publicId', string>>,
  40 + mode: ScadaModeEnum = ScadaModeEnum.DESIGN,
  41 + open = true
  42 +) => {
  43 + const params: ScadaLinkParamsType = {
  44 + configurationId: record.id!,
  45 + organizationId: record.organizationId!,
  46 + mode: mode,
  47 + platform: record.platform as Platform,
  48 + };
  49 +
  50 + if (mode === ScadaModeEnum.SHARE) {
  51 + params.publicId = record.publicId;
  52 + }
  53 +
  54 + const href = new URL(location.origin);
  55 + href.pathname = '/thingskit-scada';
  56 + href.hash = encode(params);
  57 + open && window.open(href.href);
  58 + return href.href;
  59 +};
1 <template> 1 <template>
2 - <div  
3 - @mouseenter="handleMouseenter"  
4 - @mouseleave="handleMouseleave"  
5 - class="iframe-content"  
6 - :style="getStyle(borderRadius)"  
7 - > 2 + <div @mouseenter="handleMouseenter" @mouseleave="handleMouseleave" class="iframe-content"
  3 + :style="getStyle(borderRadius)">
8 <div v-show="isShowSvg" @click="handleFullScreen" id="fullscreenButton"> 4 <div v-show="isShowSvg" @click="handleFullScreen" id="fullscreenButton">
9 - <svg  
10 - focusable="false"  
11 - data-icon="fullscreen"  
12 - width="4vw"  
13 - :style="`color:${color}`"  
14 - height="4vh"  
15 - fill="currentColor"  
16 - aria-hidden="true"  
17 - viewBox="64 64 896 896"  
18 - > 5 + <svg focusable="false" data-icon="fullscreen" width="4vw" :style="`color:${color}`" height="4vh" fill="currentColor"
  6 + aria-hidden="true" viewBox="64 64 896 896">
19 <path 7 <path
20 - d="M290 236.4l43.9-43.9a8.01 8.01 0 00-4.7-13.6L169 160c-5.1-.6-9.5 3.7-8.9 8.9L179 329.1c.8 6.6 8.9 9.4 13.6 4.7l43.7-43.7L370 423.7c3.1 3.1 8.2 3.1 11.3 0l42.4-42.3c3.1-3.1 3.1-8.2 0-11.3L290 236.4zm352.7 187.3c3.1 3.1 8.2 3.1 11.3 0l133.7-133.6 43.7 43.7a8.01 8.01 0 0013.6-4.7L863.9 169c.6-5.1-3.7-9.5-8.9-8.9L694.8 179c-6.6.8-9.4 8.9-4.7 13.6l43.9 43.9L600.3 370a8.03 8.03 0 000 11.3l42.4 42.4zM845 694.9c-.8-6.6-8.9-9.4-13.6-4.7l-43.7 43.7L654 600.3a8.03 8.03 0 00-11.3 0l-42.4 42.3a8.03 8.03 0 000 11.3L734 787.6l-43.9 43.9a8.01 8.01 0 004.7 13.6L855 864c5.1.6 9.5-3.7 8.9-8.9L845 694.9zm-463.7-94.6a8.03 8.03 0 00-11.3 0L236.3 733.9l-43.7-43.7a8.01 8.01 0 00-13.6 4.7L160.1 855c-.6 5.1 3.7 9.5 8.9 8.9L329.2 845c6.6-.8 9.4-8.9 4.7-13.6L290 787.6 423.7 654c3.1-3.1 3.1-8.2 0-11.3l-42.4-42.4z"  
21 - ></path> 8 + d="M290 236.4l43.9-43.9a8.01 8.01 0 00-4.7-13.6L169 160c-5.1-.6-9.5 3.7-8.9 8.9L179 329.1c.8 6.6 8.9 9.4 13.6 4.7l43.7-43.7L370 423.7c3.1 3.1 8.2 3.1 11.3 0l42.4-42.3c3.1-3.1 3.1-8.2 0-11.3L290 236.4zm352.7 187.3c3.1 3.1 8.2 3.1 11.3 0l133.7-133.6 43.7 43.7a8.01 8.01 0 0013.6-4.7L863.9 169c.6-5.1-3.7-9.5-8.9-8.9L694.8 179c-6.6.8-9.4 8.9-4.7 13.6l43.9 43.9L600.3 370a8.03 8.03 0 000 11.3l42.4 42.4zM845 694.9c-.8-6.6-8.9-9.4-13.6-4.7l-43.7 43.7L654 600.3a8.03 8.03 0 00-11.3 0l-42.4 42.3a8.03 8.03 0 000 11.3L734 787.6l-43.9 43.9a8.01 8.01 0 004.7 13.6L855 864c5.1.6 9.5-3.7 8.9-8.9L845 694.9zm-463.7-94.6a8.03 8.03 0 00-11.3 0L236.3 733.9l-43.7-43.7a8.01 8.01 0 00-13.6 4.7L160.1 855c-.6 5.1 3.7 9.5 8.9 8.9L329.2 845c6.6-.8 9.4-8.9 4.7-13.6L290 787.6 423.7 654c3.1-3.1 3.1-8.2 0-11.3l-42.4-42.4z">
  9 + </path>
22 </svg> 10 </svg>
23 </div> 11 </div>
24 - <iframe id="iframeContent" :src="option.dataset" :width="w" :height="h" style="border-width: 0"></iframe> 12 + <iframe id="iframeContent" :src="iframeLink" :width="w" :height="h" style="border-width: 0"></iframe>
25 </div> 13 </div>
26 </template> 14 </template>
27 15
@@ -32,6 +20,8 @@ import { CreateComponentType } from '@/packages/index.d' @@ -32,6 +20,8 @@ import { CreateComponentType } from '@/packages/index.d'
32 import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' 20 import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
33 import { useFullScreen } from '@/packages/components/external/Charts/utls/fullScreen' 21 import { useFullScreen } from '@/packages/components/external/Charts/utls/fullScreen'
34 import { isDevMode } from '@/utils/external/env' 22 import { isDevMode } from '@/utils/external/env'
  23 +import { createScadaPageLink, ScadaModeEnum } from './help'
  24 +import { option as typeOption } from './config'
35 25
36 const props = defineProps({ 26 const props = defineProps({
37 chartConfig: { 27 chartConfig: {
@@ -60,16 +50,14 @@ const getStyle = (radius: number) => { @@ -60,16 +50,14 @@ const getStyle = (radius: number) => {
60 50
61 const isDev = isDevMode() 51 const isDev = isDevMode()
62 52
  53 +const iframeLink = ref('')
  54 +
63 // 编辑更新 55 // 编辑更新
64 watch( 56 watch(
65 () => props.chartConfig.option.dataset, 57 () => props.chartConfig.option.dataset,
66 (newData: string) => { 58 (newData: string) => {
67 - const currentHost = window.location.host  
68 - const currentProtocol = window.location.protocol  
69 - //预览  
70 - option.dataset = `${currentProtocol}//${currentHost}/thingskit-scada/${  
71 - isDev ? '?dev=1&' : '?'  
72 - }configurationId=${newData}&lightbox=1` 59 + const { dataset, publicId, organizationId, platform, isShare } = props.chartConfig.option as typeof typeOption
  60 + iframeLink.value = createScadaPageLink({ id: dataset, platform, publicId, organizationId, }, isShare ? ScadaModeEnum.SHARE : ScadaModeEnum.LIGHTBOX, false)
73 }, 61 },
74 { 62 {
75 immediate: true 63 immediate: true