Merge branch 'master-fetch-dev' into master-fetch

This commit is contained in:
奔跑的面条 2022-12-16 13:55:55 +08:00
commit cb750c73b9
59 changed files with 1434 additions and 5529 deletions

View File

@ -7,7 +7,7 @@ export const prefix = `monaco-editor/esm/vs`
// chunk 警告大小 // chunk 警告大小
export const chunkSizeWarningLimit = 2000 export const chunkSizeWarningLimit = 2000
// 禁用 brotli 压缩大小报告A // 禁用 brotliSize 压缩大小报告
export const brotliSize = false export const brotliSize = false
// 分包 // 分包

6
pnpm-lock.yaml generated
View File

@ -3074,7 +3074,7 @@ packages:
source-map: 0.6.1 source-map: 0.6.1
wordwrap: 1.0.0 wordwrap: 1.0.0
optionalDependencies: optionalDependencies:
uglify-js: 3.16.0 uglify-js: 3.17.4
dev: true dev: true
/hard-rejection/2.1.0: /hard-rejection/2.1.0:
@ -5014,8 +5014,8 @@ packages:
hasBin: true hasBin: true
dev: true dev: true
/uglify-js/3.16.0: /uglify-js/3.17.4:
resolution: {integrity: sha512-FEikl6bR30n0T3amyBh3LoiBdqHRy/f4H80+My34HOesOKyHfOsxAPAxOoqC0JUnC1amnO0IwkYC3sko51caSw==} resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==}
engines: {node: '>=0.8.0'} engines: {node: '>=0.8.0'}
hasBin: true hasBin: true
requiresBuild: true requiresBuild: true

View File

