Commit caaa83061ac8aecac288580ea76bc8270b14b920

Authored by fengtao
Committed by xp.Huang
1 parent c2ad5966

feat(src/packages): 大屏自定义请求新增第三方接口动态获取Token功能

1   -import type { AxiosResponse } from 'axios';
2   -import type { RequestOptions, Result } from '/#/external/axios';
3   -import type { AxiosTransform, CreateAxiosOptions } from '@/utils/external/http/axios/axiosTransform';
4   -import { useGlobSetting } from '@/hooks/external/setting';
5   -import { RequestEnum, ContentTypeEnum } from '@/enums/external/httpEnum';
6   -import { isString } from '@/utils/external/is';
7   -import { getJwtToken, getShareJwtToken } from '@/utils/external/auth';
8   -import { setObjToUrlParams, deepMerge } from '@/utils/external';
9   -import { formatRequestDate, joinTimestamp } from '@/utils/external/http/axios/helper';
10   -import { VAxios } from '@/utils/external/http/axios/Axios';
11   -import { checkStatus } from './checkStatus';
  1 +import type { AxiosResponse } from 'axios'
  2 +import type { RequestOptions, Result } from '/#/external/axios'
  3 +import type { AxiosTransform, CreateAxiosOptions } from '@/utils/external/http/axios/axiosTransform'
  4 +import { useGlobSetting } from '@/hooks/external/setting'
  5 +import { RequestEnum, ContentTypeEnum } from '@/enums/external/httpEnum'
  6 +import { isString } from '@/utils/external/is'
  7 +import { getJwtToken, getShareJwtToken } from '@/utils/external/auth'
  8 +import { setObjToUrlParams, deepMerge } from '@/utils/external'
  9 +import { formatRequestDate, joinTimestamp } from '@/utils/external/http/axios/helper'
  10 +import { VAxios } from '@/utils/external/http/axios/Axios'
  11 +import { checkStatus } from './checkStatus'
12 12
13   -const globSetting = useGlobSetting();
14   -const urlPrefix = globSetting.urlPrefix;
  13 +const globSetting = useGlobSetting()
  14 +const urlPrefix = globSetting.urlPrefix
15 15
16 16 /**
17 17 * @description: 数据处理,方便区分多种处理方式
... ... @@ -21,62 +21,59 @@ const transform: AxiosTransform = {
21 21 * @description: 处理请求数据。如果数据不是预期格式,可直接抛出错误
22 22 */
23 23 transformRequestHook: (res: AxiosResponse<Result>, options: RequestOptions) => {
24   - const { isReturnNativeResponse } = options;
  24 + const { isReturnNativeResponse } = options
25 25 // 是否返回原生响应头 比如:需要获取响应头时使用该属性
26 26 if (isReturnNativeResponse) {
27   - return res;
  27 + return res
28 28 }
29   - return res.data;
  29 + return res.data
30 30 },
31 31
32 32 // 请求之前处理config
33 33 beforeRequestHook: (config, options) => {
34   - const { apiUrl, joinPrefix, joinParamsToUrl, formatDate, joinTime = true } = options;
  34 + const { apiUrl, joinPrefix, joinParamsToUrl, formatDate, joinTime = true } = options
35 35
36 36 if (joinPrefix) {
37   - config.url = `${urlPrefix}${config.url}`;
  37 + config.url = `${urlPrefix}${config.url}`
38 38 }
39 39
40 40 if (apiUrl && isString(apiUrl)) {
41   - config.url = `${apiUrl}${config.url}`;
  41 + config.url = `${apiUrl}${config.url}`
42 42 }
43 43
44   - const params = config.params || {};
45   - const data = config.data || false;
46   - formatDate && data && !isString(data) && formatRequestDate(data);
  44 + const params = config.params || {}
  45 + const data = config.data || false
  46 + formatDate && data && !isString(data) && formatRequestDate(data)
47 47 if (config.method?.toUpperCase() === RequestEnum.GET) {
48 48 if (!isString(params)) {
49 49 // 给 get 请求加上时间戳参数,避免从缓存中拿数据。
50   - config.params = Object.assign(params || {}, joinTimestamp(joinTime, false));
  50 + config.params = Object.assign(params || {}, joinTimestamp(joinTime, false))
51 51 } else {
52 52 // 兼容restful风格
53   - config.url = config.url + params + `${joinTimestamp(joinTime, true)}`;
54   - config.params = undefined;
  53 + config.url = config.url + params + `${joinTimestamp(joinTime, true)}`
  54 + config.params = undefined
55 55 }
56 56 } else {
57 57 if (!isString(params)) {
58   - formatDate && formatRequestDate(params);
  58 + formatDate && formatRequestDate(params)
59 59 if (Reflect.has(config, 'data') && config.data && Object.keys(config.data).length > 0) {
60   - config.data = data;
61   - config.params = params;
  60 + config.data = data
  61 + config.params = params
62 62 } else {
63 63 // 非GET请求如果没有提供data,则将params视为data
64   - config.data = params;
65   - config.params = undefined;
  64 + config.data = params
  65 + config.params = undefined
66 66 }
67 67 if (joinParamsToUrl) {
68   - config.url = setObjToUrlParams(
69   - config.url as string,
70   - Object.assign({}, config.params, config.data)
71   - );
  68 + config.url = setObjToUrlParams(config.url as string, Object.assign({}, config.params, config.data))
72 69 }
73 70 } else {
74 71 // 兼容restful风格
75   - config.url = config.url + params;
76   - config.params = undefined;
  72 + config.url = config.url + params
  73 + config.params = undefined
77 74 }
78 75 }
79   - return config;
  76 + return config
80 77 },
81 78
82 79 /**
... ... @@ -84,21 +81,32 @@ const transform: AxiosTransform = {
84 81 */
85 82 requestInterceptors: (config, options) => {
86 83 // 请求之前处理config
87   - const { requestOptions } = config;
88   - const { withShareToken } = requestOptions || {};
89   - const { requestOptions: { withToken } = {} } = options;
  84 + const { requestOptions } = config
  85 + const { withShareToken } = requestOptions || {}
  86 + const { requestOptions: { withToken } = {} } = options
  87 + const { withThirdTokenPrefix, withThirdTokenKey, withThirdTokenString } = config.requestOptions as Recordable
90 88 if (withToken !== false) {
91   - const shareToken = getShareJwtToken();
  89 + const shareToken = getShareJwtToken()
92 90 if (withShareToken && shareToken) {
93 91 config.headers!['X-Authorization'] = options.authenticationScheme
94 92 ? `${options.authenticationScheme} ${shareToken}`
95   - : shareToken;
  93 + : shareToken
96 94 } else {
97   - const token = getJwtToken();
98   - if (token) {
99   - config.headers!['X-Authorization'] = options.authenticationScheme
100   - ? `${options.authenticationScheme} ${token}`
101   - : token;
  95 + const token = getJwtToken()
  96 + if (!withThirdTokenString) {
  97 + // 则是此平台
  98 + if (token) {
  99 + config.headers!['X-Authorization'] = options.authenticationScheme
  100 + ? `${options.authenticationScheme} ${token}`
  101 + : token
  102 + }
  103 + } else {
  104 + // 第三方接口
  105 + const authenticationScheme = withThirdTokenPrefix ? withThirdTokenPrefix : null
  106 + const tokenKey = withThirdTokenKey ? withThirdTokenKey : null
  107 + config.headers![tokenKey!] = withThirdTokenPrefix
  108 + ? `${authenticationScheme} ${withThirdTokenString}`
  109 + : `${withThirdTokenString}`
102 110 }
103 111 }
104 112 }
... ... @@ -109,25 +117,22 @@ const transform: AxiosTransform = {
109 117 * @description: 响应拦截器处理
110 118 */
111 119 responseInterceptors: (res: AxiosResponse<any>) => {
112   - return res;
  120 + return res
113 121 },
114 122
115 123 /**
116 124 * @description: 响应错误处理
117 125 */
118 126 responseInterceptorsCatch: (error: any) => {
  127 + const { response, config } = error || {}
  128 + const errorMessageMode = config?.requestOptions?.errorMessageMode || 'none'
  129 + const errorMsgIsObj = typeof response?.data === 'object'
  130 + const msg: string = errorMsgIsObj ? response?.data?.message || response?.data?.msg : response?.data
119 131
120   - const { response, config } = error || {};
121   - const errorMessageMode = config?.requestOptions?.errorMessageMode || 'none';
122   - const errorMsgIsObj = typeof response?.data === 'object';
123   - const msg: string = errorMsgIsObj
124   - ? response?.data?.message || response?.data?.msg
125   - : response?.data;
126   -
127   - const flag = checkStatus(error?.response?.status, msg, errorMessageMode);
128   - return Promise.reject(response?.data);
129   - },
130   -};
  132 + const flag = checkStatus(error?.response?.status, msg, errorMessageMode)
  133 + return Promise.reject(response?.data)
  134 + }
  135 +}
