Showing
50 changed files
with
2633 additions
and
42 deletions
... | ... | @@ -2,7 +2,9 @@ module.exports = { |
2 | 2 | root: true, |
3 | 3 | parser: 'vue-eslint-parser', |
4 | 4 | globals: { |
5 | - postMessage: true | |
5 | + postMessage: true, | |
6 | + Recordable: 'readonly', | |
7 | + Nullable: 'readonly', | |
6 | 8 | }, |
7 | 9 | parserOptions: { |
8 | 10 | parser: '@typescript-eslint/parser', |
... | ... | @@ -31,8 +33,5 @@ module.exports = { |
31 | 33 | 'vue/multi-word-component-names': 'off', |
32 | 34 | 'vue/valid-template-root': 'off', |
33 | 35 | 'vue/no-mutating-props': 'off', |
34 | - }, | |
35 | - global: { | |
36 | - Recordable: 'readonly' | |
37 | 36 | } |
38 | 37 | } | ... | ... |
src/api/external/common/index.ts
0 → 100644
1 | +import { defHttp } from "@/utils/external/http/axios"; | |
2 | +import { DictItem } from "./model"; | |
3 | + | |
4 | +enum Api { | |
5 | + GET_DICT = '/dict_item' | |
6 | +} | |
7 | + | |
8 | +export const getDictItemByCode = (value: string) => { | |
9 | + return defHttp.post<DictItem[]>({ | |
10 | + url: `${Api.GET_DICT}/find`, | |
11 | + params: { | |
12 | + dictCode: value | |
13 | + } | |
14 | + }) | |
15 | +} | ... | ... |
src/api/external/common/model/index.ts
0 → 100644
src/api/external/customRequest/index.ts
0 → 100644
1 | +import { RequestBodyEnum } from "@/enums/httpEnum" | |
2 | +import { RequestConfigType, RequestGlobalConfigType } from "@/store/modules/chartEditStore/chartEditStore.d" | |
3 | +import { defHttp } from "@/utils/external/http/axios" | |
4 | + | |
5 | +export const isFullUrl = (url = '') => { | |
6 | + try { | |
7 | + new URL(url) | |
8 | + return true | |
9 | + } catch (error) { | |
10 | + return false | |
11 | + } | |
12 | +} | |
13 | + | |
14 | +export const getUrl = (url = '') => { | |
15 | + const isFullUrlFlag = isFullUrl(url) | |
16 | + const { origin } = window.location | |
17 | + return isFullUrlFlag ? new URL(url) : { pathname: url, origin } | |
18 | +} | |
19 | + | |
20 | +export const customRequest = async (request: RequestConfigType) => { | |
21 | + const { requestHttpType, requestParams, requestParamsBodyType, requestUrl } = request as RequestGlobalConfigType & RequestConfigType | |
22 | + const { Params, Header, Body } = requestParams | |
23 | + | |
24 | + const { origin, pathname } = getUrl(requestUrl!) | |
25 | + | |
26 | + const body = Body[requestParamsBodyType as Exclude<'NONE', keyof typeof RequestBodyEnum>] | |
27 | + | |
28 | + return defHttp.request<any>({ | |
29 | + url: pathname, | |
30 | + baseURL: origin, | |
31 | + method: requestHttpType, | |
32 | + params: Params, | |
33 | + data: body, | |
34 | + headers: Header | |
35 | + }, { | |
36 | + joinPrefix: false, | |
37 | + apiUrl: '' | |
38 | + }) | |
39 | +} | ... | ... |
src/api/external/dynamicRequest/index.ts
0 → 100644
1 | + import { defHttp } from '@/utils/external/http/axios'; | |
2 | +import { DeviceAttributesRecord, GetDeviceListParams, PublicInterfaceRecord } from './model'; | |
3 | +import { PaginationResult } from '/#/external/axios'; | |
4 | + | |
5 | +enum Api { | |
6 | + PUBLIC_API = '/data_view_interface', | |
7 | + ORG_LISt = '/organization/me/list', | |
8 | + DEVICE_PROFILE_LIST = '/device_profile/me/list', | |
9 | + DEVICE_LIST = '/device/list', | |
10 | + DEVICE_ATTR_LIST = '/device/attributes', | |
11 | + GET_PUBLIC_INTERFACE_ALL = '/data_view_interface/find_all_interface', | |
12 | + GET_PUBLIC_INTERFACE_DETAIL = '/data_view_interface/get_interface_details' | |
13 | +} | |
14 | + | |
15 | +export const getPublicInterface = async (params: Record<'page' | 'pageSize', number>) => { | |
16 | + return defHttp.get<PaginationResult<PublicInterfaceRecord>>({ | |
17 | + url: Api.PUBLIC_API, | |
18 | + params | |
19 | + }) | |
20 | +} | |
21 | + | |
22 | +export const getOrgList = async () => { | |
23 | + return defHttp.get({ | |
24 | + url: Api.ORG_LISt | |
25 | + }) | |
26 | +} | |
27 | + | |
28 | +export const getDeviceProfileList = async (params?: Record<'deviceType', string>) => { | |
29 | + return defHttp.get({ | |
30 | + url: Api.DEVICE_PROFILE_LIST, | |
31 | + params | |
32 | + }) | |
33 | +} | |
34 | + | |
35 | +export const getDeviceList = async (params?: GetDeviceListParams) => { | |
36 | + return defHttp.get({ | |
37 | + url: Api.DEVICE_LIST, | |
38 | + params | |
39 | + }) | |
40 | +} | |
41 | + | |
42 | +export const getDeviceAttrList = async (deviceProfileId: string) => { | |
43 | + return defHttp.get<DeviceAttributesRecord[]>({ | |
44 | + url: `${Api.DEVICE_ATTR_LIST}/${deviceProfileId}` | |
45 | + }) | |
46 | +} | |
47 | + | |
48 | + | |
49 | +export const getDeviceInterfaceDetail = async (interfaces: string[]) => { | |
50 | + return defHttp.get({ | |
51 | + url: Api.GET_PUBLIC_INTERFACE_DETAIL, | |
52 | + params: interfaces | |
53 | + }) | |
54 | +} | |
55 | + | |
56 | +export const getAllPublicInterface = async () => { | |
57 | + return defHttp.get<PublicInterfaceRecord[]>({ | |
58 | + url: Api.GET_PUBLIC_INTERFACE_ALL | |
59 | + }) | |
60 | +} | ... | ... |
1 | +import { RequestParams as OriginRequestParams } from "@/enums/httpEnum" | |
2 | + | |
3 | +export interface RequestParams { | |
4 | + Body: Recordable | |
5 | + Header: Recordable | |
6 | + Params: { | |
7 | + key: string | |
8 | + required: boolean | |
9 | + value: string | |
10 | + }[] | |
11 | +} | |
12 | + | |
13 | +export interface PublicInterfaceRecord { | |
14 | + id: string, | |
15 | + creator: string, | |
16 | + createTime: string, | |
17 | + updater: string, | |
18 | + updateTime: string, | |
19 | + enabled: boolean, | |
20 | + tenantId: string, | |
21 | + interfaceName: string, | |
22 | + requestContentType: number, | |
23 | + requestOriginUrl: string, | |
24 | + requestHttpType: string, | |
25 | + requestParamsBodyType: string, | |
26 | + requestUrl: string, | |
27 | + requestParams: string | OriginRequestParams, | |
28 | +} | |
29 | + | |
30 | + | |
31 | +export interface GetDeviceListParams { | |
32 | + organizationId?: string | |
33 | + deviceProfileId?: string | |
34 | + deviceType?: string | |
35 | +} | |
36 | + | |
37 | +export interface DeviceAttributesDetail { | |
38 | + dataType: { | |
39 | + specs: Recordable | |
40 | + type: string | |
41 | + } | |
42 | +} | |
43 | + | |
44 | +export interface DeviceAttributesRecord { | |
45 | + name: string, | |
46 | + identifier: string | |
47 | + detail: DeviceAttributesDetail | |
48 | +} | ... | ... |
src/components/external/Icon/Form/index.ts
0 → 100644
1 | +<script lang="ts" setup> | |
2 | +import { NForm, NGrid } from 'naive-ui'; | |
3 | +import { computed, reactive, ref, unref, useAttrs } from 'vue'; | |
4 | +import { BasicFormProps, FormSchema } from './types/form'; | |
5 | +import { basicProps } from './props'; | |
6 | +import { useDesign } from '@/hooks/external/useDesign'; | |
7 | +import { dateItemType } from './helper'; | |
8 | +import { dateUtil } from '@/utils/external/dateUtil'; | |
9 | +import { Dayjs } from 'dayjs'; | |
10 | +import FormItem from './components/FormItem.vue'; | |
11 | +import { deepMerge } from '@/utils/external'; | |
12 | + | |
13 | +const props = defineProps(basicProps) | |
14 | + | |
15 | +const attrs = useAttrs() | |
16 | + | |
17 | +const fromModel = reactive<Recordable>({}) | |
18 | + | |
19 | +const defaultValueRef = ref<Recordable>({}) | |
20 | + | |
21 | +const isInitialDefaultRef = ref(false) | |
22 | + | |
23 | +const propsRef = ref<Partial<BasicFormProps>>({}) | |
24 | + | |
25 | +const schemaRef = ref<Nullable<FormSchema[]>>(null) | |
26 | + | |
27 | +const formElRef = ref<Nullable<Recordable>>(null) | |
28 | + | |
29 | +const { prefixCls } = useDesign('basic-form') | |
30 | + | |
31 | +const getProps = computed(() => { | |
32 | + return { ...props, ...unref(propsRef) } as BasicFormProps | |
33 | +}) | |
34 | + | |
35 | + | |
36 | +const getBindValue = computed(() => { | |
37 | + return { ...attrs, ...unref(getProps) } as Recordable | |
38 | +}) | |
39 | + | |
40 | + | |
41 | +const getSchema = computed(() => { | |
42 | + const schemas = unref(schemaRef) || unref(getProps).schemas | |
43 | + | |
44 | + for (const schema of schemas) { | |
45 | + const { defaultValue, component } = schema | |
46 | + | |
47 | + if (defaultValue && dateItemType.includes(component)) { | |
48 | + if (!Array.isArray(defaultValue)) { | |
49 | + schema.defaultValue = dateUtil(defaultValue) | |
50 | + } else { | |
51 | + const def: Dayjs[] = [] | |
52 | + defaultValue.forEach(item => def.push(dateUtil(item))) | |
53 | + schema.defaultValue = def | |
54 | + } | |
55 | + } | |
56 | + } | |
57 | + | |
58 | + return schemas | |
59 | +}) | |
60 | + | |
61 | +async function setProps(params: Partial<BasicFormProps>) { | |
62 | + propsRef.value = deepMerge(unref(propsRef) || {},) | |
63 | +} | |
64 | + | |
65 | +const setFormModel = (key: string, value: any) => { | |
66 | + fromModel[key] = value | |
67 | + | |
68 | +} | |
69 | + | |
70 | +const handleEnterPress = () => { | |
71 | + | |
72 | +} | |
73 | + | |
74 | + | |
75 | +</script> | |
76 | + | |
77 | +<template> | |
78 | + <NForm ref="formElRef" :model="fromModel" @keypress.enter="handleEnterPress"> | |
79 | + <NGrid> | |
80 | + <slot name="formHeader" /> | |
81 | + <template v-for="schema in getSchema" :key="schema.field"> | |
82 | + <FormItem :schema="schema" :formProps="getProps" :allDefaultValues="defaultValueRef" :formModel="fromModel" | |
83 | + :setFormModel="setFormModel"> | |
84 | + <template #[item]="data" v-for="item in Object.keys($slots)"> | |
85 | + <slot :name="item" v-bind="data" /> | |
86 | + </template> | |
87 | + </FormItem> | |
88 | + </template> | |
89 | + <slot name="formFooter" /> | |
90 | + </NGrid> | |
91 | + </NForm> | |
92 | +</template> | |
93 | + | |
94 | +<style scoped lang="scss"> | |
95 | +</style> | ... | ... |
1 | +import { FormProps } from 'naive-ui' | |
2 | +import { FormSchema } from './types/form' | |
3 | + | |
4 | +const DEFAULT_FORM_PROPS: FormProps = { | |
5 | + size: 'small', | |
6 | + | |
7 | +} | |
8 | + | |
9 | +export const basicProps = { | |
10 | + formProps: { | |
11 | + type: Object as PropType<FormProps>, | |
12 | + default: () => DEFAULT_FORM_PROPS | |
13 | + }, | |
14 | + | |
15 | + /** | |
16 | + * @description 表单字段映射成时间 | |
17 | + */ | |
18 | + fieldMapToTime: { | |
19 | + type: Array as PropType<any[]>, | |
20 | + default: () => [] | |
21 | + }, | |
22 | + | |
23 | + /** | |
24 | + * @description 表单配置 | |
25 | + */ | |
26 | + schemas: { | |
27 | + type: Array as PropType<FormSchema[]>, | |
28 | + default: () => [] | |
29 | + }, | |
30 | + | |
31 | + | |
32 | +} | ... | ... |
1 | +import { ExtractPropTypes } from "vue"; | |
2 | +import { FormComponentTypeEnum } from "."; | |
3 | +import { basicProps } from "../props"; | |
4 | + | |
5 | +export type BasicFormProps = ExtractPropTypes<typeof basicProps> | |
6 | + | |
7 | + | |
8 | +export interface FormSchema { | |
9 | + field: string | |
10 | + | |
11 | + changeEvent?: string | |
12 | + | |
13 | + valueField?: string | |
14 | + | |
15 | + label: string | |
16 | + | |
17 | + component: FormComponentTypeEnum | |
18 | + | |
19 | + defaultValue?: any | |
20 | +} | ... | ... |
1 | 1 | <script lang="ts" setup> |
2 | -import { NInput, NPopover, NScrollbar } from 'naive-ui'; | |
2 | +import { NInput, NInputGroup, NInputGroupLabel, NPopover, NScrollbar } from 'naive-ui'; | |
3 | 3 | import '@/assets/external/iconfont/iconfont.js' |
4 | 4 | import iconfont from '@/assets/external/iconfont/iconfont.json' |
5 | 5 | import SvgIcon from './SvgIcon.vue'; |
6 | 6 | import { computed, ref, unref } from 'vue'; |
7 | +import { useDesignStore } from '@/store/modules/designStore/designStore'; | |
7 | 8 | |
8 | 9 | const props = defineProps({ |
9 | 10 | value: { |
... | ... | @@ -21,7 +22,11 @@ const getIconList = computed(() => { |
21 | 22 | return icons.filter(icon => icon.includes(text)) |
22 | 23 | }) |
23 | 24 | |
25 | +const designStore = useDesignStore() | |
24 | 26 | |
27 | +const themeColor = computed(() => { | |
28 | + return designStore.getAppTheme | |
29 | +}) | |
25 | 30 | |
26 | 31 | const handleChange = (icon: string) => { |
27 | 32 | emit('update:value', icon) |
... | ... | @@ -30,28 +35,38 @@ const handleChange = (icon: string) => { |
30 | 35 | </script> |
31 | 36 | |
32 | 37 | <template> |
33 | - <NInput :value="value" placeholder="请选择图标" disabled> | |
34 | - <template #suffix> | |
35 | - <NPopover trigger="click"> | |
36 | - <NInput v-model:value="searchValue" size="small" /> | |
37 | - <NScrollbar style="max-height: 120px; max-width: 210px;"> | |
38 | - <ul class="icon-list"> | |
39 | - <li class="icon-item" v-for="icon in getIconList" :key="icon" @click="handleChange(icon)" | |
40 | - :style="{ border: icon === props.value ? '1px solid #51d6a9' : '' }"> | |
41 | - <SvgIcon :name="icon" prefix="iconfont" /> | |
42 | - </li> | |
43 | - </ul> | |
44 | - </NScrollbar> | |
45 | - <template #trigger> | |
38 | + <NInputGroup class="icon-picker"> | |
39 | + <NInput :value="value" placeholder="请选择图标" disabled /> | |
40 | + <NPopover trigger="click"> | |
41 | + <NInput v-model:value="searchValue" size="small" style="text-overflow: ellipsis;" /> | |
42 | + <NScrollbar style="max-height: 120px; max-width: 210px; margin-top: 5px;"> | |
43 | + <ul class="icon-list"> | |
44 | + <li class="icon-item" v-for="icon in getIconList" :key="icon" @click="handleChange(icon)" | |
45 | + :style="{ border: icon === props.value ? `1px solid ${themeColor}` : '' }"> | |
46 | + <SvgIcon :name="icon" prefix="iconfont" /> | |
47 | + </li> | |
48 | + </ul> | |
49 | + </NScrollbar> | |
50 | + <template #trigger> | |
51 | + <NInputGroupLabel style="cursor: pointer;"> | |
46 | 52 | <SvgIcon :name="value || 'grid-one'" prefix="iconfont" style="cursor: pointer;" /> |
47 | - </template> | |
48 | - </NPopover> | |
49 | - </template> | |
50 | - </NInput> | |
53 | + </NInputGroupLabel> | |
54 | + </template> | |
55 | + </NPopover> | |
56 | + </NInputGroup> | |
51 | 57 | </template> |
52 | 58 | |
53 | -<style lang="scss"> | |
59 | +<style lang="scss" scoped> | |
54 | 60 | .icon { |
61 | + &-picker { | |
62 | + @include deep() { | |
63 | + .n-input__input-el { | |
64 | + text-overflow: ellipsis; | |
65 | + } | |
66 | + } | |
67 | + } | |
68 | + | |
69 | + | |
55 | 70 | &-list { |
56 | 71 | display: flex; |
57 | 72 | list-style: none; |
... | ... | @@ -70,11 +85,13 @@ const handleChange = (icon: string) => { |
70 | 85 | display: flex; |
71 | 86 | justify-content: center; |
72 | 87 | align-items: center; |
88 | + transition: transform .5s linear; | |
73 | 89 | |
74 | 90 | &:hover { |
75 | - border: 1px solid #51d6a9; | |
91 | + border: 1px solid v-bind("themeColor"); | |
76 | 92 | } |
77 | 93 | } |
78 | 94 | |
95 | + | |
79 | 96 | } |
80 | 97 | </style> | ... | ... |
src/enums/external/dictEnum.ts
0 → 100644
1 | +export { RequestDataTypeEnum } from '../httpEnum' | |
2 | + | |
1 | 3 | /** |
2 | 4 | * @description: Request result set |
3 | 5 | */ |
... | ... | @@ -29,3 +31,33 @@ export enum ContentTypeEnum { |
29 | 31 | // form-data upload |
30 | 32 | FORM_DATA = 'multipart/form-data;charset=UTF-8', |
31 | 33 | } |
34 | + | |
35 | + | |
36 | +// 请求主体类型 | |
37 | +export enum RequestContentTypeEnum { | |
38 | + // 普通请求 | |
39 | + DEFAULT = 0, | |
40 | + // SQL请求 | |
41 | + SQL = 1, | |
42 | + // websocket请求 | |
43 | + WEB_SOCKET = 2 | |
44 | +} | |
45 | + | |
46 | +export enum RequestContentTypeNameEnum { | |
47 | + // 普通请求 | |
48 | + DEFAULT = '普通请求', | |
49 | + // SQL请求 | |
50 | + SQL = 'SQL请求', | |
51 | + // websocket请求 | |
52 | + WEB_SOCKET = 'WebSocket请求' | |
53 | +} | |
54 | + | |
55 | + | |
56 | +export enum RequestDataTypeNameEnum { | |
57 | + // 静态数据 | |
58 | + STATIC = '静态数据', | |
59 | + // 请求数据 | |
60 | + AJAX = '自定义请求', | |
61 | + // 数据池 | |
62 | + Pond = '公共接口' | |
63 | +} | ... | ... |
src/hooks/external/useChartDataFetch.hook.ts
0 → 100644
1 | +import { ref, toRefs, toRaw } from 'vue' | |
2 | +import type VChart from 'vue-echarts' | |
3 | +import { customizeHttp } from '@/api/http' | |
4 | +import { useChartDataPondFetch } from '@/hooks/' | |
5 | +import { CreateComponentType, ChartFrameEnum } from '@/packages/index.d' | |
6 | +import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' | |
7 | +import { RequestDataTypeEnum } from '@/enums/httpEnum' | |
8 | +import { isPreview, newFunctionHandle, intervalUnitHandle } from '@/utils' | |
9 | +import { setOption } from '@/packages/public/chart' | |
10 | + | |
11 | +// 获取类型 | |
12 | +type ChartEditStoreType = typeof useChartEditStore | |
13 | + | |
14 | +/** | |
15 | + * setdata 数据监听与更改 | |
16 | + * @param targetComponent | |
17 | + * @param useChartEditStore 若直接引会报错,只能动态传递 | |
18 | + * @param updateCallback 自定义更新函数 | |
19 | + */ | |
20 | +export const useChartDataFetch = ( | |
21 | + targetComponent: CreateComponentType, | |
22 | + useChartEditStore: ChartEditStoreType, | |
23 | + updateCallback?: (...args: any) => any | |
24 | +) => { | |
25 | + const vChartRef = ref<typeof VChart | null>(null) | |
26 | + let fetchInterval: any = 0 | |
27 | + | |
28 | + // 数据池 | |
29 | + const { addGlobalDataInterface } = useChartDataPondFetch() | |
30 | + | |
31 | + // 组件类型 | |
32 | + const { chartFrame } = targetComponent.chartConfig | |
33 | + | |
34 | + // eCharts 组件配合 vChart 库更新方式 | |
35 | + const echartsUpdateHandle = (dataset: any) => { | |
36 | + if (chartFrame === ChartFrameEnum.ECHARTS) { | |
37 | + if (vChartRef.value) { | |
38 | + setOption(vChartRef.value, { dataset: dataset }) | |
39 | + } | |
40 | + } | |
41 | + } | |
42 | + | |
43 | + const requestIntervalFn = () => { | |
44 | + const chartEditStore = useChartEditStore() | |
45 | + | |
46 | + // 全局数据 | |
47 | + const { | |
48 | + requestOriginUrl, | |
49 | + requestIntervalUnit: globalUnit, | |
50 | + requestInterval: globalRequestInterval | |
51 | + } = toRefs(chartEditStore.getRequestGlobalConfig) | |
52 | + | |
53 | + // 目标组件 | |
54 | + const { | |
55 | + requestDataType, | |
56 | + requestUrl, | |
57 | + requestIntervalUnit: targetUnit, | |
58 | + requestInterval: targetInterval | |
59 | + } = toRefs(targetComponent.request) | |
60 | + | |
61 | + // 非请求类型 | |
62 | + if (requestDataType.value !== RequestDataTypeEnum.AJAX) return | |
63 | + | |
64 | + try { | |
65 | + // 处理地址 | |
66 | + if (requestUrl?.value) { | |
67 | + // requestOriginUrl 允许为空 | |
68 | + const completePath = requestOriginUrl && requestOriginUrl.value + requestUrl.value | |
69 | + if (!completePath) return | |
70 | + | |
71 | + clearInterval(fetchInterval) | |
72 | + | |
73 | + const fetchFn = async () => { | |
74 | + const res = await customizeHttp(toRaw(targetComponent.request), toRaw(chartEditStore.getRequestGlobalConfig)) | |
75 | + if (res) { | |
76 | + try { | |
77 | + const filter = targetComponent.filter | |
78 | + echartsUpdateHandle(newFunctionHandle(res?.data, res, filter)) | |
79 | + // 更新回调函数 | |
80 | + if (updateCallback) { | |
81 | + updateCallback(newFunctionHandle(res?.data, res, filter)) | |
82 | + } | |
83 | + } catch (error) { | |
84 | + console.error(error) | |
85 | + } | |
86 | + } | |
87 | + } | |
88 | + | |
89 | + // 立即调用 | |
90 | + fetchFn() | |
91 | + // 定时时间 | |
92 | + const time = targetInterval && targetInterval.value ? targetInterval.value : globalRequestInterval.value | |
93 | + // 单位 | |
94 | + const unit = targetInterval && targetInterval.value ? targetUnit.value : globalUnit.value | |
95 | + // 开启轮询 | |
96 | + if (time) fetchInterval = setInterval(fetchFn, intervalUnitHandle(time, unit)) | |
97 | + } | |
98 | + // eslint-disable-next-line no-empty | |
99 | + } catch (error) { | |
100 | + console.log(error) | |
101 | + } | |
102 | + } | |
103 | + | |
104 | + if (isPreview()) { | |
105 | + // 判断是否是数据池类型 | |
106 | + targetComponent.request.requestDataType === RequestDataTypeEnum.Pond | |
107 | + ? addGlobalDataInterface(targetComponent, useChartEditStore, updateCallback || echartsUpdateHandle) | |
108 | + : requestIntervalFn() | |
109 | + } | |
110 | + return { vChartRef } | |
111 | +} | ... | ... |
... | ... | @@ -4,9 +4,10 @@ import { ConfigType, PackagesCategoryEnum } from '@/packages/index.d' |
4 | 4 | import { ClockConfig } from '@/packages/components/external/Decorates/Mores/Icon' |
5 | 5 | |
6 | 6 | export function useInjectLib(packagesList: EPackagesType) { |
7 | + | |
7 | 8 | packagesList[EPackagesCategoryEnum.COMPOSES] = ComposesList |
8 | 9 | |
9 | - // addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.DECORATES, ClockConfig) | |
10 | + addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.DECORATES, ClockConfig) | |
10 | 11 | } |
11 | 12 | |
12 | 13 | /** | ... | ... |
src/packages/external/types/index.ts
0 → 100644
1 | +import { RequestBodyEnum, RequestContentTypeEnum, RequestDataTypeEnum, RequestHttpEnum } from "@/enums/httpEnum"; | |
2 | +import { CreateComponentType } from "@/packages/index.d"; | |
3 | + | |
4 | + | |
5 | +export interface DynamicRequest { | |
6 | + // 所选全局数据池的对应 id | |
7 | + requestDataPondId?: string | |
8 | + // 组件定制轮询时间 | |
9 | + requestInterval?: number | |
10 | + // 获取数据的方式 | |
11 | + requestDataType: RequestDataTypeEnum | |
12 | + // 请求方式 get/post/del/put/patch | |
13 | + requestHttpType: RequestHttpEnum | |
14 | + // 源后续的 url | |
15 | + requestUrl?: string | |
16 | + // 请求内容主体方式 普通/sql | |
17 | + requestContentType: RequestContentTypeEnum | |
18 | + // 请求体类型 | |
19 | + requestParamsBodyType: RequestBodyEnum | |
20 | + // SQL 请求对象 | |
21 | + requestSQLContent: { | |
22 | + sql: string | |
23 | + } | |
24 | +} | |
25 | + | |
26 | +export interface ECreateComponentType extends CreateComponentType { | |
27 | + test: 123 | |
28 | +} | ... | ... |
1 | +export enum DynamicRequestStoreEnum { | |
2 | + // 组件id | |
3 | + ID = 'id', | |
4 | + // 请求源地址 | |
5 | + REQUEST_ORIGIN_URL = 'requestOriginUrl', | |
6 | + // 请求间隔时间 | |
7 | + REQUEST_INTERVAL = 'requestInterval', | |
8 | + // 请求单位 | |
9 | + REQUEST_INTERVAL_UNIT = 'requestIntervalUnit', | |
10 | + // 请求头 | |
11 | + REQUEST_HEADER = 'requestHeader' | |
12 | +} | |
13 | + | |
14 | +export interface DynamicRequestStoreType { | |
15 | + | |
16 | +} | ... | ... |
src/store/external/module/dynamicRequest.ts
0 → 100644
src/utils/external/dateUtil.ts
0 → 100644
1 | +import dayjs, { ConfigType } from 'dayjs'; | |
2 | + | |
3 | +export const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss'; | |
4 | +export const DATE_FORMAT = 'YYYY-MM-DD '; | |
5 | + | |
6 | +export function formatToDateTime( | |
7 | + date: ConfigType = undefined, | |
8 | + format = DATE_TIME_FORMAT | |
9 | +): string { | |
10 | + return dayjs(date).format(format); | |
11 | +} | |
12 | + | |
13 | +export function formatToDate(date: ConfigType = undefined, format = DATE_FORMAT): string { | |
14 | + return dayjs(date).format(format); | |
15 | +} | |
16 | + | |
17 | +export const dateUtil = dayjs; | ... | ... |
... | ... | @@ -45,7 +45,7 @@ const transform: AxiosTransform = { |
45 | 45 | if (apiUrl && isString(apiUrl)) { |
46 | 46 | config.url = `${apiUrl}${config.url}`; |
47 | 47 | } |
48 | - | |
48 | + | |
49 | 49 | const params = config.params || {}; |
50 | 50 | const data = config.data || false; |
51 | 51 | formatDate && data && !isString(data) && formatRequestDate(data); |
... | ... | @@ -143,7 +143,7 @@ const transform: AxiosTransform = { |
143 | 143 | } |
144 | 144 | } catch (error: any) { |
145 | 145 | throw new Error(error); |
146 | - } | |
146 | + } | |
147 | 147 | checkStatus(error?.response?.status, msg, errorMessageMode); |
148 | 148 | return Promise.reject(response?.data); |
149 | 149 | }, |
... | ... | @@ -197,9 +197,3 @@ function createAxios(opt?: Partial<CreateAxiosOptions>) { |
197 | 197 | } |
198 | 198 | export const defHttp = createAxios(); |
199 | 199 | |
200 | -// other api url | |
201 | -export const otherHttp = createAxios({ | |
202 | - requestOptions: { | |
203 | - apiUrl: 'xxx', | |
204 | - }, | |
205 | -}); | ... | ... |
src/utils/external/useAppContext.ts
0 → 100644
1 | +import { inject, InjectionKey, provide, reactive, readonly as defineReadonly } from 'vue' | |
2 | + | |
3 | +export interface CreateContextOptions { | |
4 | + readonly?: boolean | |
5 | + createProvider?: boolean | |
6 | + native?: boolean | |
7 | +} | |
8 | + | |
9 | +export function createContext<T>(context: any, key: InjectionKey<T> = Symbol(), options: CreateContextOptions = {}) { | |
10 | + const { readonly, createProvider, native } = options | |
11 | + | |
12 | + const state = reactive(context) | |
13 | + | |
14 | + const provideData = readonly ? defineReadonly(state) : state | |
15 | + | |
16 | + !createProvider && provide(key, native ? context : provideData) | |
17 | + | |
18 | + return { | |
19 | + state | |
20 | + } | |
21 | +} | |
22 | + | |
23 | +export function useContext<T>(key: InjectionKey<T> = Symbol(), defaultValue?: any) { | |
24 | + return inject(key, defaultValue || {}) | |
25 | +} | ... | ... |
1 | +<template> | |
2 | + <NTimeline class="go-chart-configurations-timeline"> | |
3 | + <NTimelineItem v-show="isCharts && dimensionsAndSource" type="info" :title="TimelineTitleEnum.MAPPING"> | |
4 | + <n-table striped> | |
5 | + <thead> | |
6 | + <tr> | |
7 | + <th v-for="item in tableTitle" :key="item">{{ item }}</th> | |
8 | + </tr> | |
9 | + </thead> | |
10 | + <tbody> | |
11 | + <tr v-for="(item, index) in dimensionsAndSource" :key="index"> | |
12 | + <td>{{ item.field }}</td> | |
13 | + <td>{{ item.mapping }}</td> | |
14 | + <td> | |
15 | + <NSpace v-if="item.result === 0"> | |
16 | + <NBadge dot type="success"></NBadge> | |
17 | + <NText>无</NText> | |
18 | + </NSpace> | |
19 | + <NSpace v-else> | |
20 | + <NBadge dot :type="item.result === 1 ? 'success' : 'error'"></NBadge> | |
21 | + <NText>匹配{{ item.result === 1 ? '成功' : '失败' }}</NText> | |
22 | + </NSpace> | |
23 | + </td> | |
24 | + </tr> | |
25 | + </tbody> | |
26 | + </n-table> | |
27 | + </NTimelineItem> | |
28 | + <NTimelineItem v-show="filterShow" color="#97846c" :title="TimelineTitleEnum.FILTER"> | |
29 | + <NSpace :size="18" vertical> | |
30 | + <NText depth="3">过滤器默认处理接口返回值的「data」字段</NText> | |
31 | + <ChartDataMonacoEditor></ChartDataMonacoEditor> | |
32 | + </NSpace> | |
33 | + </NTimelineItem> | |
34 | + <NTimelineItem type="success" :title="TimelineTitleEnum.CONTENT"> | |
35 | + <NSpace vertical> | |
36 | + <NSpace class="source-btn-box"> | |
37 | + <NUpload v-model:file-list="uploadFileListRef" :show-file-list="false" :customRequest="customRequest" | |
38 | + @before-upload="beforeUpload"> | |
39 | + <NSpace> | |
40 | + <NButton v-if="!ajax" class="sourceBtn-item" :disabled="noData"> | |
41 | + <template #icon> | |
42 | + <NIcon> | |
43 | + <document-add-icon /> | |
44 | + </NIcon> | |
45 | + </template> | |
46 | + 导入(json / txt) | |
47 | + </NButton> | |
48 | + </NSpace> | |
49 | + </NUpload> | |
50 | + <div> | |
51 | + <NButton class="sourceBtn-item" :disabled="noData" @click="download"> | |
52 | + <template #icon> | |
53 | + <NIcon> | |
54 | + <document-download-icon /> | |
55 | + </NIcon> | |
56 | + </template> | |
57 | + 下载 | |
58 | + </NButton> | |
59 | + <n-tooltip trigger="hover"> | |
60 | + <template #trigger> | |
61 | + <NIcon class="go-ml-1" size="21" :depth="3"> | |
62 | + <help-outline-icon></help-outline-icon> | |
63 | + </NIcon> | |
64 | + </template> | |
65 | + <NText depth="3">点击【下载】查看完整数据</NText> | |
66 | + </n-tooltip> | |
67 | + </div> | |
68 | + </NSpace> | |
69 | + <NCard size="small"> | |
70 | + <NScrollbar style="max-height: 400px;"> | |
71 | + <NCode :code="toString(source)" language="json"></NCode> | |
72 | + </NScrollbar> | |
73 | + </NCard> | |
74 | + </NSpace> | |
75 | + </NTimelineItem> | |
76 | + </NTimeline> | |
77 | +</template> | |
78 | + | |
79 | +<script setup lang="ts"> | |
80 | +import { ref, computed, watch } from 'vue' | |
81 | +import { ChartFrameEnum } from '@/packages/index.d' | |
82 | +import { RequestDataTypeEnum } from '@/enums/httpEnum' | |
83 | +import { icon } from '@/plugins' | |
84 | +import isObject from 'lodash/isObject' | |
85 | +import { toString, isArray } from '@/utils' | |
86 | +import { useTargetData } from '../../../../hooks/useTargetData.hook' | |
87 | +import { DataResultEnum, TimelineTitleEnum } from '../../../index.d' | |
88 | +import { useFile } from '../../../hooks/useFile.hooks' | |
89 | +import { ChartDataMonacoEditor } from '../ChartDataMonacoEditor' | |
90 | +import { NBadge, NButton, NCard, NCode, NIcon, NScrollbar, NSpace, NText, NTimeline, NTimelineItem, NUpload } from 'naive-ui' | |
91 | + | |
92 | +const { targetData } = useTargetData() | |
93 | +const props = defineProps({ | |
94 | + show: { | |
95 | + type: Boolean, | |
96 | + required: false | |
97 | + }, | |
98 | + ajax: { | |
99 | + type: Boolean, | |
100 | + required: true | |
101 | + } | |
102 | +}) | |
103 | + | |
104 | +// 表格标题 | |
105 | +const tableTitle = ['字段', '映射', '状态'] | |
106 | + | |
107 | +const { HelpOutlineIcon } = icon.ionicons5 | |
108 | +const { DocumentAddIcon, DocumentDownloadIcon } = icon.carbon | |
109 | + | |
110 | +const source = ref() | |
111 | +const dimensions = ref() | |
112 | +const dimensionsAndSource = ref() | |
113 | +const noData = ref(false) | |
114 | + | |
115 | +const { uploadFileListRef, customRequest, beforeUpload, download } = useFile(targetData) | |
116 | + | |
117 | +// 是否展示过滤器 | |
118 | +const filterShow = computed(() => { | |
119 | + return targetData.value.request.requestDataType !== RequestDataTypeEnum.STATIC | |
120 | +}) | |
121 | + | |
122 | +// 是支持 dataset 的图表类型 | |
123 | +const isCharts = computed(() => { | |
124 | + return targetData.value.chartConfig.chartFrame === ChartFrameEnum.ECHARTS | |
125 | +}) | |
126 | + | |
127 | +// 处理映射列表状态结果 | |
128 | +const matchingHandle = (mapping: string) => { | |
129 | + let res = DataResultEnum.SUCCESS | |
130 | + for (let i = 0; i < source.value.length; i++) { | |
131 | + if (source.value[i][mapping] === undefined) { | |
132 | + res = DataResultEnum.FAILURE | |
133 | + return res | |
134 | + } | |
135 | + } | |
136 | + return DataResultEnum.SUCCESS | |
137 | +} | |
138 | + | |
139 | +// 处理映射列表 | |
140 | +const dimensionsAndSourceHandle = () => { | |
141 | + try { | |
142 | + // 去除首项数据轴标识 | |
143 | + return dimensions.value.map((dimensionsItem: string, index: number) => { | |
144 | + return index === 0 | |
145 | + ? { | |
146 | + // 字段 | |
147 | + field: '通用标识', | |
148 | + // 映射 | |
149 | + mapping: dimensionsItem, | |
150 | + // 结果 | |
151 | + result: DataResultEnum.NULL | |
152 | + } | |
153 | + : { | |
154 | + field: `数据项-${index}`, | |
155 | + mapping: dimensionsItem, | |
156 | + result: matchingHandle(dimensionsItem) | |
157 | + } | |
158 | + }) | |
159 | + } catch (error) { | |
160 | + return [] | |
161 | + } | |
162 | +} | |
163 | + | |
164 | +watch( | |
165 | + () => targetData.value?.option?.dataset, | |
166 | + ( | |
167 | + newData?: { | |
168 | + source: any | |
169 | + dimensions: any | |
170 | + } | null | |
171 | + ) => { | |
172 | + if (newData && targetData?.value?.chartConfig?.chartFrame === ChartFrameEnum.ECHARTS) { | |
173 | + // 只有 DataSet 数据才有对应的格式 | |
174 | + source.value = newData | |
175 | + if (isCharts.value) { | |
176 | + dimensions.value = newData.dimensions | |
177 | + dimensionsAndSource.value = dimensionsAndSourceHandle() | |
178 | + } | |
179 | + } else if (newData !== undefined && newData !== null) { | |
180 | + dimensionsAndSource.value = null | |
181 | + source.value = newData | |
182 | + } else { | |
183 | + noData.value = true | |
184 | + source.value = '此组件无数据源' | |
185 | + } | |
186 | + if (isArray(newData)) { | |
187 | + dimensionsAndSource.value = null | |
188 | + } | |
189 | + }, | |
190 | + { | |
191 | + immediate: true | |
192 | + } | |
193 | +) | |
194 | +</script> | |
195 | + | |
196 | +<style lang="scss" scoped> | |
197 | +@include go('chart-configurations-timeline') { | |
198 | + @include deep() { | |
199 | + pre { | |
200 | + white-space: pre-wrap; | |
201 | + word-wrap: break-word; | |
202 | + } | |
203 | + } | |
204 | + | |
205 | + .source-btn-box { | |
206 | + margin-top: 10px !important; | |
207 | + } | |
208 | +} | |
209 | +</style> | ... | ... |
1 | +<template> | |
2 | + <template v-if="targetData.filter"> | |
3 | + <NCard> | |
4 | + <p><span class="func-keyword">function</span> filter(res) {</p> | |
5 | + <!-- 函数体 --> | |
6 | + <div class="go-ml-4"> | |
7 | + <NCode :code="targetData.filter" language="typescript"></NCode> | |
8 | + </div> | |
9 | + <p>}</p> | |
10 | + <template #footer> | |
11 | + <NSpace justify="end"> | |
12 | + <NButton type="primary" tertiary size="small" @click="addFilter"> | |
13 | + <template #icon> | |
14 | + <NIcon> | |
15 | + <filter-edit-icon /> | |
16 | + </NIcon> | |
17 | + </template> | |
18 | + 编辑 | |
19 | + </NButton> | |
20 | + <NButton tertiary size="small" @click="delFilter"> 删除 </NButton> | |
21 | + </NSpace> | |
22 | + </template> | |
23 | + </NCard> | |
24 | + </template> | |
25 | + <template v-else> | |
26 | + <NButton class="go-ml-3" @click="addFilter"> | |
27 | + <template #icon> | |
28 | + <NIcon> | |
29 | + <filter-icon /> | |
30 | + </NIcon> | |
31 | + </template> | |
32 | + 新增过滤器 | |
33 | + </NButton> | |
34 | + </template> | |
35 | + | |
36 | + <!-- 弹窗 --> | |
37 | + <NModal class="go-chart-data-monaco-editor" v-model:show="showModal" :mask-closable="false" :closeOnEsc="false"> | |
38 | + <NCard :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 1000px; height: 600px"> | |
39 | + <template #header> | |
40 | + <NSpace> | |
41 | + <NText>过滤器函数编辑器</NText> | |
42 | + </NSpace> | |
43 | + </template> | |
44 | + <template #header-extra> </template> | |
45 | + <NSpace size="small" vertical> | |
46 | + <NSpace justify="space-between"> | |
47 | + <div> | |
48 | + <NSpace vertical> | |
49 | + <NTag type="info"> | |
50 | + <span class="func-keyword">function</span> filter(res) { | |
51 | + </NTag> | |
52 | + <monaco-editor v-model:modelValue="filter" width="460px" height="380px" language="javascript" /> | |
53 | + <NTag type="info">}</NTag> | |
54 | + </NSpace> | |
55 | + </div> | |
56 | + <NDivider vertical style="height: 480px" /> | |
57 | + <NScrollbar style="max-height: 480px"> | |
58 | + <NSpace :size="15" vertical> | |
59 | + <!-- <div class="editor-data-show"> --> | |
60 | + <!-- <NSpace> | |
61 | + <NText depth="3">默认过滤数据(data):</NText> | |
62 | + <NCode :code="toString(sourceData?.data) || '暂无'" language="json" :word-wrap="true"></NCode> | |
63 | + </NSpace> --> | |
64 | + <!-- </div> --> | |
65 | + <div class="editor-data-show"> | |
66 | + <NSpace> | |
67 | + <NText depth="3">接口返回数据(res):</NText> | |
68 | + <NScrollbar style="max-height: 300px;"> | |
69 | + <NCode :code="toString(sourceData) || '暂无'" language="json" :word-wrap="true"></NCode> | |
70 | + </NScrollbar> | |
71 | + </NSpace> | |
72 | + </div> | |
73 | + <div class="editor-data-show"> | |
74 | + <NSpace> | |
75 | + <NText depth="3">过滤器结果:</NText> | |
76 | + <NCode :code="filterRes || '暂无'" language="json" :word-wrap="true"></NCode> | |
77 | + </NSpace> | |
78 | + </div> | |
79 | + </NSpace> | |
80 | + </NScrollbar> | |
81 | + </NSpace> | |
82 | + </NSpace> | |
83 | + <template #action> | |
84 | + <NSpace justify="space-between"> | |
85 | + <div class="go-flex-items-center"> | |
86 | + <NTag :bordered="false" type="primary"> | |
87 | + <template #icon> | |
88 | + <NIcon :component="DocumentTextIcon" /> | |
89 | + </template> | |
90 | + 规则 | |
91 | + </NTag> | |
92 | + <NText class="go-ml-2" depth="2">过滤器默认处理接口返回值的「data」字段</NText> | |
93 | + </div> | |
94 | + | |
95 | + <NSpace> | |
96 | + <NButton size="medium" @click="closeFilter">取消</NButton> | |
97 | + <NButton size="medium" type="primary" @click="saveFilter">保存</NButton> | |
98 | + </NSpace> | |
99 | + </NSpace> | |
100 | + </template> | |
101 | + </NCard> | |
102 | + </NModal> | |
103 | +</template> | |
104 | + | |
105 | +<script lang="ts" setup> | |
106 | +import { ref, computed, watch, toRaw } from 'vue' | |
107 | +import { MonacoEditor } from '@/components/Pages/MonacoEditor' | |
108 | +import { icon } from '@/plugins' | |
109 | +import { goDialog, toString } from '@/utils' | |
110 | +import cloneDeep from 'lodash/cloneDeep' | |
111 | +import { useTargetData } from '../../../../hooks/useTargetData.hook' | |
112 | +import { customRequest } from '@/api/external/customRequest' | |
113 | +import { NButton, NCard, NCode, NDivider, NIcon, NModal, NScrollbar, NSpace, NTag, NText } from 'naive-ui' | |
114 | + | |
115 | +const { DocumentTextIcon } = icon.ionicons5 | |
116 | +const { FilterIcon, FilterEditIcon } = icon.carbon | |
117 | +const { targetData } = useTargetData() | |
118 | + | |
119 | +// 受控弹窗 | |
120 | +const showModal = ref(false) | |
121 | +// filter 函数模板 | |
122 | +const filter = ref(targetData.value.filter || `return res`) | |
123 | +// 过滤错误标识 | |
124 | +const errorFlag = ref(false) | |
125 | +// 目标静态/接口数据 | |
126 | +const sourceData = ref<any>('') | |
127 | + | |
128 | +// 动态获取数据 | |
129 | +const fetchTargetData = async () => { | |
130 | + try { | |
131 | + const res = await customRequest(toRaw(targetData.value.request)) | |
132 | + if (res) { | |
133 | + sourceData.value = res | |
134 | + return | |
135 | + } | |
136 | + window['$message'].warning('没有拿到返回值,请检查接口!') | |
137 | + } catch (error) { | |
138 | + console.error(error); | |
139 | + window['$message'].warning('数据异常,请检查参数!') | |
140 | + } | |
141 | +} | |
142 | + | |
143 | +// 过滤结果 | |
144 | +const filterRes = computed(() => { | |
145 | + try { | |
146 | + const fn = new Function('data', 'res', filter.value) | |
147 | + const response = cloneDeep(sourceData.value) | |
148 | + const res = fn(response?.data, response) | |
149 | + // eslint-disable-next-line vue/no-side-effects-in-computed-properties | |
150 | + errorFlag.value = false | |
151 | + return toString(res) | |
152 | + } catch (error) { | |
153 | + // eslint-disable-next-line vue/no-side-effects-in-computed-properties | |
154 | + errorFlag.value = true | |
155 | + return `过滤函数错误,日志:${error}` | |
156 | + } | |
157 | +}) | |
158 | + | |
159 | +// 新增过滤器 | |
160 | +const addFilter = () => { | |
161 | + showModal.value = true | |
162 | +} | |
163 | + | |
164 | +// 删除过滤器 | |
165 | +const delFilter = () => { | |
166 | + goDialog({ | |
167 | + message: '是否删除过滤器', | |
168 | + onPositiveCallback: () => { | |
169 | + targetData.value.filter = undefined | |
170 | + } | |
171 | + }) | |
172 | +} | |
173 | + | |
174 | +// 关闭过滤器 | |
175 | +const closeFilter = () => { | |
176 | + showModal.value = false | |
177 | +} | |
178 | + | |
179 | +// 新增过滤器 | |
180 | +const saveFilter = () => { | |
181 | + if (errorFlag.value) { | |
182 | + window['$message'].error('过滤函数错误,无法进行保存') | |
183 | + return | |
184 | + } | |
185 | + targetData.value.filter = filter.value | |
186 | + closeFilter() | |
187 | +} | |
188 | + | |
189 | +watch( | |
190 | + () => showModal.value, | |
191 | + (newData: boolean) => { | |
192 | + if (newData) { | |
193 | + fetchTargetData() | |
194 | + filter.value = targetData.value.filter || `return res` | |
195 | + } | |
196 | + } | |
197 | +) | |
198 | +</script> | |
199 | + | |
200 | +<style lang="scss" scoped> | |
201 | +.func-keyword { | |
202 | + color: #b478cf; | |
203 | +} | |
204 | + | |
205 | +@include go('chart-data-monaco-editor') { | |
206 | + | |
207 | + &.NCard.NModal, | |
208 | + .NCard { | |
209 | + @extend .go-background-filter; | |
210 | + } | |
211 | + | |
212 | + .editor-data-show { | |
213 | + @include fetch-bg-color('filter-color'); | |
214 | + width: 420px; | |
215 | + padding: 20px; | |
216 | + border-radius: 5px; | |
217 | + } | |
218 | +} | |
219 | +</style> | ... | ... |
1 | +export { default as ChartDynamicRequest } from './index.vue' | ... | ... |
1 | +<script setup lang="ts"> | |
2 | +import { ref, computed, onBeforeUnmount, watchEffect, toRaw, unref } from 'vue' | |
3 | +import { icon } from '@/plugins' | |
4 | +import { useDesignStore } from '@/store/modules/designStore/designStore' | |
5 | +import { SettingItemBox } from '@/components/Pages/ChartItemSetting' | |
6 | +import { RequestDataTypeEnum } from '@/enums/external/httpEnum' | |
7 | +import { ChartDataMatchingAndShow } from '../../../external/components/ChartDataMatchingAndShow' | |
8 | +import { newFunctionHandle } from '@/utils' | |
9 | +import { useTargetData } from '../../../../hooks/useTargetData.hook' | |
10 | +import { NButton, NSelect, NTooltip, NIcon, SelectOption } from 'naive-ui' | |
11 | +import { RequestInfoPanel } from '../RequestInfoPanel' | |
12 | +import { RequestModal } from '../RequestModal' | |
13 | +import { customRequest } from '@/api/external/customRequest' | |
14 | + | |
15 | +const { HelpOutlineIcon, FlashIcon } = icon.ionicons5 | |
16 | +const { targetData } = useTargetData() | |
17 | + | |
18 | +const requestModal = ref<InstanceType<typeof RequestModal>>() | |
19 | + | |
20 | +const designStore = useDesignStore() | |
21 | + | |
22 | + | |
23 | +const selectedRequestType = ref(targetData.value.request.requestDataType || RequestDataTypeEnum.AJAX) | |
24 | + | |
25 | +const getApiRequestType: SelectOption[] = [ | |
26 | + { label: '自定义请求', value: RequestDataTypeEnum.AJAX }, | |
27 | + { label: '公共接口', value: RequestDataTypeEnum.Pond } | |
28 | +] | |
29 | + | |
30 | +// 是否展示数据分析 | |
31 | +const loading = ref(false) | |
32 | +const showMatching = ref(false) | |
33 | + | |
34 | +let firstFocus = 0 | |
35 | +let lastFilter: any = undefined | |
36 | + | |
37 | +// 发送请求 | |
38 | +const sendHandle = async () => { | |
39 | + if (!targetData.value?.request) return | |
40 | + | |
41 | + loading.value = true | |
42 | + try { | |
43 | + console.log('enter') | |
44 | + const res = await customRequest(toRaw(targetData.value.request)) | |
45 | + loading.value = false | |
46 | + if (res) { | |
47 | + targetData.value.option.dataset = newFunctionHandle(res, res, targetData.value.filter) | |
48 | + showMatching.value = true | |
49 | + return | |
50 | + } | |
51 | + window['$message'].warning('数据异常,请检查参数!') | |
52 | + } catch (error) { | |
53 | + loading.value = false | |
54 | + window['$message'].warning('数据异常,请检查参数!') | |
55 | + } | |
56 | +} | |
57 | + | |
58 | +// 颜色 | |
59 | +const themeColor = computed(() => { | |
60 | + return designStore.getAppTheme | |
61 | +}) | |
62 | + | |
63 | +const handleClickPanel = () => { | |
64 | + unref(requestModal)?.openModal(true, unref(selectedRequestType)) | |
65 | +} | |
66 | + | |
67 | +watchEffect(() => { | |
68 | + const filter = targetData.value?.filter | |
69 | + if (lastFilter !== filter && firstFocus) { | |
70 | + lastFilter = filter | |
71 | + sendHandle() | |
72 | + } | |
73 | + firstFocus++ | |
74 | +}) | |
75 | + | |
76 | +onBeforeUnmount(() => { | |
77 | + lastFilter = null | |
78 | +}) | |
79 | + | |
80 | + | |
81 | +</script> | |
82 | + | |
83 | +<template> | |
84 | + <div class="things-kit-chart-configurations-data-ajax"> | |
85 | + <SettingItemBox name="接口方式" :alone="true"> | |
86 | + <NSelect v-model:value="selectedRequestType" :options="getApiRequestType" /> | |
87 | + </SettingItemBox> | |
88 | + | |
89 | + <RequestInfoPanel @clickPanel="handleClickPanel" /> | |
90 | + | |
91 | + <SettingItemBox :alone="true"> | |
92 | + <template #name> | |
93 | + 测试 | |
94 | + <NTooltip trigger="hover"> | |
95 | + <template #trigger> | |
96 | + <NIcon size="21" :depth="3"> | |
97 | + <HelpOutlineIcon /> | |
98 | + </NIcon> | |
99 | + </template> | |
100 | + 默认赋值给 dataset 字段 | |
101 | + </NTooltip> | |
102 | + </template> | |
103 | + <NButton type="primary" ghost @click="sendHandle"> | |
104 | + <template #icon> | |
105 | + <NIcon> | |
106 | + <FlashIcon /> | |
107 | + </NIcon> | |
108 | + </template> | |
109 | + 发送请求 | |
110 | + </NButton> | |
111 | + </SettingItemBox> | |
112 | + | |
113 | + <!-- 底部数据展示 --> | |
114 | + <ChartDataMatchingAndShow :show="showMatching && !loading" :ajax="true"></ChartDataMatchingAndShow> | |
115 | + | |
116 | + <!-- 骨架图 --> | |
117 | + <go-skeleton :load="loading" :repeat="3"></go-skeleton> | |
118 | + | |
119 | + <RequestModal ref="requestModal" /> | |
120 | + </div> | |
121 | +</template> | |
122 | + | |
123 | + | |
124 | + | |
125 | +<style lang="scss" scoped> | |
126 | +@include thingsKit('chart-configurations-data-ajax') { | |
127 | + .n-card-shallow { | |
128 | + &.n-card { | |
129 | + @extend .go-background-filter; | |
130 | + | |
131 | + @include deep() { | |
132 | + .n-card__content { | |
133 | + padding: 10px; | |
134 | + } | |
135 | + } | |
136 | + } | |
137 | + | |
138 | + .edit-text { | |
139 | + position: absolute; | |
140 | + top: 0px; | |
141 | + left: 0px; | |
142 | + width: 325px; | |
143 | + height: 270px; | |
144 | + cursor: pointer; | |
145 | + opacity: 0; | |
146 | + transition: all 0.3s; | |
147 | + @extend .go-background-filter; | |
148 | + backdrop-filter: blur(2px) !important; | |
149 | + } | |
150 | + | |
151 | + &:hover { | |
152 | + border-color: v-bind('themeColor'); | |
153 | + | |
154 | + .edit-text { | |
155 | + opacity: 1; | |
156 | + } | |
157 | + } | |
158 | + } | |
159 | +} | |
160 | +</style> | ... | ... |
1 | +export { default as PublicInterfaceForm } from './index.vue' | ... | ... |
1 | +<script lang="ts" setup> | |
2 | +import { getAllPublicInterface, getPublicInterface } from '@/api/external/dynamicRequest' | |
3 | +import { PublicInterfaceRecord } from '@/api/external/dynamicRequest/model'; | |
4 | +import { SettingItem, SettingItemBox } from '@/components/Pages/ChartItemSetting'; | |
5 | +import { RequestContentTypeEnum, RequestContentTypeNameEnum } from '@/enums/external/httpEnum'; | |
6 | +import { RequestBodyEnum, RequestHttpEnum, RequestHttpIntervalEnum, RequestParams, RequestParamsTypeEnum } from '@/enums/httpEnum'; | |
7 | +import { RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'; | |
8 | +import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'; | |
9 | +import { NForm, NCard, NDatePicker, NEmpty, NFormItem, NInput, NInputGroup, NInputNumber, NScrollbar, NSelect, NSpin, NTabPane, NTabs, NTreeSelect, SelectOption, FormInst, NButton, FormItemInst } from 'naive-ui'; | |
10 | +import { ref, reactive, onMounted, computed, unref } from 'vue' | |
11 | +import { selectTimeOptions, selectTypeOptions } from '../../../index.d'; | |
12 | +import ParamsTable from '../RequestModal/ParamsTable.vue'; | |
13 | +import RequestBody from '../RequestModal/RequestBody.vue'; | |
14 | +import { ComponentType, useDynamicPublicForm } from './useDynamicPublicForm'; | |
15 | +import { transferData } from './utils'; | |
16 | + | |
17 | +const componentMap: { [key in ComponentType]?: any } = { | |
18 | + [ComponentType.SELECT_TREE]: NTreeSelect, | |
19 | + [ComponentType.SELECT]: NSelect, | |
20 | + [ComponentType.INPUT]: NInput, | |
21 | + [ComponentType.DATE_PICKER]: NDatePicker | |
22 | +} | |
23 | +const publicInterfaceList = ref<PublicInterfaceRecord[]>([]) | |
24 | + | |
25 | +const selectedPublicInterface = ref<string>() | |
26 | + | |
27 | +const toJSON = (string: string) => { | |
28 | + try { | |
29 | + return JSON.parse(string) | |
30 | + } catch (error) { | |
31 | + return {} | |
32 | + } | |
33 | +} | |
34 | + | |
35 | +const getSelectedInterface = computed(() => { | |
36 | + const record = unref(publicInterfaceList).find(item => item.id === unref(selectedPublicInterface))! || {} | |
37 | + const _record = JSON.parse(JSON.stringify(record)) | |
38 | + _record.requestParams = toJSON(_record.requestParams) | |
39 | + return _record | |
40 | +}) | |
41 | + | |
42 | +const getPublicInterfaceList = async () => { | |
43 | + if (unref(publicInterfaceList).length) return | |
44 | + const result = await getAllPublicInterface() | |
45 | + publicInterfaceList.value = result | |
46 | +} | |
47 | + | |
48 | +const handleFilter = (query: string, option: SelectOption) => { | |
49 | + return ((option as Recordable).interfaceName).includes(query) | |
50 | +} | |
51 | + | |
52 | +const { getDynamicFormSchemas, params, createForm, validFlag, setDynamicFormValue } = useDynamicPublicForm(getSelectedInterface) | |
53 | + | |
54 | +const getConfigurationData = () => { | |
55 | + const value = transferData(unref(getSelectedInterface), unref(getSelectedInterface).requestParams as unknown as RequestParams, params) | |
56 | + return value | |
57 | +} | |
58 | + | |
59 | +const requestHttpTypeRef = ref<RequestHttpEnum>() | |
60 | + | |
61 | +const requestIntervalValueRef = ref<number>(30) | |
62 | + | |
63 | +const requestIntervalUnitRef = ref<RequestHttpIntervalEnum>(RequestHttpIntervalEnum.SECOND) | |
64 | + | |
65 | +const requestContentTypeRef = ref<RequestContentTypeEnum>() | |
66 | + | |
67 | +const requestParamsTypeRef = ref<RequestParamsTypeEnum>(RequestParamsTypeEnum.PARAMS) | |
68 | + | |
69 | +const requestParams = ref<RequestParams>({ Body: { [RequestBodyEnum.FORM_DATA]: {}, [RequestBodyEnum.JSON]: '', [RequestBodyEnum.XML]: '', [RequestBodyEnum.X_WWW_FORM_URLENCODED]: {} }, Header: {}, Params: {} }) | |
70 | + | |
71 | +const requestParamsBodyTypeRef = ref<RequestBodyEnum>(RequestBodyEnum.X_WWW_FORM_URLENCODED) | |
72 | + | |
73 | +const headerRef = ref() | |
74 | + | |
75 | +const dynamicFormItemEl = ref<FormItemInst[]>() | |
76 | + | |
77 | +const handleSelectedInterfaceChange = (value: string, option: PublicInterfaceRecord) => { | |
78 | + createForm() | |
79 | + requestContentTypeRef.value = option.requestContentType as RequestContentTypeEnum | |
80 | + requestHttpTypeRef.value = option.requestHttpType as RequestHttpEnum | |
81 | +} | |
82 | + | |
83 | +const getGetRequestTypeName = (key: RequestContentTypeEnum) => { | |
84 | + return RequestContentTypeNameEnum[RequestContentTypeEnum[key] as keyof typeof RequestContentTypeEnum] | |
85 | +} | |
86 | + | |
87 | +const setConfigurationData = async (request: RequestConfigType) => { | |
88 | + await getPublicInterfaceList() | |
89 | + const { requestDataPondId, requestParams: params, requestParamsBodyType, requestContentType, requestHttpType, } = request | |
90 | + const { Header } = params | |
91 | + selectedPublicInterface.value = requestDataPondId | |
92 | + requestContentTypeRef.value = requestContentType | |
93 | + requestHttpTypeRef.value = requestHttpType | |
94 | + headerRef.value = Header | |
95 | + requestParamsBodyTypeRef.value = requestParamsBodyType | |
96 | + requestParams.value = params | |
97 | + setDynamicFormValue(params) | |
98 | +} | |
99 | + | |
100 | + | |
101 | +const validate = async () => { | |
102 | + for (const item of unref(dynamicFormItemEl) || []) { | |
103 | + await item.validate() | |
104 | + } | |
105 | + return unref(validFlag) | |
106 | +} | |
107 | + | |
108 | + | |
109 | +defineExpose({ | |
110 | + getConfigurationData, | |
111 | + setConfigurationData, | |
112 | + validate | |
113 | +}) | |
114 | + | |
115 | +onMounted(() => { | |
116 | + getPublicInterfaceList() | |
117 | +}) | |
118 | + | |
119 | +</script> | |
120 | + | |
121 | +<template> | |
122 | + <SettingItemBox name="公共接口" :alone="true" :item-right-style="{ gridTemplateColumns: '5fr 2fr 1fr' }"> | |
123 | + <SettingItem name="请求方式 & URL地址"> | |
124 | + <NInputGroup> | |
125 | + <NSelect v-model:value="selectedPublicInterface" label-field="interfaceName" value-field="id" | |
126 | + :options="publicInterfaceList" :filter="handleFilter" filterable :reset-menu-on-options-change="false" | |
127 | + @update-value="handleSelectedInterfaceChange" size="small"> | |
128 | + </NSelect> | |
129 | + <NSelect v-if="requestContentTypeRef !== RequestContentTypeEnum.WEB_SOCKET" v-model:value="requestHttpTypeRef" | |
130 | + style="width: 150px;" size="small" :options="(selectTypeOptions as SelectOption[])" :disabled="true" /> | |
131 | + <NSelect v-if="requestContentTypeRef === RequestContentTypeEnum.WEB_SOCKET" :disabled="true" style="width: 150px;" | |
132 | + :default-value="RequestContentTypeEnum.WEB_SOCKET" size="small" | |
133 | + :options="[{ label: 'WebSocket', value: RequestContentTypeEnum.WEB_SOCKET, type: 'ignored' }]"> | |
134 | + </NSelect> | |
135 | + </NInputGroup> | |
136 | + </SettingItem> | |
137 | + <SettingItem name="更新间隔,为 0 只会初始化"> | |
138 | + <NInputGroup> | |
139 | + <NInputNumber v-model:value="requestIntervalValueRef" class="select-time-number" size="small" min="0" | |
140 | + :show-button="false" placeholder="请输入数字" /> | |
141 | + <!-- 单位 --> | |
142 | + <NSelect v-model:value="requestIntervalUnitRef" class="select-time-options" size="small" | |
143 | + :options="(selectTimeOptions as SelectOption[])" /> | |
144 | + </NInputGroup> | |
145 | + </SettingItem> | |
146 | + </SettingItemBox> | |
147 | + <SettingItemBox name="请求方式" :alone="true" :item-right-style="{ gridTemplateColumns: '1fr 1fr' }"> | |
148 | + <NTabs v-model:value="requestContentTypeRef" type="segment" size="small"> | |
149 | + <NTabPane :disabled="requestContentTypeRef !== RequestContentTypeEnum.DEFAULT" | |
150 | + :name="RequestContentTypeEnum.DEFAULT" :tab="getGetRequestTypeName(RequestContentTypeEnum.DEFAULT)" /> | |
151 | + <NTabPane :disabled="requestContentTypeRef !== RequestContentTypeEnum.SQL" :name="RequestContentTypeEnum.SQL" | |
152 | + :tab="getGetRequestTypeName(RequestContentTypeEnum.SQL)" /> | |
153 | + <NTabPane :disabled="requestContentTypeRef !== RequestContentTypeEnum.WEB_SOCKET" | |
154 | + :name="RequestContentTypeEnum.WEB_SOCKET" :tab="getGetRequestTypeName(RequestContentTypeEnum.WEB_SOCKET)" /> | |
155 | + </NTabs> | |
156 | + </SettingItemBox> | |
157 | + <SettingItemBox> | |
158 | + <NTabs v-model:value="requestParamsTypeRef" :default-value="RequestParamsTypeEnum.PARAMS"> | |
159 | + <NTabPane v-for="item in RequestParamsTypeEnum" :name="item" :key="item"></NTabPane> | |
160 | + </NTabs> | |
161 | + </SettingItemBox> | |
162 | + | |
163 | + <SettingItemBox :item-right-style="{ gridTemplateColumns: '3fr 2fr' }"> | |
164 | + <NCard v-if="requestParamsTypeRef === RequestParamsTypeEnum.PARAMS" class="dynamic-form"> | |
165 | + <NScrollbar style="max-height: 400px; padding: 0 10px; box-sizing: border-box;;"> | |
166 | + <NForm> | |
167 | + <template v-for="item in getDynamicFormSchemas" :key="item.key"> | |
168 | + <NFormItem ref="dynamicFormItemEl" :required="item.required" :label="item.name" :rule="item.rules"> | |
169 | + <component :is="componentMap[item.component]" v-bind="item.props" clearable /> | |
170 | + </NFormItem> | |
171 | + </template> | |
172 | + </NForm> | |
173 | + <NEmpty v-if="!selectedPublicInterface || !getDynamicFormSchemas.length" description="请选择公共接口" /> | |
174 | + </NScrollbar> | |
175 | + </NCard> | |
176 | + | |
177 | + | |
178 | + <RequestBody v-if="requestParamsTypeRef === RequestParamsTypeEnum.BODY" | |
179 | + v-model:request-params-body-type="requestParamsBodyTypeRef" v-model:value="requestParams" /> | |
180 | + | |
181 | + <ParamsTable v-if="requestParamsTypeRef === RequestParamsTypeEnum.HEADER" v-model:value="headerRef" /> | |
182 | + | |
183 | + </SettingItemBox> | |
184 | +</template> | |
185 | + | |
186 | +<style scoped lang="scss"> | |
187 | +.loading-container { | |
188 | + display: flex; | |
189 | + align-items: center; | |
190 | + justify-content: center; | |
191 | +} | |
192 | + | |
193 | +.dynamic-form { | |
194 | + @include deep() { | |
195 | + .n-date-picker { | |
196 | + width: 100%; | |
197 | + } | |
198 | + } | |
199 | +} | |
200 | +</style> | ... | ... |
1 | +import { getDictItemByCode } from "@/api/external/common" | |
2 | +import { DictItem } from "@/api/external/common/model" | |
3 | +import { getDeviceAttrList, getDeviceList, getDeviceProfileList, getOrgList } from "@/api/external/dynamicRequest" | |
4 | +import { PublicInterfaceRecord, RequestParams } from "@/api/external/dynamicRequest/model" | |
5 | +import { RequestConfigType } from "@/store/modules/chartEditStore/chartEditStore.d" | |
6 | +import { DatePickerProps, FormItemRule, InputProps, SelectProps, TreeSelectProps } from "naive-ui" | |
7 | +import { computed, onMounted, reactive, Ref, ref, unref } from "vue" | |
8 | +import { DictEnum } from '@/enums/external/dictEnum' | |
9 | + | |
10 | +const GROUP_SEPARATOR = ',' | |
11 | + | |
12 | +export enum BuiltInVariable { | |
13 | + DATE = 'date', | |
14 | + KEYS = 'keys', | |
15 | + ENTITY_ID = 'entityId', | |
16 | + ORGANIZATION_ID = 'organizationId', | |
17 | + DEVICE_PROFILE_ID = 'deviceProfileId', | |
18 | +} | |
19 | + | |
20 | +export enum ComponentType { | |
21 | + SELECT = 'select', | |
22 | + SELECT_TREE = 'selectTree', | |
23 | + DATE_PICKER = 'datePicker', | |
24 | + INPUT = 'input' | |
25 | +} | |
26 | + | |
27 | +export interface DynamicFormSchema { | |
28 | + key: string | |
29 | + name?: string | |
30 | + component: ComponentType, | |
31 | + required?: boolean | |
32 | + rules?: FormItemRule | |
33 | + props: Recordable | |
34 | +} | |
35 | + | |
36 | +export type BuiltInVariableRecord = { [key in BuiltInVariable]: DictItem } | |
37 | + | |
38 | +export const useDynamicPublicForm = (publicInterfaceRef: Ref<PublicInterfaceRecord>) => { | |
39 | + | |
40 | + const getParams = computed(() => { | |
41 | + let params = (publicInterfaceRef.value.requestParams as unknown as RequestParams).Params || [] | |
42 | + if (!Array.isArray(params)) params = [] | |
43 | + return params | |
44 | + }) | |
45 | + | |
46 | + const getUsedBuiltInVariable = computed(() => { | |
47 | + const hasUsed = unref(getParams).reduce((prev, next) => { | |
48 | + const groupList = next.key.split(GROUP_SEPARATOR) | |
49 | + return [...prev, ...(groupList.length > 1 ? groupList : [next.key])] | |
50 | + }, [] as string[]) | |
51 | + return hasUsed | |
52 | + }) | |
53 | + | |
54 | + const builtInVariable = ref<BuiltInVariableRecord>() | |
55 | + | |
56 | + const params = reactive<Recordable & { [key in BuiltInVariable]?: any }>({}) | |
57 | + | |
58 | + const optionsSet = reactive<Recordable>({}) | |
59 | + | |
60 | + const basicPreset = (filterKey: string) => { | |
61 | + return { | |
62 | + size: 'small', | |
63 | + filterable: true, | |
64 | + filter(query, option: Recordable) { | |
65 | + return option[filterKey].includes(query) | |
66 | + } | |
67 | + } as SelectProps | |
68 | + } | |
69 | + | |
70 | + const validIsExist = (keys: BuiltInVariable) => { | |
71 | + return unref(getUsedBuiltInVariable).includes(keys) | |
72 | + } | |
73 | + | |
74 | + const handleSelectOrgEffect = () => { | |
75 | + params[BuiltInVariable.ENTITY_ID] = null | |
76 | + getDeviceOption() | |
77 | + } | |
78 | + | |
79 | + const handleSelectDeviceProfileEffect = () => { | |
80 | + params[BuiltInVariable.ENTITY_ID] = null | |
81 | + params[BuiltInVariable.KEYS] = null | |
82 | + getDeviceOption() | |
83 | + getDeviceAttrOption() | |
84 | + } | |
85 | + | |
86 | + const getBuiltInVariable = async () => { | |
87 | + if (Object.keys(unref(builtInVariable) || {}).length) return | |
88 | + const result = await getDictItemByCode(DictEnum.BUILTIN_PARAMS) | |
89 | + builtInVariable.value = result.reduce((prev, next) => { | |
90 | + return { ...prev, [next.itemValue]: next } | |
91 | + }, {} as BuiltInVariableRecord) | |
92 | + } | |
93 | + | |
94 | + const getOrgOption = async () => { | |
95 | + if (!validIsExist(BuiltInVariable.ORGANIZATION_ID)) return | |
96 | + optionsSet[BuiltInVariable.ORGANIZATION_ID] = await getOrgList() | |
97 | + } | |
98 | + | |
99 | + const getDeviceProfileOption = async () => { | |
100 | + if (!validIsExist(BuiltInVariable.DEVICE_PROFILE_ID)) return | |
101 | + optionsSet[BuiltInVariable.DEVICE_PROFILE_ID] = await getDeviceProfileList() | |
102 | + } | |
103 | + | |
104 | + const getDeviceOption = async () => { | |
105 | + if (!validIsExist(BuiltInVariable.DEVICE_PROFILE_ID) || !validIsExist(BuiltInVariable.ORGANIZATION_ID) || !params[BuiltInVariable.ORGANIZATION_ID]) return | |
106 | + optionsSet[BuiltInVariable.ENTITY_ID] = await getDeviceList({ [BuiltInVariable.ORGANIZATION_ID]: params[BuiltInVariable.ORGANIZATION_ID], [BuiltInVariable.DEVICE_PROFILE_ID]: params[BuiltInVariable.DEVICE_PROFILE_ID] }) | |
107 | + } | |
108 | + | |
109 | + const getDeviceAttrOption = async () => { | |
110 | + if (!validIsExist(BuiltInVariable.KEYS)) return | |
111 | + if (!params[BuiltInVariable.DEVICE_PROFILE_ID]) return | |
112 | + const result = await getDeviceAttrList(params[BuiltInVariable.DEVICE_PROFILE_ID]) | |
113 | + if (Array.isArray(result)) optionsSet[BuiltInVariable.KEYS] = result | |
114 | + } | |
115 | + | |
116 | + const getSelectOrgTree = computed<TreeSelectProps>(() => { | |
117 | + return { | |
118 | + ...basicPreset('name'), | |
119 | + value: params[BuiltInVariable.ORGANIZATION_ID], | |
120 | + options: unref(optionsSet[BuiltInVariable.ORGANIZATION_ID]), | |
121 | + labelField: 'name', | |
122 | + keyField: 'id', | |
123 | + childrenField: 'children', | |
124 | + onUpdateValue(value) { | |
125 | + params[BuiltInVariable.ORGANIZATION_ID] = value | |
126 | + handleSelectOrgEffect() | |
127 | + } | |
128 | + } as TreeSelectProps | |
129 | + }) | |
130 | + | |
131 | + | |
132 | + const getSelectDeviceProfile = computed<SelectProps>(() => { | |
133 | + return { | |
134 | + ...basicPreset('name'), | |
135 | + value: params[BuiltInVariable.DEVICE_PROFILE_ID], | |
136 | + options: unref(optionsSet[BuiltInVariable.DEVICE_PROFILE_ID]), | |
137 | + labelField: 'name', | |
138 | + valueField: 'id', | |
139 | + onUpdateValue(value) { | |
140 | + params[BuiltInVariable.DEVICE_PROFILE_ID] = value | |
141 | + handleSelectDeviceProfileEffect() | |
142 | + } | |
143 | + } | |
144 | + }) | |
145 | + | |
146 | + const getSelectDevice = computed<SelectProps>(() => { | |
147 | + return { | |
148 | + ...basicPreset('name'), | |
149 | + value: params[BuiltInVariable.ENTITY_ID], | |
150 | + options: unref(optionsSet[BuiltInVariable.ENTITY_ID]), | |
151 | + labelField: 'name', | |
152 | + valueField: 'id', | |
153 | + onUpdateValue(value) { | |
154 | + params[BuiltInVariable.ENTITY_ID] = value | |
155 | + } | |
156 | + } | |
157 | + }) | |
158 | + | |
159 | + const getSelectDeviceAttr = computed<SelectProps>(() => { | |
160 | + return { | |
161 | + ...basicPreset('name'), | |
162 | + value: params[BuiltInVariable.KEYS], | |
163 | + options: unref(optionsSet[BuiltInVariable.KEYS]), | |
164 | + labelField: 'name', | |
165 | + valueField: 'identifier', | |
166 | + onUpdateValue(value) { | |
167 | + params[BuiltInVariable.KEYS] = value | |
168 | + } | |
169 | + } | |
170 | + }) | |
171 | + | |
172 | + const getSelectDate = computed(() => { | |
173 | + return { | |
174 | + size: 'small', | |
175 | + value: params[BuiltInVariable.DATE], | |
176 | + type: 'datetimerange', | |
177 | + clearable: true, | |
178 | + defaultTime: ['00:00:00', '00:00:00'], | |
179 | + onUpdateValue(value) { | |
180 | + params[BuiltInVariable.DATE] = value | |
181 | + } | |
182 | + } as DatePickerProps | |
183 | + }) | |
184 | + | |
185 | + const getBasicInput = (key: string) => { | |
186 | + return { | |
187 | + size: 'small', | |
188 | + value: params[key], | |
189 | + onUpdateValue(value) { | |
190 | + params[key] = value | |
191 | + } | |
192 | + } as InputProps | |
193 | + } | |
194 | + | |
195 | + const builtInVariableConfiguration: { [key in BuiltInVariable]?: DynamicFormSchema } = { | |
196 | + [BuiltInVariable.ORGANIZATION_ID]: { | |
197 | + component: ComponentType.SELECT_TREE, | |
198 | + key: BuiltInVariable.ORGANIZATION_ID, | |
199 | + props: getSelectOrgTree | |
200 | + }, | |
201 | + [BuiltInVariable.DEVICE_PROFILE_ID]: { | |
202 | + component: ComponentType.SELECT, | |
203 | + key: BuiltInVariable.DEVICE_PROFILE_ID, | |
204 | + props: getSelectDeviceProfile | |
205 | + }, | |
206 | + [BuiltInVariable.ENTITY_ID]: { | |
207 | + component: ComponentType.SELECT, | |
208 | + key: BuiltInVariable.ENTITY_ID, | |
209 | + props: getSelectDevice | |
210 | + }, | |
211 | + [BuiltInVariable.KEYS]: { | |
212 | + component: ComponentType.SELECT, | |
213 | + key: BuiltInVariable.KEYS, | |
214 | + props: getSelectDeviceAttr | |
215 | + }, | |
216 | + [BuiltInVariable.DATE]: { | |
217 | + component: ComponentType.DATE_PICKER, | |
218 | + key: BuiltInVariable.DATE, | |
219 | + props: getSelectDate | |
220 | + } | |
221 | + } | |
222 | + | |
223 | + const validFlag = ref(true) | |
224 | + | |
225 | + const createRules = (required: boolean, key: string, message: string) => { | |
226 | + return [{ | |
227 | + trigger: ['blur', 'change'], | |
228 | + validator() { | |
229 | + if (required && !params[key]) { | |
230 | + validFlag.value = false | |
231 | + return new Error(`${message}是必填项`) | |
232 | + } | |
233 | + validFlag.value = true | |
234 | + } | |
235 | + }] as FormItemRule | |
236 | + } | |
237 | + | |
238 | + const toFormSchemas = (builtInVariableKey: string, required: boolean, value: any) => { | |
239 | + const groupList = builtInVariableKey.split(GROUP_SEPARATOR) | |
240 | + return groupList.reduce((prev, next) => { | |
241 | + const result = builtInVariableConfiguration[next as BuiltInVariable] | |
242 | + const props = unref(result?.props) | |
243 | + const name = (unref(builtInVariable) || {})[next as BuiltInVariable]?.itemText | |
244 | + let schema: DynamicFormSchema | |
245 | + if (builtInVariableConfiguration[next as BuiltInVariable]) { | |
246 | + schema = { | |
247 | + ...result, | |
248 | + props, | |
249 | + name, | |
250 | + required, | |
251 | + rules: createRules(required, next, name || next) | |
252 | + } as DynamicFormSchema | |
253 | + } else { | |
254 | + schema = { | |
255 | + key: value, | |
256 | + name: value, | |
257 | + component: ComponentType.INPUT, | |
258 | + props: getBasicInput(value), | |
259 | + required, | |
260 | + rules: createRules(required, value, value) | |
261 | + } as DynamicFormSchema | |
262 | + } | |
263 | + | |
264 | + return [...prev, schema] | |
265 | + | |
266 | + }, [] as DynamicFormSchema[]) | |
267 | + | |
268 | + } | |
269 | + | |
270 | + const getDynamicFormSchemas = computed(() => { | |
271 | + return unref(getParams).reduce((prev, { key, value, required }) => { | |
272 | + const schemas = toFormSchemas(key, required, value) | |
273 | + return [...prev, ...schemas] | |
274 | + }, [] as DynamicFormSchema[]) | |
275 | + }) | |
276 | + | |
277 | + const createForm = async () => { | |
278 | + await getBuiltInVariable() | |
279 | + await getOrgOption() | |
280 | + getDeviceProfileOption() | |
281 | + getDeviceOption() | |
282 | + } | |
283 | + | |
284 | + const setParams = (Params: Recordable) => { | |
285 | + unref(getParams).forEach(({ key, value }) => { | |
286 | + if (unref(getUsedBuiltInVariable).includes(key)) { | |
287 | + params[key] = Params[key] | |
288 | + } | |
289 | + params[value] = Params[value] | |
290 | + }) | |
291 | + } | |
292 | + | |
293 | + const setDynamicFormValue = (requestParams: RequestConfigType['requestParams']) => { | |
294 | + const { Params } = requestParams | |
295 | + setParams(Params) | |
296 | + getOrgOption() | |
297 | + getDeviceProfileOption() | |
298 | + getDeviceOption() | |
299 | + getDeviceAttrOption() | |
300 | + } | |
301 | + | |
302 | + onMounted(() => { | |
303 | + getBuiltInVariable() | |
304 | + }) | |
305 | + | |
306 | + return { | |
307 | + validFlag, | |
308 | + params, | |
309 | + getDynamicFormSchemas, | |
310 | + setDynamicFormValue, | |
311 | + createForm | |
312 | + } | |
313 | +} | |
314 | + | ... | ... |
1 | +import { PublicInterfaceRecord } from "@/api/external/dynamicRequest/model" | |
2 | +import { RequestDataTypeEnum, RequestParams } from "@/enums/httpEnum" | |
3 | +import { RequestConfigType } from "@/store/modules/chartEditStore/chartEditStore.d" | |
4 | + | |
5 | +export const transferData = (publicInterfaceRecord: PublicInterfaceRecord, requestParams: RequestParams, fillParams: Recordable) => { | |
6 | + const { requestContentType, requestHttpType, id, requestUrl, requestParamsBodyType, requestOriginUrl } = publicInterfaceRecord | |
7 | + const { Header, Body } = requestParams | |
8 | + return { | |
9 | + requestDataPondId: id, | |
10 | + // requestInterval | |
11 | + // 获取数据的方式 | |
12 | + requestDataType: RequestDataTypeEnum.Pond, | |
13 | + // 请求方式 get/post/del/put/patch | |
14 | + requestHttpType, | |
15 | + // 源后续的 url | |
16 | + requestUrl: `${requestOriginUrl}${requestUrl}`, | |
17 | + // 请求内容主体方式 普通/sql | |
18 | + requestContentType, | |
19 | + // 请求体类型 | |
20 | + requestParamsBodyType, | |
21 | + // SQL 请求对象 | |
22 | + // requestSQLContent: { | |
23 | + // sql: '' | |
24 | + // } | |
25 | + // requestIntervalUnit | |
26 | + requestParams: { | |
27 | + Header, | |
28 | + Body, | |
29 | + Params: fillParams | |
30 | + } | |
31 | + | |
32 | + } as RequestConfigType | |
33 | +} | ... | ... |
1 | +export { default as RequestInfoPanel } from './index.vue' | ... | ... |
1 | +<script setup lang="ts"> | |
2 | +import { toRefs, computed } from 'vue' | |
3 | +import { icon } from '@/plugins' | |
4 | +import { useDesignStore } from '@/store/modules/designStore/designStore' | |
5 | +import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting' | |
6 | +import { SelectHttpTimeNameObj, RequestContentTypeEnum } from '@/enums/httpEnum' | |
7 | +import { useTargetData } from '@/views/chart/ContentConfigurations/components/hooks/useTargetData.hook' | |
8 | +import { NButton, NCard, NTag, NInput, NIcon } from 'naive-ui' | |
9 | + | |
10 | +const emit = defineEmits(['clickPanel']) | |
11 | + | |
12 | +const { FlashIcon, PulseIcon } = icon.ionicons5 | |
13 | +const { targetData, chartEditStore } = useTargetData() | |
14 | + | |
15 | +const { | |
16 | + requestOriginUrl, | |
17 | + requestInterval: GlobalRequestInterval, | |
18 | + requestIntervalUnit: GlobalRequestIntervalUnit | |
19 | +} = toRefs(chartEditStore.getRequestGlobalConfig) | |
20 | + | |
21 | +const designStore = useDesignStore() | |
22 | + | |
23 | +// 请求配置 model | |
24 | +const requestModelHandle = () => { | |
25 | + emit('clickPanel') | |
26 | +} | |
27 | + | |
28 | +// 颜色 | |
29 | +const themeColor = computed(() => { | |
30 | + return designStore.getAppTheme | |
31 | +}) | |
32 | + | |
33 | +</script> | |
34 | + | |
35 | +<template> | |
36 | + <NCard class="n-card-shallow"> | |
37 | + <SettingItemBox name="请求配置"> | |
38 | + <SettingItem name="类型"> | |
39 | + <NTag :bordered="false" type="primary" style="border-radius: 5px"> | |
40 | + {{ targetData.request.requestContentType === RequestContentTypeEnum.DEFAULT ? '普通请求' : 'SQL请求' }} | |
41 | + </NTag> | |
42 | + </SettingItem> | |
43 | + | |
44 | + <SettingItem name="方式"> | |
45 | + <NInput size="small" :placeholder="targetData.request.requestHttpType || '暂无'" :disabled="true"></NInput> | |
46 | + </SettingItem> | |
47 | + | |
48 | + <SettingItem name="组件间隔"> | |
49 | + <NInput size="small" :placeholder="`${targetData.request.requestInterval || '暂无'}`" :disabled="true"> | |
50 | + <template #suffix> {{ SelectHttpTimeNameObj[targetData.request.requestIntervalUnit] }} </template> | |
51 | + </NInput> | |
52 | + </SettingItem> | |
53 | + | |
54 | + <SettingItem name="全局间隔(默认)"> | |
55 | + <NInput size="small" :placeholder="`${GlobalRequestInterval || '暂无'} `" :disabled="true"> | |
56 | + <template #suffix> {{ SelectHttpTimeNameObj[GlobalRequestIntervalUnit] }} </template> | |
57 | + </NInput> | |
58 | + </SettingItem> | |
59 | + </SettingItemBox> | |
60 | + | |
61 | + <SettingItemBox name="源地址" :alone="true"> | |
62 | + <NInput size="small" :placeholder="requestOriginUrl || '暂无'" :disabled="true"> | |
63 | + <template #prefix> | |
64 | + <NIcon :component="PulseIcon" /> | |
65 | + </template> | |
66 | + </NInput> | |
67 | + </SettingItemBox> | |
68 | + | |
69 | + <SettingItemBox name="组件地址" :alone="true"> | |
70 | + <NInput size="small" :placeholder="targetData.request.requestUrl || '暂无'" :disabled="true"> | |
71 | + <template #prefix> | |
72 | + <NIcon :component="FlashIcon" /> | |
73 | + </template> | |
74 | + </NInput> | |
75 | + </SettingItemBox> | |
76 | + | |
77 | + <div class="edit-text" @click="requestModelHandle"> | |
78 | + <div class="go-absolute-center"> | |
79 | + <NButton type="primary" secondary>编辑配置</NButton> | |
80 | + </div> | |
81 | + </div> | |
82 | + </NCard> | |
83 | +</template> | |
84 | + | |
85 | +<style lang="scss" scoped> | |
86 | +.n-card-shallow { | |
87 | + &.n-card { | |
88 | + @extend .go-background-filter; | |
89 | + | |
90 | + @include deep() { | |
91 | + .n-card__content { | |
92 | + padding: 10px; | |
93 | + } | |
94 | + } | |
95 | + } | |
96 | + | |
97 | + .edit-text { | |
98 | + position: absolute; | |
99 | + top: 0px; | |
100 | + left: 0px; | |
101 | + width: 325px; | |
102 | + height: 270px; | |
103 | + cursor: pointer; | |
104 | + opacity: 0; | |
105 | + transition: all 0.3s; | |
106 | + @extend .go-background-filter; | |
107 | + backdrop-filter: blur(2px) !important; | |
108 | + } | |
109 | + | |
110 | + &:hover { | |
111 | + border-color: v-bind('themeColor'); | |
112 | + | |
113 | + .edit-text { | |
114 | + opacity: 1; | |
115 | + } | |
116 | + } | |
117 | +} | |
118 | +</style> | ... | ... |
1 | +<script setup lang="ts"> | |
2 | +import { NInput, NInputNumber, NInputGroup, NButton, NSelect, SelectOption, NTabs, NTabPane, NSpace } from 'naive-ui' | |
3 | +import { SettingItem, SettingItemBox } from '@/components/Pages/ChartItemSetting'; | |
4 | +import { selectTimeOptions, selectTypeOptions } from '../../../index.d'; | |
5 | +import { RequestBodyEnum, RequestContentTypeEnum, RequestDataTypeEnum, RequestHttpEnum, RequestHttpIntervalEnum, RequestParams } from '@/enums/httpEnum'; | |
6 | +import { ref, unref } from 'vue'; | |
7 | +import DefaultRequestContent from './DefaultRequestContent.vue'; | |
8 | +import SqlConfiguration from './SqlConfiguration.vue'; | |
9 | +import { RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'; | |
10 | +import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'; | |
11 | +import { getUrl } from '@/api/external/customRequest' | |
12 | + | |
13 | +const chartEditStore = useChartEditStore() | |
14 | + | |
15 | +const requestContentTypeRef = ref(RequestContentTypeEnum.DEFAULT) | |
16 | + | |
17 | +const requestHttpTypeRef = ref(RequestHttpEnum.GET) | |
18 | + | |
19 | +const requestIntervalRef = ref<number | undefined>(20) | |
20 | + | |
21 | +const requestIntervalUnitRef = ref(RequestHttpIntervalEnum.SECOND) | |
22 | + | |
23 | +const requestSQLContentRef = ref('select * from where') | |
24 | + | |
25 | +const requestParamsRef = ref({ Header: {}, Params: {}, Body: { 'form-data': {}, 'json': '', 'x-www-form-urlencoded': {}, 'xml': '' } } as RequestParams) | |
26 | + | |
27 | +const requestParamsBodyTypeRef = ref(RequestBodyEnum.NONE) | |
28 | + | |
29 | +const requestUrlRef = ref<string>() | |
30 | + | |
31 | +const getConfigurationData = (): RequestConfigType => { | |
32 | + return { | |
33 | + requestContentType: unref(requestContentTypeRef), | |
34 | + requestHttpType: unref(requestHttpTypeRef), | |
35 | + requestInterval: unref(requestIntervalRef), | |
36 | + requestIntervalUnit: unref(requestIntervalUnitRef), | |
37 | + requestDataType: RequestDataTypeEnum.AJAX, | |
38 | + requestParamsBodyType: unref(requestParamsBodyTypeRef), | |
39 | + requestSQLContent: { | |
40 | + sql: unref(requestSQLContentRef) | |
41 | + }, | |
42 | + requestParams: unref(requestParamsRef), | |
43 | + requestUrl: `${chartEditStore.requestGlobalConfig.requestOriginUrl}${unref(requestUrlRef)}` | |
44 | + } | |
45 | +} | |
46 | + | |
47 | + | |
48 | +const setConfigurationData = (request: RequestConfigType) => { | |
49 | + const { requestContentType, requestHttpType, requestInterval, requestIntervalUnit, requestParamsBodyType, requestSQLContent, requestParams, requestUrl } = request | |
50 | + requestContentTypeRef.value = requestContentType | |
51 | + requestHttpTypeRef.value = requestHttpType | |
52 | + requestIntervalRef.value = requestInterval | |
53 | + requestIntervalUnitRef.value = requestIntervalUnit | |
54 | + requestParamsBodyTypeRef.value = requestParamsBodyType | |
55 | + requestSQLContentRef.value = requestSQLContent.sql | |
56 | + requestParamsRef.value = requestParams | |
57 | + const { pathname } = getUrl(requestUrl!) | |
58 | + requestUrlRef.value = pathname | |
59 | +} | |
60 | + | |
61 | +defineExpose({ | |
62 | + getConfigurationData, | |
63 | + setConfigurationData | |
64 | +}) | |
65 | + | |
66 | +</script> | |
67 | + | |
68 | +<template> | |
69 | + <SettingItemBox name="地址" :itemRightStyle="{ | |
70 | + gridTemplateColumns: '5fr 2fr 1fr' | |
71 | + }"> | |
72 | + <SettingItem name="请求方式 & URL地址"> | |
73 | + <NInputGroup> | |
74 | + <NSelect v-model:value="requestHttpTypeRef" style="width: 150px;" size="small" | |
75 | + :options="(selectTypeOptions as SelectOption[])" /> | |
76 | + <NInput v-model:value="requestUrlRef" class="select-time-number" size="small" min="0" :show-button="false" | |
77 | + placeholder="请输入URL地址" /> | |
78 | + </NInputGroup> | |
79 | + </SettingItem> | |
80 | + <SettingItem name="更新间隔,为 0 只会初始化"> | |
81 | + <NInputGroup> | |
82 | + <NInputNumber v-model:value="requestIntervalRef" class="select-time-number" size="small" min="0" | |
83 | + :show-button="false" placeholder="请输入数字" /> | |
84 | + <!-- 单位 --> | |
85 | + <NSelect v-model:value="requestIntervalUnitRef" class="select-time-options" size="small" | |
86 | + :options="(selectTimeOptions as SelectOption[])" /> | |
87 | + </NInputGroup> | |
88 | + </SettingItem> | |
89 | + </SettingItemBox> | |
90 | + <SettingItemBox name="选择方式"> | |
91 | + <NTabs v-model:value="requestContentTypeRef" type="segment" size="small"> | |
92 | + <NTabPane :name="RequestContentTypeEnum.DEFAULT" tab="普通请求" /> | |
93 | + <NTabPane :name="RequestContentTypeEnum.SQL" tab="SQL请求" /> | |
94 | + </NTabs> | |
95 | + </SettingItemBox> | |
96 | + <SettingItemBox> | |
97 | + <DefaultRequestContent v-if="requestContentTypeRef === RequestContentTypeEnum.DEFAULT" | |
98 | + v-model:value="requestParamsRef" v-model:request-params-body-type="requestParamsBodyTypeRef" /> | |
99 | + <SqlConfiguration v-model:value="requestSQLContentRef" v-if="requestContentTypeRef === RequestContentTypeEnum.SQL" /> | |
100 | + </SettingItemBox> | |
101 | +</template> | ... | ... |
1 | +<script lang="ts" setup> | |
2 | +import { RequestBodyEnum, RequestParams, RequestParamsTypeEnum } from '@/enums/httpEnum'; | |
3 | +import { NTabPane, NTabs } from 'naive-ui'; | |
4 | +import { ref } from 'vue'; | |
5 | +import ParamsTable from './ParamsTable.vue'; | |
6 | +import RequestBody from './RequestBody.vue'; | |
7 | + | |
8 | +defineProps<{ | |
9 | + value: RequestParams | |
10 | + requestParamsBodyType: RequestBodyEnum | |
11 | +}>() | |
12 | + | |
13 | +const emit = defineEmits(['update:requestParamsBodyType']) | |
14 | + | |
15 | +const tabValue = ref(RequestParamsTypeEnum.PARAMS) | |
16 | + | |
17 | +const handleSyncRequestParamsBodyType = (value: RequestBodyEnum) => { | |
18 | + emit('update:requestParamsBodyType', value) | |
19 | +} | |
20 | + | |
21 | + | |
22 | +</script> | |
23 | + | |
24 | +<template> | |
25 | + <section class="container"> | |
26 | + <NTabs v-model:value="tabValue"> | |
27 | + <NTabPane v-for="item in RequestParamsTypeEnum" :name="item" :key="item"></NTabPane> | |
28 | + </NTabs> | |
29 | + <section v-if="tabValue === RequestParamsTypeEnum.PARAMS"> | |
30 | + <ParamsTable v-model:value="value[RequestParamsTypeEnum.PARAMS]" /> | |
31 | + </section> | |
32 | + | |
33 | + <RequestBody v-model:value="value" @update:requestParamsBodyType="handleSyncRequestParamsBodyType" | |
34 | + v-model:requestParamsBodyType="requestParamsBodyType" v-if="tabValue === RequestParamsTypeEnum.BODY" /> | |
35 | + | |
36 | + <ParamsTable v-if="tabValue === RequestParamsTypeEnum.HEADER" v-model:value="value.Header" /> | |
37 | + </section> | |
38 | +</template> | |
39 | + | |
40 | +<style lang="scss" scoped> | |
41 | +.container { | |
42 | + width: 600px; | |
43 | +} | |
44 | + | |
45 | +.body-container { | |
46 | + margin-top: 20px; | |
47 | +} | |
48 | +</style> | ... | ... |
1 | +<script lang="ts" setup> | |
2 | +import { RequestParamsTypeEnum } from '@/enums/httpEnum'; | |
3 | +import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'; | |
4 | +import { NTabPane, NTabs } from 'naive-ui'; | |
5 | +import { ref } from 'vue'; | |
6 | +import ParamsTable from './ParamsTable.vue'; | |
7 | + | |
8 | +const chartEditStore = useChartEditStore() | |
9 | + | |
10 | +const tabs: RequestParamsTypeEnum[] = [RequestParamsTypeEnum.HEADER] | |
11 | + | |
12 | +const currenPanel = ref(RequestParamsTypeEnum.HEADER) | |
13 | + | |
14 | + | |
15 | +</script> | |
16 | + | |
17 | +<template> | |
18 | + <NTabs type="line" animated> | |
19 | + <NTabPane v-model:value="currenPanel" v-for="item in tabs" :name="item" :tab="item" :key="item" /> | |
20 | + </NTabs> | |
21 | + <section> | |
22 | + <ParamsTable v-if="currenPanel === RequestParamsTypeEnum.HEADER" v-model:value="chartEditStore.requestGlobalConfig.requestParams.Header" /> | |
23 | + </section> | |
24 | +</template> | ... | ... |
1 | +<script lang="ts" setup> | |
2 | +import { SettingItem, SettingItemBox } from '@/components/Pages/ChartItemSetting'; | |
3 | +import { icon } from '@/plugins'; | |
4 | +import { NButton, NCard, NCollapseTransition, NIcon, NInput, NInputGroup, NInputNumber, NSelect, NSpace, NTag, NTooltip, SelectOption } from 'naive-ui'; | |
5 | +import { computed, ref, unref } from 'vue'; | |
6 | +import GlobalParamsConfiguration from './GlobalParamsConfiguration.vue' | |
7 | +import { ChevronDown, ChevronUp } from '@vicons/carbon' | |
8 | +import { useDesignStore } from '@/store/modules/designStore/designStore'; | |
9 | +import { selectTimeOptions } from '../../../index.d'; | |
10 | +import { RequestConfigType, RequestGlobalConfigType } from '@/store/modules/chartEditStore/chartEditStore.d' | |
11 | +import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'; | |
12 | +import { useTargetData } from '../../../../hooks/useTargetData.hook'; | |
13 | +import { RequestHttpIntervalEnum } from '@/enums/httpEnum'; | |
14 | + | |
15 | +const { PencilIcon } = icon.ionicons5 | |
16 | +const designStore = useDesignStore() | |
17 | +const editDisabled = ref(false) | |
18 | +const collapseHeaderTable = ref(false) | |
19 | + | |
20 | +const { chartEditStore } = useTargetData() | |
21 | + | |
22 | +const handleCollapse = () => { | |
23 | + collapseHeaderTable.value = !unref(collapseHeaderTable) | |
24 | +} | |
25 | + | |
26 | + | |
27 | +// 颜色 | |
28 | +const themeColor = computed(() => { | |
29 | + return designStore.getAppTheme | |
30 | +}) | |
31 | + | |
32 | + | |
33 | + | |
34 | +</script> | |
35 | + | |
36 | +<template> | |
37 | + <NCard> | |
38 | + <template #header> | |
39 | + <NTag type="info">全局公共配置</NTag> | |
40 | + </template> | |
41 | + <NSpace vertical> | |
42 | + <SettingItemBox name="服务" :itemRightStyle="{ | |
43 | + gridTemplateColumns: '5fr 2fr 1fr' | |
44 | + }"> | |
45 | + <!-- 源地址 --> | |
46 | + <SettingItem name="前置 URL"> | |
47 | + <NInput v-model:value="chartEditStore.requestGlobalConfig.requestOriginUrl" default-value="http://127.0.0.1" :disabled="editDisabled" | |
48 | + size="small" placeholder="例:http://127.0.0.1"></NInput> | |
49 | + </SettingItem> | |
50 | + <SettingItem name="更新间隔,为 0 只会初始化"> | |
51 | + <NInputGroup> | |
52 | + <NInputNumber v-model:value="chartEditStore.requestGlobalConfig.requestInterval" class="select-time-number" | |
53 | + size="small" min="0" :show-button="false" :disabled="editDisabled" placeholder="请输入数字"> | |
54 | + </NInputNumber> | |
55 | + <!-- 单位 --> | |
56 | + <NSelect v-model:value="chartEditStore.requestGlobalConfig.requestIntervalUnit" class="select-time-options" | |
57 | + size="small" :default-value="RequestHttpIntervalEnum.SECOND" :options="selectTimeOptions as SelectOption[]" | |
58 | + :disabled="editDisabled" /> | |
59 | + </NInputGroup> | |
60 | + </SettingItem> | |
61 | + <NButton v-show="editDisabled" type="primary" ghost @click="editDisabled = false"> | |
62 | + <template #icon> | |
63 | + <NIcon> | |
64 | + <PencilIcon /> | |
65 | + </NIcon> | |
66 | + </template> | |
67 | + 编辑配置 | |
68 | + </NButton> | |
69 | + </SettingItemBox> | |
70 | + <NCollapseTransition :show="collapseHeaderTable"> | |
71 | + <GlobalParamsConfiguration /> | |
72 | + </NCollapseTransition> | |
73 | + <section class="arrow"> | |
74 | + <NTooltip> | |
75 | + <template #trigger> | |
76 | + <NIcon @click="handleCollapse" size="30"> | |
77 | + <ChevronDown v-show="!collapseHeaderTable" /> | |
78 | + <ChevronUp v-show="collapseHeaderTable" /> | |
79 | + </NIcon> | |
80 | + </template> | |
81 | + <span>{{ collapseHeaderTable ? '收起' : '展开' }}</span> | |
82 | + </NTooltip> | |
83 | + </section> | |
84 | + </NSpace> | |
85 | + </NCard> | |
86 | +</template> | |
87 | + | |
88 | + | |
89 | +<style lang="scss" scoped> | |
90 | +.arrow { | |
91 | + display: flex; | |
92 | + justify-content: center; | |
93 | + align-items: center; | |
94 | + cursor: pointer; | |
95 | + | |
96 | + &:hover { | |
97 | + color: v-bind('themeColor'); | |
98 | + | |
99 | + } | |
100 | +} | |
101 | +</style> | ... | ... |
1 | +<script setup lang="ts" > | |
2 | +import { getUUID } from '@/utils'; | |
3 | +import { ButtonProps, DataTableColumns, InputProps, NButton, NDataTable, NIcon, NInput, NSpace, NTag, NTooltip, TagProps } from 'naive-ui'; | |
4 | +import { computed, h, ref, unref, watch } from 'vue'; | |
5 | +import { Subtract, Add } from '@vicons/carbon' | |
6 | +import { isObject } from '@/utils/external/is'; | |
7 | + | |
8 | +interface DataSource { | |
9 | + id: string | |
10 | + value?: string | |
11 | + keyName?: string | |
12 | + result?: boolean | |
13 | +} | |
14 | + | |
15 | +const columns: DataTableColumns<DataSource> = [ | |
16 | + { | |
17 | + title: '序号', | |
18 | + key: 'index', | |
19 | + render: (_, index) => index + 1, | |
20 | + width: 50, | |
21 | + }, | |
22 | + { | |
23 | + title: 'Key', | |
24 | + key: 'keyName', | |
25 | + render: (row, index) => { | |
26 | + return h( | |
27 | + NInput, | |
28 | + { | |
29 | + value: row.keyName, | |
30 | + onBlur: () => handleInputBlur(row), | |
31 | + onUpdateValue: (value: string) => unref(dataSource)[index].keyName = value, | |
32 | + size: 'small', | |
33 | + disabled: props.disabled | |
34 | + } as InputProps | |
35 | + ) | |
36 | + } | |
37 | + }, | |
38 | + { | |
39 | + title: 'Value', | |
40 | + key: 'value', | |
41 | + render: (row, index) => { | |
42 | + return h( | |
43 | + NInput, | |
44 | + { | |
45 | + value: row.value, | |
46 | + onBlur: () => handleInputBlur(row), | |
47 | + onUpdateValue: (value: string) => unref(dataSource)[index].value = value, | |
48 | + size: 'small', | |
49 | + disabled: props.disabled | |
50 | + } as InputProps | |
51 | + ) | |
52 | + } | |
53 | + }, | |
54 | + { | |
55 | + title: '操作', | |
56 | + key: 'actions', | |
57 | + render: (row) => { | |
58 | + return h( | |
59 | + NSpace, | |
60 | + () => [ | |
61 | + h( | |
62 | + NTooltip, | |
63 | + null, | |
64 | + { | |
65 | + trigger: () => h( | |
66 | + NButton, | |
67 | + { | |
68 | + type: 'success', | |
69 | + size: 'small', | |
70 | + ghost: true, | |
71 | + onClick: () => handleAddRow(row), | |
72 | + disabled: props.disabled || !unref(canAddRow) | |
73 | + } as ButtonProps, | |
74 | + { | |
75 | + default: () => h(NIcon, () => h(Add)) | |
76 | + } | |
77 | + ), | |
78 | + default: () => '插入行' | |
79 | + } | |
80 | + ), | |
81 | + h( | |
82 | + NTooltip, | |
83 | + null, | |
84 | + { | |
85 | + trigger: () => h( | |
86 | + NButton, | |
87 | + { | |
88 | + type: 'warning', | |
89 | + size: 'small', | |
90 | + ghost: true, | |
91 | + onClick: () => handleSubtractRow(row), | |
92 | + disabled: props.disabled || !unref(canDeleteRow) | |
93 | + } as ButtonProps, | |
94 | + { | |
95 | + default: () => h(NIcon, () => h(Subtract)) | |
96 | + } | |
97 | + ), | |
98 | + default: () => '删除行' | |
99 | + } | |
100 | + ) | |
101 | + ] | |
102 | + ) | |
103 | + }, | |
104 | + width: 100, | |
105 | + }, | |
106 | + { | |
107 | + title: '结果', | |
108 | + key: 'result', | |
109 | + render: (row) => { | |
110 | + return h(NTag, { type: row.result ? 'success' : 'error' } as TagProps, () => `${row.result ? '' : '未'}通过`) | |
111 | + }, | |
112 | + width: 80 | |
113 | + } | |
114 | +] | |
115 | + | |
116 | +const props = withDefaults( | |
117 | + defineProps<{ | |
118 | + value?: Recordable | |
119 | + disabled?: boolean | |
120 | + maxRow?: number | |
121 | + }>(), | |
122 | + { | |
123 | + disabled: false, | |
124 | + maxRow: 50, | |
125 | + } | |
126 | +) | |
127 | + | |
128 | +const emit = defineEmits(['update:value']) | |
129 | + | |
130 | +const createNewRow = () => { | |
131 | + return { id: getUUID(), result: true } as DataSource | |
132 | +} | |
133 | + | |
134 | +const dataSource = ref<DataSource[]>([ | |
135 | + createNewRow() | |
136 | +]) | |
137 | + | |
138 | +watch( | |
139 | + () => props.value, | |
140 | + (target) => { | |
141 | + if (target && isObject(target) && Object.keys(target).length) { | |
142 | + dataSource.value = Object.keys(props.value || {}).map(keyName => ({ ...createNewRow(), keyName, value: Reflect.get(props.value || {}, keyName) })) | |
143 | + } else { | |
144 | + dataSource.value = [createNewRow()] | |
145 | + } | |
146 | + }, | |
147 | + { | |
148 | + immediate: true, | |
149 | + deep: true | |
150 | + } | |
151 | +) | |
152 | + | |
153 | +const canDeleteRow = computed(() => { | |
154 | + return unref(dataSource).length >= 2 | |
155 | +}) | |
156 | + | |
157 | +const canAddRow = computed(() => { | |
158 | + return unref(dataSource).length < props.maxRow | |
159 | +}) | |
160 | + | |
161 | +const handleAddRow = (record: DataSource) => { | |
162 | + const index = unref(dataSource).findIndex(item => item.id === record.id) | |
163 | + unref(dataSource).splice(index + 1, 0, createNewRow()) | |
164 | +} | |
165 | + | |
166 | +const handleSubtractRow = (record: DataSource) => { | |
167 | + const index = unref(dataSource).findIndex(item => item.id === record.id) | |
168 | + unref(dataSource).splice(index, 1) | |
169 | +} | |
170 | + | |
171 | + | |
172 | +const handleInputBlur = (record: DataSource) => { | |
173 | + const { keyName, value } = record | |
174 | + record.result = !!(keyName && value) | |
175 | + if (unref(dataSource).every(item => item.result)) { | |
176 | + emit('update:value', getHeaderConfiguration()) | |
177 | + } | |
178 | +} | |
179 | + | |
180 | +const getHeaderConfiguration = () => { | |
181 | + return unref(dataSource).reduce((prev, next) => { | |
182 | + const { result, value, keyName } = next | |
183 | + const header = result && value && keyName ? { [keyName]: value } : {} | |
184 | + return { ...prev, ...header } | |
185 | + }, {} as Recordable) | |
186 | +} | |
187 | + | |
188 | +</script> | |
189 | + | |
190 | +<template> | |
191 | + <NDataTable size="small" :columns="columns" :data="dataSource" max-height="300" /> | |
192 | +</template> | ... | ... |
1 | +<script lang="ts" setup> | |
2 | +import { MonacoEditor } from '@/components/Pages/MonacoEditor'; | |
3 | +import { RequestBodyEnum, RequestBodyEnumList, RequestParams } from '@/enums/httpEnum'; | |
4 | +import { NCard } from 'naive-ui'; | |
5 | +import ParamsTable from './ParamsTable.vue'; | |
6 | + | |
7 | +defineProps<{ | |
8 | + requestParamsBodyType: RequestBodyEnum | |
9 | + value: RequestParams | |
10 | +}>() | |
11 | + | |
12 | +const emit = defineEmits(['update:requestParamsBodyType']) | |
13 | + | |
14 | +const handleSyncRequestParamsBodyType = (value: RequestBodyEnum) => { | |
15 | + emit('update:requestParamsBodyType', value) | |
16 | +} | |
17 | + | |
18 | +</script> | |
19 | + | |
20 | +<template> | |
21 | + <section> | |
22 | + <NRadioGroup v-model:value="requestParamsBodyType" @update:value="handleSyncRequestParamsBodyType"> | |
23 | + <NSpace> | |
24 | + <NRadio v-for="item in RequestBodyEnumList" :key="item" :value="item"> | |
25 | + {{ item }} | |
26 | + </NRadio> | |
27 | + </NSpace> | |
28 | + </NRadioGroup> | |
29 | + | |
30 | + <section class="body-container"> | |
31 | + <!-- 为 none 时 --> | |
32 | + <NCard v-if="requestParamsBodyType === RequestBodyEnum.NONE"> | |
33 | + <NText depth="3">该接口没有 Body 体</NText> | |
34 | + </NCard> | |
35 | + | |
36 | + <ParamsTable v-if="requestParamsBodyType === RequestBodyEnum.FORM_DATA" | |
37 | + v-model:value="value.Body[RequestBodyEnum.FORM_DATA]" /> | |
38 | + | |
39 | + <ParamsTable v-if="requestParamsBodyType === RequestBodyEnum.X_WWW_FORM_URLENCODED" | |
40 | + v-model:value="value.Body[RequestBodyEnum.X_WWW_FORM_URLENCODED]" /> | |
41 | + | |
42 | + <MonacoEditor v-if="requestParamsBodyType === RequestBodyEnum.JSON" | |
43 | + v-model:modelValue="value.Body[RequestBodyEnum.JSON]" width="600px" height="200px" language="json" /> | |
44 | + | |
45 | + <MonacoEditor v-if="requestParamsBodyType === RequestBodyEnum.XML" | |
46 | + v-model:modelValue="value.Body[RequestBodyEnum.XML]" width="600px" height="200px" language="xml" /> | |
47 | + </section> | |
48 | + </section> | |
49 | +</template> | |
50 | + | |
51 | +<style lang="scss" scoped> | |
52 | + .body-container { | |
53 | + margin-top: 20px; | |
54 | + } | |
55 | +</style> | ... | ... |
1 | +<script lang="ts" setup> | |
2 | +import { SettingItemBox } from '@/components/Pages/ChartItemSetting'; | |
3 | +import { MonacoEditor } from '@/components/Pages/MonacoEditor'; | |
4 | +import { NTag } from 'naive-ui'; | |
5 | + | |
6 | +defineProps<{ | |
7 | + value: string | |
8 | +}>() | |
9 | + | |
10 | +const emits = defineEmits(['update:value']) | |
11 | + | |
12 | +const updateValue = (value: string) => { | |
13 | + emits('update:value', value) | |
14 | +} | |
15 | + | |
16 | +</script> | |
17 | + | |
18 | +<template> | |
19 | + <section> | |
20 | + <NTag type="warning">需要后台提供专门处理sql的借口</NTag> | |
21 | + <SettingItemBox name="键名"> | |
22 | + <NTag type="success" style="width: fit-content;">sql</NTag> | |
23 | + </SettingItemBox> | |
24 | + <SettingItemBox name="键值"> | |
25 | + <MonacoEditor v-model:modelValue="value" @update:modelValue="updateValue" width="600px" height="200px" | |
26 | + language="sql" /> | |
27 | + </SettingItemBox> | |
28 | + </section> | |
29 | +</template> | ... | ... |
src/views/chart/ContentConfigurations/components/ChartData/external/components/RequestModal/index.ts
0 → 100644
1 | +export { default as RequestModal } from './index.vue' | ... | ... |
1 | +<script lang="ts" setup> | |
2 | +import { RequestDataTypeEnum, RequestDataTypeNameEnum } from '@/enums/external/httpEnum'; | |
3 | +import { useDesign } from '@/hooks/external/useDesign'; | |
4 | +import { CreateComponentType } from '@/packages/index.d'; | |
5 | +import { CreateComponentGroupType } from '@/packages/index.d'; | |
6 | +import { RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'; | |
7 | +import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'; | |
8 | +import { GlobalComponentConfig, NButton, NDivider, NModal, NSpace, NTag } from 'naive-ui'; | |
9 | +import { ref, unref, computed, nextTick } from 'vue'; | |
10 | +import { PublicInterfaceForm } from '../PublicInterfaceForm'; | |
11 | +import ComponentConfiguration from './ComponentConfiguration.vue'; | |
12 | +import GlobalPublicConfiguration from './GlobalPublicConfiguration.vue'; | |
13 | +import { createRequestModalContext } from './useRequestModalContext'; | |
14 | + | |
15 | +const requestDataType = ref<RequestDataTypeEnum>(RequestDataTypeEnum.AJAX) | |
16 | + | |
17 | +const showModal = ref(false) | |
18 | + | |
19 | +const chartEditStore = useChartEditStore() | |
20 | + | |
21 | +const globalConfigurationEl = ref<Nullable<InstanceType<typeof GlobalPublicConfiguration>>>() | |
22 | + | |
23 | +const componentConfigurationEl = ref<Nullable<InstanceType<typeof ComponentConfiguration>>>() | |
24 | + | |
25 | +const publicInterfaceFormEl = ref<Nullable<InstanceType<typeof PublicInterfaceForm>>>() | |
26 | + | |
27 | +const getRequestTypeName = computed(() => { | |
28 | + return RequestDataTypeNameEnum[RequestDataTypeEnum[unref(requestDataType)] as keyof typeof RequestDataTypeEnum] | |
29 | +}) | |
30 | + | |
31 | +const { prefixCls } = useDesign('chart-data-request') | |
32 | + | |
33 | +const openModal = async (flag = true, type: RequestDataTypeEnum) => { | |
34 | + requestDataType.value = type | |
35 | + showModal.value = flag | |
36 | + await nextTick() | |
37 | + unref(componentConfigurationEl)?.setConfigurationData(unref(selectTarget)!.request || {}) | |
38 | + unref(publicInterfaceFormEl)?.setConfigurationData(unref(selectTarget)!.request || {}) | |
39 | +} | |
40 | + | |
41 | +const handleSaveAndRequest = () => { | |
42 | + handleSaveAction() | |
43 | +} | |
44 | + | |
45 | +const selectTarget = computed<CreateComponentType | CreateComponentGroupType | undefined>(() => { | |
46 | + const selectId = chartEditStore.getTargetChart.selectId | |
47 | + // 排除多个 | |
48 | + if (selectId.length !== 1) return undefined | |
49 | + const target = chartEditStore.componentList[chartEditStore.fetchTargetIndex()] | |
50 | + return target as CreateComponentType | CreateComponentGroupType | |
51 | +}) | |
52 | + | |
53 | +const validate = async () => { | |
54 | + if (unref(requestDataType) === RequestDataTypeEnum.Pond) { | |
55 | + return await unref(publicInterfaceFormEl)?.validate() | |
56 | + } | |
57 | + return true | |
58 | +} | |
59 | + | |
60 | +const getResult = () => { | |
61 | + if (unref(requestDataType) === RequestDataTypeEnum.AJAX) { | |
62 | + return unref(componentConfigurationEl)?.getConfigurationData() | |
63 | + } else if (unref(requestDataType) === RequestDataTypeEnum.Pond) { | |
64 | + return unref(publicInterfaceFormEl)?.getConfigurationData() | |
65 | + } | |
66 | + | |
67 | + return {} as unknown as RequestConfigType | |
68 | +} | |
69 | + | |
70 | +const handleSaveAction = async () => { | |
71 | + if (!(await validate())) return | |
72 | + const value = getResult() | |
73 | + console.log(value) | |
74 | + if (unref(selectTarget)) { | |
75 | + chartEditStore.updateComponentList(chartEditStore.fetchTargetIndex(), { | |
76 | + ...unref(selectTarget)!, | |
77 | + request: value! | |
78 | + }) | |
79 | + } | |
80 | + showModal.value = false | |
81 | +} | |
82 | + | |
83 | +createRequestModalContext({ | |
84 | + requestDataType | |
85 | +}) | |
86 | + | |
87 | +defineExpose({ | |
88 | + openModal, | |
89 | +}) | |
90 | + | |
91 | +</script> | |
92 | + | |
93 | +<template> | |
94 | + <NModal :class="prefixCls" v-model:show="showModal" preset="card" style="width: 1000px;" title="请求配置"> | |
95 | + <GlobalPublicConfiguration v-if="requestDataType === RequestDataTypeEnum.AJAX" ref="globalConfigurationEl" /> | |
96 | + <NDivider v-if="requestDataType === RequestDataTypeEnum.AJAX" /> | |
97 | + <ComponentConfiguration v-if="requestDataType === RequestDataTypeEnum.AJAX" ref="componentConfigurationEl" /> | |
98 | + <PublicInterfaceForm v-if="requestDataType === RequestDataTypeEnum.Pond" ref="publicInterfaceFormEl" /> | |
99 | + <template #action> | |
100 | + <NSpace justify="space-between"> | |
101 | + <div style="display: flex; align-items: center; "> | |
102 | + <span>「 更多 」</span> | |
103 | + <span style="margin-right: 5px;">——</span> | |
104 | + <NTag type="info">{{ getRequestTypeName }}</NTag> | |
105 | + </div> | |
106 | + <NButton type="primary" @click="handleSaveAndRequest">保存 & 发送请求</NButton> | |
107 | + </NSpace> | |
108 | + </template> | |
109 | + </NModal> | |
110 | +</template> | |
111 | + | |
112 | + | |
113 | +<style lang="scss" > | |
114 | +@include thingsKit('chart-data-request') { | |
115 | + | |
116 | + &.n-card.n-modal, | |
117 | + .n-card { | |
118 | + @extend .go-background-filter; | |
119 | + } | |
120 | + | |
121 | + .n-card-shallow { | |
122 | + background-color: rgba(0, 0, 0, 0) !important; | |
123 | + } | |
124 | + | |
125 | + @include deep() { | |
126 | + &>.n-card__content { | |
127 | + padding-right: 0; | |
128 | + } | |
129 | + | |
130 | + .n-card__content { | |
131 | + padding-bottom: 5px; | |
132 | + } | |
133 | + } | |
134 | +} | |
135 | +</style> | ... | ... |
1 | +import { RequestDataTypeEnum } from "@/enums/external/httpEnum" | |
2 | +import { createContext, useContext } from "@/utils/external/useAppContext" | |
3 | +import { InjectionKey, Ref } from "vue" | |
4 | + | |
5 | +export interface RequestContextProps { | |
6 | + requestDataType: Ref<RequestDataTypeEnum> | |
7 | +} | |
8 | + | |
9 | +const key: InjectionKey<RequestContextProps> = Symbol() | |
10 | + | |
11 | +export const useRequestModalContext = () => { | |
12 | + return useContext<RequestContextProps>(key) | |
13 | +} | |
14 | + | |
15 | +export const createRequestModalContext = (context: RequestContextProps) => { | |
16 | + return createContext(context, key) | |
17 | +} | ... | ... |
1 | 1 | <template> |
2 | 2 | <div class="go-chart-configurations-data" v-if="targetData"> |
3 | 3 | <setting-item-box name="请求方式" :alone="true"> |
4 | - <n-select v-model:value="targetData.request.requestDataType" :disabled="isNotData" :options="selectOptions" /> | |
4 | + <!-- THINGS_KIT 请求方式选项修改--> | |
5 | + <n-select v-if="targetData.request.requestDataType !== RequestDataTypeEnum.Pond" | |
6 | + v-model:value="targetData.request.requestDataType" :disabled="isNotData" :options="selectOptions" /> | |
7 | + <n-select v-if="targetData.request.requestDataType === RequestDataTypeEnum.Pond" | |
8 | + v-model:value="targetData.request.requestDataType" :disabled="isNotData" :options="[ | |
9 | + { | |
10 | + label: SelectCreateDataEnum.STATIC, | |
11 | + value: RequestDataTypeEnum.STATIC | |
12 | + }, | |
13 | + { | |
14 | + label: SelectCreateDataEnum.AJAX, | |
15 | + value: RequestDataTypeEnum.Pond | |
16 | + } | |
17 | + ]" /> | |
5 | 18 | </setting-item-box> |
6 | 19 | <!-- 静态 --> |
7 | 20 | <chart-data-static v-if="targetData.request.requestDataType === RequestDataTypeEnum.STATIC"></chart-data-static> |
21 | + <!-- THINGS_KIT 重写动态请求面板 --> | |
22 | + <ChartDynamicRequest v-if="targetData.request.requestDataType !== RequestDataTypeEnum.STATIC" /> | |
8 | 23 | <!-- 动态 --> |
9 | - <chart-data-ajax v-if="targetData.request.requestDataType === RequestDataTypeEnum.AJAX"></chart-data-ajax> | |
24 | + <!-- <chart-data-ajax v-if="targetData.request.requestDataType === RequestDataTypeEnum.AJAX"></chart-data-ajax> --> | |
25 | + | |
26 | + <!-- THINGS_KIT 隐藏公共请求面板 --> | |
10 | 27 | <!-- 数据池 --> |
11 | - <chart-data-pond v-if="targetData.request.requestDataType === RequestDataTypeEnum.Pond"></chart-data-pond> | |
28 | + <!-- <chart-data-pond v-if="targetData.request.requestDataType === RequestDataTypeEnum.Pond"></chart-data-pond> --> | |
12 | 29 | </div> |
13 | 30 | </template> |
14 | 31 | |
... | ... | @@ -23,7 +40,10 @@ import { SelectCreateDataType, SelectCreateDataEnum } from './index.d' |
23 | 40 | |
24 | 41 | const ChartDataStatic = loadAsyncComponent(() => import('./components/ChartDataStatic/index.vue')) |
25 | 42 | const ChartDataAjax = loadAsyncComponent(() => import('./components/ChartDataAjax/index.vue')) |
26 | -const ChartDataPond = loadAsyncComponent(() => import('./components/ChartDataPond/index.vue')) | |
43 | + | |
44 | +// THINGS_KIT 重写动态请求面板 | |
45 | +// const ChartDataPond = loadAsyncComponent(() => import('./components/ChartDataPond/index.vue')) | |
46 | +const ChartDynamicRequest = loadAsyncComponent(() => import('./external/components/ChartDynamicRequest/index.vue')) | |
27 | 47 | |
28 | 48 | const { targetData } = useTargetData() |
29 | 49 | |
... | ... | @@ -37,10 +57,11 @@ const selectOptions: SelectCreateDataType[] = [ |
37 | 57 | label: SelectCreateDataEnum.AJAX, |
38 | 58 | value: RequestDataTypeEnum.AJAX |
39 | 59 | }, |
40 | - { | |
41 | - label: SelectCreateDataEnum.Pond, | |
42 | - value: RequestDataTypeEnum.Pond | |
43 | - } | |
60 | + // THINGS_KIT 隐藏公共请求面板 | |
61 | + // { | |
62 | + // label: SelectCreateDataEnum.Pond, | |
63 | + // value: RequestDataTypeEnum.Pond | |
64 | + // } | |
44 | 65 | ] |
45 | 66 | |
46 | 67 | // 无数据源 | ... | ... |