@ -1,4 +1,4 @@
import axios, { AxiosResponse, AxiosRequestConfig } from 'axios' import axios, { AxiosResponse, AxiosRequestConfig, Axios } from 'axios'
import { ResultEnum, ModuleTypeEnum } from "@/enums/httpEnum" import { ResultEnum, ModuleTypeEnum } from "@/enums/httpEnum"
import { PageEnum, ErrorPageNameMap } from "@/enums/pageEnum" import { PageEnum, ErrorPageNameMap } from "@/enums/pageEnum"
import { StorageEnum } from '@/enums/storageEnum' import { StorageEnum } from '@/enums/storageEnum'
@ -8,10 +8,20 @@ import { redirectErrorPage, getLocalStorage, routerTurnByName, isPreview } from
import { fetchAllowList } from './axios.config' import { fetchAllowList } from './axios.config'
import includes from 'lodash/includes' import includes from 'lodash/includes'
export interface MyResponseType<T> {
code: ResultEnum
data: T
message: string
}
export interface MyRequestInstance extends Axios {
<T = any>(config: AxiosRequestConfig): Promise<MyResponseType<T>>
}
const axiosInstance = axios.create({ const axiosInstance = axios.create({
baseURL: `${import.meta.env.PROD ? import.meta.env.VITE_PRO_PATH : ''}${axiosPre}`, baseURL: `${import.meta.env.PROD ? import.meta.env.VITE_PRO_PATH : ''}${axiosPre}`,
timeout: ResultEnum.TIMEOUT, timeout: ResultEnum.TIMEOUT,
}) }) as unknown as MyRequestInstance
axiosInstance.interceptors.request.use( axiosInstance.interceptors.request.use(
(config: AxiosRequestConfig) => { (config: AxiosRequestConfig) => {

View File

@ -9,16 +9,16 @@ import {
} from '@/enums/httpEnum' } from '@/enums/httpEnum'
import type { RequestGlobalConfigType, RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d' import type { RequestGlobalConfigType, RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
export const get = (url: string, params?: object) => { export const get = <T = any>(url: string, params?: object) => {
return axiosInstance({ return axiosInstance<T>({
url: url, url: url,
method: RequestHttpEnum.GET, method: RequestHttpEnum.GET,
params: params, params: params,
}) })
} }
export const post = (url: string, data?: object, headersType?: string) => { export const post = <T = any>(url: string, data?: object, headersType?: string) => {
return axiosInstance({ return axiosInstance<T>({
url: url, url: url,
method: RequestHttpEnum.POST, method: RequestHttpEnum.POST,
data: data, data: data,
@ -28,8 +28,8 @@ export const post = (url: string, data?: object, headersType?: string) => {
}) })
} }
export const patch = (url: string, data?: object, headersType?: string) => { export const patch = <T = any>(url: string, data?: object, headersType?: string) => {
return axiosInstance({ return axiosInstance<T>({
url: url, url: url,
method: RequestHttpEnum.PATCH, method: RequestHttpEnum.PATCH,
data: data, data: data,
@ -39,8 +39,8 @@ export const patch = (url: string, data?: object, headersType?: string) => {
}) })
} }
export const put = (url: string, data?: object, headersType?: ContentTypeEnum) => { export const put = <T = any>(url: string, data?: object, headersType?: ContentTypeEnum) => {
return axiosInstance({ return axiosInstance<T>({
url: url, url: url,
method: RequestHttpEnum.PUT, method: RequestHttpEnum.PUT,
data: data, data: data,
@ -50,8 +50,8 @@ export const put = (url: string, data?: object, headersType?: ContentTypeEnum) =
}) })
} }
export const del = (url: string, params?: object) => { export const del = <T = any>(url: string, params?: object) => {
return axiosInstance({ return axiosInstance<T>({
url: url, url: url,
method: RequestHttpEnum.DELETE, method: RequestHttpEnum.DELETE,
params params
@ -82,11 +82,11 @@ export const http = (type?: RequestHttpEnum) => {
} }
const prefix = 'javascript:' const prefix = 'javascript:'
// 对输入字符进行转义处理 // 对输入字符进行转义处理
export const translateStr = (target: string | object) => { export const translateStr = (target: string | Record<any, any>) => {
if (typeof target === 'string') { if (typeof target === 'string') {
if (target.startsWith(prefix)) { if (target.startsWith(prefix)) {
const funcStr = target.split(prefix)[1] const funcStr = target.split(prefix)[1]
let result; let result
try { try {
result = new Function(`${funcStr}`)() result = new Function(`${funcStr}`)()
} catch (error) { } catch (error) {
@ -100,8 +100,8 @@ export const translateStr = (target: string | object) => {
} }
for (const key in target) { for (const key in target) {
if (Object.prototype.hasOwnProperty.call(target, key)) { if (Object.prototype.hasOwnProperty.call(target, key)) {
const subTarget = (target as any)[key]; const subTarget = target[key]
(target as any)[key] = translateStr(subTarget) target[key] = translateStr(subTarget)
} }
} }
return target return target
@ -116,7 +116,6 @@ export const customizeHttp = (targetParams: RequestConfigType, globalParams: Req
if (!targetParams || !globalParams) { if (!targetParams || !globalParams) {
return return
} }
// 全局 // 全局
const { const {
// 全局请求源地址 // 全局请求源地址

View File

@ -1,84 +1,98 @@
import { http } from '@/api/http' import { http } from '@/api/http'
import { httpErrorHandle } from '@/utils' import { httpErrorHandle } from '@/utils'
import { ContentTypeEnum, RequestHttpEnum, ModuleTypeEnum } from '@/enums/httpEnum' import { ContentTypeEnum, RequestHttpEnum, ModuleTypeEnum } from '@/enums/httpEnum'
import { ProjectItem, ProjectDetail } from './project'
// * 项目列表 // * 项目列表
export const projectListApi = async (data: object) => { export const projectListApi = async (data: object) => {
try { try {
const res = await http(RequestHttpEnum.GET)(`${ModuleTypeEnum.PROJECT}/list`, data); const res = await http(RequestHttpEnum.GET)<ProjectItem[]>(`${ModuleTypeEnum.PROJECT}/list`, data)
return res; return res
} catch { } catch {
httpErrorHandle(); httpErrorHandle()
} }
} }
// * 新增项目 // * 新增项目
export const createProjectApi = async (data: object) => { export const createProjectApi = async (data: object) => {
try { try {
const res = await http(RequestHttpEnum.POST)(`${ModuleTypeEnum.PROJECT}/create`, data); const res = await http(RequestHttpEnum.POST)<{
return res; /**
* id
*/
id: number
}>(`${ModuleTypeEnum.PROJECT}/create`, data)
return res
} catch { } catch {
httpErrorHandle(); httpErrorHandle()
} }
} }
// * 获取项目 // * 获取项目
export const fetchProjectApi = async (data: object) => { export const fetchProjectApi = async (data: object) => {
try { try {
const res = await http(RequestHttpEnum.GET)(`${ModuleTypeEnum.PROJECT}/getData`, data); const res = await http(RequestHttpEnum.GET)<ProjectDetail>(`${ModuleTypeEnum.PROJECT}/getData`, data)
return res; return res
} catch { } catch {
httpErrorHandle(); httpErrorHandle()
} }
} }
// * 保存项目 // * 保存项目
export const saveProjectApi = async (data: object) => { export const saveProjectApi = async (data: object) => {
try { try {
const res = await http(RequestHttpEnum.POST)(`${ModuleTypeEnum.PROJECT}/save/data`, data, ContentTypeEnum.FORM_URLENCODED); const res = await http(RequestHttpEnum.POST)(
return res; `${ModuleTypeEnum.PROJECT}/save/data`,
data,
ContentTypeEnum.FORM_URLENCODED
)
return res
} catch { } catch {
httpErrorHandle(); httpErrorHandle()
} }
} }
// * 修改项目基础信息 // * 修改项目基础信息
export const updateProjectApi = async (data: object) => { export const updateProjectApi = async (data: object) => {
try { try {
const res = await http(RequestHttpEnum.POST)(`${ModuleTypeEnum.PROJECT}/edit`, data); const res = await http(RequestHttpEnum.POST)(`${ModuleTypeEnum.PROJECT}/edit`, data)
return res; return res
} catch { } catch {
httpErrorHandle(); httpErrorHandle()
} }
} }
// * 删除项目 // * 删除项目
export const deleteProjectApi = async (data: object) => { export const deleteProjectApi = async (data: object) => {
try { try {
const res = await http(RequestHttpEnum.DELETE)(`${ModuleTypeEnum.PROJECT}/delete`, data); const res = await http(RequestHttpEnum.DELETE)(`${ModuleTypeEnum.PROJECT}/delete`, data)
return res; return res
} catch { } catch {
httpErrorHandle(); httpErrorHandle()
} }
} }
// * 修改发布状态 [-1未发布,1发布] // * 修改发布状态 [-1未发布,1发布]
export const changeProjectReleaseApi = async (data: object) => { export const changeProjectReleaseApi = async (data: object) => {
try { try {
const res = await http(RequestHttpEnum.PUT)(`${ModuleTypeEnum.PROJECT}/publish`, data); const res = await http(RequestHttpEnum.PUT)(`${ModuleTypeEnum.PROJECT}/publish`, data)
return res; return res
} catch { } catch {
httpErrorHandle(); httpErrorHandle()
} }
} }
// * 上传文件 // * 上传文件
export const uploadFile = async (data: object) => { export const uploadFile = async (data: object) => {
try { try {
const res = await http(RequestHttpEnum.POST)(`${ModuleTypeEnum.PROJECT}/upload`, data, ContentTypeEnum.FORM_DATA); const res = await http(RequestHttpEnum.POST)<{
return res; /**
*
*/
fileName: string
}>(`${ModuleTypeEnum.PROJECT}/upload`, data, ContentTypeEnum.FORM_DATA)
return res
} catch { } catch {
httpErrorHandle(); httpErrorHandle()
} }
} }

39
src/api/path/project.d.ts vendored Normal file
View File

@ -0,0 +1,39 @@
export type ProjectItem = {
/**
* id
*/
id: string
/**
*
*/
projectName: string
/**
* :\
* -1: 未发布\
* 1: 已发布
*/
state: number
/**
*
*/
createTime: string
/**
* url
*/
indexImage: string
/**
* id
*/
createUserId: string
/**
*
*/
remarks: string
}
export interface ProjectDetail extends ProjectItem {
/**
*
*/
content: string
}

View File

@ -1,33 +1,39 @@
import { http } from '@/api/http' import { http } from '@/api/http'
import { httpErrorHandle } from '@/utils' import { httpErrorHandle } from '@/utils'
import { RequestHttpEnum, ModuleTypeEnum } from '@/enums/httpEnum' import { RequestHttpEnum, ModuleTypeEnum } from '@/enums/httpEnum'
import { LoginResult } from './system'
// * 登录 // * 登录
export const loginApi = async (data: object) => { export const loginApi = async (data: object) => {
try { try {
const res = await http(RequestHttpEnum.POST)(`${ModuleTypeEnum.SYSTEM}/login`, data); const res = await http(RequestHttpEnum.POST)<LoginResult>(`${ModuleTypeEnum.SYSTEM}/login`, data)
return res; return res
} catch(err) { } catch (err) {
httpErrorHandle(); httpErrorHandle()
} }
} }
// * 登出 // * 登出
export const logoutApi = async () => { export const logoutApi = async () => {
try { try {
const res = await http(RequestHttpEnum.GET)(`${ModuleTypeEnum.SYSTEM}/logout`); const res = await http(RequestHttpEnum.GET)(`${ModuleTypeEnum.SYSTEM}/logout`)
return res; return res
} catch(err) { } catch (err) {
httpErrorHandle(); httpErrorHandle()
} }
} }
// * 获取 oss 上传接口 // * 获取 oss 上传接口
export const ossUrlApi = async (data: object) => { export const ossUrlApi = async (data: object) => {
try { try {
const res = await http(RequestHttpEnum.GET)(`${ModuleTypeEnum.SYSTEM}/getOssInfo`, data); const res = await http(RequestHttpEnum.GET)<{
return res; /**
} catch(err) { * bucket
httpErrorHandle(); */
bucketURL?: string
}>(`${ModuleTypeEnum.SYSTEM}/getOssInfo`, data)
return res
} catch (err) {
httpErrorHandle()
} }
} }

26
src/api/path/system.d.ts vendored Normal file
View File

@ -0,0 +1,26 @@
export interface LoginResult {
token: {
/**
* token
*/
tokenValue: string
/**
* token key
*/
tokenName: string
}
userinfo: {
/**
*
*/
nickname: string
/**
*
*/
username: string
/**
* id
*/
id: string
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

View File

@ -42,15 +42,21 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, watch } from 'vue'
import { icon } from '@/plugins' import { icon } from '@/plugins'
const { HelpOutlineIcon, CloseIcon } = icon.ionicons5 const props = defineProps({
const emit = defineEmits(['update:modelShow'])
defineProps({
modelShow: Boolean modelShow: Boolean
}) })
const emit = defineEmits(['update:modelShow'])
const { HelpOutlineIcon, CloseIcon } = icon.ionicons5
const modelShow = ref(false)
watch(() => props.modelShow, (newValue) => {
modelShow.value = newValue
})
const closeHandle = () => { const closeHandle = () => {
emit('update:modelShow', false) emit('update:modelShow', false)
} }

View File

@ -69,21 +69,20 @@
</template> </template>
<script script lang="ts" setup> <script script lang="ts" setup>
import { reactive } from 'vue' import { reactive, ref, watch } from 'vue'
import { ListType } from './index.d' import { ListType } from './index.d'
import { useSettingStore } from '@/store/modules/settingStore/settingStore' import { useSettingStore } from '@/store/modules/settingStore/settingStore'
import { SettingStoreEnums, ToolsStatusEnum } from '@/store/modules/settingStore/settingStore.d' import { SettingStoreEnums, ToolsStatusEnum } from '@/store/modules/settingStore/settingStore.d'
import { icon } from '@/plugins' import { icon } from '@/plugins'
const { HelpOutlineIcon, CloseIcon } = icon.ionicons5 const props = defineProps({
const emit = defineEmits(['update:modelShow'])
defineProps({
modelShow: Boolean modelShow: Boolean
}) })
const emit = defineEmits(['update:modelShow'])
const { HelpOutlineIcon, CloseIcon } = icon.ionicons5
const settingStore = useSettingStore() const settingStore = useSettingStore()
const modelShow = ref(false)
const list = reactive<ListType[]>([ const list = reactive<ListType[]>([
{ {
@ -168,6 +167,10 @@ const list = reactive<ListType[]>([
} }
]) ])
watch(() => props.modelShow, (newValue) => {
modelShow.value = newValue
})
const closeHandle = () => { const closeHandle = () => {
emit('update:modelShow', false) emit('update:modelShow', false)
} }

View File

@ -99,6 +99,7 @@ const colorSelectHandle = (color: AppThemeColorType) => {
overflow: hidden; overflow: hidden;
border-radius: 5px; border-radius: 5px;
@extend .go-background-filter-shallow; @extend .go-background-filter-shallow;
backdrop-filter: none;
} }
&-color { &-color {
width: 8px; width: 8px;

View File

@ -20,7 +20,9 @@ export enum RequestDataTypeEnum {
// 静态数据 // 静态数据
STATIC = 0, STATIC = 0,
// 请求数据 // 请求数据
AJAX = 1 AJAX = 1,
// 数据池
Pond = 2
} }
// 请求主体类型 // 请求主体类型

View File

@ -26,11 +26,10 @@ export const useChartDataFetch = (
// 数据池 // 数据池
const { addGlobalDataInterface } = useChartDataPondFetch() const { addGlobalDataInterface } = useChartDataPondFetch()
const { requestDataPondId } = toRefs(targetComponent.request)
// 组件类型 // 组件类型
const { chartFrame } = targetComponent.chartConfig const { chartFrame } = targetComponent.chartConfig
// eCharts 组件配合 vChart 库更新方式 // eCharts 组件配合 vChart 库更新方式
const echartsUpdateHandle = (dataset: any) => { const echartsUpdateHandle = (dataset: any) => {
if (chartFrame === ChartFrameEnum.ECHARTS) { if (chartFrame === ChartFrameEnum.ECHARTS) {
@ -89,7 +88,6 @@ export const useChartDataFetch = (
// 立即调用 // 立即调用
fetchFn() fetchFn()
// 定时时间 // 定时时间
const time = targetInterval && targetInterval.value ? targetInterval.value : globalRequestInterval.value const time = targetInterval && targetInterval.value ? targetInterval.value : globalRequestInterval.value
// 单位 // 单位
@ -104,8 +102,8 @@ export const useChartDataFetch = (
} }
if (isPreview()) { if (isPreview()) {
// 判断是否有数据池对应 id // 判断是否是数据池类型
requestDataPondId targetComponent.request.requestDataType === RequestDataTypeEnum.Pond
? addGlobalDataInterface(targetComponent, useChartEditStore, updateCallback || echartsUpdateHandle) ? addGlobalDataInterface(targetComponent, useChartEditStore, updateCallback || echartsUpdateHandle)
: requestIntervalFn() : requestIntervalFn()
} }

View File

@ -3,7 +3,7 @@ import { customizeHttp } from '@/api/http'
import { CreateComponentType } from '@/packages/index.d' import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { RequestGlobalConfigType, RequestDataPondItemType } from '@/store/modules/chartEditStore/chartEditStore.d' import { RequestGlobalConfigType, RequestDataPondItemType } from '@/store/modules/chartEditStore/chartEditStore.d'
import { newFunctionHandle } from '@/utils' import { newFunctionHandle, intervalUnitHandle } from '@/utils'
// 获取类型 // 获取类型
type ChartEditStoreType = typeof useChartEditStore type ChartEditStoreType = typeof useChartEditStore
@ -24,6 +24,9 @@ const newPondItemInterval = (
dataPondMapItem?: DataPondMapType[] dataPondMapItem?: DataPondMapType[]
) => { ) => {
if (!dataPondMapItem) return if (!dataPondMapItem) return
let fetchInterval: any = 0
clearInterval(fetchInterval)
// 请求 // 请求
const fetchFn = async () => { const fetchFn = async () => {
@ -48,6 +51,19 @@ const newPondItemInterval = (
// 立即调用 // 立即调用
fetchFn() fetchFn()
const targetInterval = requestDataPondItem.dataPondRequestConfig.requestInterval
const targetUnit = requestDataPondItem.dataPondRequestConfig.requestIntervalUnit
const globalRequestInterval = requestGlobalConfig.requestInterval
const globalUnit = requestGlobalConfig.requestIntervalUnit
// 定时时间
const time = targetInterval ? targetInterval : globalRequestInterval
// 单位
const unit = targetInterval ? targetUnit : globalUnit
// 开启轮询
if (time) fetchInterval = setInterval(fetchFn, intervalUnitHandle(time, unit))
} }
/** /**
@ -64,7 +80,7 @@ export const useChartDataPondFetch = () => {
const { requestDataPond } = chartEditStore.getRequestGlobalConfig const { requestDataPond } = chartEditStore.getRequestGlobalConfig
// 组件对应的数据池 Id // 组件对应的数据池 Id
const requestDataPondId = '111' || (targetComponent.request.requestDataPondId as string) const requestDataPondId = targetComponent.request.requestDataPondId as string
// 新增数据项 // 新增数据项
const mittPondIdArr = mittDataPondMap.get(requestDataPondId) || [] const mittPondIdArr = mittDataPondMap.get(requestDataPondId) || []
mittPondIdArr.push({ mittPondIdArr.push({
@ -74,6 +90,11 @@ export const useChartDataPondFetch = () => {
mittDataPondMap.set(requestDataPondId, mittPondIdArr) mittDataPondMap.set(requestDataPondId, mittPondIdArr)
} }
// 清除旧数据
const clearMittDataPondMap = () => {
mittDataPondMap.clear()
}
// 初始化数据池 // 初始化数据池
const initDataPond = (requestGlobalConfig: RequestGlobalConfigType) => { const initDataPond = (requestGlobalConfig: RequestGlobalConfigType) => {
const { requestDataPond } = requestGlobalConfig const { requestDataPond } = requestGlobalConfig
@ -88,6 +109,7 @@ export const useChartDataPondFetch = () => {
return { return {
addGlobalDataInterface, addGlobalDataInterface,
clearMittDataPondMap,
initDataPond initDataPond
} }
} }

View File

@ -10,8 +10,8 @@ export const useSystemInit = async () => {
// 获取 OSS 信息的 url 地址,用来拼接展示图片的地址 // 获取 OSS 信息的 url 地址,用来拼接展示图片的地址
const getOssUrl = async () => { const getOssUrl = async () => {
const res = await ossUrlApi({}) as unknown as MyResponseType const res = await ossUrlApi({})
if (res.code === ResultEnum.SUCCESS) { if (res && res.code === ResultEnum.SUCCESS) {
systemStore.setItem(SystemStoreEnum.FETCH_INFO, { systemStore.setItem(SystemStoreEnum.FETCH_INFO, {
OSSUrl: res.data?.bucketURL OSSUrl: res.data?.bucketURL
}) })

View File

@ -1,2 +1,3 @@
export * from './axis' export * from './axis'
export * from './line' export * from './line'
export * from './label'

View File

@ -0,0 +1,7 @@
export const labelConfig = {
position: [
{ label: '外侧', value: 'outside' },
{ label: '内部', value: 'inside' },
{ label: '中心', value: 'center' }
]
}

View File

@ -14,41 +14,37 @@
<n-text>展示标签</n-text> <n-text>展示标签</n-text>
</n-space> </n-space>
</SettingItem> </SettingItem>
<SettingItem name="位置">
<n-select v-model:value="optionData.series[0].label.position" :options="[
{ label: '外侧', value: 'outside' },
{ label: '内部', value: 'inside' },
{ label: '中心', value: 'center' }
]" />
</SettingItem>
</SettingItemBox>
<setting-item-box name="标签数据">
<setting-item>
<n-select v-model:value="optionData.series[0].label.formatter" :options="[
{ label: '数据名', value: '{b}' },
{ label: '百分比', value: '{d}' },
{ label: '列名:百分比', value: '{b}:{d}%' },
]" />
</setting-item>
</setting-item-box>
<setting-item-box name="引导线">
<setting-item> <setting-item>
<n-space> <n-space>
<n-switch v-model:value="optionData.series[0].labelLine.show" size="small"></n-switch> <n-switch v-model:value="optionData.series[0].labelLine.show" size="small"></n-switch>
<n-text>展示引导线</n-text> <n-text>引导线</n-text>
</n-space> </n-space>
</setting-item> </setting-item>
</setting-item-box> <SettingItem name="位置">
<n-select v-model:value="optionData.series[0].label.position" size="small" :options="labelConfig.position" />
</SettingItem>
<setting-item name="展示类型">
<n-select v-model:value="optionData.series[0].label.formatter" size="small" :options="labelFormatterOptions" />
</setting-item>
</SettingItemBox>
<setting-item-box name="圆角"> <setting-item-box name="圆角">
<setting-item> <setting-item>
<n-space> <n-space>
<n-input-number v-model:value="optionData.series[0].itemStyle.borderRadius" size="small" :min="0"></n-input-number> <n-input-number
v-model:value="optionData.series[0].itemStyle.borderRadius"
size="small"
:min="0"
></n-input-number>
<n-text>圆角大小</n-text> <n-text>圆角大小</n-text>
</n-space> </n-space>
</setting-item> </setting-item>
<setting-item> <setting-item>
<n-space> <n-space>
<n-input-number v-model:value="optionData.series[0].itemStyle.borderWidth" size="small" :min="0"></n-input-number> <n-input-number
v-model:value="optionData.series[0].itemStyle.borderWidth"
size="small"
:min="0"
></n-input-number>
<n-text>线条宽度</n-text> <n-text>线条宽度</n-text>
</n-space> </n-space>
</setting-item> </setting-item>
@ -61,6 +57,7 @@ import { PropType, watch } from 'vue'
import { GlobalThemeJsonType } from '@/settings/chartThemes/index' import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
import { GlobalSetting, CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting' import { GlobalSetting, CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { PieTypeObject, PieTypeEnum } from './config' import { PieTypeObject, PieTypeEnum } from './config'
import { labelConfig } from '@/packages/chartConfiguration/echarts'
const props = defineProps({ const props = defineProps({
optionData: { optionData: {
@ -82,4 +79,10 @@ const fontWeightOptions = [
value: PieTypeObject[PieTypeEnum.ROSE] value: PieTypeObject[PieTypeEnum.ROSE]
} }
] ]
const labelFormatterOptions = [
{ label: '数据名', value: '{b}' },
{ label: '百分比', value: '{d}' },
{ label: '列名:百分比', value: '{b}:{d}%' }
]
</script> </script>

View File

@ -6,7 +6,7 @@ export const FlipperNumberConfig: ConfigType = {
key: 'FlipperNumber', key: 'FlipperNumber',
chartKey: 'VFlipperNumber', chartKey: 'VFlipperNumber',
conKey: 'VCFlipperNumber', conKey: 'VCFlipperNumber',
title: '数字翻牌', title: '数字翻牌-需动态触发',
category: ChatCategoryEnum.MORE, category: ChatCategoryEnum.MORE,
categoryName: ChatCategoryEnumName.MORE, categoryName: ChatCategoryEnumName.MORE,
package: PackagesCategoryEnum.DECORATES, package: PackagesCategoryEnum.DECORATES,

View File

@ -20,7 +20,7 @@ import { chartInitConfig } from '@/settings/designSetting'
import cloneDeep from 'lodash/cloneDeep' import cloneDeep from 'lodash/cloneDeep'
// 请求基础属性 // 请求基础属性
const requestConfig: RequestConfigType = { export const requestConfig: RequestConfigType = {
requestDataType: RequestDataTypeEnum.STATIC, requestDataType: RequestDataTypeEnum.STATIC,
requestHttpType: RequestHttpEnum.GET, requestHttpType: RequestHttpEnum.GET,
requestUrl: '', requestUrl: '',

View File

@ -7,6 +7,7 @@ import {
NH2, NH2,
NH3, NH3,
NH4, NH4,
NH5,
NCode, NCode,
NCountdown, NCountdown,
NText, NText,
@ -109,6 +110,7 @@ const naive = create({
NH2, NH2,
NH3, NH3,
NH4, NH4,
NH5,
NCode, NCode,
NCountdown, NCountdown,
NText, NText,

View File

@ -106,8 +106,8 @@ export const reloadRoutePage = () => {
*/ */
export const logout = async () => { export const logout = async () => {
try { try {
const res = await logoutApi() as unknown as MyResponseType const res = await logoutApi()
if(res.code === ResultEnum.SUCCESS) { if(res && res.code === ResultEnum.SUCCESS) {
window['$message'].success(window['$t']('global.logout_success')) window['$message'].success(window['$t']('global.logout_success'))
clearCookie(RequestHttpHeaderEnum.COOKIE) clearCookie(RequestHttpHeaderEnum.COOKIE)
clearLocalStorage(StorageEnum.GO_SYSTEM_STORE) clearLocalStorage(StorageEnum.GO_SYSTEM_STORE)

View File

@ -1,35 +1,41 @@
<template> <template>
<div class="go-content-charts-item-box" :class="{ double: chartMode === ChartModeEnum.DOUBLE }"> <div class="go-content-charts-item-animation-patch">
<!-- 每一项组件的渲染 -->
<div <div
class="item-box" ref="contentChartsItemBoxRef"
v-for="(item, index) in menuOptions" class="go-content-charts-item-box"
:key="index" :class="[chartMode === ChartModeEnum.DOUBLE ? 'double' : 'single']"
draggable
@dragstart="dragStartHandle($event, item)"
@dragend="dragendHandle"
@dblclick="dblclickHandle(item)"
> >
<div class="list-header"> <!-- 每一项组件的渲染 -->
<mac-os-control-btn class="list-header-control-btn" :mini="true" :disabled="true"></mac-os-control-btn> <div
<n-text class="list-header-text" depth="3"> class="item-box"
<n-ellipsis>{{ item.title }}</n-ellipsis> v-for="(item, index) in menuOptions"
</n-text> :key="index"
</div> draggable
<div class="list-center go-flex-center"> @dragstart="dragStartHandle($event, item)"
<img class="list-img" v-lazy="item.image" alt="图表图片" /> @dragend="dragendHandle"
</div> @dblclick="dblclickHandle(item)"
<div class="list-bottom"> >
<n-text class="list-bottom-text" depth="3"> <div class="list-header">
<n-ellipsis style="max-width: 90%">{{ item.title }}</n-ellipsis> <mac-os-control-btn class="list-header-control-btn" :mini="true" :disabled="true"></mac-os-control-btn>
</n-text> <n-text class="list-header-text" depth="3">
<n-ellipsis>{{ item.title }}</n-ellipsis>
</n-text>
</div>
<div class="list-center go-flex-center go-transition">
<img class="list-img" v-lazy="item.image" alt="图表图片" />
</div>
<div class="list-bottom">
<n-text class="list-bottom-text" depth="3">
<n-ellipsis style="max-width: 90%">{{ item.title }}</n-ellipsis>
</n-text>
</div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { PropType, ref, Ref, computed } from 'vue' import { PropType, watch, ref, Ref, computed, nextTick } from 'vue'
import { MacOsControlBtn } from '@/components/Tips/MacOsControlBtn/index' import { MacOsControlBtn } from '@/components/Tips/MacOsControlBtn/index'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d' import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
@ -51,6 +57,7 @@ defineProps({
}) })
const chartLayoutStore = useChartLayoutStore() const chartLayoutStore = useChartLayoutStore()
const contentChartsItemBoxRef = ref()
// //
const chartMode: Ref<ChartModeEnum> = computed(() => { const chartMode: Ref<ChartModeEnum> = computed(() => {
@ -92,21 +99,38 @@ const dblclickHandle = async (item: ConfigType) => {
window['$message'].warning(`图表正在研发中, 敬请期待...`) window['$message'].warning(`图表正在研发中, 敬请期待...`)
} }
} }
watch(
() => chartMode.value,
(newValue: ChartModeEnum) => {
if (newValue === ChartModeEnum.DOUBLE) {
nextTick(() => {
contentChartsItemBoxRef.value.classList.add('miniAnimation')
})
}
}
)
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
/* 列表项宽度 */ /* 列表项宽度 */
$itemWidth: 100%; $itemWidth: 100%;
$maxItemWidth: 180px;
$halfItemWidth: 46%; $halfItemWidth: 46%;
/* 内容高度 */ /* 内容高度 */
$centerHeight: 100px; $centerHeight: 100px;
$halfCenterHeight: 50px; $halfCenterHeight: 50px;
@include go('content-charts-item-animation-patch') {
padding: 10px;
}
@include go('content-charts-item-box') { @include go('content-charts-item-box') {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: space-between; justify-content: space-between;
gap: 9px; gap: 9px;
padding: 10px; transition: all 0.7s linear;
.item-box { .item-box {
margin: 0; margin: 0;
width: $itemWidth; width: $itemWidth;
@ -115,7 +139,6 @@ $halfCenterHeight: 50px;
cursor: pointer; cursor: pointer;
border: 1px solid rgba(0, 0, 0, 0); border: 1px solid rgba(0, 0, 0, 0);
@include fetch-bg-color('background-color2'); @include fetch-bg-color('background-color2');
@extend .go-transition;
&:hover { &:hover {
@include hover-border-color('background-color4'); @include hover-border-color('background-color4');
.list-img { .list-img {
@ -152,7 +175,11 @@ $halfCenterHeight: 50px;
} }
} }
} }
/* 缩小展示 */ &.single {
.item-box {
@extend .go-transition;
}
}
&.double { &.double {
.list-header { .list-header {
padding: 2px 5px; padding: 2px 5px;
@ -165,6 +192,7 @@ $halfCenterHeight: 50px;
} }
.item-box { .item-box {
width: $halfItemWidth; width: $halfItemWidth;
max-width: $maxItemWidth;
} }
.list-center { .list-center {
height: $halfCenterHeight; height: $halfCenterHeight;
@ -172,11 +200,24 @@ $halfCenterHeight: 50px;
.list-img { .list-img {
height: $halfCenterHeight; height: $halfCenterHeight;
width: auto; width: auto;
transition: all 0.2s;
} }
} }
.list-bottom { .list-bottom {
display: block; display: block;
} }
} }
/* 缩小展示 */
@keyframes miniAnimation {
from {
width: $itemWidth * 2;
}
to {
width: $itemWidth;
}
}
&.miniAnimation {
animation: miniAnimation 0.5s;
}
} }
</style> </style>

View File

@ -282,9 +282,9 @@ const customRequest = (options: UploadCustomRequestOptions) => {
) )
let uploadParams = new FormData() let uploadParams = new FormData()
uploadParams.append('object', newNameFile) uploadParams.append('object', newNameFile)
const uploadRes = await uploadFile(uploadParams) as unknown as MyResponseType const uploadRes = await uploadFile(uploadParams)
if(uploadRes.code === ResultEnum.SUCCESS) { if(uploadRes && uploadRes.code === ResultEnum.SUCCESS) {
chartEditStore.setEditCanvasConfig( chartEditStore.setEditCanvasConfig(
EditCanvasConfigEnum.BACKGROUND_IMAGE, EditCanvasConfigEnum.BACKGROUND_IMAGE,
`${systemStore.getFetchInfo.OSSUrl}${uploadRes.data.fileName}?time=${new Date().getTime()}` `${systemStore.getFetchInfo.OSSUrl}${uploadRes.data.fileName}?time=${new Date().getTime()}`

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="go-chart-configurations-animations" v-if="targetData"> <div class="go-chart-configurations-animations" v-if="targetData">
<n-button <n-button
class="clear-btn" class="clear-btn go-my-2"
:disabled="!targetData.styles.animations.length" :disabled="!targetData.styles.animations.length"
@click="clearAnimation" @click="clearAnimation"
> >
@ -72,7 +72,7 @@ const addAnimation = (item: { label: string; value: string }) => {
<style lang="scss" scoped> <style lang="scss" scoped>
@include go('chart-configurations-animations') { @include go('chart-configurations-animations') {
padding: 20px 10px; padding: 0;
.clear-btn { .clear-btn {
width: 100%; width: 100%;
} }

View File

@ -12,7 +12,7 @@
<n-input size="small" :placeholder="targetData.request.requestHttpType || '暂无'" :disabled="true"></n-input> <n-input size="small" :placeholder="targetData.request.requestHttpType || '暂无'" :disabled="true"></n-input>
</setting-item> </setting-item>
<setting-item name="组件间隔(高级)"> <setting-item name="组件间隔">
<n-input size="small" :placeholder="`${targetData.request.requestInterval || '暂无'}`" :disabled="true"> <n-input size="small" :placeholder="`${targetData.request.requestInterval || '暂无'}`" :disabled="true">
<template #suffix> {{ SelectHttpTimeNameObj[targetData.request.requestIntervalUnit] }} </template> <template #suffix> {{ SelectHttpTimeNameObj[targetData.request.requestIntervalUnit] }} </template>
</n-input> </n-input>
@ -41,13 +41,9 @@
</n-input> </n-input>
</setting-item-box> </setting-item-box>
<n-space justify="end">
<n-text depth="3" style="font-size: 12px">更新内容请点击展示区域</n-text>
</n-space>
<div class="edit-text" @click="requestModelHandle"> <div class="edit-text" @click="requestModelHandle">
<div class="go-absolute-center"> <div class="go-absolute-center">
<n-button type="primary" secondary>查看更多</n-button> <n-button type="primary" secondary>编辑配置</n-button>
</div> </div>
</div> </div>
</n-card> </n-card>
@ -76,10 +72,16 @@
<!-- 底部数据展示 --> <!-- 底部数据展示 -->
<chart-data-matching-and-show :show="showMatching && !loading" :ajax="true"></chart-data-matching-and-show> <chart-data-matching-and-show :show="showMatching && !loading" :ajax="true"></chart-data-matching-and-show>
<!-- 骨架图 --> <!-- 骨架图 -->
<go-skeleton :load="loading" :repeat="3"></go-skeleton> <go-skeleton :load="loading" :repeat="3"></go-skeleton>
<!-- 请求配置model --> <!-- 请求配置model -->
<chart-data-request v-model:modelShow="requestShow" @sendHandle="sendHandle"></chart-data-request> <chart-data-request
v-model:modelShow="requestShow"
:targetData="targetData"
@sendHandle="sendHandle"
></chart-data-request>
</div> </div>
</template> </template>
@ -95,7 +97,7 @@ import { http, customizeHttp } from '@/api/http'
import { SelectHttpType } from '../../index.d' import { SelectHttpType } from '../../index.d'
import { ChartDataMatchingAndShow } from '../ChartDataMatchingAndShow' import { ChartDataMatchingAndShow } from '../ChartDataMatchingAndShow'
import { useTargetData } from '../../../hooks/useTargetData.hook' import { useTargetData } from '../../../hooks/useTargetData.hook'
import { isDev, newFunctionHandle } from '@/utils' import { newFunctionHandle } from '@/utils'
const { HelpOutlineIcon, FlashIcon, PulseIcon } = icon.ionicons5 const { HelpOutlineIcon, FlashIcon, PulseIcon } = icon.ionicons5
const { targetData, chartEditStore } = useTargetData() const { targetData, chartEditStore } = useTargetData()
@ -128,7 +130,7 @@ const sendHandle = async () => {
const res = await customizeHttp(toRaw(targetData.value.request), toRaw(chartEditStore.getRequestGlobalConfig)) const res = await customizeHttp(toRaw(targetData.value.request), toRaw(chartEditStore.getRequestGlobalConfig))
loading.value = false loading.value = false
if (res) { if (res) {
if(!res?.data && !targetData.value.filter) window['$message'].warning('您的数据不符合默认格式,请配置过滤器!') if (!res?.data && !targetData.value.filter) window['$message'].warning('您的数据不符合默认格式,请配置过滤器!')
targetData.value.option.dataset = newFunctionHandle(res?.data, res, targetData.value.filter) targetData.value.option.dataset = newFunctionHandle(res?.data, res, targetData.value.filter)
showMatching.value = true showMatching.value = true
return return
@ -175,7 +177,7 @@ onBeforeUnmount(() => {
top: 0px; top: 0px;
left: 0px; left: 0px;
width: 325px; width: 325px;
height: 292px; height: 270px;
cursor: pointer; cursor: pointer;
opacity: 0; opacity: 0;
transition: all 0.3s; transition: all 0.3s;

View File

@ -117,7 +117,7 @@ const { uploadFileListRef, customRequest, beforeUpload, download } = useFile(tar
// //
const filterShow = computed(() => { const filterShow = computed(() => {
return targetData.value.request.requestDataType === RequestDataTypeEnum.AJAX return targetData.value.request.requestDataType !== RequestDataTypeEnum.STATIC
}) })
// dataset // dataset

View File

@ -34,7 +34,7 @@
</template> </template>
<!-- 弹窗 --> <!-- 弹窗 -->
<n-modal class="go-chart-data-monaco-editor" v-model:show="showModal" :mask-closable="false"> <n-modal class="go-chart-data-monaco-editor" v-model:show="showModal" :mask-closable="false" :closeOnEsc="false">
<n-card :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 1000px; height: 600px"> <n-card :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 1000px; height: 600px">
<template #header> <template #header>
<n-space> <n-space>
@ -101,7 +101,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, computed, watch, toRefs, toRaw } from 'vue' import { ref, computed, watch, toRef, toRefs, toRaw, reactive } from 'vue'
import { useTargetData } from '../../../hooks/useTargetData.hook' import { useTargetData } from '../../../hooks/useTargetData.hook'
import { MonacoEditor } from '@/components/Pages/MonacoEditor' import { MonacoEditor } from '@/components/Pages/MonacoEditor'
import { icon } from '@/plugins' import { icon } from '@/plugins'
@ -187,7 +187,10 @@ const saveFilter = () => {
watch( watch(
() => showModal.value, () => showModal.value,
(newData: boolean) => { (newData: boolean) => {
if (newData) fetchTargetData() if (newData) {
fetchTargetData()
filter.value = targetData.value.filter || `return data`
}
} }
) )
</script> </script>

View File

@ -0,0 +1,64 @@
<template>
<n-table
:bordered="false"
:single-line="false"
size="small"
style="border-bottom-right-radius: 7px; border-bottom-left-radius: 7px"
>
<thead>
<tr>
<th>key</th>
<th>value</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in tableArray.content" :key="index">
<td>
{{ item.key || '暂无'}}
</td>
<td>
{{ item.value || '暂无'}}
</td>
</tr>
</tbody>
</n-table>
</template>
<script setup lang="ts">
import { PropType, reactive, ref, toRefs, watch } from 'vue'
import { RequestParamsObjType } from '@/enums/httpEnum'
import noData from '@/assets/images/canvas/noData.png'
const props = defineProps({
target: Object as PropType<RequestParamsObjType>
})
//
const defaultItem = {
key: '',
value: ''
}
const tableArray = reactive<{
content: typeof defaultItem[]
}>({ content: [] })
//
watch(
() => props.target as RequestParamsObjType,
(target: RequestParamsObjType) => {
tableArray.content = []
for (const k in target) {
tableArray.content.push({
key: k,
value: target[k]
})
}
//
if (!tableArray.content.length) tableArray.content = [JSON.parse(JSON.stringify(defaultItem))]
},
{
immediate: true,
deep: true
}
)
</script>

View File

@ -0,0 +1,3 @@
import ChartDataDisplay from './index.vue'
export { ChartDataDisplay }

View File

@ -0,0 +1,191 @@
<template>
<div class="go-chart-data-display">
<n-scrollbar style="max-height: 570px">
<div class="go-mr-3">
<div>
<setting-item-box name="主体信息">
<setting-item name="接口名称">
<n-input size="small" :placeholder="targetData?.dataPondName || '暂无'" :disabled="true"> </n-input>
</setting-item>
<setting-item name="接口类型">
<n-input size="small" :placeholder="requestHttpType || '暂无'" :disabled="true"></n-input>
</setting-item>
</setting-item-box>
<setting-item-box>
<setting-item name="组件间隔">
<n-input size="small" :placeholder="`${requestInterval || '暂无'}`" :disabled="true">
<template #suffix>
{{ targetData && SelectHttpTimeNameObj[requestIntervalUnit] }}
</template>
</n-input>
</setting-item>
<setting-item name="全局间隔(默认)">
<n-input size="small" :placeholder="`${globalData?.requestInterval || '暂无'}`" :disabled="true">
<template #suffix> {{ globalData && SelectHttpTimeNameObj[globalData.requestIntervalUnit] }} </template>
</n-input>
</setting-item>
</setting-item-box>
<setting-item-box name="源地址" :alone="true">
<n-input size="small" :placeholder="globalData?.requestOriginUrl || '暂无'" :disabled="true">
<template #prefix>
<n-icon :component="PulseIcon" />
</template>
</n-input>
</setting-item-box>
<setting-item-box name="接口地址" :alone="true">
<n-input
size="small"
:placeholder="requestUrl || '暂无'"
:disabled="true"
>
<template #prefix>
<n-icon :component="FlashIcon" />
</template>
</n-input>
</setting-item-box>
</div>
<n-divider />
<setting-item-box name="类型">
<setting-item name="配置类型">
<n-input
size="small"
:placeholder="targetData && requestContentTypeObj[requestContentType]"
:disabled="true"
></n-input>
</setting-item>
<setting-item name="body 类型" v-if="requestContentType === RequestContentTypeEnum.DEFAULT">
<n-input size="small" :placeholder="targetData && requestParamsBodyType" :disabled="true"></n-input>
</setting-item>
</setting-item-box>
<div v-if="requestContentType === RequestContentTypeEnum.DEFAULT">
<n-tabs type="line" animated v-model:value="tabValue">
<n-tab v-for="item in RequestParamsTypeEnum" :key="item" :name="item" :tab="item"> {{ item }} </n-tab>
</n-tabs>
<!-- 各个页面 -->
<div class="go-mt-3">
<div v-if="tabValue !== RequestParamsTypeEnum.BODY">
<display-table class="go-my-3" :target="requestParams[tabValue]"> </display-table>
</div>
<!-- 选择了 body -->
<div v-else>
<!-- none -->
<n-card class="go-mt-3 go-pb-3" v-if="requestParamsBodyType === RequestBodyEnum['NONE']">
<n-text depth="3">该接口没有 Body </n-text>
</n-card>
<!-- 具有对象属性时 -->
<template
v-else-if="
requestParamsBodyType === RequestBodyEnum['FORM_DATA'] ||
requestParamsBodyType === RequestBodyEnum['X_WWW_FORM_URLENCODED']
"
>
<display-table
class="go-my-3"
:target="requestParams[RequestParamsTypeEnum.BODY][requestParamsBodyType]"
></display-table>
</template>
<!-- json -->
<template v-else-if="requestParamsBodyType === RequestBodyEnum['JSON']">
<n-card size="small" style="padding-bottom: 7px">
<n-code
:code="requestParams[RequestParamsTypeEnum.BODY][requestParamsBodyType] || '暂无内容'"
language="json"
></n-code>
</n-card>
</template>
<!-- xml -->
<template v-else-if="requestParamsBodyType === RequestBodyEnum['XML']">
<n-code
:code="requestParams[RequestParamsTypeEnum.BODY][requestParamsBodyType] || ''"
language="html"
></n-code>
</template>
</div>
</div>
</div>
<!-- SQL 请求 -->
<div v-else>
<setting-item-box name="键名">
<n-text>sql</n-text>
</setting-item-box>
<setting-item-box name="键值">
<n-code :code="requestSQLContent.sql || ''" language="sql"></n-code>
</setting-item-box>
</div>
</div>
</n-scrollbar>
</div>
</template>
<script setup lang="ts">
import { PropType, ref, toRefs } from 'vue'
import { icon } from '@/plugins'
import { MonacoEditor } from '@/components/Pages/MonacoEditor'
import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { RequestDataPondItemType, RequestGlobalConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
import displayTable from './displayTable.vue'
import {
RequestBodyEnum,
RequestParamsTypeEnum,
SelectHttpTimeNameObj,
RequestContentTypeEnum,
RequestBodyEnumList,
RequestParamsObjType
} from '@/enums/httpEnum'
const props = defineProps({
globalData: Object as PropType<RequestGlobalConfigType>,
targetData: Object as PropType<RequestDataPondItemType>
})
const { HelpOutlineIcon, FlashIcon, PulseIcon } = icon.ionicons5
const {
requestUrl,
requestInterval,
requestHttpType,
requestContentType,
requestSQLContent,
requestParams,
requestParamsBodyType,
requestIntervalUnit
} = toRefs((props.targetData as RequestDataPondItemType).dataPondRequestConfig)
const tabs = [RequestParamsTypeEnum.HEADER]
const requestContentTypeObj = {
[RequestContentTypeEnum.DEFAULT]: '普通请求',
[RequestContentTypeEnum.SQL]: 'SQL 请求'
}
const tabValue = ref<RequestParamsTypeEnum>(RequestParamsTypeEnum.PARAMS)
//
const updateRequestParams = (paramsObj: RequestParamsObjType) => {
if (tabValue.value !== RequestParamsTypeEnum.BODY) {
requestParams.value[tabValue.value] = paramsObj
}
}
//
const updateRequestBodyTable = (paramsObj: RequestParamsObjType) => {
if (
tabValue.value === RequestParamsTypeEnum.BODY &&
// body
(requestParamsBodyType.value === RequestBodyEnum.FORM_DATA ||
requestParamsBodyType.value === RequestBodyEnum.X_WWW_FORM_URLENCODED)
) {
requestParams.value[RequestParamsTypeEnum.BODY][requestParamsBodyType.value] = paramsObj
}
}
</script>
<style lang="scss" scoped>
@include go('chart-data-display') {
flex: 1;
}
</style>

View File

@ -0,0 +1,3 @@
import ChartDataPondControl from './index.vue'
export { ChartDataPondControl }

View File

@ -0,0 +1,230 @@
<template>
<n-modal class="go-chart-data-pond-control" v-model:show="modelShow" :mask-closable="false">
<n-card :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 900px; height: 650px">
<template #header></template>
<template #header-extra> </template>
<div class="pond-content">
<!-- 展示区域 -->
<chart-data-display
v-if="pondData && !loading"
:targetData="pondData"
:globalData="chartEditStore.getRequestGlobalConfig"
></chart-data-display>
<!-- 无数据 -->
<div v-else class="no-data go-flex-center">
<img :src="noData" alt="暂无数据" />
<n-text :depth="3">暂未选择公共接口</n-text>
</div>
<!-- 左侧列表 -->
<chart-data-pond-list @createPond="createPond" @deletePond="deletePond"></chart-data-pond-list>
</div>
<!-- 底部 -->
<template #action>
<n-space justify="space-between">
<n-button type="info" secondary :disabled="!pondData" @click="openPond(true)">
编辑内容
<template #icon>
<n-icon>
<pencil-icon />
</n-icon>
</template>
</n-button>
<n-button type="primary" @click="closeHandle">保存 & 发送请求</n-button>
</n-space>
</template>
</n-card>
</n-modal>
<!-- 请求配置model -->
<pond-data-request
v-if="requestShow"
v-model:modelShow="requestShow"
:targetDataRequest="editData"
:isEdit="isEdit"
@editSaveHandle="saveHandle"
></pond-data-request>
</template>
<script setup lang="ts">
import { ref, toRefs, computed, nextTick, watch, toRaw } from 'vue'
import noData from '@/assets/images/canvas/noData.png'
import { ChartDataPondList } from '../ChartDataPondList'
import { PondDataRequest } from '../../../ChartDataRequest'
import { ChartDataDisplay } from '../ChartDataDisplay'
import { requestConfig } from '@/packages/public/publicConfig'
import { useTargetData } from '@/views/chart/ContentConfigurations/components/hooks/useTargetData.hook'
import { RequestDataPondItemType } from '@/store/modules/chartEditStore/chartEditStore.d'
import { RequestDataTypeEnum } from '@/enums/httpEnum'
import { icon } from '@/plugins'
import { getUUID, goDialog } from '@/utils'
import { cloneDeep } from 'lodash'
defineProps({
modelShow: Boolean
})
const emit = defineEmits(['update:modelShow', 'sendHandle'])
const { PencilIcon } = icon.ionicons5
const { chartEditStore, targetData } = useTargetData()
const { requestDataPond } = toRefs(chartEditStore.getRequestGlobalConfig)
const requestShow = ref(false)
const loading = ref(false)
const isEdit = ref(false)
const editData = ref<RequestDataPondItemType>()
//
const pondData = computed(() => {
const selectId = targetData?.value?.request?.requestDataPondId
if (!selectId) return undefined
const data = requestDataPond.value.filter(item => {
return selectId === item.dataPondId
})
return data[0]
})
watch(
() => pondData.value,
newValue => {
loading.value = true
editData.value = newValue
nextTick(() => {
loading.value = false
})
},
{
immediate: true
}
)
// /
const openPond = (isEditFlag: boolean = false) => {
isEdit.value = !!isEditFlag
requestShow.value = true
}
//
const createPond = () => {
const id = getUUID()
editData.value = {
dataPondId: id,
dataPondName: id,
dataPondRequestConfig: cloneDeep({ ...requestConfig, requestDataType: RequestDataTypeEnum.Pond })
}
openPond()
}
// /
const saveHandle = (newData: RequestDataPondItemType) => {
//
if (isEdit.value) {
editSaveHandle(newData)
} else {
createSaveHandle(newData)
}
isEdit.value = false
requestShow.value = false
}
//
const editSaveHandle = (newData: RequestDataPondItemType) => {
try {
const targetIndex = requestDataPond.value.findIndex(item => item.dataPondId === newData.dataPondId)
if (targetIndex !== -1) {
requestDataPond.value.splice(targetIndex, 1, newData)
// ,
chartEditStore.getComponentList.forEach(item => {
if (
item.request.requestDataType === RequestDataTypeEnum.Pond &&
item.request.requestDataPondId === newData.dataPondId
) {
item.request = {
...toRaw(newData.dataPondRequestConfig),
requestDataPondId: newData.dataPondId
}
}
})
window.$message.success('保存成功!')
} else {
window.$message.error('编辑失败,请稍后重试!')
}
} catch (error) {
window.$message.error('编辑失败,请稍后重试!')
}
}
//
const createSaveHandle = (newData: RequestDataPondItemType) => {
try {
if (editData.value) {
requestDataPond.value.unshift(newData)
window.$message.success('创建成功!')
} else {
window.$message.error('创建失败,请稍后重试!')
}
} catch (error) {
window.$message.error('创建失败,请稍后重试!')
}
}
//
const deletePond = (targetData: RequestDataPondItemType) => {
goDialog({
message: '删除数据后,需手动处理使用改接口的组件,是否继续?',
isMaskClosable: true,
transformOrigin: 'center',
onPositiveCallback: () => {
const targetIndex = requestDataPond.value.findIndex(item => item.dataPondId === targetData.dataPondId)
if (targetIndex !== -1) {
requestDataPond.value.splice(targetIndex, 1)
window.$message.success('删除成功!')
} else {
window.$message.error('删除失败,请稍后重试!')
}
}
})
}
//
const closeHandle = () => {
//
if (pondData.value) {
targetData.value.request = {
...toRaw(pondData.value.dataPondRequestConfig),
requestDataPondId: pondData.value.dataPondId
}
}
emit('update:modelShow', false)
emit('sendHandle')
}
</script>
<style lang="scss" scoped>
@include go('chart-data-pond-control') {
/* 中间 */
.pond-content {
display: flex;
}
.no-data {
flex-direction: column;
width: 100%;
img {
width: 200px;
}
}
&.n-card.n-modal,
.n-card {
@extend .go-background-filter;
}
.n-card-shallow {
background-color: rgba(0, 0, 0, 0) !important;
}
@include deep() {
& > .n-card__content {
padding-right: 0;
}
.n-card__content {
padding-bottom: 5px;
}
}
}
</style>

View File

@ -0,0 +1,3 @@
import ChartDataPondList from './index.vue'
export { ChartDataPondList }

View File

@ -0,0 +1,202 @@
<template>
<div class="go-chart-data-pond-list">
<n-timeline style="width: 20px">
<n-timeline-item type="info"> </n-timeline-item>
<n-timeline-item type="success"></n-timeline-item>
</n-timeline>
<div class="pond-item-box">
<!-- 新增 -->
<n-button class="create-btn go-py-4" ghost @click="createPond">
<span> 创建 </span>
<template #icon>
<n-icon>
<DuplicateOutlineIcon></DuplicateOutlineIcon>
</n-icon>
</template>
</n-button>
<n-divider style="margin: 10px 0"></n-divider>
<n-space v-if="!requestDataPond.length" justify="center">
<n-text class="not-layer-text" :depth="3">
暂无数据内容
<n-a @click="createPond">立即创建</n-a>
</n-text>
</n-space>
<n-scrollbar style="max-height: 490px">
<div
v-for="item in requestDataPond"
:key="item.dataPondId"
:class="{ select: item.dataPondId === selectPondId }"
class="pond-item"
@click="clickHandle(item)"
>
<div class="item-content">
<div class="item-content-body">
<div>
<n-tag class="go-mr-1" :type="item.dataPondId === selectPondId ? 'warning' : ''" :bordered="false">
名称
</n-tag>
<n-ellipsis style="max-width: 180px">
{{ item.dataPondName || '暂无' }}
</n-ellipsis>
</div>
<div>
<n-tag class="go-mr-1" :type="item.dataPondId === selectPondId ? 'warning' : ''" :bordered="false">
地址
</n-tag>
<n-ellipsis style="max-width: 180px">
{{ item.dataPondRequestConfig.requestUrl || '暂无' }}
</n-ellipsis>
</div>
</div>
<div class="item-content-icon go-transition-quick" @click="deletePond($event, item)">
<n-icon>
<trash-icon></trash-icon>
</n-icon>
</div>
</div>
<div :class="{ 'select-modal': item.dataPondId === selectPondId }"></div>
</div>
</n-scrollbar>
</div>
</div>
</template>
<script setup lang="ts">
import { toRefs, computed } from 'vue'
import { useTargetData } from '@/views/chart/ContentConfigurations/components/hooks/useTargetData.hook'
import { useDesignStore } from '@/store/modules/designStore/designStore'
import { RequestDataPondItemType } from '@/store/modules/chartEditStore/chartEditStore.d'
import { icon } from '@/plugins'
const emit = defineEmits(['createPond', 'deletePond'])
const { DuplicateOutlineIcon, TrashIcon } = icon.ionicons5
const designStore = useDesignStore()
const { chartEditStore, targetData } = useTargetData()
const { requestDataPond } = toRefs(chartEditStore.getRequestGlobalConfig)
//
const selectPondId = computed(() => {
return targetData.value.request.requestDataPondId
})
//
const themeColor = computed(() => {
return designStore.getAppTheme
})
//
const createPond = () => {
emit('createPond', true)
}
//
const deletePond = (target: Event, targetData: RequestDataPondItemType) => {
target.stopPropagation()
target.preventDefault()
emit('deletePond', targetData)
}
//
const clickHandle = (item: RequestDataPondItemType) => {
targetData.value.request.requestDataPondId = item.dataPondId
}
</script>
<style scoped lang="scss">
$height: 530px;
$listWidth: 280px;
$centerHeight: 60px;
$centerMiniHeight: 28px;
$textSize: 10px;
@include go('chart-data-pond-list') {
padding-top: 10px;
padding-bottom: 5px;
margin-right: 5px;
display: flex;
@include deep() {
.n-timeline > .n-timeline-item {
&:first-child {
height: $height;
}
}
}
.pond-item-box {
width: $listWidth;
position: relative;
.create-btn {
width: calc(#{$listWidth - 15px});
margin-right: 15px;
}
.pond-item {
position: relative;
height: $centerHeight;
padding: 5px;
margin-bottom: 10px;
margin-right: 15px;
border-radius: 5px;
cursor: pointer;
border: 1px solid rgba(0, 0, 0, 0);
@include fetch-bg-color('background-color3');
@extend .go-transition-quick;
&.hover,
&:hover {
@include fetch-bg-color('background-color4');
}
&:hover {
@include deep() {
.icon-item {
opacity: 1;
}
}
.item-content-icon {
opacity: 1 !important;
}
}
&.select {
border: 1px solid v-bind('themeColor');
background-color: rgba(0, 0, 0, 0);
.item-content-icon {
display: none;
}
}
.select-modal,
.item-content {
position: absolute;
top: 0;
left: 0;
}
.item-content {
z-index: 1;
display: flex;
justify-content: space-between;
align-items: center;
padding: 5px;
.item-content-body {
width: 230px;
display: flex;
flex-direction: column;
gap: 5px;
}
.item-content-icon {
opacity: 0;
height: $centerHeight;
line-height: $centerHeight;
padding-left: 5px;
}
}
.select-modal {
width: 100%;
height: 100%;
opacity: 0.3;
background-color: v-bind('themeColor');
}
}
}
}
</style>

View File

@ -0,0 +1,3 @@
import ChartDataPond from './index.vue'
export { ChartDataPond }

View File

@ -0,0 +1,185 @@
<template>
<!-- 选中内容 -->
<div class="go-chart-data-pond">
<n-card class="n-card-shallow">
<setting-item-box name="请求名称" :alone="true">
<n-input size="small" :placeholder="pondData?.dataPondName || '暂无'" :disabled="true">
<template #prefix>
<n-icon :component="FishIcon" />
</template>
</n-input>
</setting-item-box>
<setting-item-box name="接口地址" :alone="true">
<n-input size="small" :placeholder="pondData?.dataPondRequestConfig.requestUrl || '暂无'" :disabled="true">
<template #prefix>
<n-icon :component="FlashIcon" />
</template>
</n-input>
</setting-item-box>
<div class="edit-text" @click="controlModelHandle">
<div class="go-absolute-center">
<n-button type="primary" secondary>编辑配置</n-button>
</div>
</div>
</n-card>
</div>
<setting-item-box :alone="true">
<template #name>
测试
<n-tooltip trigger="hover">
<template #trigger>
<n-icon size="21" :depth="3">
<help-outline-icon></help-outline-icon>
</n-icon>
</template>
默认赋值给 dataset 字段
</n-tooltip>
</template>
<n-button type="primary" ghost @click="sendHandle">
<template #icon>
<n-icon>
<flash-icon />
</n-icon>
</template>
发送请求
</n-button>
</setting-item-box>
<!-- 底部数据展示 -->
<chart-data-matching-and-show :show="showMatching && !loading" :ajax="true"></chart-data-matching-and-show>
<!-- 骨架图 -->
<go-skeleton :load="loading" :repeat="3"></go-skeleton>
<!-- 编辑 / 新增弹窗 -->
<chart-data-pond-control v-model:modelShow="controlModel" @sendHandle="sendHandle"></chart-data-pond-control>
</template>
<script setup lang="ts">
import { ref, toRefs, toRaw, onBeforeUnmount, computed, watchEffect } from 'vue'
import { icon } from '@/plugins'
import { http, customizeHttp } from '@/api/http'
import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { ChartDataPondControl } from './components/ChartDataPondControl'
import { useDesignStore } from '@/store/modules/designStore/designStore'
import { useTargetData } from '../../../hooks/useTargetData.hook'
import { ChartDataMatchingAndShow } from '../ChartDataMatchingAndShow'
import { newFunctionHandle } from '@/utils'
const designStore = useDesignStore()
const { HelpOutlineIcon, FlashIcon, PulseIcon, FishIcon } = icon.ionicons5
const { targetData, chartEditStore } = useTargetData()
const {
requestDataPond,
requestInterval: GlobalRequestInterval,
requestIntervalUnit: GlobalRequestIntervalUnit
} = toRefs(chartEditStore.getRequestGlobalConfig)
const loading = ref(false)
const controlModel = ref(false)
const showMatching = ref(false)
let firstFocus = 0
let lastFilter: any = undefined
//
const pondData = computed(() => {
const selectId = targetData.value.request.requestDataPondId
if (!selectId) return undefined
const data = requestDataPond.value.filter(item => {
return selectId === item.dataPondId
})
return data[0]
})
//
const themeColor = computed(() => {
return designStore.getAppTheme
})
// model
const controlModelHandle = () => {
controlModel.value = true
}
//
const sendHandle = async () => {
if (!targetData.value?.request) {
window.$message.warning('请选择一个公共接口!')
return
}
loading.value = true
try {
// const res = await customizeHttp(
// toRaw(pondData.value?.dataPondRequestConfig),
// toRaw(chartEditStore.getRequestGlobalConfig)
// )
const res = await customizeHttp(toRaw(targetData.value.request), toRaw(chartEditStore.getRequestGlobalConfig))
loading.value = false
if (res) {
if (!res?.data && !targetData.value.filter) window['$message'].warning('您的数据不符合默认格式,请配置过滤器!')
targetData.value.option.dataset = newFunctionHandle(res?.data, res, targetData.value.filter)
showMatching.value = true
return
}
window['$message'].warning('数据异常,请检查参数!')
} catch (error) {
loading.value = false
window['$message'].warning('数据异常,请检查参数!')
}
}
watchEffect(() => {
const filter = targetData.value?.filter
if (lastFilter !== filter && firstFocus) {
lastFilter = filter
sendHandle()
}
firstFocus++
})
onBeforeUnmount(() => {
lastFilter = null
})
</script>
<style scoped lang="scss">
@include go('chart-data-pond') {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
.n-card-shallow {
&.n-card {
@extend .go-background-filter;
@include deep() {
.n-card__content {
padding: 10px;
}
}
}
.edit-text {
position: absolute;
top: 0px;
left: 0px;
width: 325px;
height: 136px;
cursor: pointer;
opacity: 0;
transition: all 0.3s;
@extend .go-background-filter;
backdrop-filter: blur(2px) !important;
}
&:hover {
border-color: v-bind('themeColor');
.edit-text {
opacity: 1;
}
}
}
}
</style>

View File

@ -1,7 +1,7 @@
<template> <template>
<!-- 全局配置 --> <!-- 全局配置 -->
<n-card class="n-card-shallow"> <n-card class="n-card-shallow">
<n-tag type="info" :bordered="false" style="border-radius: 5px"> 全局配置 </n-tag> <n-tag type="info" :bordered="false" style="border-radius: 5px"> 全局公共配置 </n-tag>
<setting-item-box <setting-item-box
name="服务" name="服务"
:itemRightStyle="{ :itemRightStyle="{

View File

@ -29,7 +29,7 @@
<!-- none --> <!-- none -->
<n-card class="go-mt-3 go-pb-3" v-if="requestParamsBodyType === RequestBodyEnum['NONE']"> <n-card class="go-mt-3 go-pb-3" v-if="requestParamsBodyType === RequestBodyEnum['NONE']">
<n-text depth="3">请求没有 Body </n-text> <n-text depth="3">接口没有 Body </n-text>
</n-card> </n-card>
<!-- 具有对象属性时 --> <!-- 具有对象属性时 -->
@ -86,13 +86,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, toRefs } from 'vue' import { ref, toRefs, PropType } from 'vue'
import { MonacoEditor } from '@/components/Pages/MonacoEditor' import { MonacoEditor } from '@/components/Pages/MonacoEditor'
import { RequestHeaderTable } from '../RequestHeaderTable/index'
import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting' import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { useTargetData } from '@/views/chart/ContentConfigurations/components/hooks/useTargetData.hook' import { useTargetData } from '@/views/chart/ContentConfigurations/components/hooks/useTargetData.hook'
import { RequestHeaderTable } from '../RequestHeaderTable/index' import { RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
import { import {
RequestParamsTypeEnum, RequestParamsTypeEnum,
RequestContentTypeEnum, RequestContentTypeEnum,
@ -102,9 +101,13 @@ import {
RequestHttpEnum RequestHttpEnum
} from '@/enums/httpEnum' } from '@/enums/httpEnum'
const { targetData } = useTargetData() const props = defineProps({
targetDataRequest: Object as PropType<RequestConfigType>
})
const { requestHttpType, requestContentType, requestSQLContent, requestParams, requestParamsBodyType } = toRefs(targetData.value.request) const { requestHttpType, requestContentType, requestSQLContent, requestParams, requestParamsBodyType } = toRefs(
props.targetDataRequest as RequestConfigType
)
const tabValue = ref<RequestParamsTypeEnum>(RequestParamsTypeEnum.PARAMS) const tabValue = ref<RequestParamsTypeEnum>(RequestParamsTypeEnum.PARAMS)

View File

@ -5,7 +5,7 @@
:itemRightStyle="{ :itemRightStyle="{
gridTemplateColumns: '6fr 2fr' gridTemplateColumns: '6fr 2fr'
}" }"
style="padding-right: 25px;" style="padding-right: 25px"
> >
<template #name> <template #name>
地址 地址
@ -51,15 +51,16 @@
</setting-item> </setting-item>
</setting-item-box> </setting-item-box>
<setting-item-box name="选择方式" class="go-mt-0"> <setting-item-box name="选择方式" class="go-mt-0">
<request-header></request-header> <request-header :targetDataRequest="targetDataRequest"></request-header>
</setting-item-box> </setting-item-box>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, toRefs } from 'vue' import { PropType, toRefs } from 'vue'
import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting' import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { useTargetData } from '@/views/chart/ContentConfigurations/components/hooks/useTargetData.hook' import { useTargetData } from '@/views/chart/ContentConfigurations/components/hooks/useTargetData.hook'
import { selectTypeOptions, selectTimeOptions } from '@/views/chart/ContentConfigurations/components/ChartData/index.d' import { selectTypeOptions, selectTimeOptions } from '@/views/chart/ContentConfigurations/components/ChartData/index.d'
import { RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
import { RequestHeader } from '../RequestHeader' import { RequestHeader } from '../RequestHeader'
import { isDev } from '@/utils' import { isDev } from '@/utils'
import { icon } from '@/plugins' import { icon } from '@/plugins'
@ -82,10 +83,16 @@ import {
threeEarth01Url threeEarth01Url
} from '@/api/mock' } from '@/api/mock'
const props = defineProps({
targetDataRequest: Object as PropType<RequestConfigType>
})
const { HelpOutlineIcon } = icon.ionicons5 const { HelpOutlineIcon } = icon.ionicons5
const { targetData, chartEditStore } = useTargetData() const { chartEditStore } = useTargetData()
const { requestOriginUrl } = toRefs(chartEditStore.getRequestGlobalConfig) const { requestOriginUrl } = toRefs(chartEditStore.getRequestGlobalConfig)
const { requestInterval, requestIntervalUnit, requestHttpType, requestUrl } = toRefs(targetData.value.request) const { requestInterval, requestIntervalUnit, requestHttpType, requestUrl } = toRefs(
props.targetDataRequest as RequestConfigType
)
const apiList = [ const apiList = [
{ {

View File

@ -1,3 +1,4 @@
import ChartDataRequest from './index.vue' import ChartDataRequest from './index.vue'
import PondDataRequest from './pondIndex.vue'
export { ChartDataRequest } export { ChartDataRequest, PondDataRequest }

View File

@ -1,5 +1,5 @@
<template> <template>
<n-modal class="go-chart-data-request" v-model:show="modelShow" :mask-closable="false"> <n-modal class="go-chart-data-request" v-model:show="modelShow" :mask-closable="false" :closeOnEsc="false">
<n-card :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 1000px; height: 800px"> <n-card :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 1000px; height: 800px">
<template #header></template> <template #header></template>
<template #header-extra> </template> <template #header-extra> </template>
@ -7,7 +7,7 @@
<div class="go-pr-3"> <div class="go-pr-3">
<n-space vertical> <n-space vertical>
<request-global-config></request-global-config> <request-global-config></request-global-config>
<request-target-config></request-target-config> <request-target-config :target-data-request="targetData?.request"></request-target-config>
</n-space> </n-space>
</div> </div>
</n-scrollbar> </n-scrollbar>
@ -17,9 +17,11 @@
<div> <div>
<n-text> {{ chartConfig.categoryName }} </n-text> <n-text> {{ chartConfig.categoryName }} </n-text>
<n-text> </n-text> <n-text> </n-text>
<n-tag type="primary" :bordered="false" style="border-radius: 5px"> {{ requestContentTypeObj[requestContentType] }} </n-tag> <n-tag type="primary" :bordered="false" style="border-radius: 5px">
{{ requestContentTypeObj[requestContentType] }}
</n-tag>
</div> </div>
<n-button type="primary" @click="closeHandle">保存 & 发送请求</n-button> <n-button type="primary" @click="closeAndSendHandle"> {{ saveBtnText || '保存 & 发送请求' }}</n-button>
</n-space> </n-space>
</template> </template>
</n-card> </n-card>
@ -27,31 +29,38 @@
</template> </template>
<script script lang="ts" setup> <script script lang="ts" setup>
import { toRefs } from 'vue' import { toRefs, PropType } from 'vue'
import { RequestContentTypeEnum } from '@/enums/httpEnum' import { RequestContentTypeEnum } from '@/enums/httpEnum'
import { useTargetData } from '../../../hooks/useTargetData.hook' import { useTargetData } from '../../../hooks/useTargetData.hook'
import { RequestGlobalConfig } from './components/RequestGlobalConfig' import { RequestGlobalConfig } from './components/RequestGlobalConfig'
import { RequestTargetConfig } from './components/RequestTargetConfig' import { RequestTargetConfig } from './components/RequestTargetConfig'
import { useSync } from '@/views/chart/hooks/useSync.hook' import { useSync } from '@/views/chart/hooks/useSync.hook'
import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
const props = defineProps({
modelShow: Boolean,
targetData: Object as PropType<CreateComponentType>,
saveBtnText: String || null
})
const emit = defineEmits(['update:modelShow', 'sendHandle']) const emit = defineEmits(['update:modelShow', 'sendHandle'])
const { targetData } = useTargetData() const { targetData } = useTargetData()
const { dataSyncUpdate } = useSync() const { dataSyncUpdate } = useSync()
// //
const { chartConfig } = toRefs(targetData.value) const { chartConfig } = toRefs(props.targetData as CreateComponentType)
const { requestContentType } = toRefs(targetData.value.request) const { requestContentType } = toRefs((props.targetData as CreateComponentType).request)
const requestContentTypeObj = { const requestContentTypeObj = {
[RequestContentTypeEnum.DEFAULT]: '普通请求', [RequestContentTypeEnum.DEFAULT]: '普通请求',
[RequestContentTypeEnum.SQL]: 'SQL 请求' [RequestContentTypeEnum.SQL]: 'SQL 请求'
} }
defineProps({
modelShow: Boolean
})
const closeHandle = () => { const closeHandle = () => {
emit('update:modelShow', false) emit('update:modelShow', false)
}
const closeAndSendHandle = () => {
emit('update:modelShow', false)
emit('sendHandle') emit('sendHandle')
dataSyncUpdate() dataSyncUpdate()
} }

View File

@ -0,0 +1,105 @@
<template>
<n-modal class="go-chart-data-request" v-model:show="modelShow" :mask-closable="false" :closeOnEsc="false">
<n-card :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 1000px; height: 800px">
<template #header></template>
<template #header-extra> </template>
<n-scrollbar style="max-height: 718px">
<div class="go-pr-3">
<n-space vertical>
<request-global-config></request-global-config>
<request-target-config
:target-data-request="targetDataRequest?.dataPondRequestConfig"
></request-target-config>
</n-space>
</div>
</n-scrollbar>
<!-- 底部 -->
<template #action>
<n-space justify="space-between">
<n-space v-if="targetDataRequest">
<n-tag :bordered="false" type="primary">名称</n-tag>
<n-input
v-model:value="targetDataRequest.dataPondName"
ref="inputInstRef"
type="text"
size="small"
:autofocus="true"
:clearable="true"
:minlength="1"
:maxlength="16"
placeholder="请输入名称"
></n-input>
</n-space>
<span v-else></span>
<n-space>
<n-button @click="closeHandle">取消</n-button>
<n-button type="primary" @click="closeAndSendHandle">保存</n-button>
</n-space>
</n-space>
</template>
</n-card>
</n-modal>
</template>
<script script lang="ts" setup>
import { PropType, ref, watchEffect } from 'vue'
import { RequestContentTypeEnum } from '@/enums/httpEnum'
import { useTargetData } from '../../../hooks/useTargetData.hook'
import { RequestGlobalConfig } from './components/RequestGlobalConfig'
import { RequestTargetConfig } from './components/RequestTargetConfig'
import { RequestDataPondItemType } from '@/store/modules/chartEditStore/chartEditStore.d'
import { useSync } from '@/views/chart/hooks/useSync.hook'
import { goDialog } from '@/utils'
const props = defineProps({
modelShow: Boolean,
targetDataRequest: Object as PropType<RequestDataPondItemType>
})
const emit = defineEmits(['update:modelShow', 'editSaveHandle'])
const { dataSyncUpdate } = useSync()
const pondName = ref()
const inputInstRef = ref()
const closeHandle = () => {
emit('update:modelShow', false)
}
const closeAndSendHandle = () => {
if (!props.targetDataRequest?.dataPondName) {
window.$message.warning('请在左下角输入名称!')
inputInstRef.value?.focus()
return
}
goDialog({
message: '保存内容将同步修改所有使用此接口的组件, 是否继续?',
isMaskClosable: true,
transformOrigin: 'center',
onPositiveCallback: () => {
emit('update:modelShow', false)
emit('editSaveHandle', props.targetDataRequest)
dataSyncUpdate()
}
})
}
</script>
<style lang="scss" scoped>
@include go('chart-data-request') {
&.n-card.n-modal,
.n-card {
@extend .go-background-filter;
}
.n-card-shallow {
background-color: rgba(0, 0, 0, 0) !important;
}
@include deep() {
& > .n-card__content {
padding-right: 0;
}
.n-card__content {
padding-bottom: 5px;
}
}
}
</style>

View File

@ -16,6 +16,7 @@ export enum TimelineTitleEnum {
export enum SelectCreateDataEnum { export enum SelectCreateDataEnum {
STATIC = '静态数据', STATIC = '静态数据',
AJAX = '动态请求', AJAX = '动态请求',
Pond = '公共接口',
} }
export interface SelectCreateDataType { export interface SelectCreateDataType {

View File

@ -3,24 +3,27 @@
<setting-item-box name="请求方式" :alone="true"> <setting-item-box name="请求方式" :alone="true">
<n-select v-model:value="targetData.request.requestDataType" :disabled="isNotData" :options="selectOptions" /> <n-select v-model:value="targetData.request.requestDataType" :disabled="isNotData" :options="selectOptions" />
</setting-item-box> </setting-item-box>
<!-- 静态 --> <!-- 静态 -->
<chart-data-static v-if="targetData.request.requestDataType === RequestDataTypeEnum.STATIC"></chart-data-static> <chart-data-static v-if="targetData.request.requestDataType === RequestDataTypeEnum.STATIC"></chart-data-static>
<!-- 动态 --> <!-- 动态 -->
<chart-data-ajax v-else></chart-data-ajax> <chart-data-ajax v-if="targetData.request.requestDataType === RequestDataTypeEnum.AJAX"></chart-data-ajax>
<!-- 数据池 -->
<chart-data-pond v-if="targetData.request.requestDataType === RequestDataTypeEnum.Pond"></chart-data-pond>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue' import { computed } from 'vue'
import { loadAsyncComponent } from '@/utils'
import { SettingItemBox } from '@/components/Pages/ChartItemSetting' import { SettingItemBox } from '@/components/Pages/ChartItemSetting'
import { useTargetData } from '../hooks/useTargetData.hook' import { useTargetData } from '../hooks/useTargetData.hook'
import { ChartDataStatic } from './components/ChartDataStatic/index'
import { ChartDataAjax } from './components/ChartDataAjax/index'
import { SelectCreateDataType, SelectCreateDataEnum } from './index.d' import { SelectCreateDataType, SelectCreateDataEnum } from './index.d'
import { RequestDataTypeEnum } from '@/enums/httpEnum' import { RequestDataTypeEnum } from '@/enums/httpEnum'
const ChartDataStatic = loadAsyncComponent(() => import('./components/ChartDataStatic/index.vue'))
const ChartDataAjax = loadAsyncComponent(() => import('./components/ChartDataAjax/index.vue'))
const ChartDataPond = loadAsyncComponent(() => import('./components/ChartDataPond/index.vue'))
const { targetData } = useTargetData() const { targetData } = useTargetData()
// //
@ -32,6 +35,10 @@ const selectOptions: SelectCreateDataType[] = [
{ {
label: SelectCreateDataEnum.AJAX, label: SelectCreateDataEnum.AJAX,
value: RequestDataTypeEnum.AJAX value: RequestDataTypeEnum.AJAX
},
{
label: SelectCreateDataEnum.Pond,
value: RequestDataTypeEnum.Pond
} }
] ]

View File

@ -152,9 +152,9 @@ const sendHandle = async () => {
id: fetchRouteParamsLocation(), id: fetchRouteParamsLocation(),
// //
state: release.value ? -1 : 1, state: release.value ? -1 : 1,
})) as unknown as MyResponseType }))
if (res.code === ResultEnum.SUCCESS) { if (res && res.code === ResultEnum.SUCCESS) {
modelShowHandle() modelShowHandle()
if (!release.value) { if (!release.value) {
copyPreviewPath('发布成功!已复制地址到剪贴板~', '发布成功!') copyPreviewPath('发布成功!已复制地址到剪贴板~', '发布成功!')

View File

@ -67,8 +67,8 @@ const handleBlur = async () => {
const res = (await updateProjectApi({ const res = (await updateProjectApi({
id: fetchRouteParamsLocation(), id: fetchRouteParamsLocation(),
projectName: title.value projectName: title.value
})) as unknown as MyResponseType }))
if (res.code === ResultEnum.SUCCESS) { if (res && res.code === ResultEnum.SUCCESS) {
dataSyncUpdate() dataSyncUpdate()
} else { } else {
httpErrorHandle() httpErrorHandle()

View File

@ -142,7 +142,6 @@ $textSize: 10px;
/* 选中样式 */ /* 选中样式 */
&.select { &.select {
border: 1px solid v-bind('themeColor'); border: 1px solid v-bind('themeColor');
/* 需要设置最高级,覆盖 hover 的颜色 */
background-color: rgba(0, 0, 0, 0); background-color: rgba(0, 0, 0, 0);
} }

View File

@ -224,10 +224,13 @@ export const useSync = () => {
// * 数据获取 // * 数据获取
const dataSyncFetch = async () => { const dataSyncFetch = async () => {
// FIX:重新执行dataSyncFetch需清空chartEditStore.componentList,否则会导致图层重复
// 切换语言等操作会导致重新执行 dataSyncFetch,此时pinia中并未清空chartEditStore.componentList导致图层重复
chartEditStore.componentList = []
chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.START) chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.START)
try { try {
const res = await fetchProjectApi({ projectId: fetchRouteParamsLocation() }) as unknown as MyResponseType const res = await fetchProjectApi({ projectId: fetchRouteParamsLocation() })
if (res.code === ResultEnum.SUCCESS) { if (res && res.code === ResultEnum.SUCCESS) {
if (res.data) { if (res.data) {
updateStoreInfo(res.data) updateStoreInfo(res.data)
// 更新全局数据 // 更新全局数据
@ -275,9 +278,9 @@ export const useSync = () => {
// 上传预览图 // 上传预览图
let uploadParams = new FormData() let uploadParams = new FormData()
uploadParams.append('object', base64toFile(canvasImage.toDataURL(), `${fetchRouteParamsLocation()}_index_preview.png`)) uploadParams.append('object', base64toFile(canvasImage.toDataURL(), `${fetchRouteParamsLocation()}_index_preview.png`))
const uploadRes = await uploadFile(uploadParams) as unknown as MyResponseType const uploadRes = await uploadFile(uploadParams)
// 保存预览图 // 保存预览图
if(uploadRes.code === ResultEnum.SUCCESS) { if(uploadRes && uploadRes.code === ResultEnum.SUCCESS) {
await updateProjectApi({ await updateProjectApi({
id: fetchRouteParamsLocation(), id: fetchRouteParamsLocation(),
indexImage: `${systemStore.getFetchInfo.OSSUrl}${uploadRes.data.fileName}` indexImage: `${systemStore.getFetchInfo.OSSUrl}${uploadRes.data.fileName}`
@ -292,9 +295,9 @@ export const useSync = () => {
let params = new FormData() let params = new FormData()
params.append('projectId', projectId) params.append('projectId', projectId)
params.append('content', JSON.stringify(chartEditStore.getStorageInfo || {})) params.append('content', JSON.stringify(chartEditStore.getStorageInfo || {}))
const res= await saveProjectApi(params) as unknown as MyResponseType const res= await saveProjectApi(params)
if (res.code === ResultEnum.SUCCESS) { if (res && res.code === ResultEnum.SUCCESS) {
// 成功状态 // 成功状态
setTimeout(() => { setTimeout(() => {
chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.SUCCESS) chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.SUCCESS)

View File

@ -207,8 +207,8 @@ const handleSubmit = async (e: Event) => {
const res = await loginApi({ const res = await loginApi({
username, username,
password password
}) as unknown as MyResponseType })
if(res.data) { if(res && res.data) {
const { tokenValue, tokenName } = res.data.token const { tokenValue, tokenName } = res.data.token
const { nickname, username, id } = res.data.userinfo const { nickname, username, id } = res.data.userinfo

View File

@ -54,5 +54,6 @@ const props = defineProps({
<style lang="scss" scoped> <style lang="scss" scoped>
.chart-item { .chart-item {
position: absolute; position: absolute;
overflow: hidden;
} }
</style> </style>

View File

@ -47,7 +47,7 @@ import { getSizeStyle, getComponentAttrStyle, getStatusStyle } from '../../utils
import { useLifeHandler } from '@/hooks' import { useLifeHandler } from '@/hooks'
// //
const { initDataPond } = useChartDataPondFetch() const { initDataPond, clearMittDataPondMap } = useChartDataPondFetch()
const props = defineProps({ const props = defineProps({
localStorageInfo: { localStorageInfo: {
@ -69,6 +69,7 @@ const themeColor = computed(() => {
}) })
// //
clearMittDataPondMap()
onMounted(() => { onMounted(() => {
initDataPond(props.localStorageInfo.requestGlobalConfig) initDataPond(props.localStorageInfo.requestGlobalConfig)
}) })
@ -77,5 +78,6 @@ onMounted(() => {
<style lang="scss" scoped> <style lang="scss" scoped>
.chart-item { .chart-item {
position: absolute; position: absolute;
overflow: hidden;
} }
</style> </style>

View File

@ -11,15 +11,13 @@ export interface ChartEditStorageType extends ChartEditStorage {
// 根据路由 id 获取存储数据的信息 // 根据路由 id 获取存储数据的信息
export const getSessionStorageInfo = async () => { export const getSessionStorageInfo = async () => {
const id = fetchRouteParamsLocation() const id = fetchRouteParamsLocation()
const storageList: ChartEditStorageType[] = getSessionStorage( const storageList: ChartEditStorageType[] = getSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST)
StorageEnum.GO_CHART_STORAGE_LIST
)
// 是否本地预览 // 是否本地预览
if (!storageList || storageList.findIndex(e => e.id === id.toString()) === -1) { if (!storageList || storageList.findIndex(e => e.id === id.toString()) === -1) {
// 接口调用 // 接口调用
const res = await fetchProjectApi({ projectId: id }) as unknown as MyResponseType const res = await fetchProjectApi({ projectId: id })
if (res.code === ResultEnum.SUCCESS) { if (res && res.code === ResultEnum.SUCCESS) {
const { content, state } = res.data const { content, state } = res.data
if (state === -1) { if (state === -1) {
// 跳转未发布页 // 跳转未发布页
@ -37,4 +35,4 @@ export const getSessionStorageInfo = async () => {
} }
} }
} }
} }

View File

@ -1,4 +1,4 @@
import { ref, reactive } from 'vue'; import { ref, reactive } from 'vue'
import { goDialog, httpErrorHandle } from '@/utils' import { goDialog, httpErrorHandle } from '@/utils'
import { DialogEnum } from '@/enums/pluginEnum' import { DialogEnum } from '@/enums/pluginEnum'
import { projectListApi, deleteProjectApi, changeProjectReleaseApi } from '@/api/path' import { projectListApi, deleteProjectApi, changeProjectReleaseApi } from '@/api/path'
@ -7,16 +7,15 @@ import { ResultEnum } from '@/enums/httpEnum'
// 数据初始化 // 数据初始化
export const useDataListInit = () => { export const useDataListInit = () => {
const loading = ref(true) const loading = ref(true)
const paginat = reactive({ const paginat = reactive({
// 当前页数 // 当前页数
page: 1, page: 1,
// 每页值 // 每页值
limit: 12, limit: 12,
// 总数 // 总数
count: 10, count: 10
}) })
const list = ref<ChartList>([]) const list = ref<ChartList>([])
@ -27,11 +26,11 @@ export const useDataListInit = () => {
const res = await projectListApi({ const res = await projectListApi({
page: paginat.page, page: paginat.page,
limit: paginat.limit limit: paginat.limit
}) as any })
if (res.data) { if (res && res.data) {
const { count } = res const { count } = res as any // 这里的count与data平级不在Response结构中
paginat.count = count paginat.count = count
list.value = res.data.map((e: any) => { list.value = res.data.map(e => {
const { id, projectName, state, createTime, indexImage, createUserId } = e const { id, projectName, state, createTime, indexImage, createUserId } = e
return { return {
id: id, id: id,
@ -67,11 +66,14 @@ export const useDataListInit = () => {
goDialog({ goDialog({
type: DialogEnum.DELETE, type: DialogEnum.DELETE,
promise: true, promise: true,
onPositiveCallback: () => new Promise(res => { onPositiveCallback: () =>
res(deleteProjectApi({ new Promise(res => {
ids: cardData.id res(
})) deleteProjectApi({
}), ids: cardData.id
})
)
}),
promiseResCallback: (res: any) => { promiseResCallback: (res: any) => {
if (res.code === ResultEnum.SUCCESS) { if (res.code === ResultEnum.SUCCESS) {
window['$message'].success(window['$t']('global.r_delete_success')) window['$message'].success(window['$t']('global.r_delete_success'))
@ -90,8 +92,8 @@ export const useDataListInit = () => {
id: id, id: id,
// [-1未发布, 1发布] // [-1未发布, 1发布]
state: !release ? 1 : -1 state: !release ? 1 : -1
}) as unknown as MyResponseType })
if (res.code === ResultEnum.SUCCESS) { if (res && res.code === ResultEnum.SUCCESS) {
list.value = [] list.value = []
fetchList() fetchList()
// 发布 -> 未发布 // 发布 -> 未发布

View File

@ -1,7 +1,7 @@
export type Chartype = { export type Chartype = {
id: number | string id: number | string
title: string // 标题 title: string // 标题
label: string // 标签 label?: string // 标签
time: string, // 时间 time: string, // 时间
image: string, // 预览图地址 image: string, // 预览图地址
createId: string, // 创建者 createId: string, // 创建者

View File

@ -96,8 +96,8 @@ const btnHandle = async (key: string) => {
remarks: null, remarks: null,
// //
indexImage: null, indexImage: null,
}) as unknown as MyResponseType })
if(res.code === ResultEnum.SUCCESS) { if(res && res.code === ResultEnum.SUCCESS) {
window['$message'].success(window['$t']('project.create_success')) window['$message'].success(window['$t']('project.create_success'))
const { id } = res.data const { id } = res.data

7
types/global.d.ts vendored
View File

@ -11,11 +11,4 @@ interface Window {
opener: any opener: any
} }
declare interface MyResponseType {
code: number;
msg: string;
data: any;
}
declare type Recordable<T = any> = Record<string, T> declare type Recordable<T = any> = Record<string, T>

5295
yarn.lock

File diff suppressed because it is too large Load Diff