131 136
132 137 function createAxios(opt?: Partial<CreateAxiosOptions>) {
133 138 return new VAxios(
... ... @@ -169,11 +174,11 @@ function createAxios(opt?: Partial<CreateAxiosOptions>) {
169 174 ignoreCancelToken: true,
170 175 // 是否携带token
171 176 withToken: true
172   - },
  177 + }
173 178 },
174 179 opt || {}
175 180 )
176   - );
  181 + )
177 182 }
178   -export const customHttp = createAxios();
179 183
  184 +export const customHttp = createAxios()
... ...
1   -import { RequestBodyEnum, RequestHttpEnum, RequestParams } from "@/enums/httpEnum"
2   -import { ExtraRequestConfigType } from "@/store/external/modules/extraComponentInfo.d"
3   -import { RequestConfigType } from "@/store/modules/chartEditStore/chartEditStore.d"
4   -import { isShareMode } from "@/views/share/hook"
5   -import { customHttp } from "./http"
6   -import { SelectTimeAggregationFieldEnum } from "@/views/chart/ContentConfigurations/components/ChartData/external/components/SelectTImeAggregation"
  1 +import { RequestBodyEnum, RequestHttpEnum, RequestParams, RequestParamsObjType } from '@/enums/httpEnum'
  2 +import { ExtraRequestConfigType } from '@/store/external/modules/extraComponentInfo.d'
  3 +import { RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
  4 +import { isShareMode } from '@/views/share/hook'
  5 +import { customHttp } from './http'
  6 +import { SelectTimeAggregationFieldEnum } from '@/views/chart/ContentConfigurations/components/ChartData/external/components/SelectTImeAggregation'
7 7
8 8 export enum ParamsType {
9 9 REQUIRED,
... ... @@ -20,7 +20,7 @@ const regDynamicParams = /(?={).+?(?<=})/g
20 20
21 21 /**
22 22 * @description 判断是否是动态参数
23   - * @param url
  23 + * @param url
24 24 */
25 25 export const isDynamicUrl = (url: string) => {
26 26 regDynamicParams.lastIndex = 0
... ... @@ -29,7 +29,7 @@ export const isDynamicUrl = (url: string) => {
29 29
30 30 /**
31 31 * @description 解析动态参数
32   - * @param url
  32 + * @param url
33 33 */
34 34 export const decomposeDynamicParams = (url: string) => {
35 35 regDynamicParams.lastIndex = 0
... ... @@ -46,8 +46,8 @@ export const decomposeDynamicParams = (url: string) => {
46 46
47 47 /**
48 48 * @description 正则替换url中的动态参数
49   - * @param requestUrl
50   - * @param Params
  49 + * @param requestUrl
  50 + * @param Params
51 51 */
52 52 const getDynamicRequestUrl = (requestUrl = '', Params: Recordable) => {
53 53 requestUrl = decodeURI(requestUrl || '')
... ... @@ -101,9 +101,9 @@ const handleParams = (Params: Recordable) => {
101 101 * 源代码 Params.keys = (Params.keys || [] as any).join(',')
102 102 */
103 103 if (!Array.isArray(Params.keys)) {
104   - Params.keys = ([Params.keys] || [] as any).join(',')
  104 + Params.keys = ([Params.keys] || ([] as any)).join(',')
105 105 } else {
106   - Params.keys = (Params.keys || [] as any).join(',')
  106 + Params.keys = (Params.keys || ([] as any)).join(',')
107 107 }
108 108 //ft
109 109 }
... ... @@ -115,27 +115,37 @@ const handleParams = (Params: Recordable) => {
115 115 Reflect.deleteProperty(Params, SelectTimeAggregationFieldEnum.TIME_PERIOD)
116 116 }
117 117
118   - return Object.keys(Params).filter(Boolean).reduce((prev, next) => ({ ...prev, [next]: Params[next] }), {})
  118 + return Object.keys(Params)
  119 + .filter(Boolean)
  120 + .reduce((prev, next) => ({ ...prev, [next]: Params[next] }), {})
119 121 }
120 122
121 123 //post请求动态追加query参数
122 124 const objConvertQuery = (data: Recordable) => {
123   - const _result = [];
  125 + const _result = []
124 126 for (const key in data) {
125   - const value = data[key];
  127 + const value = data[key]
126 128 if (value.constructor == Array) {
127 129 value.forEach(function (_value) {
128   - _result.push(key + "=" + _value);
129   - });
  130 + _result.push(key + '=' + _value)
  131 + })
130 132 } else {
131   - _result.push(key + '=' + value);
  133 + _result.push(key + '=' + value)
132 134 }
133 135 }
134   - return _result.join('&');
  136 + return _result.join('&')
135 137 }
136 138
137 139 export const customRequest = async (request: RequestConfigType) => {
138   - const { requestHttpType, requestParams, requestParamsBodyType, requestOriginUrl } = request as ExtraRequestConfigType
  140 + const {
  141 + requestHttpType,
  142 + requestParams,
  143 + requestParamsBodyType,
  144 + requestOriginUrl,
  145 + requestVerificationToken,
  146 + requestTokenKey,
  147 + requestTokenSuffix
  148 + } = request as ExtraRequestConfigType
139 149 let { requestUrl } = request as ExtraRequestConfigType
140 150 const { Header, Body } = requestParams
141 151 let { Params } = requestParams
... ... @@ -155,18 +165,47 @@ export const customRequest = async (request: RequestConfigType) => {
155 165 * 修改后代码 requestHttpType === RequestHttpEnum.GET.toUpperCase() ? requestUrl: `${requestUrl}?${objConvertQuery(Params)}
156 166 */
157 167 Params = handleParams(Params)
158   -
159   - return customHttp.request<any>({
160   - url: requestHttpType === RequestHttpEnum.GET.toUpperCase() ? requestUrl : `${requestUrl}?${objConvertQuery(Params)}`,
161   - baseURL: getOriginUrl(requestOriginUrl!),
162   - method: requestHttpType,
163   - params: requestHttpType === RequestHttpEnum.GET.toUpperCase() ? Params : null,
164   - data: body,
165   - headers: extraValue(Header)
166   - }, {
167   - joinPrefix: false,
168   - apiUrl: '',
169   - withShareToken: isShareMode()
170   - })
  168 + return customHttp.request<any>(
  169 + {
  170 + url:
  171 + requestHttpType === RequestHttpEnum.GET.toUpperCase() ? requestUrl : `${requestUrl}?${objConvertQuery(Params)}`,
  172 + baseURL: requestVerificationToken ? '' : getOriginUrl(requestOriginUrl!), // 如果是第三方接口,则无需添加baseURL
  173 + method: requestHttpType,
  174 + params: requestHttpType === RequestHttpEnum.GET.toUpperCase() ? Params : null,
  175 + data: body,
  176 + headers: extraValue(Header)
  177 + },
  178 + {
  179 + joinPrefix: false,
  180 + apiUrl: '',
  181 + withShareToken: isShareMode(),
  182 + withThirdTokenString: requestVerificationToken,
  183 + withThirdTokenKey: requestTokenKey,
  184 + withThirdTokenPrefix: requestTokenSuffix
  185 + }
  186 + )
171 187 //ft
172 188 }
  189 +
  190 +export interface thirdInterfaceRequest {
  191 + requestOriginUrl: string
  192 + body: RequestParamsObjType
  193 +}
  194 +
  195 +//特殊处理第三方接口,一般获取token是POST请求,暂定POST
  196 +export const customThirdInterfaceRequest = async (request: thirdInterfaceRequest) => {
  197 + const { body, requestOriginUrl } = request
  198 +
  199 + return customHttp.request<any>(
  200 + {
  201 + url: requestOriginUrl,
  202 + method: RequestHttpEnum.POST,
  203 + data: body
  204 + },
  205 + {
  206 + joinPrefix: false,
  207 + apiUrl: '',
  208 + withToken: false
  209 + }
  210 + )
  211 +}
... ...
  1 +export enum DataTypeEnum {
  2 + DATA_RANGE = 'dataRange',
  3 + DATA_INPUT = 'dataInput'
  4 +}
  5 +
  6 +export enum DataTypeNameEnum {
  7 + DATA_RANGE = '日期区间',
  8 + DATA_INPUT = '文本输入'
  9 +}
... ...
  1 +export enum TokenEnum {
  2 + DEFAULT_TOKEN = 'Token',
  3 + TOKEN_STRING = 'TokenString',
  4 + NO_VERIFICATION = 'NoVerification'
  5 +}
  6 +
  7 +export enum TokenNameEnum {
  8 + DEFAULT_TOKEN = 'Token',
  9 + TOKEN_STRING = '令牌',
  10 + NO_VERIFICATION = '无验证'
  11 +}
... ...
... ... @@ -23,7 +23,7 @@ export enum EditCanvasTypeEnum {
23 23 IS_CREATE = 'isCreate',
24 24 IS_DRAG = 'isDrag',
25 25 IS_SELECT = 'isSelect',
26   - IS_CODE_EDIT = "isCodeEdit"
  26 + IS_CODE_EDIT = 'isCodeEdit'
27 27 }
28 28
29 29 // 编辑区域
... ... @@ -61,10 +61,9 @@ export enum EditCanvasConfigEnum {
61 61 BACKGROUND_IMAGE = 'backgroundImage',
62 62 SELECT_COLOR = 'selectColor',
63 63 PREVIEW_SCALE_TYPE = 'previewScaleType',
64   - ANIMATION_STYLE_CONFIG = 'animationsStyleConfig',
  64 + ANIMATION_STYLE_CONFIG = 'animationsStyleConfig'
65 65 }
66 66
67   -
68 67 export interface EditCanvasConfigType {
69 68 // 滤镜-启用
70 69 [FilterEnum.FILTERS_SHOW]: boolean
... ... @@ -176,8 +175,8 @@ type RequestPublicConfigType = {
176 175
177 176 // 数据池项类型
178 177 export type RequestDataPondItemType = {
179   - dataPondId: string,
180   - dataPondName: string,
  178 + dataPondId: string
  179 + dataPondName: string
181 180 dataPondRequestConfig: RequestConfigType
182 181 }
183 182
... ... @@ -189,6 +188,14 @@ export interface RequestGlobalConfigType extends RequestPublicConfigType {
189 188 requestOriginUrl?: string
190 189 // 公共数据池
191 190 requestDataPond: RequestDataPondItemType[]
  191 + // 验证方式
  192 + requestVerificationMethods?: TokenEnum
  193 + // 全局Token
  194 + requestVerificationToken?: string
  195 + // 请求头里的Token键
  196 + requestTokenKey?: string
  197 + // 请求头里的Token前缀
  198 + requestTokenSuffix?: string,
192 199 }
193 200
194 201 // 单个图表请求配置
... ... @@ -211,6 +218,12 @@ export interface RequestConfigType extends RequestPublicConfigType {
211 218 requestSQLContent: {
212 219 sql: string
213 220 }
  221 + // Token
  222 + requestVerificationToken?: string
  223 + // 请求头里的Token键
  224 + requestTokenKey?: string
  225 + // 请求头里的Token前缀
  226 + requestTokenSuffix?: string
214 227 }
215 228
216 229 // Store 类型
... ...
... ... @@ -135,7 +135,9 @@ function createNewPageItem(id: string = getUUID(), title = '页面'): PageChartE
135 135 },
136 136 Header: {},
137 137 Params: {}
138   - }
  138 + },
  139 + requestVerificationMethods: 'Token',
  140 + requestVerificationToken: '',
139 141 },
140 142 // 图表数组(需存储给后端)
141 143 componentList: []
... ...
... ... @@ -119,7 +119,16 @@ export class VAxios {
119 119 if (userStore) {
120 120 try {
121 121 const { requestOptions = {} } = config
122   - const { withShareToken, withToken } = requestOptions
  122 + const { withShareToken, withToken, withThirdTokenString } = requestOptions
  123 + if (withThirdTokenString) {
  124 + //三方平台逻辑
  125 + const res = jwt_decode(withThirdTokenString) as Recordable;
  126 + const currentTime = (new Date().getTime() + (config.timeout || 0)) / 1000;
  127 + if (currentTime >= res?.exp) {
  128 + window['$message'].warning('第三方平台Token已经失效,请您重新返回设计页面点击执行请求获取最新Token')
  129 + }
  130 + } else {
  131 + //此平台逻辑
123 132 const token = withShareToken && withToken ? userStore.shareJwtToken : userStore.jwtToken
124 133 const doRefresh = withShareToken && withToken ? userStore.doShareRefresh : userStore.doRefresh
125 134 if (token) {
... ... @@ -129,7 +138,8 @@ export class VAxios {
129 138 await this.refreshTokenBeforeReq(doRefresh);
130 139 }
131 140 }
132   -
  141 + //
  142 + }
133 143 } catch (error) {
134 144 userStore.logout();
135 145 }
... ...
... ... @@ -38,3 +38,30 @@ export const parseWebUrl = (str = window.location.search) => {
38 38 str.replace(reg, (_, k, v) => (params[k] = v))
39 39 return params
40 40 }
  41 +
  42 +//嵌套对象转换为级联选择器数据格式
  43 +interface cascadingData {
  44 + label: string
  45 + value: string | cascadingData[] | number
  46 + children: cascadingData[] | null
  47 +}
  48 +export const convertToCascadingData = (obj: Recordable): cascadingData[] => {
  49 + const result: cascadingData[] = []
  50 + for (const key in obj) {
  51 + // eslint-disable-next-line no-prototype-builtins
  52 + if (obj.hasOwnProperty(key)) {
  53 + let value: cascadingData[] | string | number
  54 + if (typeof obj[key] === 'object' && obj[key] !== null) {
  55 + value = convertToCascadingData(obj[key])
  56 + } else {
  57 + value = String(obj[key])
  58 + }
  59 + result.push({
  60 + label: key,
  61 + value,
  62 + children: Array.isArray(value) ? value : null
  63 + })
  64 + }
  65 + }
  66 + return result
  67 +}
... ...
... ... @@ -166,6 +166,20 @@ const closeFilter = () => {
166 166 showModal.value = false
167 167 }
168 168
  169 +// 发送请求
  170 +const sendHandle = async () => {
  171 + try {
  172 + const res = await fetchHandle()
  173 + if (res) {
  174 + const { value } = useFilterFn(targetData.value.filter, res)
  175 + targetData.value.option.dataset = value
  176 + return
  177 + }
  178 + } catch(e) {
  179 + console.error(e)
  180 + }
  181 +}
  182 +
169 183 // 新增过滤器
170 184 const saveFilter = () => {
171 185 if (errorFlag.value) {
... ... @@ -174,6 +188,7 @@ const saveFilter = () => {
174 188 }
175 189 targetData.value.filter = filter.value
176 190 closeFilter()
  191 + sendHandle()
177 192 }
178 193
179 194 watch(
... ...
... ... @@ -14,21 +14,18 @@ import { RequestDataTypeEnum } from '@/enums/external/httpEnum'
14 14
15 15 const { HelpOutlineIcon, FlashIcon } = icon.ionicons5
16 16 const { targetData } = useTargetData()
17   -
18   -
19 17
20 18 const requestModal = ref<InstanceType<typeof RequestModal>>()
21 19
22 20 const designStore = useDesignStore()
23 21
24   -
25 22 /**
26   - * ft 修改在公共接口下拉框里默认选择公共接口
27   - * 修改后的代码在注释之间,并标注好源代码和修改后代码,方便回溯
28   - * 源代码 const selectedRequestType = ref(targetData.value.request.requestDataType || RequestDataTypeEnum.AJAX)
29   - * 修改后的代码 const selectedRequestType = ref(targetData.value.request.requestDataType || RequestDataTypeEnum.Pond)
30   - * 修改后代码在//ft之间
31   - */
  23 + * ft 修改在公共接口下拉框里默认选择公共接口
  24 + * 修改后的代码在注释之间,并标注好源代码和修改后代码,方便回溯
  25 + * 源代码 const selectedRequestType = ref(targetData.value.request.requestDataType || RequestDataTypeEnum.AJAX)
  26 + * 修改后的代码 const selectedRequestType = ref(targetData.value.request.requestDataType || RequestDataTypeEnum.Pond)
  27 + * 修改后代码在//ft之间
  28 + */
32 29 const selectedRequestType = ref(targetData.value.request.requestDataType || RequestDataTypeEnum.Pond)
33 30
34 31 const getApiRequestType: SelectOption[] = [
... ... @@ -43,7 +40,7 @@ const showMatching = ref(false)
43 40 let firstFocus = 0
44 41 let lastFilter: any = undefined
45 42
46   -const { fetchTargetData, } = useFetchTargetData()
  43 +const { fetchTargetData } = useFetchTargetData()
47 44
48 45 // 发送请求
49 46 const sendHandle = async () => {
... ... @@ -63,9 +60,9 @@ const sendHandle = async () => {
63 60 } finally {
64 61 loading.value = false
65 62 }
66   -
67 63 }
68 64
  65 +
69 66 // 颜色
70 67 const themeColor = computed(() => {
71 68 return designStore.getAppTheme
... ... @@ -73,6 +70,9 @@ const themeColor = computed(() => {
73 70
74 71 const handleClickPanel = () => {
75 72 unref(requestModal as any)?.openModal?.(true, unref(selectedRequestType))
  73 + if (selectedRequestType.value === RequestDataTypeEnum.AJAX) {
  74 + targetData.value.request.requestDataType = RequestDataTypeEnum.AJAX
  75 + }
76 76 }
77 77
78 78 // TODO socket 请求时会触发
... ... @@ -81,7 +81,7 @@ watchEffect(() => {
81 81 /**
82 82 * FT 修改
83 83 */
84   - if(!filter) return
  84 + if (!filter) return
85 85 //ft
86 86 if (lastFilter !== filter && firstFocus) {
87 87 lastFilter = filter
... ... @@ -93,8 +93,6 @@ watchEffect(() => {
93 93 onBeforeUnmount(() => {
94 94 lastFilter = null
95 95 })
96   -
97   -
98 96 </script>
99 97
100 98 <template>
... ... @@ -137,8 +135,6 @@ onBeforeUnmount(() => {
137 135 </div>
138 136 </template>
139 137
140   -
141   -
142 138 <style lang="scss" scoped>
143 139 @include thingsKit('chart-configurations-data-ajax') {
144 140 .n-card-shallow {
... ... @@ -174,4 +170,4 @@ onBeforeUnmount(() => {
174 170 }
175 171 }
176 172 }
177   -</style>
  173 +</style>
... ...
1 1 <script setup lang="ts">
2   -import { NInput, NInputNumber, NInputGroup, NButton, NSelect, SelectOption, NTabs, NTabPane, NSpace } from 'naive-ui'
  2 +import { NInput, NInputNumber, NInputGroup, NSelect, SelectOption, NTabs, NTabPane } from 'naive-ui'
3 3 import { SettingItem, SettingItemBox } from '@/components/Pages/ChartItemSetting';
4 4 import { selectTimeOptions, selectTypeOptions } from '../../../index.d';
5 5 import { RequestBodyEnum, RequestContentTypeEnum, RequestDataTypeEnum, RequestHttpEnum, RequestHttpIntervalEnum, RequestParams } from '@/enums/httpEnum';
... ... @@ -7,9 +7,6 @@ import { ref, unref } from 'vue';
7 7 import DefaultRequestContent from './DefaultRequestContent.vue';
8 8 import SqlConfiguration from './SqlConfiguration.vue';
9 9 import { RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d';
10   -import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore';
11   -
12   -const chartEditStore = useChartEditStore()
13 10
14 11 const requestContentTypeRef = ref(RequestContentTypeEnum.DEFAULT)
15 12
... ... @@ -39,7 +36,7 @@ const getConfigurationData = (): RequestConfigType => {
39 36 sql: unref(requestSQLContentRef)
40 37 },
41 38 requestParams: unref(requestParamsRef),
42   - requestUrl: `${chartEditStore.getRequestGlobalConfig.requestOriginUrl}${unref(requestUrlRef)}`
  39 + requestUrl: `${unref(requestUrlRef)}`
43 40 }
44 41 }
45 42
... ... @@ -53,7 +50,7 @@ const setConfigurationData = (request: RequestConfigType) => {
53 50 requestParamsBodyTypeRef.value = requestParamsBodyType
54 51 requestSQLContentRef.value = requestSQLContent.sql
55 52 requestParamsRef.value = requestParams
56   - requestUrlRef.value = !requestUrl ? ``: 'h' + requestUrl?.split('h')[1]
  53 + requestUrlRef.value = requestUrl
57 54 }
58 55
59 56 defineExpose({
... ...
1 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';
  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 7
8 8 const props = defineProps<{
9 9 value: RequestParams
... ... @@ -21,7 +21,6 @@ const handleSyncRequestParamsBodyType = (value: RequestBodyEnum) => {
21 21 const handleUpdate = (key: RequestParamsTypeEnum, value: Recordable) => {
22 22 emit('update:value', { ...props.value, [key]: value })
23 23 }
24   -
25 24 </script>
26 25
27 26 <template>
... ... @@ -30,24 +29,29 @@ const handleUpdate = (key: RequestParamsTypeEnum, value: Recordable) => {
30 29 <NTabPane v-for="item in RequestParamsTypeEnum" :name="item" :key="item"></NTabPane>
31 30 </NTabs>
32 31 <section v-if="tabValue === RequestParamsTypeEnum.PARAMS">
33   - <ParamsTable :value="value[RequestParamsTypeEnum.PARAMS]"
34   - @update:value="(value: Recordable) => handleUpdate(RequestParamsTypeEnum.PARAMS, value)" />
  32 + <ParamsTable
  33 + :value="value[RequestParamsTypeEnum.PARAMS]"
  34 + @update:value="(value: Recordable) => handleUpdate(RequestParamsTypeEnum.PARAMS, value)"
  35 + />
35 36 </section>
36 37
37   - <RequestBody :value="value" @update:value="(value: Recordable) => handleUpdate(RequestParamsTypeEnum.BODY, value)"
38   - @update:requestParamsBodyType="handleSyncRequestParamsBodyType" :requestParamsBodyType="requestParamsBodyType"
39   - v-if="tabValue === RequestParamsTypeEnum.BODY" />
40   -
41   - <ParamsTable v-if="tabValue === RequestParamsTypeEnum.HEADER" :value="value.Header"
42   - @update:value="(value: Recordable) => handleUpdate(RequestParamsTypeEnum.HEADER, value)" />
  38 + <RequestBody
  39 + :value="value"
  40 + @update:value="(value: Recordable) => handleUpdate(RequestParamsTypeEnum.BODY, value)"
  41 + @update:requestParamsBodyType="handleSyncRequestParamsBodyType"
  42 + :requestParamsBodyType="requestParamsBodyType"
  43 + v-if="tabValue === RequestParamsTypeEnum.BODY"
  44 + />
  45 +
  46 + <ParamsTable
  47 + v-if="tabValue === RequestParamsTypeEnum.HEADER"
  48 + :value="value.Header"
  49 + @update:value="(value: Recordable) => handleUpdate(RequestParamsTypeEnum.HEADER, value)"
  50 + />
43 51 </section>
44 52 </template>
45 53
46 54 <style lang="scss" scoped>
47   -.container {
48   - width: 600px;
49   -}
50   -
51 55 .body-container {
52 56 margin-top: 20px;
53 57 }
... ...
1 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';
  2 +import { SettingItem, SettingItemBox } from '@/components/Pages/ChartItemSetting'
  3 +import { icon } from '@/plugins'
  4 +import {
  5 + NButton,
  6 + NCard,
  7 + NCollapseTransition,
  8 + NIcon,
  9 + NInput,
  10 + NInputGroup,
  11 + NInputNumber,
  12 + NSelect,
  13 + NSpace,
  14 + NTag,
  15 + NTooltip,
  16 + SelectOption,
  17 + NCascader
  18 +} from 'naive-ui'
  19 +import { computed, ref, unref, onMounted, reactive } from 'vue'
6 20 import GlobalParamsConfiguration from './GlobalParamsConfiguration.vue'
7 21 import { ChevronDown, ChevronUp } from '@vicons/carbon'
8   -import { useDesignStore } from '@/store/modules/designStore/designStore';
9   -import { selectTimeOptions } from '../../../index.d';
10   -import { useTargetData } from '../../../../hooks/useTargetData.hook';
11   -import { RequestHttpIntervalEnum } from '@/enums/httpEnum';
  22 +import { useDesignStore } from '@/store/modules/designStore/designStore'
  23 +import { selectTimeOptions } from '../../../index.d'
  24 +import { useTargetData } from '../../../../hooks/useTargetData.hook'
  25 +import { RequestDataTypeEnum, RequestHttpIntervalEnum } from '@/enums/httpEnum'
  26 +import { TokenNameEnum, TokenEnum } from '@/enums/external/tokenEnum'
  27 +import { customThirdInterfaceRequest, thirdInterfaceRequest } from '@/api/external/customRequest'
  28 +import { CascaderOption } from 'naive-ui'
  29 +import { convertToCascadingData } from '@/utils/external/utils'
12 30
13 31 const { PencilIcon } = icon.ionicons5
14 32 const designStore = useDesignStore()
15 33 const editDisabled = ref(false)
16 34 const collapseHeaderTable = ref(false)
17 35
18   -const { chartEditStore } = useTargetData()
  36 +const { targetData, chartEditStore } = useTargetData()
19 37
20 38 const handleCollapse = () => {
21 39 collapseHeaderTable.value = !unref(collapseHeaderTable)
22 40 }
23 41
24   -
25 42 // 颜色
26 43 const themeColor = computed(() => {
27 44 return designStore.getAppTheme
28 45 })
29 46
  47 +//第三方接口相关代码
  48 +const verifiationValue = ref(TokenEnum.DEFAULT_TOKEN)
  49 +
  50 +const tokenString = ref('')
  51 +
  52 +const getTokenString = ref()
  53 +
  54 +const resOptions = ref<CascaderOption[]>([])
  55 +
  56 +const resValue = ref()
  57 +
  58 +const cascaderConfig = reactive({
  59 + hoverTrigger: true,
  60 + checkStrategyIsChild: true,
  61 + filterable: false,
  62 + showPath: true
  63 +})
  64 +
  65 +const requestTokenSuffix = ref('Bearer')
  66 +
  67 +const requestTokenKey = ref('Token')
  68 +
  69 +//验证方式
  70 +const verificationMethods = [
  71 + {
  72 + label: TokenNameEnum.DEFAULT_TOKEN,
  73 + value: TokenEnum.DEFAULT_TOKEN
  74 + },
  75 + {
  76 + label: TokenNameEnum.TOKEN_STRING,
  77 + value: TokenEnum.TOKEN_STRING
  78 + },
  79 + {
  80 + label: TokenNameEnum.NO_VERIFICATION,
  81 + value: TokenEnum.NO_VERIFICATION
  82 + }
  83 +]
  84 +
  85 +const hasDefaultToken = (value: string[]) => value.includes(TokenEnum.DEFAULT_TOKEN)
  86 +
  87 +const hasTokenString = (value: string[]) => value.includes(TokenEnum.TOKEN_STRING)
30 88
  89 +const handleVerificationUpdate = (value: string) => {
  90 + chartEditStore.getRequestGlobalConfig.requestVerificationMethods = value
  91 + hasTokenString([value])
  92 + hasDefaultToken([value])
  93 + resValue.value = null
  94 + resOptions.value = []
  95 + getTokenString.value = ''
  96 + requestTokenKey.value = ''
  97 + requestTokenSuffix.value = ''
  98 +}
  99 +
  100 +const handleResCascader = (value: string | number) => {
  101 + getTokenString.value = value as string | number
  102 + chartEditStore.getRequestGlobalConfig.requestVerificationToken = value as string
  103 + targetData.value.request.requestVerificationToken = value as string
  104 + targetData.value.request.requestDataType = RequestDataTypeEnum.AJAX
  105 +}
31 106
  107 +//执行请求获取三方Token
  108 +const handleExecuteRequest = async () => {
  109 + try {
  110 + const request = {
  111 + requestOriginUrl: chartEditStore.getRequestGlobalConfig.requestOriginUrl,
  112 + body: chartEditStore.getRequestGlobalConfig.requestParams.Header
  113 + }
  114 + const res = await customThirdInterfaceRequest(request as thirdInterfaceRequest)
  115 + resOptions.value = convertToCascadingData(res) as unknown as CascaderOption[]
  116 + chartEditStore.getRequestGlobalConfig.requestVerificationMethods = verifiationValue.value
  117 + chartEditStore.getRequestGlobalConfig.requestVerificationToken = resValue.value as string
  118 + chartEditStore.getRequestGlobalConfig.requestTokenKey = requestTokenKey.value
  119 + chartEditStore.getRequestGlobalConfig.requestTokenSuffix = requestTokenSuffix.value
  120 + //存储到当前组件的请求对象里
  121 + targetData.value.request.requestTokenSuffix = requestTokenSuffix.value
  122 + targetData.value.request.requestTokenKey = requestTokenKey.value
  123 + } catch (e) {
  124 + getTokenString.value = JSON.stringify(e) as string
  125 + }
  126 +}
  127 +
  128 +onMounted(() => {
  129 + getTokenString.value = chartEditStore.getRequestGlobalConfig.requestVerificationToken
  130 + verifiationValue.value = chartEditStore.getRequestGlobalConfig.requestVerificationMethods || TokenEnum.DEFAULT_TOKEN
  131 + requestTokenKey.value = chartEditStore.getRequestGlobalConfig.requestTokenKey!
  132 + requestTokenSuffix.value = chartEditStore.getRequestGlobalConfig.requestTokenSuffix!
  133 +})
  134 +//
32 135 </script>
33 136
34 137 <template>
... ... @@ -37,23 +140,43 @@ const themeColor = computed(() => {
37 140 <NTag type="info">全局公共配置</NTag>
38 141 </template>
39 142 <NSpace vertical>
40   - <SettingItemBox name="服务" :itemRightStyle="{
41   - gridTemplateColumns: '5fr 2fr 1fr'
42   - }">
  143 + <SettingItemBox
  144 + name="服务"
  145 + :itemRightStyle="{
  146 + gridTemplateColumns: '5fr 2fr 1fr'
  147 + }"
  148 + >
43 149 <!-- 源地址 -->
44 150 <SettingItem name="前置 URL">
45   - <NInput v-model:value="chartEditStore.getRequestGlobalConfig.requestOriginUrl" default-value="http://127.0.0.1" :disabled="editDisabled"
46   - size="small" placeholder="例:http://127.0.0.1"></NInput>
  151 + <NInput
  152 + v-model:value="chartEditStore.getRequestGlobalConfig.requestOriginUrl"
  153 + default-value="http://127.0.0.1"
  154 + :disabled="editDisabled"
  155 + size="small"
  156 + placeholder="例:http://127.0.0.1"
  157 + ></NInput>
47 158 </SettingItem>
48 159 <SettingItem name="更新间隔,为 0 只会初始化">
49 160 <NInputGroup>
50   - <NInputNumber v-model:value="chartEditStore.getRequestGlobalConfig.requestInterval" class="select-time-number"
51   - size="small" min="0" :show-button="false" :disabled="editDisabled" placeholder="请输入数字">
  161 + <NInputNumber
  162 + v-model:value="chartEditStore.getRequestGlobalConfig.requestInterval"
  163 + class="select-time-number"
  164 + size="small"
  165 + min="0"
  166 + :show-button="false"
  167 + :disabled="editDisabled"
  168 + placeholder="请输入数字"
  169 + >
52 170 </NInputNumber>
53 171 <!-- 单位 -->
54   - <NSelect v-model:value="chartEditStore.getRequestGlobalConfig.requestIntervalUnit" class="select-time-options"
55   - size="small" :default-value="RequestHttpIntervalEnum.SECOND" :options="selectTimeOptions as SelectOption[]"
56   - :disabled="editDisabled" />
  172 + <NSelect
  173 + v-model:value="chartEditStore.getRequestGlobalConfig.requestIntervalUnit"
  174 + class="select-time-options"
  175 + size="small"
  176 + :default-value="RequestHttpIntervalEnum.SECOND"
  177 + :options="selectTimeOptions as SelectOption[]"
  178 + :disabled="editDisabled"
  179 + />
57 180 </NInputGroup>
58 181 </SettingItem>
59 182 <NButton v-show="editDisabled" type="primary" ghost @click="editDisabled = false">
... ... @@ -65,8 +188,67 @@ const themeColor = computed(() => {
65 188 编辑配置
66 189 </NButton>
67 190 </SettingItemBox>
  191 + <!-- 针对第三方接口 -->
  192 + <SettingItemBox
  193 + name="验证方式"
  194 + :itemRightStyle="{
  195 + gridTemplateColumns: '5fr 2fr 1fr'
  196 + }"
  197 + >
  198 + <n-radio-group v-model:value="verifiationValue" name="radiogroup" @update:value="handleVerificationUpdate">
  199 + <n-space>
  200 + <n-radio
  201 + v-for="verificationItem in verificationMethods"
  202 + :key="verificationItem.value"
  203 + :value="verificationItem.value"
  204 + >
  205 + {{ verificationItem.label }}
  206 + </n-radio>
  207 + </n-space>
  208 + </n-radio-group>
  209 + </SettingItemBox>
  210 + <SettingItemBox v-if="hasDefaultToken([verifiationValue])" name="配置">
  211 + <SettingItem name="Token前缀">
  212 + <n-input v-model:value.trim="requestTokenSuffix" type="text" placeholder="例如:Bearer" />
  213 + </SettingItem>
  214 + <SettingItem name="Token键">
  215 + <n-input v-model:value.trim="requestTokenKey" type="text" placeholder="例如:X-Authorization" />
  216 + </SettingItem>
  217 + </SettingItemBox>
68 218 <NCollapseTransition :show="collapseHeaderTable">
69   - <GlobalParamsConfiguration />
  219 + <GlobalParamsConfiguration v-if="hasDefaultToken([verifiationValue])" />
  220 + <n-input
  221 + v-else-if="hasTokenString([verifiationValue])"
  222 + v-model:value="tokenString"
  223 + type="text"
  224 + placeholder="请输入令牌字符串"
  225 + />
  226 + <n-empty v-else description="无"> </n-empty>
  227 + <div style="margin-top: 10px">
  228 + <n-space vertical>
  229 + <n-button type="primary" @click="handleExecuteRequest">执行请求</n-button>
  230 + <NCascader
  231 + v-model:value="resValue"
  232 + @update:value="handleResCascader"
  233 + :expand-trigger="cascaderConfig.hoverTrigger ? 'hover' : 'click'"
  234 + :check-strategy="cascaderConfig.checkStrategyIsChild ? 'child' : 'all'"
  235 + :show-path="cascaderConfig.showPath"
  236 + :filterable="cascaderConfig.filterable"
  237 + placeholder="请选择"
  238 + :options="resOptions"
  239 + />
  240 + <n-input
  241 + :autosize="{
  242 + minRows: 3,
  243 + maxRows: 9
  244 + }"
  245 + v-model:value="getTokenString"
  246 + type="textarea"
  247 + placeholder="Token:"
  248 + />
  249 + </n-space>
  250 + </div>
  251 + <!-- 针对第三方接口 -->
70 252 </NCollapseTransition>
71 253 <section class="arrow">
72 254 <NTooltip>
... ... @@ -83,7 +265,6 @@ const themeColor = computed(() => {
83 265 </NCard>
84 266 </template>
85 267
86   -
87 268 <style lang="scss" scoped>
88 269 .arrow {
89 270 display: flex;
... ... @@ -93,7 +274,6 @@ const themeColor = computed(() => {
93 274
94 275 &:hover {
95 276 color: v-bind('themeColor');
96   -
97 277 }
98 278 }
99 279 </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';
  1 +<script setup lang="ts">
  2 +import { getUUID } from '@/utils'
  3 +import {
  4 + ButtonProps,
  5 + DataTableColumns,
  6 + InputProps,
  7 + NButton,
  8 + NDataTable,
  9 + NIcon,
  10 + NInput,
  11 + NSpace,
  12 + NTooltip,
  13 + NSelect,
  14 + SelectProps,
  15 + NDatePicker,
  16 + DatePickerProps
  17 +} from 'naive-ui'
  18 +import { computed, h, ref, unref, watch } from 'vue'
5 19 import { Subtract, Add } from '@vicons/carbon'
6   -import { isObject } from '@/utils/external/is';
  20 +import { isArray, isObject } from '@/utils/external/is'
  21 +import { DataTypeEnum, DataTypeNameEnum } from '@/enums/external/dataTypeEnum'
  22 +import { Recordable } from 'vite-plugin-mock'
7 23
8 24 interface DataSource {
9 25 id: string
10 26 value?: string
11 27 keyName?: string
  28 + indexName?: number
  29 + typeName?: string
  30 + dateRange?: number[] | null
12 31 result?: boolean
13 32 }
14 33
... ... @@ -17,99 +36,126 @@ const columns: DataTableColumns<DataSource> = [
17 36 title: '序号',
18 37 key: 'index',
19 38 render: (_, index) => index + 1,
20   - width: 50,
  39 + width: 50
  40 + },
  41 + {
  42 + title: 'Type',
  43 + key: 'typeName',
  44 + render: (row, index) => {
  45 + return h(NSelect, {
  46 + value: row.typeName,
  47 + options: [
  48 + {
  49 + label: DataTypeNameEnum.DATA_RANGE,
  50 + value: DataTypeEnum.DATA_RANGE
  51 + },
  52 + {
  53 + label: DataTypeNameEnum.DATA_INPUT,
  54 + value: DataTypeEnum.DATA_INPUT
  55 + }
  56 + ],
  57 + onUpdateValue: (value: string) => {
  58 + unref(dataSource)[index].typeName = value
  59 + unref(dataSource)[index].indexName = index
  60 + },
  61 + size: 'small',
  62 + disabled: props.disabled
  63 + } as SelectProps)
  64 + },
  65 + width: 120
21 66 },
22 67 {
23 68 title: 'Key',
24 69 key: 'keyName',
25 70 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   - }
  71 + return h(NInput, {
  72 + value: row.keyName,
  73 + onBlur: () => handleInputBlur(),
  74 + onUpdateValue: (value: string) => (unref(dataSource)[index].keyName = value),
  75 + size: 'small',
  76 + disabled: props.disabled
  77 + } as InputProps)
  78 + },
  79 + width: 120
37 80 },
38 81 {
39 82 title: 'Value',
40 83 key: 'value',
41 84 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   - }
  85 + const findIndexName = unref(dataSource).find(item => item.indexName === index)
  86 + return findIndexName?.indexName === index && findIndexName.typeName === DataTypeEnum.DATA_INPUT
  87 + ? h(NInput, {
  88 + value: row.value,
  89 + onBlur: () => handleInputBlur(),
  90 + onUpdateValue: (value: string) => (unref(dataSource)[index].value = value),
  91 + size: 'small',
  92 + disabled: props.disabled
  93 + } as InputProps)
  94 + : ''
  95 + },
  96 + width: 120
53 97 },
54 98 {
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   - )
  99 + title: 'Date',
  100 + key: 'dateRange',
  101 + render: (row, index) => {
  102 + const findIndexName = unref(dataSource).find(item => item.indexName === index)
  103 + return findIndexName?.indexName === index && findIndexName.typeName === DataTypeEnum.DATA_RANGE
  104 + ? h(NDatePicker, {
  105 + value: row.value,
  106 + size: 'small',
  107 + type: 'datetimerange',
  108 + onBlur: () => handleInputBlur(),
  109 + onUpdateValue: (value: number[]) => {
  110 + unref(dataSource)[index].dateRange = value
  111 + },
  112 + disabled: props.disabled
  113 + } as DatePickerProps)
  114 + : ''
103 115 },
104   - width: 100,
  116 + width: 200
105 117 },
106 118 {
107   - title: '结果',
108   - key: 'result',
109   - render: (row) => {
110   - return h(NTag, { type: row.result ? 'success' : 'error' } as TagProps, () => `${row.result ? '' : '未'}通过`)
  119 + title: '操作',
  120 + key: 'actions',
  121 + render: row => {
  122 + return h(NSpace, () => [
  123 + h(NTooltip, null, {
  124 + trigger: () =>
  125 + h(
  126 + NButton,
  127 + {
  128 + type: 'success',
  129 + size: 'small',
  130 + ghost: true,
  131 + onClick: () => handleAddRow(row),
  132 + disabled: props.disabled || !unref(canAddRow)
  133 + } as ButtonProps,
  134 + {
  135 + default: () => h(NIcon, () => h(Add))
  136 + }
  137 + ),
  138 + default: () => '插入行'
  139 + }),
  140 + h(NTooltip, null, {
  141 + trigger: () =>
  142 + h(
  143 + NButton,
  144 + {
  145 + type: 'warning',
  146 + size: 'small',
  147 + ghost: true,
  148 + onClick: () => handleSubtractRow(row)
  149 + } as ButtonProps,
  150 + {
  151 + default: () => h(NIcon, () => h(Subtract))
  152 + }
  153 + ),
  154 + default: () => '删除行'
  155 + })
  156 + ])
111 157 },
112   - width: 80
  158 + width: 120
113 159 }
114 160 ]
115 161
... ... @@ -121,29 +167,33 @@ const props = withDefaults(
121 167 }>(),
122 168 {
123 169 disabled: false,
124   - maxRow: 50,
  170 + maxRow: 50
125 171 }
126 172 )
127 173
128   -
129 174 const emit = defineEmits(['update:value'])
130 175
131 176 const createNewRow = () => {
132 177 return { id: getUUID(), result: true } as DataSource
133 178 }
134 179
135   -const dataSource = ref<DataSource[]>([
136   - createNewRow()
137   -])
  180 +const dataSource = ref<DataSource[]>([createNewRow()])
  181 +
  182 +const blurFlag = ref(false)
138 183
139 184 watch(
140 185 () => props.value,
141   - (target) => {
  186 + (target: Recordable) => {
142 187 if (target && isObject(target) && Object.keys(target).length) {
143   - dataSource.value = Object.keys(props.value || {}).map(keyName => ({ ...createNewRow(), keyName, value: Reflect.get(props.value || {}, keyName) }))
144   - } else {
145   - dataSource.value = [createNewRow()]
146   - }
  188 + if (blurFlag.value) return
  189 + dataSource.value = Object.keys(props.value || {}).map((keyName, keyIndex) => ({
  190 + ...createNewRow(),
  191 + keyName,
  192 + indexName: keyIndex,
  193 + typeName: isArray(props.value![keyName]) ? DataTypeEnum.DATA_RANGE : DataTypeEnum.DATA_INPUT,
  194 + value: Reflect.get(props.value || {}, keyName)
  195 + }))
  196 + }
147 197 },
148 198 {
149 199 immediate: true,
... ... @@ -151,10 +201,6 @@ watch(
151 201 }
152 202 )
153 203
154   -const canDeleteRow = computed(() => {
155   - return unref(dataSource).length >= 2
156   -})
157   -
158 204 const canAddRow = computed(() => {
159 205 return unref(dataSource).length < props.maxRow
160 206 })
... ... @@ -174,23 +220,19 @@ const handleSubtractRow = (record: DataSource) => {
174 220 }
175 221 }
176 222
177   -
178   -const handleInputBlur = (record: DataSource) => {
179   - const { keyName, value } = record
180   - record.result = !!(keyName && value)
181   - if (unref(dataSource).every(item => item.result)) {
182   - emit('update:value', getHeaderConfiguration())
183   - }
  223 +const handleInputBlur = () => {
  224 + blurFlag.value = true
  225 + emit('update:value', getHeaderConfiguration())
184 226 }
185 227
186 228 const getHeaderConfiguration = () => {
187 229 return unref(dataSource).reduce((prev, next) => {
188   - const { result, value, keyName } = next
189   - const header = result && value && keyName ? { [keyName]: value } : {}
  230 + const { value, keyName, dateRange } = next
  231 + const header = keyName ? { [keyName as unknown as string]: dateRange && isArray(dateRange) ? dateRange: value } : {}
  232 + for (let item in header) if (!Reflect.get(header, item)) Reflect.deleteProperty(header, item)
190 233 return { ...prev, ...header }
191 234 }, {} as Recordable)
192 235 }
193   -
194 236 </script>
195 237
196 238 <template>
... ...
1 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 { 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   -import { useTargetData } from '../../../../hooks/useTargetData.hook';
15   -import { useFetchTargetData } from '@/hooks/external/useFetchTargetData';
16   -import { useFilterFn } from '@/hooks/external/useFilterFn';
17   -
  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 { 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 +import { useTargetData } from '../../../../hooks/useTargetData.hook'
  15 +import { useFetchTargetData } from '@/hooks/external/useFetchTargetData'
  16 +import { useFilterFn } from '@/hooks/external/useFilterFn'
18 17
19 18 const requestDataType = ref<RequestDataTypeEnum>(RequestDataTypeEnum.AJAX)
20 19
... ... @@ -84,12 +83,22 @@ const sendHandle = async () => {
84 83 targetData.value.option.dataset = value
85 84 return
86 85 }
  86 +}
87 87
  88 +const setRequestKey = (value: Recordable, key: string) => {
  89 + value[key] =
  90 + targetData.value.request.requestDataType === RequestDataTypeEnum.AJAX
  91 + ? (targetData.value.request as unknown as Recordable)[key] ||
  92 + (chartEditStore.getRequestGlobalConfig as unknown as Recordable)[key]
  93 + : null
88 94 }
89 95
90 96 const handleSaveAction = async () => {
91 97 if (!(await validate())) return
92 98 const value = getResult()
  99 + setRequestKey(value, 'requestTokenSuffix')
  100 + setRequestKey(value, 'requestTokenKey')
  101 + setRequestKey(value, 'requestVerificationToken')
93 102 if (unref(selectTarget)) {
94 103 chartEditStore.updateComponentList(chartEditStore.fetchTargetIndex(), {
95 104 ...unref(selectTarget)!,
... ... @@ -105,26 +114,29 @@ createRequestModalContext({
105 114 })
106 115
107 116 defineExpose({
108   - openModal,
  117 + openModal
109 118 })
110   -
111 119 </script>
112 120
113 121 <template>
114   - <NModal :class="prefixCls" v-model:show="showModal" preset="card" style="width: 1000px;" title="请求配置">
  122 + <NModal :class="prefixCls" v-model:show="showModal" preset="card" style="width: 1000px" title="请求配置">
115 123 <GlobalPublicConfiguration v-if="requestDataType === RequestDataTypeEnum.AJAX" />
116 124 <NDivider v-if="requestDataType === RequestDataTypeEnum.AJAX" />
117 125 <ComponentConfiguration v-if="requestDataType === RequestDataTypeEnum.AJAX" ref="componentConfigurationEl" />
118 126 <PublicInterfaceForm v-if="requestDataType === RequestDataTypeEnum.Pond" ref="publicInterfaceFormEl" />
119 127 <template #action>
120   - <NSpace justify="space-between">
121   - <div style="display: flex;flex-direction: column;">
122   - <NTag type="info">当公共接口选择“实时轨迹或者获取设备经纬度历史数据”时,属性选择则选择经纬度即可(longitude,latitude)</NTag>
123   - <div style="height:5px"></div>
124   - <NTag type="info">如果是结构体属性的话,选择对应结构体属性即可,里面的经纬度,平台已经通过接口里面的过滤函数进行处理</NTag>
125   - <div style="display: flex; align-items: center; margin-top:10px">
  128 + <NSpace justify="space-between">
  129 + <div style="display: flex; flex-direction: column">
  130 + <NTag type="info"
  131 + >当公共接口选择“实时轨迹或者获取设备经纬度历史数据”时,属性选择则选择经纬度即可(longitude,latitude)</NTag
  132 + >
  133 + <div style="height: 5px"></div>
  134 + <NTag type="info"
  135 + >如果是结构体属性的话,选择对应结构体属性即可,里面的经纬度,平台已经通过接口里面的过滤函数进行处理</NTag
  136 + >
  137 + <div style="display: flex; align-items: center; margin-top: 10px">
126 138 <span>「 更多 」</span>
127   - <span style="margin-right: 5px;">——</span>
  139 + <span style="margin-right: 5px">——</span>
128 140 <NTag type="info">{{ getRequestTypeName }}</NTag>
129 141 </div>
130 142 </div>
... ... @@ -134,10 +146,8 @@ defineExpose({
134 146 </NModal>
135 147 </template>
136 148
137   -
138   -<style lang="scss" >
  149 +<style lang="scss">
139 150 @include thingsKit('chart-data-request') {
140   -
141 151 &.n-card.n-modal,
142 152 .n-card {
143 153 @extend .go-background-filter;
... ... @@ -148,7 +158,7 @@ defineExpose({
148 158 }
149 159
150 160 @include deep() {
151   - &>.n-card__content {
  161 + & > .n-card__content {
152 162 padding-right: 0;
153 163 }
154 164
... ...
... ... @@ -23,6 +23,9 @@ export interface RequestOptions {
23 23 withToken?: boolean;
24 24 // Carry and share token 携带分享的访问令牌
25 25 withShareToken?: boolean
  26 + withThirdTokenString?: string;
  27 + withThirdTokenKey?: string;
  28 + withThirdTokenPrefix?: string;
26 29 }
27 30
28 31 export interface Result<T = any> {
... ...