mirror of
https://gitee.com/dromara/go-view.git
synced 2026-02-10 00:03:02 +08:00
Compare commits
80 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f15e0cd15f | ||
|
|
aa17e93966 | ||
|
|
feb9796449 | ||
|
|
e4b641a9c9 | ||
|
|
0cd31f48c1 | ||
|
|
e35e98c023 | ||
|
|
352a1742cf | ||
|
|
11cd4d0da1 | ||
|
|
8987dd1682 | ||
|
|
ff1384c825 | ||
|
|
1af7ae865d | ||
|
|
0e42f4ff35 | ||
|
|
cfcc262fd6 | ||
|
|
36ca877d49 | ||
|
|
3bad7ec758 | ||
|
|
e1e26cafcf | ||
|
|
99cd66c835 | ||
|
|
e4aac1597f | ||
|
|
2dc7bc3b61 | ||
|
|
07b7eec457 | ||
|
|
eaab8d1d49 | ||
|
|
7bc6ff7619 | ||
|
|
9903e73a69 | ||
|
|
7f1c001c99 | ||
|
|
67f6dcd1fe | ||
|
|
de60c7cde5 | ||
|
|
889e5075ba | ||
|
|
2bba1dcae0 | ||
|
|
9d81159141 | ||
|
|
f8ebaa60b1 | ||
|
|
02ec3c78d6 | ||
|
|
21ba5c02b0 | ||
|
|
500795b7e5 | ||
|
|
8230757bd1 | ||
|
|
c1de1f9db6 | ||
|
|
1b0591ee62 | ||
|
|
5ea963fb93 | ||
|
|
3ee5faa248 | ||
|
|
ab9b79e8a8 | ||
|
|
be014225c1 | ||
|
|
b6a78c64ed | ||
|
|
9855d28e33 | ||
|
|
16fb258908 | ||
|
|
936d78975e | ||
|
|
52ed72e502 | ||
|
|
6f9993e9e8 | ||
|
|
3347e3b12a | ||
|
|
b4a5ff7935 | ||
|
|
a25f9bc5a1 | ||
|
|
e75e2ccfe6 | ||
|
|
5454f19f3d | ||
|
|
b95cf946a8 | ||
|
|
1b9a3f6f5b | ||
|
|
d91cd00310 | ||
|
|
e4f821f46d | ||
|
|
ed5a452e2f | ||
|
|
907a0afb77 | ||
|
|
b32c718780 | ||
|
|
adbdad1e88 | ||
|
|
f8229a0518 | ||
|
|
3d568f08de | ||
|
|
48f00e44f6 | ||
|
|
5cc20e9b19 | ||
|
|
dec1130ace | ||
|
|
e3a294eb00 | ||
|
|
104551b600 | ||
|
|
5c6bf57de1 | ||
|
|
b0cb3addbd | ||
|
|
8c089b800a | ||
|
|
44199fa4c4 | ||
|
|
77ff4cdffd | ||
|
|
5e20689356 | ||
|
|
9a9b752a96 | ||
|
|
1ddf056ca6 | ||
|
|
572ab73c92 | ||
|
|
dde92bfe60 | ||
|
|
afc8f907ce | ||
|
|
f6bad1513b | ||
|
|
fce514c490 | ||
|
|
30a9deaee7 |
@@ -1,7 +1,5 @@
|
||||
## 总览
|
||||
|
||||

|
||||
|
||||
**`master-fetch` 分支是带有后端接口请求的分支**
|
||||
|
||||
**后端项目地址:[https://gitee.com/MTrun/go-view-serve](https://gitee.com/MTrun/go-view-serve)**
|
||||
@@ -14,12 +12,6 @@
|
||||
|
||||
接口地址修改:`.env`
|
||||
|
||||
### 🤯 后端项目
|
||||
|
||||
后端项目gitee地址:[https://gitee.com/MTrun/go-view-serve](https://gitee.com/MTrun/go-view-serve)
|
||||
|
||||
接口说明地址:[https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb](https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb)
|
||||
|
||||
```shell
|
||||
# port
|
||||
VITE_DEV_PORT = '8080'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import path from 'path'
|
||||
export const OUTPUT_DIR = 'dist'
|
||||
|
||||
// monaco-editor 路径
|
||||
@@ -6,7 +7,7 @@ export const prefix = `monaco-editor/esm/vs`
|
||||
// chunk 警告大小
|
||||
export const chunkSizeWarningLimit = 2000
|
||||
|
||||
// 禁用 brotli 压缩大小报告
|
||||
// 禁用 brotliSize 压缩大小报告
|
||||
export const brotliSize = false
|
||||
|
||||
// 分包
|
||||
@@ -14,7 +15,12 @@ export const rollupOptions = {
|
||||
output: {
|
||||
chunkFileNames: 'static/js/[name]-[hash].js',
|
||||
entryFileNames: 'static/js/[name]-[hash].js',
|
||||
assetFileNames: 'static/[ext]/[name]-[hash].[ext]',
|
||||
assetFileNames: (chunkInfo) => {
|
||||
if(['.png', '.jpg', '.jpeg'].includes(path.extname(chunkInfo.name))) {
|
||||
return `static/[ext]/[name].[ext]`
|
||||
}
|
||||
return `static/[ext]/[name]-[hash].[ext]`
|
||||
},
|
||||
manualChunks: {
|
||||
jsonWorker: [`${prefix}/language/json/json.worker`],
|
||||
cssWorker: [`${prefix}/language/css/css.worker`],
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "go-view",
|
||||
"version": "2.1.1",
|
||||
"version": "2.1.3",
|
||||
"scripts": {
|
||||
"dev": "vite --host",
|
||||
"build": "vue-tsc --noEmit && vite build",
|
||||
|
||||
6
pnpm-lock.yaml
generated
6
pnpm-lock.yaml
generated
@@ -3074,7 +3074,7 @@ packages:
|
||||
source-map: 0.6.1
|
||||
wordwrap: 1.0.0
|
||||
optionalDependencies:
|
||||
uglify-js: 3.16.0
|
||||
uglify-js: 3.17.4
|
||||
dev: true
|
||||
|
||||
/hard-rejection/2.1.0:
|
||||
@@ -5014,8 +5014,8 @@ packages:
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/uglify-js/3.16.0:
|
||||
resolution: {integrity: sha512-FEikl6bR30n0T3amyBh3LoiBdqHRy/f4H80+My34HOesOKyHfOsxAPAxOoqC0JUnC1amnO0IwkYC3sko51caSw==}
|
||||
/uglify-js/3.17.4:
|
||||
resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==}
|
||||
engines: {node: '>=0.8.0'}
|
||||
hasBin: true
|
||||
requiresBuild: true
|
||||
|
||||
@@ -1,17 +1,27 @@
|
||||
import axios, { AxiosResponse, AxiosRequestConfig } from 'axios'
|
||||
import { ResultEnum } from "@/enums/httpEnum"
|
||||
import axios, { AxiosResponse, AxiosRequestConfig, Axios } from 'axios'
|
||||
import { ResultEnum, ModuleTypeEnum } from "@/enums/httpEnum"
|
||||
import { PageEnum, ErrorPageNameMap } from "@/enums/pageEnum"
|
||||
import { StorageEnum } from '@/enums/storageEnum'
|
||||
import { axiosPre } from '@/settings/httpSetting'
|
||||
import { SystemStoreEnum, SystemStoreUserInfoEnum } from '@/store/modules/systemStore/systemStore.d'
|
||||
import { redirectErrorPage, getLocalStorage, routerTurnByName, httpErrorHandle } from '@/utils'
|
||||
import { redirectErrorPage, getLocalStorage, routerTurnByName, isPreview } from '@/utils'
|
||||
import { fetchAllowList } from './axios.config'
|
||||
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({
|
||||
baseURL: `${import.meta.env.PROD ? import.meta.env.VITE_PRO_PATH : ''}${axiosPre}`,
|
||||
timeout: ResultEnum.TIMEOUT,
|
||||
})
|
||||
}) as unknown as MyRequestInstance
|
||||
|
||||
axiosInstance.interceptors.request.use(
|
||||
(config: AxiosRequestConfig) => {
|
||||
@@ -39,6 +49,10 @@ axiosInstance.interceptors.request.use(
|
||||
// 响应拦截器
|
||||
axiosInstance.interceptors.response.use(
|
||||
(res: AxiosResponse) => {
|
||||
// 预览页面错误不进行处理
|
||||
if (isPreview()) {
|
||||
return Promise.resolve(res.data)
|
||||
}
|
||||
const { code } = res.data as { code: number }
|
||||
|
||||
// 成功
|
||||
|
||||
@@ -9,16 +9,16 @@ import {
|
||||
} from '@/enums/httpEnum'
|
||||
import type { RequestGlobalConfigType, RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
|
||||
|
||||
export const get = (url: string, params?: object) => {
|
||||
return axiosInstance({
|
||||
export const get = <T = any>(url: string, params?: object) => {
|
||||
return axiosInstance<T>({
|
||||
url: url,
|
||||
method: RequestHttpEnum.GET,
|
||||
params: params,
|
||||
})
|
||||
}
|
||||
|
||||
export const post = (url: string, data?: object, headersType?: string) => {
|
||||
return axiosInstance({
|
||||
export const post = <T = any>(url: string, data?: object, headersType?: string) => {
|
||||
return axiosInstance<T>({
|
||||
url: url,
|
||||
method: RequestHttpEnum.POST,
|
||||
data: data,
|
||||
@@ -28,8 +28,8 @@ export const post = (url: string, data?: object, headersType?: string) => {
|
||||
})
|
||||
}
|
||||
|
||||
export const patch = (url: string, data?: object, headersType?: string) => {
|
||||
return axiosInstance({
|
||||
export const patch = <T = any>(url: string, data?: object, headersType?: string) => {
|
||||
return axiosInstance<T>({
|
||||
url: url,
|
||||
method: RequestHttpEnum.PATCH,
|
||||
data: data,
|
||||
@@ -39,8 +39,8 @@ export const patch = (url: string, data?: object, headersType?: string) => {
|
||||
})
|
||||
}
|
||||
|
||||
export const put = (url: string, data?: object, headersType?: ContentTypeEnum) => {
|
||||
return axiosInstance({
|
||||
export const put = <T = any>(url: string, data?: object, headersType?: ContentTypeEnum) => {
|
||||
return axiosInstance<T>({
|
||||
url: url,
|
||||
method: RequestHttpEnum.PUT,
|
||||
data: data,
|
||||
@@ -50,8 +50,8 @@ export const put = (url: string, data?: object, headersType?: ContentTypeEnum) =
|
||||
})
|
||||
}
|
||||
|
||||
export const del = (url: string, params?: object) => {
|
||||
return axiosInstance({
|
||||
export const del = <T = any>(url: string, params?: object) => {
|
||||
return axiosInstance<T>({
|
||||
url: url,
|
||||
method: RequestHttpEnum.DELETE,
|
||||
params
|
||||
@@ -82,11 +82,11 @@ export const http = (type?: RequestHttpEnum) => {
|
||||
}
|
||||
const prefix = 'javascript:'
|
||||
// 对输入字符进行转义处理
|
||||
export const translateStr = (target: string | object) => {
|
||||
export const translateStr = (target: string | Record<any, any>) => {
|
||||
if (typeof target === 'string') {
|
||||
if (target.startsWith(prefix)) {
|
||||
const funcStr = target.split(prefix)[1]
|
||||
let result;
|
||||
let result
|
||||
try {
|
||||
result = new Function(`${funcStr}`)()
|
||||
} catch (error) {
|
||||
@@ -100,8 +100,8 @@ export const translateStr = (target: string | object) => {
|
||||
}
|
||||
for (const key in target) {
|
||||
if (Object.prototype.hasOwnProperty.call(target, key)) {
|
||||
const subTarget = (target as any)[key];
|
||||
(target as any)[key] = translateStr(subTarget)
|
||||
const subTarget = target[key]
|
||||
target[key] = translateStr(subTarget)
|
||||
}
|
||||
}
|
||||
return target
|
||||
@@ -116,7 +116,6 @@ export const customizeHttp = (targetParams: RequestConfigType, globalParams: Req
|
||||
if (!targetParams || !globalParams) {
|
||||
return
|
||||
}
|
||||
|
||||
// 全局
|
||||
const {
|
||||
// 全局请求源地址
|
||||
|
||||
@@ -1,84 +1,98 @@
|
||||
import { http } from '@/api/http'
|
||||
import { httpErrorHandle } from '@/utils'
|
||||
import { ContentTypeEnum, RequestHttpEnum, ModuleTypeEnum } from '@/enums/httpEnum'
|
||||
import { ProjectItem, ProjectDetail } from './project'
|
||||
|
||||
// * 项目列表
|
||||
export const projectListApi = async (data: object) => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.GET)(`${ModuleTypeEnum.PROJECT}/list`, data);
|
||||
return res;
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.GET)<ProjectItem[]>(`${ModuleTypeEnum.PROJECT}/list`, data)
|
||||
return res
|
||||
} catch {
|
||||
httpErrorHandle();
|
||||
httpErrorHandle()
|
||||
}
|
||||
}
|
||||
|
||||
// * 新增项目
|
||||
export const createProjectApi = async (data: object) => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.POST)(`${ModuleTypeEnum.PROJECT}/create`, data);
|
||||
return res;
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.POST)<{
|
||||
/**
|
||||
* 项目id
|
||||
*/
|
||||
id: number
|
||||
}>(`${ModuleTypeEnum.PROJECT}/create`, data)
|
||||
return res
|
||||
} catch {
|
||||
httpErrorHandle();
|
||||
httpErrorHandle()
|
||||
}
|
||||
}
|
||||
|
||||
// * 获取项目
|
||||
export const fetchProjectApi = async (data: object) => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.GET)(`${ModuleTypeEnum.PROJECT}/getData`, data);
|
||||
return res;
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.GET)<ProjectDetail>(`${ModuleTypeEnum.PROJECT}/getData`, data)
|
||||
return res
|
||||
} catch {
|
||||
httpErrorHandle();
|
||||
httpErrorHandle()
|
||||
}
|
||||
}
|
||||
|
||||
// * 保存项目
|
||||
export const saveProjectApi = async (data: object) => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.POST)(`${ModuleTypeEnum.PROJECT}/save/data`, data, ContentTypeEnum.FORM_URLENCODED);
|
||||
return res;
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.POST)(
|
||||
`${ModuleTypeEnum.PROJECT}/save/data`,
|
||||
data,
|
||||
ContentTypeEnum.FORM_URLENCODED
|
||||
)
|
||||
return res
|
||||
} catch {
|
||||
httpErrorHandle();
|
||||
httpErrorHandle()
|
||||
}
|
||||
}
|
||||
|
||||
// * 修改项目基础信息
|
||||
export const updateProjectApi = async (data: object) => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.POST)(`${ModuleTypeEnum.PROJECT}/edit`, data);
|
||||
return res;
|
||||
const res = await http(RequestHttpEnum.POST)(`${ModuleTypeEnum.PROJECT}/edit`, data)
|
||||
return res
|
||||
} catch {
|
||||
httpErrorHandle();
|
||||
httpErrorHandle()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * 删除项目
|
||||
export const deleteProjectApi = async (data: object) => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.DELETE)(`${ModuleTypeEnum.PROJECT}/delete`, data);
|
||||
return res;
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.DELETE)(`${ModuleTypeEnum.PROJECT}/delete`, data)
|
||||
return res
|
||||
} catch {
|
||||
httpErrorHandle();
|
||||
httpErrorHandle()
|
||||
}
|
||||
}
|
||||
|
||||
// * 修改发布状态 [-1未发布,1发布]
|
||||
export const changeProjectReleaseApi = async (data: object) => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.PUT)(`${ModuleTypeEnum.PROJECT}/publish`, data);
|
||||
return res;
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.PUT)(`${ModuleTypeEnum.PROJECT}/publish`, data)
|
||||
return res
|
||||
} catch {
|
||||
httpErrorHandle();
|
||||
httpErrorHandle()
|
||||
}
|
||||
}
|
||||
|
||||
// * 上传文件
|
||||
export const uploadFile = async (data: object) => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.POST)(`${ModuleTypeEnum.PROJECT}/upload`, data, ContentTypeEnum.FORM_DATA);
|
||||
return res;
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.POST)<{
|
||||
/**
|
||||
* 文件地址
|
||||
*/
|
||||
fileName: string
|
||||
}>(`${ModuleTypeEnum.PROJECT}/upload`, data, ContentTypeEnum.FORM_DATA)
|
||||
return res
|
||||
} catch {
|
||||
httpErrorHandle();
|
||||
httpErrorHandle()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
39
src/api/path/project.d.ts
vendored
Normal file
39
src/api/path/project.d.ts
vendored
Normal 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
|
||||
}
|
||||
@@ -1,33 +1,39 @@
|
||||
import { http } from '@/api/http'
|
||||
import { httpErrorHandle } from '@/utils'
|
||||
import { RequestHttpEnum, ModuleTypeEnum } from '@/enums/httpEnum'
|
||||
import { LoginResult } from './system'
|
||||
|
||||
// * 登录
|
||||
export const loginApi = async (data: object) => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.POST)(`${ModuleTypeEnum.SYSTEM}/login`, data);
|
||||
return res;
|
||||
} catch(err) {
|
||||
httpErrorHandle();
|
||||
const res = await http(RequestHttpEnum.POST)<LoginResult>(`${ModuleTypeEnum.SYSTEM}/login`, data)
|
||||
return res
|
||||
} catch (err) {
|
||||
httpErrorHandle()
|
||||
}
|
||||
}
|
||||
|
||||
// * 登出
|
||||
export const logoutApi = async () => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.GET)(`${ModuleTypeEnum.SYSTEM}/logout`);
|
||||
return res;
|
||||
} catch(err) {
|
||||
httpErrorHandle();
|
||||
const res = await http(RequestHttpEnum.GET)(`${ModuleTypeEnum.SYSTEM}/logout`)
|
||||
return res
|
||||
} catch (err) {
|
||||
httpErrorHandle()
|
||||
}
|
||||
}
|
||||
|
||||
// * 获取 oss 上传接口
|
||||
export const ossUrlApi = async (data: object) => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.GET)(`${ModuleTypeEnum.SYSTEM}/getOssInfo`, data);
|
||||
return res;
|
||||
} catch(err) {
|
||||
httpErrorHandle();
|
||||
const res = await http(RequestHttpEnum.GET)<{
|
||||
/**
|
||||
* bucket 地址
|
||||
*/
|
||||
bucketURL?: string
|
||||
}>(`${ModuleTypeEnum.SYSTEM}/getOssInfo`, data)
|
||||
return res
|
||||
} catch (err) {
|
||||
httpErrorHandle()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
26
src/api/path/system.d.ts
vendored
Normal file
26
src/api/path/system.d.ts
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
export interface LoginResult {
|
||||
token: {
|
||||
/**
|
||||
* token 值
|
||||
*/
|
||||
tokenValue: string
|
||||
/**
|
||||
* token key
|
||||
*/
|
||||
tokenName: string
|
||||
}
|
||||
userinfo: {
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
nickname: string
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
username: string
|
||||
/**
|
||||
* 用户 id
|
||||
*/
|
||||
id: string
|
||||
}
|
||||
}
|
||||
BIN
src/assets/images/canvas/noData.png
Normal file
BIN
src/assets/images/canvas/noData.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.9 KiB |
@@ -42,15 +42,21 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from 'vue'
|
||||
import { icon } from '@/plugins'
|
||||
|
||||
const { HelpOutlineIcon, CloseIcon } = icon.ionicons5
|
||||
const emit = defineEmits(['update:modelShow'])
|
||||
|
||||
defineProps({
|
||||
const props = defineProps({
|
||||
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 = () => {
|
||||
emit('update:modelShow', false)
|
||||
}
|
||||
|
||||
@@ -69,21 +69,20 @@
|
||||
</template>
|
||||
|
||||
<script script lang="ts" setup>
|
||||
import { reactive } from 'vue'
|
||||
import { reactive, ref, watch } from 'vue'
|
||||
import { ListType } from './index.d'
|
||||
import { useSettingStore } from '@/store/modules/settingStore/settingStore'
|
||||
import { SettingStoreEnums, ToolsStatusEnum } from '@/store/modules/settingStore/settingStore.d'
|
||||
import { icon } from '@/plugins'
|
||||
|
||||
const { HelpOutlineIcon, CloseIcon } = icon.ionicons5
|
||||
|
||||
const emit = defineEmits(['update:modelShow'])
|
||||
|
||||
defineProps({
|
||||
const props = defineProps({
|
||||
modelShow: Boolean
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:modelShow'])
|
||||
const { HelpOutlineIcon, CloseIcon } = icon.ionicons5
|
||||
const settingStore = useSettingStore()
|
||||
const modelShow = ref(false)
|
||||
|
||||
const list = reactive<ListType[]>([
|
||||
{
|
||||
@@ -168,6 +167,10 @@ const list = reactive<ListType[]>([
|
||||
}
|
||||
])
|
||||
|
||||
watch(() => props.modelShow, (newValue) => {
|
||||
modelShow.value = newValue
|
||||
})
|
||||
|
||||
const closeHandle = () => {
|
||||
emit('update:modelShow', false)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,9 @@
|
||||
<script lang="ts" setup>
|
||||
import { h, ref } from 'vue'
|
||||
import { NAvatar, NText } from 'naive-ui'
|
||||
import { renderIcon } from '@/utils'
|
||||
import { renderIcon, getLocalStorage } from '@/utils'
|
||||
import { SystemStoreEnum, SystemStoreUserInfoEnum } from '@/store/modules/systemStore/systemStore.d'
|
||||
import { StorageEnum } from '@/enums/storageEnum'
|
||||
import { logout, renderLang } from '@/utils'
|
||||
import { GoSystemSet } from '@/components/GoSystemSet/index'
|
||||
import { GoSystemInfo } from '@/components/GoSystemInfo/index'
|
||||
@@ -64,7 +66,17 @@ const renderUserInfo = () => {
|
||||
}),
|
||||
h('div', null, [
|
||||
h('div', null, [
|
||||
h(NText, { depth: 2 }, { default: () => '奔跑的面条' })
|
||||
h(NText, { depth: 2 }, {
|
||||
default: () => {
|
||||
const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE)
|
||||
if (info) {
|
||||
return info[SystemStoreEnum.USER_INFO][SystemStoreUserInfoEnum.USER_NAME];
|
||||
}
|
||||
else {
|
||||
return 'admin';
|
||||
}
|
||||
}
|
||||
})
|
||||
])
|
||||
])
|
||||
]
|
||||
@@ -137,4 +149,4 @@ const handleSelect = (key: string) => {
|
||||
cursor: pointer;
|
||||
transform: scale(0.7);
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -99,6 +99,7 @@ const colorSelectHandle = (color: AppThemeColorType) => {
|
||||
overflow: hidden;
|
||||
border-radius: 5px;
|
||||
@extend .go-background-filter-shallow;
|
||||
backdrop-filter: none;
|
||||
}
|
||||
&-color {
|
||||
width: 8px;
|
||||
|
||||
@@ -20,7 +20,9 @@ export enum RequestDataTypeEnum {
|
||||
// 静态数据
|
||||
STATIC = 0,
|
||||
// 请求数据
|
||||
AJAX = 1
|
||||
AJAX = 1,
|
||||
// 数据池
|
||||
Pond = 2
|
||||
}
|
||||
|
||||
// 请求主体类型
|
||||
|
||||
@@ -3,5 +3,6 @@ export * from '@/hooks/usePreviewScale.hook'
|
||||
export * from '@/hooks/useCode.hook'
|
||||
export * from '@/hooks/useChartDataFetch.hook'
|
||||
export * from '@/hooks/useSystemInit.hook'
|
||||
export * from '@/hooks/useChartDataPondFetch.hook'
|
||||
export * from '@/hooks/useLifeHandler.hook'
|
||||
export * from '@/hooks/useLang.hook'
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ref, toRefs, toRaw } from 'vue'
|
||||
import type VChart from 'vue-echarts'
|
||||
import { customizeHttp } from '@/api/http'
|
||||
import { useChartDataPondFetch } from '@/hooks/'
|
||||
import { CreateComponentType, ChartFrameEnum } from '@/packages/index.d'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { RequestDataTypeEnum } from '@/enums/httpEnum'
|
||||
@@ -23,6 +24,21 @@ export const useChartDataFetch = (
|
||||
const vChartRef = ref<typeof VChart | null>(null)
|
||||
let fetchInterval: any = 0
|
||||
|
||||
// 数据池
|
||||
const { addGlobalDataInterface } = useChartDataPondFetch()
|
||||
|
||||
// 组件类型
|
||||
const { chartFrame } = targetComponent.chartConfig
|
||||
|
||||
// eCharts 组件配合 vChart 库更新方式
|
||||
const echartsUpdateHandle = (dataset: any) => {
|
||||
if (chartFrame === ChartFrameEnum.ECHARTS) {
|
||||
if (vChartRef.value) {
|
||||
vChartRef.value.setOption({ dataset: dataset })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const requestIntervalFn = () => {
|
||||
const chartEditStore = useChartEditStore()
|
||||
|
||||
@@ -41,9 +57,6 @@ export const useChartDataFetch = (
|
||||
requestInterval: targetInterval
|
||||
} = toRefs(targetComponent.request)
|
||||
|
||||
// 组件类型
|
||||
const { chartFrame } = targetComponent.chartConfig
|
||||
|
||||
// 非请求类型
|
||||
if (requestDataType.value !== RequestDataTypeEnum.AJAX) return
|
||||
|
||||
@@ -58,16 +71,11 @@ export const useChartDataFetch = (
|
||||
clearInterval(fetchInterval)
|
||||
|
||||
const fetchFn = async () => {
|
||||
const res = await customizeHttp(toRaw(targetComponent.request), toRaw(chartEditStore.requestGlobalConfig))
|
||||
const res = await customizeHttp(toRaw(targetComponent.request), toRaw(chartEditStore.getRequestGlobalConfig))
|
||||
if (res) {
|
||||
try {
|
||||
const filter = targetComponent.filter
|
||||
// eCharts 组件配合 vChart 库更新方式
|
||||
if (chartFrame === ChartFrameEnum.ECHARTS) {
|
||||
if (vChartRef.value) {
|
||||
vChartRef.value.setOption({ dataset: newFunctionHandle(res?.data, res, filter) })
|
||||
}
|
||||
}
|
||||
echartsUpdateHandle(newFunctionHandle(res?.data, res, filter))
|
||||
// 更新回调函数
|
||||
if (updateCallback) {
|
||||
updateCallback(newFunctionHandle(res?.data, res, filter))
|
||||
@@ -80,7 +88,6 @@ export const useChartDataFetch = (
|
||||
|
||||
// 立即调用
|
||||
fetchFn()
|
||||
|
||||
// 定时时间
|
||||
const time = targetInterval && targetInterval.value ? targetInterval.value : globalRequestInterval.value
|
||||
// 单位
|
||||
@@ -94,6 +101,11 @@ export const useChartDataFetch = (
|
||||
}
|
||||
}
|
||||
|
||||
isPreview() && requestIntervalFn()
|
||||
if (isPreview()) {
|
||||
// 判断是否是数据池类型
|
||||
targetComponent.request.requestDataType === RequestDataTypeEnum.Pond
|
||||
? addGlobalDataInterface(targetComponent, useChartEditStore, updateCallback || echartsUpdateHandle)
|
||||
: requestIntervalFn()
|
||||
}
|
||||
return { vChartRef }
|
||||
}
|
||||
|
||||
115
src/hooks/useChartDataPondFetch.hook.ts
Normal file
115
src/hooks/useChartDataPondFetch.hook.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
import { toRaw } from 'vue'
|
||||
import { customizeHttp } from '@/api/http'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { RequestGlobalConfigType, RequestDataPondItemType } from '@/store/modules/chartEditStore/chartEditStore.d'
|
||||
import { newFunctionHandle, intervalUnitHandle } from '@/utils'
|
||||
|
||||
// 获取类型
|
||||
type ChartEditStoreType = typeof useChartEditStore
|
||||
|
||||
// 数据池存储的数据类型
|
||||
type DataPondMapType = {
|
||||
updateCallback: (...args: any) => any
|
||||
filter?: string | undefined
|
||||
}
|
||||
|
||||
// 数据池 Map 中请求对应 callback
|
||||
const mittDataPondMap = new Map<string, DataPondMapType[]>()
|
||||
|
||||
// 创建单个数据项轮询接口
|
||||
const newPondItemInterval = (
|
||||
requestGlobalConfig: RequestGlobalConfigType,
|
||||
requestDataPondItem: RequestDataPondItemType,
|
||||
dataPondMapItem?: DataPondMapType[]
|
||||
) => {
|
||||
if (!dataPondMapItem) return
|
||||
let fetchInterval: any = 0
|
||||
|
||||
clearInterval(fetchInterval)
|
||||
|
||||
// 请求
|
||||
const fetchFn = async () => {
|
||||
try {
|
||||
const res = await customizeHttp(toRaw(requestDataPondItem.dataPondRequestConfig), toRaw(requestGlobalConfig))
|
||||
|
||||
if (res) {
|
||||
try {
|
||||
// 遍历更新回调函数
|
||||
dataPondMapItem.forEach(item => {
|
||||
item.updateCallback(newFunctionHandle(res?.data, res, item.filter))
|
||||
})
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return error
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
return error
|
||||
}
|
||||
}
|
||||
|
||||
// 立即调用
|
||||
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))
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据池接口处理
|
||||
*/
|
||||
export const useChartDataPondFetch = () => {
|
||||
// 新增全局接口
|
||||
const addGlobalDataInterface = (
|
||||
targetComponent: CreateComponentType,
|
||||
useChartEditStore: ChartEditStoreType,
|
||||
updateCallback: (...args: any) => any
|
||||
) => {
|
||||
const chartEditStore = useChartEditStore()
|
||||
const { requestDataPond } = chartEditStore.getRequestGlobalConfig
|
||||
|
||||
// 组件对应的数据池 Id
|
||||
const requestDataPondId = targetComponent.request.requestDataPondId as string
|
||||
// 新增数据项
|
||||
const mittPondIdArr = mittDataPondMap.get(requestDataPondId) || []
|
||||
mittPondIdArr.push({
|
||||
updateCallback: updateCallback,
|
||||
filter: targetComponent.filter
|
||||
})
|
||||
mittDataPondMap.set(requestDataPondId, mittPondIdArr)
|
||||
}
|
||||
|
||||
// 清除旧数据
|
||||
const clearMittDataPondMap = () => {
|
||||
mittDataPondMap.clear()
|
||||
}
|
||||
|
||||
// 初始化数据池
|
||||
const initDataPond = (requestGlobalConfig: RequestGlobalConfigType) => {
|
||||
const { requestDataPond } = requestGlobalConfig
|
||||
// 根据 mapId 查找对应的数据池配置
|
||||
for (let pondKey of mittDataPondMap.keys()) {
|
||||
const requestDataPondItem = requestDataPond.find(item => item.dataPondId === pondKey)
|
||||
if (requestDataPondItem) {
|
||||
newPondItemInterval(requestGlobalConfig, requestDataPondItem, mittDataPondMap.get(pondKey))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
addGlobalDataInterface,
|
||||
clearMittDataPondMap,
|
||||
initDataPond
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CreateComponentType, EventLife } from '@/packages/index.d'
|
||||
import { CreateComponentType, CreateComponentGroupType, EventLife, BaseEvent } from '@/packages/index.d'
|
||||
import * as echarts from 'echarts'
|
||||
|
||||
// 所有图表组件集合对象
|
||||
@@ -7,26 +7,57 @@ const components: { [K in string]?: any } = {}
|
||||
// 项目提供的npm 包变量
|
||||
export const npmPkgs = { echarts }
|
||||
|
||||
export const useLifeHandler = (chartConfig: CreateComponentType) => {
|
||||
const events = chartConfig.events || {}
|
||||
// 组件事件处理 hook
|
||||
export const useLifeHandler = (chartConfig: CreateComponentType | CreateComponentGroupType) => {
|
||||
if (!chartConfig.events) return {}
|
||||
|
||||
// 处理基础事件
|
||||
const baseEvent: { [key: string]: any } = {}
|
||||
for (const key in chartConfig.events.baseEvent) {
|
||||
const fnStr: string | undefined = (chartConfig.events.baseEvent as any)[key]
|
||||
// 动态绑定基础事件
|
||||
if (fnStr) {
|
||||
baseEvent[key] = generateBaseFunc(fnStr)
|
||||
}
|
||||
}
|
||||
|
||||
// 生成生命周期事件
|
||||
const events = chartConfig.events.advancedEvents || {}
|
||||
const lifeEvents = {
|
||||
[EventLife.BEFORE_MOUNT](e: any) {
|
||||
[EventLife.VNODE_BEFORE_MOUNT](e: any) {
|
||||
// 存储组件
|
||||
components[chartConfig.id] = e.component
|
||||
const fnStr = (events[EventLife.BEFORE_MOUNT] || '').trim()
|
||||
const fnStr = (events[EventLife.VNODE_BEFORE_MOUNT] || '').trim()
|
||||
generateFunc(fnStr, e)
|
||||
},
|
||||
[EventLife.MOUNTED](e: any) {
|
||||
const fnStr = (events[EventLife.MOUNTED] || '').trim()
|
||||
[EventLife.VNODE_MOUNTED](e: any) {
|
||||
const fnStr = (events[EventLife.VNODE_MOUNTED] || '').trim()
|
||||
generateFunc(fnStr, e)
|
||||
}
|
||||
}
|
||||
return lifeEvents
|
||||
return { ...baseEvent, ...lifeEvents }
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 生成基础函数
|
||||
* @param fnStr 用户方法体代码
|
||||
* @param event 鼠标事件
|
||||
*/
|
||||
export function generateBaseFunc(fnStr: string) {
|
||||
try {
|
||||
return new Function(`
|
||||
return (
|
||||
async function(mouseEvent){
|
||||
${fnStr}
|
||||
}
|
||||
)`)()
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成高级函数
|
||||
* @param fnStr 用户方法体代码
|
||||
* @param e 执行生命周期的动态组件实例
|
||||
*/
|
||||
|
||||
@@ -10,8 +10,8 @@ export const useSystemInit = async () => {
|
||||
|
||||
// 获取 OSS 信息的 url 地址,用来拼接展示图片的地址
|
||||
const getOssUrl = async () => {
|
||||
const res = await ossUrlApi({}) as unknown as MyResponseType
|
||||
if (res.code === ResultEnum.SUCCESS) {
|
||||
const res = await ossUrlApi({})
|
||||
if (res && res.code === ResultEnum.SUCCESS) {
|
||||
systemStore.setItem(SystemStoreEnum.FETCH_INFO, {
|
||||
OSSUrl: res.data?.bucketURL
|
||||
})
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from './axis'
|
||||
export * from './line'
|
||||
export * from './line'
|
||||
export * from './label'
|
||||
7
src/packages/chartConfiguration/echarts/label.ts
Normal file
7
src/packages/chartConfiguration/echarts/label.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export const labelConfig = {
|
||||
position: [
|
||||
{ label: '外侧', value: 'outside' },
|
||||
{ label: '内部', value: 'inside' },
|
||||
{ label: '中心', value: 'center' }
|
||||
]
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
<div
|
||||
v-if="state.mergedConfig"
|
||||
class="go-dv-capsule-chart"
|
||||
:style="{
|
||||
:style="{
|
||||
fontSize: numberSizeHandle(state.mergedConfig.valueFontSize),
|
||||
paddingLeft: numberSizeHandle(state.mergedConfig.paddingLeft),
|
||||
paddingRight: numberSizeHandle(state.mergedConfig.paddingRight)
|
||||
@@ -53,11 +53,10 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, watch, reactive, PropType } from 'vue'
|
||||
import merge from 'lodash/merge'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
import { useChartDataFetch } from '@/hooks'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import config, { option } from './config'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
|
||||
type DataProps = {
|
||||
name: string | number
|
||||
@@ -114,12 +113,11 @@ watch(
|
||||
|
||||
const calcData = (data: any) => {
|
||||
mergeConfig(props.chartConfig.option)
|
||||
|
||||
calcCapsuleLengthAndLabelData()
|
||||
}
|
||||
|
||||
const mergeConfig = (data: any) => {
|
||||
state.mergedConfig = merge(cloneDeep(state.defaultConfig), data || {})
|
||||
state.mergedConfig = cloneDeep(data || {})
|
||||
}
|
||||
|
||||
// 数据解析
|
||||
|
||||
@@ -2,6 +2,7 @@ import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
|
||||
import { LineCommonConfig } from './index'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import { defaultTheme, chartColorsSearch } from '@/settings/chartThemes/index'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
import dataJson from './data.json'
|
||||
|
||||
export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
|
||||
@@ -47,7 +48,7 @@ export const option = {
|
||||
|
||||
export default class Config extends PublicConfigClass implements CreateComponentType {
|
||||
public key: string = LineCommonConfig.key
|
||||
public chartConfig = LineCommonConfig
|
||||
public chartConfig = cloneDeep(LineCommonConfig)
|
||||
// 图表配置项
|
||||
public option = echartOptionProfixHandle(option, includes)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { LineGradientSingleConfig } from './index'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import { graphic } from 'echarts/core'
|
||||
import { defaultTheme, chartColorsSearch } from '@/settings/chartThemes/index'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
import dataJson from './data.json'
|
||||
|
||||
export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
|
||||
@@ -58,7 +59,7 @@ const options = {
|
||||
|
||||
export default class Config extends PublicConfigClass implements CreateComponentType {
|
||||
public key: string = LineGradientSingleConfig.key
|
||||
public chartConfig = LineGradientSingleConfig
|
||||
public chartConfig = cloneDeep(LineGradientSingleConfig)
|
||||
// 图表配置项
|
||||
public option = echartOptionProfixHandle(options, includes)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { LineGradientsConfig } from './index'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import { graphic } from 'echarts/core'
|
||||
import { defaultTheme, chartColorsSearch } from '@/settings/chartThemes/index'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
import dataJson from './data.json'
|
||||
|
||||
export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
|
||||
@@ -85,7 +86,7 @@ const option = {
|
||||
|
||||
export default class Config extends PublicConfigClass implements CreateComponentType {
|
||||
public key: string = LineGradientsConfig.key
|
||||
public chartConfig = LineGradientsConfig
|
||||
public chartConfig = cloneDeep(LineGradientsConfig)
|
||||
// 图表配置项
|
||||
public option = echartOptionProfixHandle(option, includes)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
|
||||
import { LineLinearSingleConfig } from './index'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import { defaultTheme, chartColorsSearch } from '@/settings/chartThemes/index'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
import dataJson from './data.json'
|
||||
|
||||
export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
|
||||
@@ -54,7 +55,7 @@ export const option = {
|
||||
|
||||
export default class Config extends PublicConfigClass implements CreateComponentType {
|
||||
public key: string = LineLinearSingleConfig.key
|
||||
public chartConfig = LineLinearSingleConfig
|
||||
public chartConfig = cloneDeep(LineLinearSingleConfig)
|
||||
// 图表配置项
|
||||
public option = echartOptionProfixHandle(option, includes)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
|
||||
import { MapBaseConfig } from './index'
|
||||
import { chartInitConfig } from '@/settings/designSetting'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
import dataJson from './data.json'
|
||||
|
||||
export const includes = []
|
||||
@@ -151,6 +152,6 @@ export const MapDefaultConfig = { ...option }
|
||||
export default class Config extends PublicConfigClass implements CreateComponentType {
|
||||
public key: string = MapBaseConfig.key
|
||||
public attr = { ...chartInitConfig, w: 750, h: 800, zIndex: -1 }
|
||||
public chartConfig = MapBaseConfig
|
||||
public chartConfig = cloneDeep(MapBaseConfig)
|
||||
public option = echartOptionProfixHandle(option, includes)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
|
||||
import { PieCircleConfig } from './index'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
|
||||
export const includes = []
|
||||
|
||||
@@ -57,7 +58,7 @@ const option = {
|
||||
export default class Config extends PublicConfigClass implements CreateComponentType {
|
||||
public key: string = PieCircleConfig.key
|
||||
|
||||
public chartConfig = PieCircleConfig
|
||||
public chartConfig = cloneDeep(PieCircleConfig)
|
||||
|
||||
// 图表配置项
|
||||
public option = echartOptionProfixHandle(option, includes)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
|
||||
import { PieCommonConfig } from './index'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
import dataJson from './data.json'
|
||||
|
||||
export const includes = ['legend']
|
||||
@@ -42,7 +43,9 @@ const option = {
|
||||
},
|
||||
label: {
|
||||
show: false,
|
||||
position: 'center'
|
||||
position: 'center',
|
||||
formatter: '{b}',
|
||||
fontSize:12
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
@@ -61,7 +64,7 @@ const option = {
|
||||
export default class Config extends PublicConfigClass implements CreateComponentType {
|
||||
public key: string = PieCommonConfig.key
|
||||
|
||||
public chartConfig = PieCommonConfig
|
||||
public chartConfig = cloneDeep(PieCommonConfig)
|
||||
|
||||
// 图表配置项
|
||||
public option = echartOptionProfixHandle(option, includes)
|
||||
|
||||
@@ -7,6 +7,48 @@
|
||||
<n-select v-model:value="optionData.type" size="small" :options="fontWeightOptions" />
|
||||
</SettingItem>
|
||||
</SettingItemBox>
|
||||
<SettingItemBox name="标签">
|
||||
<SettingItem>
|
||||
<n-space>
|
||||
<n-switch v-model:value="optionData.series[0].label.show" size="small"></n-switch>
|
||||
<n-text>展示标签</n-text>
|
||||
</n-space>
|
||||
</SettingItem>
|
||||
<setting-item>
|
||||
<n-space>
|
||||
<n-switch v-model:value="optionData.series[0].labelLine.show" size="small"></n-switch>
|
||||
<n-text>引导线</n-text>
|
||||
</n-space>
|
||||
</setting-item>
|
||||
<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>
|
||||
<n-space>
|
||||
<n-input-number
|
||||
v-model:value="optionData.series[0].itemStyle.borderRadius"
|
||||
size="small"
|
||||
:min="0"
|
||||
></n-input-number>
|
||||
<n-text>圆角大小</n-text>
|
||||
</n-space>
|
||||
</setting-item>
|
||||
<setting-item>
|
||||
<n-space>
|
||||
<n-input-number
|
||||
v-model:value="optionData.series[0].itemStyle.borderWidth"
|
||||
size="small"
|
||||
:min="0"
|
||||
></n-input-number>
|
||||
<n-text>线条宽度</n-text>
|
||||
</n-space>
|
||||
</setting-item>
|
||||
</setting-item-box>
|
||||
</CollapseItem>
|
||||
</template>
|
||||
|
||||
@@ -15,6 +57,7 @@ import { PropType, watch } from 'vue'
|
||||
import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
|
||||
import { GlobalSetting, CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
|
||||
import { PieTypeObject, PieTypeEnum } from './config'
|
||||
import { labelConfig } from '@/packages/chartConfiguration/echarts'
|
||||
|
||||
const props = defineProps({
|
||||
optionData: {
|
||||
@@ -36,4 +79,10 @@ const fontWeightOptions = [
|
||||
value: PieTypeObject[PieTypeEnum.ROSE]
|
||||
}
|
||||
]
|
||||
|
||||
const labelFormatterOptions = [
|
||||
{ label: '数据名', value: '{b}' },
|
||||
{ label: '百分比', value: '{d}' },
|
||||
{ label: '列名:百分比', value: '{b}:{d}%' }
|
||||
]
|
||||
</script>
|
||||
|
||||
@@ -6,7 +6,7 @@ export const FlipperNumberConfig: ConfigType = {
|
||||
key: 'FlipperNumber',
|
||||
chartKey: 'VFlipperNumber',
|
||||
conKey: 'VCFlipperNumber',
|
||||
title: '数字翻牌',
|
||||
title: '数字翻牌-需动态触发',
|
||||
category: ChatCategoryEnum.MORE,
|
||||
categoryName: ChatCategoryEnumName.MORE,
|
||||
package: PackagesCategoryEnum.DECORATES,
|
||||
|
||||
@@ -62,7 +62,7 @@ const status = reactive({
|
||||
const calcRowsData = () => {
|
||||
let { dataset, rowNum, sort } = status.mergedConfig
|
||||
// @ts-ignore
|
||||
sort && dataset.sort(({ value: a }, { value: b }) => {
|
||||
sort &&dataset.sort(({ value: a }, { value: b } ) => {
|
||||
if (a > b) return -1
|
||||
if (a < b) return 1
|
||||
if (a === b) return 0
|
||||
@@ -94,6 +94,7 @@ const calcHeights = (onresize = false) => {
|
||||
const { rowNum, dataset } = status.mergedConfig
|
||||
const avgHeight = h.value / rowNum
|
||||
status.avgHeight = avgHeight
|
||||
|
||||
if (!onresize) status.heights = new Array(dataset.length).fill(avgHeight)
|
||||
}
|
||||
|
||||
@@ -131,12 +132,17 @@ const stopAnimation = () => {
|
||||
const onRestart = async () => {
|
||||
try {
|
||||
if (!status.mergedConfig) return
|
||||
let { dataset, rowNum, sort } = status.mergedConfig
|
||||
stopAnimation()
|
||||
calcRowsData()
|
||||
calcHeights(true)
|
||||
animation(true)
|
||||
let flag = true
|
||||
if (dataset.length <= rowNum) {
|
||||
flag=false
|
||||
}
|
||||
calcHeights(flag)
|
||||
animation(flag)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
27
src/packages/index.d.ts
vendored
27
src/packages/index.d.ts
vendored
@@ -90,12 +90,24 @@ export const BlendModeEnumList = [
|
||||
{ label: '亮度', value: 'luminosity' }
|
||||
]
|
||||
|
||||
// 基础事件类型(vue不加 on)
|
||||
export enum BaseEvent {
|
||||
// 点击
|
||||
ON_CLICK = 'click',
|
||||
// 双击
|
||||
ON_DBL_CLICK = 'dblclick',
|
||||
// 移入
|
||||
ON_MOUSE_ENTER = 'mouseenter',
|
||||
// 移出
|
||||
ON_MOUSE_LEAVE = 'mouseleave',
|
||||
}
|
||||
|
||||
// vue3 生命周期事件
|
||||
export enum EventLife {
|
||||
export enum EventLife {
|
||||
// 渲染之后
|
||||
MOUNTED = 'vnodeMounted',
|
||||
VNODE_MOUNTED = 'vnodeMounted',
|
||||
// 渲染之前
|
||||
BEFORE_MOUNT = 'vnodeBeforeMount',
|
||||
VNODE_BEFORE_MOUNT = 'vnodeBeforeMount',
|
||||
}
|
||||
|
||||
// 组件实例类
|
||||
@@ -123,8 +135,13 @@ export interface PublicConfigType {
|
||||
}
|
||||
filter?: string
|
||||
status: StatusType
|
||||
events?: {
|
||||
[K in EventLife]?: string
|
||||
events: {
|
||||
baseEvent: {
|
||||
[K in BaseEvent]?: string
|
||||
},
|
||||
advancedEvents: {
|
||||
[K in EventLife]?: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { getUUID } from '@/utils'
|
||||
import { ChartFrameEnum, PublicConfigType, CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
|
||||
import { RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
|
||||
import { groupTitle } from '@/settings/designSetting'
|
||||
import {
|
||||
@@ -9,11 +8,19 @@ import {
|
||||
RequestContentTypeEnum,
|
||||
RequestBodyEnum
|
||||
} from '@/enums/httpEnum'
|
||||
import {
|
||||
BaseEvent,
|
||||
EventLife,
|
||||
ChartFrameEnum,
|
||||
PublicConfigType,
|
||||
CreateComponentType,
|
||||
CreateComponentGroupType
|
||||
} from '@/packages/index.d'
|
||||
import { chartInitConfig } from '@/settings/designSetting'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
|
||||
// 请求基础属性
|
||||
const requestConfig: RequestConfigType = {
|
||||
export const requestConfig: RequestConfigType = {
|
||||
requestDataType: RequestDataTypeEnum.STATIC,
|
||||
requestHttpType: RequestHttpEnum.GET,
|
||||
requestUrl: '',
|
||||
@@ -82,7 +89,18 @@ export class PublicConfigClass implements PublicConfigType {
|
||||
// 数据过滤
|
||||
public filter = undefined
|
||||
// 事件
|
||||
public events = undefined
|
||||
public events = {
|
||||
baseEvent: {
|
||||
[BaseEvent.ON_CLICK]: undefined,
|
||||
[BaseEvent.ON_DBL_CLICK]: undefined,
|
||||
[BaseEvent.ON_MOUSE_ENTER]: undefined,
|
||||
[BaseEvent.ON_MOUSE_LEAVE]: undefined
|
||||
},
|
||||
advancedEvents: {
|
||||
[EventLife.VNODE_MOUNTED]: undefined,
|
||||
[EventLife.VNODE_BEFORE_MOUNT]: undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 多选成组类
|
||||
|
||||
@@ -64,7 +64,8 @@ import {
|
||||
Images as ImagesIcon,
|
||||
List as ListIcon,
|
||||
EyeOutline as EyeOutlineIcon,
|
||||
EyeOffOutline as EyeOffOutlineIcon
|
||||
EyeOffOutline as EyeOffOutlineIcon,
|
||||
Albums as AlbumsIcon
|
||||
} from '@vicons/ionicons5'
|
||||
|
||||
import {
|
||||
@@ -97,7 +98,8 @@ import {
|
||||
Carbon3DCursor as Carbon3DCursorIcon,
|
||||
Carbon3DSoftware as Carbon3DSoftwareIcon,
|
||||
Filter as FilterIcon,
|
||||
FilterEdit as FilterEditIcon
|
||||
FilterEdit as FilterEditIcon,
|
||||
Laptop as LaptopIcon
|
||||
} from '@vicons/carbon'
|
||||
|
||||
const ionicons5 = {
|
||||
@@ -232,7 +234,9 @@ const ionicons5 = {
|
||||
ListIcon,
|
||||
// 眼睛
|
||||
EyeOutlineIcon,
|
||||
EyeOffOutlineIcon
|
||||
EyeOffOutlineIcon,
|
||||
// 图表列表
|
||||
AlbumsIcon
|
||||
}
|
||||
|
||||
const carbon = {
|
||||
@@ -285,7 +289,9 @@ const carbon = {
|
||||
Carbon3DSoftwareIcon,
|
||||
// 过滤器
|
||||
FilterIcon,
|
||||
FilterEditIcon
|
||||
FilterEditIcon,
|
||||
// 图层
|
||||
LaptopIcon
|
||||
}
|
||||
|
||||
// https://www.xicons.org/#/ 还有很多
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
NH2,
|
||||
NH3,
|
||||
NH4,
|
||||
NH5,
|
||||
NCode,
|
||||
NCountdown,
|
||||
NText,
|
||||
@@ -109,6 +110,7 @@ const naive = create({
|
||||
NH2,
|
||||
NH3,
|
||||
NH4,
|
||||
NH5,
|
||||
NCode,
|
||||
NCountdown,
|
||||
NText,
|
||||
|
||||
@@ -185,16 +185,27 @@ type RequestPublicConfigType = {
|
||||
requestParams: RequestParams
|
||||
}
|
||||
|
||||
// 数据池项类型
|
||||
export type RequestDataPondItemType = {
|
||||
dataPondId: string,
|
||||
dataPondName: string,
|
||||
dataPondRequestConfig: RequestConfigType
|
||||
}
|
||||
|
||||
// 全局的图表请求配置
|
||||
export interface RequestGlobalConfigType extends RequestPublicConfigType {
|
||||
// 组件定制轮询时间
|
||||
requestInterval: number
|
||||
// 请求源地址
|
||||
requestOriginUrl?: string
|
||||
// 公共数据池
|
||||
requestDataPond: RequestDataPondItemType[]
|
||||
}
|
||||
|
||||
// 单个图表请求配置
|
||||
export interface RequestConfigType extends RequestPublicConfigType {
|
||||
// 所选全局数据池的对应 id
|
||||
requestDataPondId?: string
|
||||
// 组件定制轮询时间
|
||||
requestInterval?: number
|
||||
// 获取数据的方式
|
||||
|
||||
@@ -126,11 +126,12 @@ export const useChartEditStore = defineStore({
|
||||
chartThemeColor: defaultTheme || 'dark',
|
||||
// 全局配置
|
||||
chartThemeSetting: globalThemeJson,
|
||||
// 预览方式
|
||||
// 适配方式
|
||||
previewScaleType: previewScaleType
|
||||
},
|
||||
// 数据请求处理(需存储给后端)
|
||||
requestGlobalConfig: {
|
||||
requestDataPond: [],
|
||||
requestOriginUrl: '',
|
||||
requestInterval: requestInterval,
|
||||
requestIntervalUnit: requestIntervalUnit,
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
export enum ChartModeEnum {
|
||||
SINGLE= 'single',
|
||||
DOUBLE = 'double'
|
||||
}
|
||||
|
||||
export enum LayerModeEnum {
|
||||
THUMBNAIL = 'thumbnail',
|
||||
TEXT = 'text'
|
||||
@@ -7,6 +12,7 @@ export enum ChartLayoutStoreEnum {
|
||||
LAYERS = 'layers',
|
||||
CHARTS = 'charts',
|
||||
DETAILS = 'details',
|
||||
Chart_TYPE = 'chartType',
|
||||
LAYER_TYPE = 'layerType'
|
||||
}
|
||||
|
||||
@@ -17,6 +23,8 @@ export interface ChartLayoutType {
|
||||
[ChartLayoutStoreEnum.CHARTS]: boolean
|
||||
// 详情设置
|
||||
[ChartLayoutStoreEnum.DETAILS]: boolean
|
||||
// 组件展示方式
|
||||
[ChartLayoutStoreEnum.Chart_TYPE]: ChartModeEnum
|
||||
// 层级展示方式
|
||||
[ChartLayoutStoreEnum.LAYER_TYPE]: LayerModeEnum
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ChartLayoutType, LayerModeEnum } from './chartLayoutStore.d'
|
||||
import { ChartLayoutType, LayerModeEnum, ChartModeEnum } from './chartLayoutStore.d'
|
||||
import { setLocalStorage, getLocalStorage } from '@/utils'
|
||||
import { StorageEnum } from '@/enums/storageEnum'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
@@ -8,22 +8,25 @@ const chartEditStore = useChartEditStore()
|
||||
|
||||
const { GO_CHART_LAYOUT_STORE } = StorageEnum
|
||||
|
||||
const storageChartLayout: ChartLayoutType = getLocalStorage(GO_CHART_LAYOUT_STORE)
|
||||
const storageChartLayout: Partial<ChartLayoutType> = getLocalStorage(GO_CHART_LAYOUT_STORE)
|
||||
|
||||
// 编辑区域布局和静态设置
|
||||
export const useChartLayoutStore = defineStore({
|
||||
id: 'useChartLayoutStore',
|
||||
state: (): ChartLayoutType =>
|
||||
storageChartLayout || {
|
||||
// 图层控制
|
||||
layers: true,
|
||||
// 图表组件
|
||||
charts: true,
|
||||
// 详情设置(收缩为true)
|
||||
details: false,
|
||||
// 图层类型(默认图片)
|
||||
layerType: LayerModeEnum.THUMBNAIL
|
||||
},
|
||||
state: (): ChartLayoutType => ({
|
||||
// 图层控制
|
||||
layers: true,
|
||||
// 图表组件
|
||||
charts: true,
|
||||
// 详情设置(收缩为true)
|
||||
details: false,
|
||||
// 组件列表展示类型(默认单列)
|
||||
chartType: ChartModeEnum.SINGLE,
|
||||
// 图层类型(默认图片)
|
||||
layerType: LayerModeEnum.THUMBNAIL,
|
||||
// 防止值不存在
|
||||
...storageChartLayout
|
||||
}),
|
||||
getters: {
|
||||
getLayers(): boolean {
|
||||
return this.layers
|
||||
@@ -34,6 +37,9 @@ export const useChartLayoutStore = defineStore({
|
||||
getDetails(): boolean {
|
||||
return this.details
|
||||
},
|
||||
getChartType(): ChartModeEnum {
|
||||
return this.chartType
|
||||
},
|
||||
getLayerType(): LayerModeEnum {
|
||||
return this.layerType
|
||||
}
|
||||
@@ -41,8 +47,8 @@ export const useChartLayoutStore = defineStore({
|
||||
actions: {
|
||||
setItem<T extends keyof ChartLayoutType, K extends ChartLayoutType[T]>(key: T, value: K): void {
|
||||
this.$patch(state => {
|
||||
state[key]= value
|
||||
});
|
||||
state[key] = value
|
||||
})
|
||||
setLocalStorage(GO_CHART_LAYOUT_STORE, this.$state)
|
||||
// 重新计算拖拽区域缩放比例
|
||||
setTimeout(() => {
|
||||
|
||||
@@ -106,8 +106,8 @@ export const reloadRoutePage = () => {
|
||||
*/
|
||||
export const logout = async () => {
|
||||
try {
|
||||
const res = await logoutApi() as unknown as MyResponseType
|
||||
if(res.code === ResultEnum.SUCCESS) {
|
||||
const res = await logoutApi()
|
||||
if(res && res.code === ResultEnum.SUCCESS) {
|
||||
window['$message'].success(window['$t']('global.logout_success'))
|
||||
clearCookie(RequestHttpHeaderEnum.COOKIE)
|
||||
clearLocalStorage(StorageEnum.GO_SYSTEM_STORE)
|
||||
|
||||
@@ -1,31 +1,46 @@
|
||||
<template>
|
||||
<div class="go-content-charts-item-box">
|
||||
<!-- 每一项组件的渲染 -->
|
||||
<div class="go-content-charts-item-animation-patch">
|
||||
<div
|
||||
class="item-box"
|
||||
v-for="(item, index) in menuOptions"
|
||||
:key="index"
|
||||
draggable
|
||||
@dragstart="dragStartHandle($event, item)"
|
||||
@dragend="dragendHandle"
|
||||
@dblclick="dblclickHandle(item)"
|
||||
ref="contentChartsItemBoxRef"
|
||||
class="go-content-charts-item-box"
|
||||
:class="[chartMode === ChartModeEnum.DOUBLE ? 'double' : 'single']"
|
||||
>
|
||||
<div class="list-header">
|
||||
<mac-os-control-btn :mini="true" :disabled="true"></mac-os-control-btn>
|
||||
<n-text class="list-header-text" depth="3">{{ item.title }}</n-text>
|
||||
</div>
|
||||
<div class="list-center go-flex-center">
|
||||
<img class="list-img" v-lazy="item.image" alt="图表图片" />
|
||||
<!-- 每一项组件的渲染 -->
|
||||
<div
|
||||
class="item-box"
|
||||
v-for="(item, index) in menuOptions"
|
||||
:key="index"
|
||||
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>
|
||||
<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>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PropType } from 'vue'
|
||||
import { PropType, watch, ref, Ref, computed, nextTick } from 'vue'
|
||||
import { MacOsControlBtn } from '@/components/Tips/MacOsControlBtn/index'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
|
||||
import { ChartModeEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d'
|
||||
import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore'
|
||||
import { componentInstall, loadingStart, loadingFinish, loadingError } from '@/utils'
|
||||
import { DragKeyEnum } from '@/enums/editPageEnum'
|
||||
import { createComponent } from '@/packages'
|
||||
@@ -41,6 +56,14 @@ defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
const chartLayoutStore = useChartLayoutStore()
|
||||
const contentChartsItemBoxRef = ref()
|
||||
|
||||
// 组件展示状态
|
||||
const chartMode: Ref<ChartModeEnum> = computed(() => {
|
||||
return chartLayoutStore.getChartType
|
||||
})
|
||||
|
||||
// 拖拽处理
|
||||
const dragStartHandle = (e: DragEvent, item: ConfigType) => {
|
||||
// 动态注册图表组件
|
||||
@@ -76,24 +99,46 @@ const dblclickHandle = async (item: ConfigType) => {
|
||||
window['$message'].warning(`图表正在研发中, 敬请期待...`)
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => chartMode.value,
|
||||
(newValue: ChartModeEnum) => {
|
||||
if (newValue === ChartModeEnum.DOUBLE) {
|
||||
nextTick(() => {
|
||||
contentChartsItemBoxRef.value.classList.add('miniAnimation')
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 列表项宽度 */
|
||||
$itemWidth: 86%;
|
||||
$itemWidth: 100%;
|
||||
$maxItemWidth: 180px;
|
||||
$halfItemWidth: 46%;
|
||||
/* 内容高度 */
|
||||
$centerHeight: 100px;
|
||||
$halfCenterHeight: 50px;
|
||||
|
||||
@include go('content-charts-item-animation-patch') {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
@include go('content-charts-item-box') {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
gap: 9px;
|
||||
transition: all 0.7s linear;
|
||||
.item-box {
|
||||
margin: 0 7%;
|
||||
margin-bottom: 15px;
|
||||
margin: 0;
|
||||
width: $itemWidth;
|
||||
overflow: hidden;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
border: 1px solid rgba(0, 0, 0, 0);
|
||||
@include fetch-bg-color('background-color2');
|
||||
@extend .go-transition;
|
||||
&:hover {
|
||||
@include hover-border-color('background-color4');
|
||||
.list-img {
|
||||
@@ -122,6 +167,57 @@ $centerHeight: 100px;
|
||||
@extend .go-transition;
|
||||
}
|
||||
}
|
||||
.list-bottom {
|
||||
display: none;
|
||||
.list-bottom-text {
|
||||
font-size: 12px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.single {
|
||||
.item-box {
|
||||
@extend .go-transition;
|
||||
}
|
||||
}
|
||||
&.double {
|
||||
.list-header {
|
||||
padding: 2px 5px;
|
||||
.list-header-text {
|
||||
display: none;
|
||||
}
|
||||
.list-header-control-btn {
|
||||
transform: scale(0.7);
|
||||
}
|
||||
}
|
||||
.item-box {
|
||||
width: $halfItemWidth;
|
||||
max-width: $maxItemWidth;
|
||||
}
|
||||
.list-center {
|
||||
height: $halfCenterHeight;
|
||||
padding-bottom: 0px;
|
||||
.list-img {
|
||||
height: $halfCenterHeight;
|
||||
width: auto;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
}
|
||||
.list-bottom {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
/* 缩小展示 */
|
||||
@keyframes miniAnimation {
|
||||
from {
|
||||
width: $itemWidth * 2;
|
||||
}
|
||||
to {
|
||||
width: $itemWidth;
|
||||
}
|
||||
}
|
||||
&.miniAnimation {
|
||||
animation: miniAnimation 0.5s;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -123,7 +123,6 @@ $menuWidth: 65px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 10px 0;
|
||||
}
|
||||
@include deep() {
|
||||
.n-menu-item {
|
||||
|
||||
@@ -1,82 +1,104 @@
|
||||
<template>
|
||||
<div class="go-chart-search">
|
||||
<n-popover
|
||||
class="chart-search-popover"
|
||||
:show-arrow="false"
|
||||
:show="showPopover"
|
||||
:to="false"
|
||||
trigger="hover"
|
||||
placement="bottom-start"
|
||||
>
|
||||
<template #trigger>
|
||||
<n-input-group>
|
||||
<n-input
|
||||
v-model:value.trim="search"
|
||||
size="small"
|
||||
:loading="loading"
|
||||
placeholder="请输入组件名称"
|
||||
@update:value="searchHandle"
|
||||
>
|
||||
<template #suffix>
|
||||
<n-icon v-show="!loading" :component="SearchIcon" />
|
||||
</template>
|
||||
</n-input>
|
||||
</n-input-group>
|
||||
</template>
|
||||
<div class="go-chart-search-box">
|
||||
<div class="chart-search go-transition" :class="{ 'chart-search-focus': isFocus }">
|
||||
<n-popover
|
||||
class="chart-search-popover"
|
||||
:show-arrow="false"
|
||||
:show="showPopover"
|
||||
:to="false"
|
||||
trigger="hover"
|
||||
placement="bottom-start"
|
||||
>
|
||||
<template #trigger>
|
||||
<n-input-group>
|
||||
<n-input
|
||||
size="small"
|
||||
placeholder="搜索组件"
|
||||
v-model:value.trim="search"
|
||||
:loading="loading"
|
||||
@focus="focusHandle(true)"
|
||||
@blur="focusHandle(false)"
|
||||
@update:value="searchHandle"
|
||||
>
|
||||
<template #suffix>
|
||||
<n-icon v-show="!loading" :component="SearchIcon" />
|
||||
</template>
|
||||
</n-input>
|
||||
</n-input-group>
|
||||
</template>
|
||||
|
||||
<div class="search-list-box">
|
||||
<n-scrollbar style="max-height: 500px">
|
||||
<n-empty
|
||||
v-show="!searchRes.length"
|
||||
size="small"
|
||||
description="没有找到组件~"
|
||||
></n-empty>
|
||||
<div
|
||||
class="list-item go-flex-items-center go-ellipsis-1"
|
||||
v-for="item in searchRes"
|
||||
:key="item.key"
|
||||
:title="item.title"
|
||||
@click="selectChartHandle(item)"
|
||||
>
|
||||
<img class="list-item-img" v-lazy="item.image" alt="展示图" />
|
||||
<n-text class="list-item-fs" depth="2">{{ item.title }}</n-text>
|
||||
</div>
|
||||
</n-scrollbar>
|
||||
<div class="popover-modal"></div>
|
||||
</div>
|
||||
</n-popover>
|
||||
<div class="search-list-box">
|
||||
<n-scrollbar style="max-height: 500px">
|
||||
<n-empty v-show="!searchRes.length" size="small" description="没有找到组件~"></n-empty>
|
||||
<div
|
||||
class="list-item go-flex-items-center go-ellipsis-1"
|
||||
v-for="item in searchRes"
|
||||
:key="item.key"
|
||||
:title="item.title"
|
||||
@click="selectChartHandle(item)"
|
||||
>
|
||||
<img class="list-item-img" v-lazy="item.image" alt="展示图" />
|
||||
<n-text class="list-item-fs" depth="2">{{ item.title }}</n-text>
|
||||
</div>
|
||||
</n-scrollbar>
|
||||
<div class="popover-modal"></div>
|
||||
</div>
|
||||
</n-popover>
|
||||
</div>
|
||||
<n-button-group class="btn-group go-transition" :class="{ 'btn-group-focus': isFocus }" style="display: flex">
|
||||
<n-button
|
||||
ghost
|
||||
size="small"
|
||||
:key="index"
|
||||
:type="chartMode === item.value ? 'primary' : 'tertiary'"
|
||||
v-for="(item, index) in chartModeList"
|
||||
@click="changeChartModeType(item.value)"
|
||||
>
|
||||
<n-tooltip :show-arrow="false" trigger="hover">
|
||||
<template #trigger>
|
||||
<n-icon size="14" :component="item.icon" />
|
||||
</template>
|
||||
{{ item.label }}
|
||||
</n-tooltip>
|
||||
</n-button>
|
||||
</n-button-group>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onUnmounted } from 'vue'
|
||||
import { icon } from '@/plugins'
|
||||
import { createComponent } from '@/packages'
|
||||
import { ConfigType, CreateComponentType } from '@/packages/index.d'
|
||||
import { themeColor, MenuOptionsType } from '../../hooks/useAside.hook'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { ConfigType, CreateComponentType } from '@/packages/index.d'
|
||||
import { createComponent } from '@/packages'
|
||||
import { ChartModeEnum, ChartLayoutStoreEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d'
|
||||
import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore'
|
||||
import { isString, addEventListener, removeEventListener } from '@/utils'
|
||||
import { fetchConfigComponent, fetchChartComponent } from '@/packages/index'
|
||||
import {
|
||||
componentInstall,
|
||||
loadingStart,
|
||||
loadingFinish,
|
||||
loadingError,
|
||||
} from '@/utils'
|
||||
import { componentInstall, loadingStart, loadingFinish, loadingError } from '@/utils'
|
||||
|
||||
const props = defineProps({
|
||||
menuOptions: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
|
||||
const { SearchIcon } = icon.ionicons5
|
||||
const chartEditStore = useChartEditStore()
|
||||
const chartLayoutStore = useChartLayoutStore()
|
||||
const { SearchIcon, AlbumsIcon, GridIcon } = icon.ionicons5
|
||||
const isFocus = ref<boolean>(false)
|
||||
const showPopover = ref<boolean>(false)
|
||||
const loading = ref<boolean | undefined>(undefined)
|
||||
const search = ref<string | null>(null)
|
||||
const searchRes = ref<ConfigType[]>([])
|
||||
const chartMode = ref<ChartModeEnum>(chartLayoutStore.getChartType)
|
||||
|
||||
const chartModeList = [
|
||||
{ label: '单列', icon: AlbumsIcon, value: ChartModeEnum.SINGLE },
|
||||
{ label: '双列', icon: GridIcon, value: ChartModeEnum.DOUBLE }
|
||||
]
|
||||
|
||||
// 组件数组提取
|
||||
const listFormatHandle = (options: any[]) => {
|
||||
@@ -106,9 +128,7 @@ const searchHandle = (key: string | null) => {
|
||||
}
|
||||
loading.value = true
|
||||
showPopover.value = true
|
||||
searchRes.value = List.filter(
|
||||
(e: ConfigType) => !key || e.title.toLowerCase().includes(key.toLowerCase())
|
||||
)
|
||||
searchRes.value = List.filter((e: ConfigType) => !key || e.title.toLowerCase().includes(key.toLowerCase()))
|
||||
setTimeout(() => {
|
||||
loading.value = undefined
|
||||
}, 500)
|
||||
@@ -145,6 +165,17 @@ const selectChartHandle = async (item: ConfigType) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 聚焦设置
|
||||
const focusHandle = (value: boolean) => {
|
||||
isFocus.value = value
|
||||
}
|
||||
|
||||
// 修改图表展示方式
|
||||
const changeChartModeType = (value: ChartModeEnum) => {
|
||||
chartMode.value = value
|
||||
chartLayoutStore.setItem(ChartLayoutStoreEnum.Chart_TYPE, value)
|
||||
}
|
||||
|
||||
addEventListener(document, 'click', (e: Event) => {
|
||||
listenerCloseHandle(e)
|
||||
})
|
||||
@@ -155,54 +186,78 @@ onUnmounted(() => {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$width: 178px;
|
||||
@include go('chart-search') {
|
||||
width: $width;
|
||||
margin-right: -12px;
|
||||
.chart-search-popover {
|
||||
.search-list-box {
|
||||
width: calc(#{$width} - 30px);
|
||||
.list-item {
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
padding: 2px;
|
||||
padding-left: 6px;
|
||||
margin-bottom: 5px;
|
||||
&-fs {
|
||||
font-size: 12px;
|
||||
}
|
||||
&-img {
|
||||
height: 28px;
|
||||
margin-right: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
&:hover {
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 3px;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
border-radius: 2px;
|
||||
background-color: v-bind('themeColor');
|
||||
$width: 98px;
|
||||
$searchWidth: 176px;
|
||||
|
||||
@include go('chart-search-box') {
|
||||
display: flex;
|
||||
.chart-search {
|
||||
width: $width;
|
||||
margin-right: 10px;
|
||||
&.chart-search-focus {
|
||||
width: $searchWidth;
|
||||
&.chart-search {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
@include deep() {
|
||||
.chart-search-popover {
|
||||
padding-left: 5px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
}
|
||||
.chart-search-popover {
|
||||
.search-list-box {
|
||||
width: 163px;
|
||||
.list-item {
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
padding: 2px;
|
||||
padding-left: 6px;
|
||||
margin-bottom: 5px;
|
||||
&-fs {
|
||||
font-size: 12px;
|
||||
}
|
||||
&::after {
|
||||
z-index: -1;
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.1;
|
||||
left: 0;
|
||||
top: 0;
|
||||
&-img {
|
||||
height: 28px;
|
||||
margin-right: 5px;
|
||||
border-radius: 5px;
|
||||
background-color: v-bind('themeColor');
|
||||
}
|
||||
&:hover {
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 3px;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
border-radius: 2px;
|
||||
background-color: v-bind('themeColor');
|
||||
}
|
||||
&::after {
|
||||
z-index: -1;
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.1;
|
||||
left: 0;
|
||||
top: 0;
|
||||
border-radius: 5px;
|
||||
background-color: v-bind('themeColor');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.btn-group {
|
||||
width: 68px;
|
||||
overflow: hidden;
|
||||
&.btn-group-focus {
|
||||
width: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
</n-button>
|
||||
</n-space>
|
||||
<n-space>
|
||||
<n-text>预览方式</n-text>
|
||||
<n-text>适配方式</n-text>
|
||||
<n-button-group>
|
||||
<n-button
|
||||
v-for="item in previewTypeList"
|
||||
@@ -282,9 +282,9 @@ const customRequest = (options: UploadCustomRequestOptions) => {
|
||||
)
|
||||
let uploadParams = new FormData()
|
||||
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(
|
||||
EditCanvasConfigEnum.BACKGROUND_IMAGE,
|
||||
`${systemStore.getFetchInfo.OSSUrl}${uploadRes.data.fileName}?time=${new Date().getTime()}`
|
||||
@@ -302,7 +302,7 @@ const customRequest = (options: UploadCustomRequestOptions) => {
|
||||
})
|
||||
}
|
||||
|
||||
// 选择预览方式
|
||||
// 选择适配方式
|
||||
const selectPreviewType = (key: PreviewScaleEnum) => {
|
||||
chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.PREVIEW_SCALE_TYPE, key)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="go-chart-configurations-animations" v-if="targetData">
|
||||
<n-button
|
||||
class="clear-btn"
|
||||
class="clear-btn go-my-2"
|
||||
:disabled="!targetData.styles.animations.length"
|
||||
@click="clearAnimation"
|
||||
>
|
||||
@@ -72,7 +72,7 @@ const addAnimation = (item: { label: string; value: string }) => {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@include go('chart-configurations-animations') {
|
||||
padding: 20px 10px;
|
||||
padding: 0;
|
||||
.clear-btn {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<n-input size="small" :placeholder="targetData.request.requestHttpType || '暂无'" :disabled="true"></n-input>
|
||||
</setting-item>
|
||||
|
||||
<setting-item name="组件间隔(高级)">
|
||||
<setting-item name="组件间隔">
|
||||
<n-input size="small" :placeholder="`${targetData.request.requestInterval || '暂无'}`" :disabled="true">
|
||||
<template #suffix> {{ SelectHttpTimeNameObj[targetData.request.requestIntervalUnit] }} </template>
|
||||
</n-input>
|
||||
@@ -41,13 +41,9 @@
|
||||
</n-input>
|
||||
</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="go-absolute-center">
|
||||
<n-button type="primary" secondary>查看更多</n-button>
|
||||
<n-button type="primary" secondary>编辑配置</n-button>
|
||||
</div>
|
||||
</div>
|
||||
</n-card>
|
||||
@@ -76,10 +72,16 @@
|
||||
|
||||
<!-- 底部数据展示 -->
|
||||
<chart-data-matching-and-show :show="showMatching && !loading" :ajax="true"></chart-data-matching-and-show>
|
||||
|
||||
<!-- 骨架图 -->
|
||||
<go-skeleton :load="loading" :repeat="3"></go-skeleton>
|
||||
|
||||
<!-- 请求配置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>
|
||||
</template>
|
||||
|
||||
@@ -95,7 +97,7 @@ import { http, customizeHttp } from '@/api/http'
|
||||
import { SelectHttpType } from '../../index.d'
|
||||
import { ChartDataMatchingAndShow } from '../ChartDataMatchingAndShow'
|
||||
import { useTargetData } from '../../../hooks/useTargetData.hook'
|
||||
import { isDev, newFunctionHandle } from '@/utils'
|
||||
import { newFunctionHandle } from '@/utils'
|
||||
|
||||
const { HelpOutlineIcon, FlashIcon, PulseIcon } = icon.ionicons5
|
||||
const { targetData, chartEditStore } = useTargetData()
|
||||
@@ -125,10 +127,10 @@ const sendHandle = async () => {
|
||||
if (!targetData.value?.request) return
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await customizeHttp(toRaw(targetData.value.request), toRaw(chartEditStore.requestGlobalConfig))
|
||||
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('您的数据不符合默认格式,请配置过滤器!')
|
||||
if (!res?.data && !targetData.value.filter) window['$message'].warning('您的数据不符合默认格式,请配置过滤器!')
|
||||
targetData.value.option.dataset = newFunctionHandle(res?.data, res, targetData.value.filter)
|
||||
showMatching.value = true
|
||||
return
|
||||
@@ -175,7 +177,7 @@ onBeforeUnmount(() => {
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 325px;
|
||||
height: 292px;
|
||||
height: 270px;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
transition: all 0.3s;
|
||||
|
||||
@@ -117,7 +117,7 @@ const { uploadFileListRef, customRequest, beforeUpload, download } = useFile(tar
|
||||
|
||||
// 是否展示过滤器
|
||||
const filterShow = computed(() => {
|
||||
return targetData.value.request.requestDataType === RequestDataTypeEnum.AJAX
|
||||
return targetData.value.request.requestDataType !== RequestDataTypeEnum.STATIC
|
||||
})
|
||||
|
||||
// 是支持 dataset 的图表类型
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
</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">
|
||||
<template #header>
|
||||
<n-space>
|
||||
@@ -101,13 +101,12 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, watch, toRefs, toRaw } from 'vue'
|
||||
import { MonacoEditor } from '@/components/Pages/MonacoEditor'
|
||||
import { ref, computed, watch, toRef, toRefs, toRaw, reactive } from 'vue'
|
||||
import { useTargetData } from '../../../hooks/useTargetData.hook'
|
||||
import { RequestHttpEnum, RequestDataTypeEnum, ResultEnum } from '@/enums/httpEnum'
|
||||
import { MonacoEditor } from '@/components/Pages/MonacoEditor'
|
||||
import { icon } from '@/plugins'
|
||||
import { goDialog, toString } from '@/utils'
|
||||
import { http, customizeHttp } from '@/api/http'
|
||||
import { customizeHttp } from '@/api/http'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
|
||||
const { DocumentTextIcon } = icon.ionicons5
|
||||
@@ -128,7 +127,7 @@ const sourceData = ref<any>('')
|
||||
// 动态获取数据
|
||||
const fetchTargetData = async () => {
|
||||
try {
|
||||
const res = await customizeHttp(toRaw(targetData.value.request), toRaw(chartEditStore.requestGlobalConfig))
|
||||
const res = await customizeHttp(toRaw(targetData.value.request), toRaw(chartEditStore.getRequestGlobalConfig))
|
||||
if (res) {
|
||||
sourceData.value = res
|
||||
return
|
||||
@@ -188,7 +187,10 @@ const saveFilter = () => {
|
||||
watch(
|
||||
() => showModal.value,
|
||||
(newData: boolean) => {
|
||||
if (newData) fetchTargetData()
|
||||
if (newData) {
|
||||
fetchTargetData()
|
||||
filter.value = targetData.value.filter || `return data`
|
||||
}
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
@@ -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>
|
||||
@@ -0,0 +1,3 @@
|
||||
import ChartDataDisplay from './index.vue'
|
||||
|
||||
export { ChartDataDisplay }
|
||||
@@ -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>
|
||||
@@ -0,0 +1,3 @@
|
||||
import ChartDataPondControl from './index.vue'
|
||||
|
||||
export { ChartDataPondControl }
|
||||
@@ -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>
|
||||
@@ -0,0 +1,3 @@
|
||||
import ChartDataPondList from './index.vue'
|
||||
|
||||
export { ChartDataPondList }
|
||||
@@ -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>
|
||||
@@ -0,0 +1,3 @@
|
||||
import ChartDataPond from './index.vue'
|
||||
|
||||
export { ChartDataPond }
|
||||
@@ -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>
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<!-- 全局配置 -->
|
||||
<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
|
||||
name="服务"
|
||||
:itemRightStyle="{
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
<!-- 为 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>
|
||||
|
||||
<!-- 具有对象属性时 -->
|
||||
@@ -86,13 +86,12 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, toRefs } from 'vue'
|
||||
|
||||
import { ref, toRefs, PropType } from 'vue'
|
||||
import { MonacoEditor } from '@/components/Pages/MonacoEditor'
|
||||
import { RequestHeaderTable } from '../RequestHeaderTable/index'
|
||||
import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
|
||||
import { useTargetData } from '@/views/chart/ContentConfigurations/components/hooks/useTargetData.hook'
|
||||
import { RequestHeaderTable } from '../RequestHeaderTable/index'
|
||||
|
||||
import { RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
|
||||
import {
|
||||
RequestParamsTypeEnum,
|
||||
RequestContentTypeEnum,
|
||||
@@ -102,9 +101,13 @@ import {
|
||||
RequestHttpEnum
|
||||
} 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)
|
||||
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
<n-divider class="go-my-3" title-placement="left"></n-divider>
|
||||
<setting-item-box
|
||||
:itemRightStyle="{
|
||||
gridTemplateColumns: '5fr 2fr 1fr'
|
||||
gridTemplateColumns: '6fr 2fr'
|
||||
}"
|
||||
style="padding-right: 25px"
|
||||
>
|
||||
<template #name>
|
||||
地址
|
||||
@@ -50,15 +51,16 @@
|
||||
</setting-item>
|
||||
</setting-item-box>
|
||||
<setting-item-box name="选择方式" class="go-mt-0">
|
||||
<request-header></request-header>
|
||||
<request-header :targetDataRequest="targetDataRequest"></request-header>
|
||||
</setting-item-box>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, toRefs } from 'vue'
|
||||
import { PropType, toRefs } from 'vue'
|
||||
import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
|
||||
import { useTargetData } from '@/views/chart/ContentConfigurations/components/hooks/useTargetData.hook'
|
||||
import { selectTypeOptions, selectTimeOptions } from '@/views/chart/ContentConfigurations/components/ChartData/index.d'
|
||||
import { RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
|
||||
import { RequestHeader } from '../RequestHeader'
|
||||
import { isDev } from '@/utils'
|
||||
import { icon } from '@/plugins'
|
||||
@@ -81,10 +83,16 @@ import {
|
||||
threeEarth01Url
|
||||
} from '@/api/mock'
|
||||
|
||||
const props = defineProps({
|
||||
targetDataRequest: Object as PropType<RequestConfigType>
|
||||
})
|
||||
|
||||
const { HelpOutlineIcon } = icon.ionicons5
|
||||
const { targetData, chartEditStore } = useTargetData()
|
||||
const { chartEditStore } = useTargetData()
|
||||
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 = [
|
||||
{
|
||||
@@ -134,7 +142,7 @@ const apiList = [
|
||||
},
|
||||
{
|
||||
value: `【三维地球】${threeEarth01Url}`
|
||||
},
|
||||
}
|
||||
]
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import ChartDataRequest from './index.vue'
|
||||
import PondDataRequest from './pondIndex.vue'
|
||||
|
||||
export { ChartDataRequest }
|
||||
export { ChartDataRequest, PondDataRequest }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<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">
|
||||
<template #header></template>
|
||||
<template #header-extra> </template>
|
||||
@@ -7,7 +7,7 @@
|
||||
<div class="go-pr-3">
|
||||
<n-space vertical>
|
||||
<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>
|
||||
</div>
|
||||
</n-scrollbar>
|
||||
@@ -17,9 +17,11 @@
|
||||
<div>
|
||||
<n-text>「 {{ chartConfig.categoryName }} 」</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>
|
||||
<n-button type="primary" @click="closeHandle">保存 & 发送请求</n-button>
|
||||
<n-button type="primary" @click="closeAndSendHandle"> {{ saveBtnText || '保存 & 发送请求' }}</n-button>
|
||||
</n-space>
|
||||
</template>
|
||||
</n-card>
|
||||
@@ -27,31 +29,38 @@
|
||||
</template>
|
||||
|
||||
<script script lang="ts" setup>
|
||||
import { toRefs } from 'vue'
|
||||
import { toRefs, PropType } from 'vue'
|
||||
import { RequestContentTypeEnum } from '@/enums/httpEnum'
|
||||
import { useTargetData } from '../../../hooks/useTargetData.hook'
|
||||
import { RequestGlobalConfig } from './components/RequestGlobalConfig'
|
||||
import { RequestTargetConfig } from './components/RequestTargetConfig'
|
||||
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 { targetData } = useTargetData()
|
||||
const { dataSyncUpdate } = useSync()
|
||||
|
||||
// 解构基础配置
|
||||
const { chartConfig } = toRefs(targetData.value)
|
||||
const { requestContentType } = toRefs(targetData.value.request)
|
||||
const { chartConfig } = toRefs(props.targetData as CreateComponentType)
|
||||
const { requestContentType } = toRefs((props.targetData as CreateComponentType).request)
|
||||
const requestContentTypeObj = {
|
||||
[RequestContentTypeEnum.DEFAULT]: '普通请求',
|
||||
[RequestContentTypeEnum.SQL]: 'SQL 请求'
|
||||
}
|
||||
|
||||
defineProps({
|
||||
modelShow: Boolean
|
||||
})
|
||||
|
||||
const closeHandle = () => {
|
||||
emit('update:modelShow', false)
|
||||
}
|
||||
|
||||
const closeAndSendHandle = () => {
|
||||
emit('update:modelShow', false)
|
||||
emit('sendHandle')
|
||||
dataSyncUpdate()
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
@@ -16,6 +16,7 @@ export enum TimelineTitleEnum {
|
||||
export enum SelectCreateDataEnum {
|
||||
STATIC = '静态数据',
|
||||
AJAX = '动态请求',
|
||||
Pond = '公共接口',
|
||||
}
|
||||
|
||||
export interface SelectCreateDataType {
|
||||
|
||||
@@ -3,24 +3,27 @@
|
||||
<setting-item-box name="请求方式" :alone="true">
|
||||
<n-select v-model:value="targetData.request.requestDataType" :disabled="isNotData" :options="selectOptions" />
|
||||
</setting-item-box>
|
||||
|
||||
<!-- 静态 -->
|
||||
<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>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { loadAsyncComponent } from '@/utils'
|
||||
import { SettingItemBox } from '@/components/Pages/ChartItemSetting'
|
||||
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 { 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()
|
||||
|
||||
// 选项
|
||||
@@ -32,6 +35,10 @@ const selectOptions: SelectCreateDataType[] = [
|
||||
{
|
||||
label: SelectCreateDataEnum.AJAX,
|
||||
value: RequestDataTypeEnum.AJAX
|
||||
},
|
||||
{
|
||||
label: SelectCreateDataEnum.Pond,
|
||||
value: RequestDataTypeEnum.Pond
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
import ChartEventAdvancedHandle from './index.vue'
|
||||
|
||||
export { ChartEventAdvancedHandle }
|
||||
@@ -10,13 +10,17 @@
|
||||
编辑
|
||||
</n-button>
|
||||
</template>
|
||||
<n-card>
|
||||
<n-card class="collapse-show-box">
|
||||
<!-- 函数体 -->
|
||||
<div v-for="eventName in EventLife" :key="eventName">
|
||||
<p>
|
||||
<span class="func-annotate">// {{ EventLifeName[eventName] }}</span>
|
||||
<br />
|
||||
<span class="func-keyword">async {{ eventName }}</span> (e, components, echarts, node_modules) {
|
||||
</p>
|
||||
<p class="go-ml-4"><n-code :code="(targetData.events || {})[eventName]" language="typescript"></n-code></p>
|
||||
<p class="go-ml-4">
|
||||
<n-code :code="(targetData.events.advancedEvents || {})[eventName] || ''" language="typescript"></n-code>
|
||||
</p>
|
||||
<p>}<span>,</span></p>
|
||||
</div>
|
||||
</n-card>
|
||||
@@ -30,13 +34,15 @@
|
||||
<n-text>高级事件编辑器(配合源码使用)</n-text>
|
||||
</n-space>
|
||||
</template>
|
||||
|
||||
<template #header-extra> </template>
|
||||
|
||||
<n-layout has-sider sider-placement="right">
|
||||
<n-layout style="height: 580px; padding-right: 20px">
|
||||
<n-tabs v-model:value="editTab" type="card" tab-style="min-width: 100px;">
|
||||
<!-- 提示 -->
|
||||
<template #suffix>
|
||||
<n-text class="tab-tip" type="warning">tips: {{ EventLifeTip[editTab] }}</n-text>
|
||||
<n-text class="tab-tip" type="warning">提示: {{ EventLifeTip[editTab] }}</n-text>
|
||||
</template>
|
||||
<n-tab-pane
|
||||
v-for="(eventName, index) in EventLife"
|
||||
@@ -50,7 +56,7 @@
|
||||
<span class="func-keyNameWord">{{ eventName }}(e, components, echarts, node_modules) {</span>
|
||||
</p>
|
||||
<!-- 编辑主体 -->
|
||||
<monaco-editor v-model:modelValue="events[eventName]" height="480px" language="javascript" />
|
||||
<monaco-editor v-model:modelValue="advancedEvents[eventName]" height="480px" language="javascript" />
|
||||
<!-- 函数结束 -->
|
||||
<p class="go-pl-3 func-keyNameWord">}</p>
|
||||
</n-tab-pane>
|
||||
@@ -136,7 +142,7 @@
|
||||
<template #icon>
|
||||
<n-icon :component="DocumentTextIcon" />
|
||||
</template>
|
||||
提示
|
||||
说明
|
||||
</n-tag>
|
||||
<n-text class="go-ml-2" depth="2">通过提供的参数可为图表增加定制化的tooltip、交互事件等等</n-text>
|
||||
</div>
|
||||
@@ -158,29 +164,27 @@ import { useTargetData } from '../../../hooks/useTargetData.hook'
|
||||
import { templateList } from './importTemplate'
|
||||
import { npmPkgs } from '@/hooks'
|
||||
import { icon } from '@/plugins'
|
||||
import { goDialog, toString } from '@/utils'
|
||||
import { CreateComponentType, EventLife } from '@/packages/index.d'
|
||||
import { Script } from 'vm'
|
||||
|
||||
const { targetData, chartEditStore } = useTargetData()
|
||||
const { DocumentTextIcon, ChevronDownIcon, PencilIcon } = icon.ionicons5
|
||||
|
||||
const EventLifeName = {
|
||||
[EventLife.BEFORE_MOUNT]: '渲染之前',
|
||||
[EventLife.MOUNTED]: '渲染之后'
|
||||
[EventLife.VNODE_BEFORE_MOUNT]: '渲染之前',
|
||||
[EventLife.VNODE_MOUNTED]: '渲染之后'
|
||||
}
|
||||
|
||||
const EventLifeTip = {
|
||||
[EventLife.BEFORE_MOUNT]: '此时组件 DOM 还未存在',
|
||||
[EventLife.MOUNTED]: '此时组件 DOM 已经存在'
|
||||
[EventLife.VNODE_BEFORE_MOUNT]: '此时组件 DOM 还未存在',
|
||||
[EventLife.VNODE_MOUNTED]: '此时组件 DOM 已经存在'
|
||||
}
|
||||
|
||||
// 受控弹窗
|
||||
const showModal = ref(false)
|
||||
// 编辑区域控制
|
||||
const editTab = ref(EventLife.MOUNTED)
|
||||
const editTab = ref(EventLife.VNODE_MOUNTED)
|
||||
// events 函数模板
|
||||
let events = ref({ ...targetData.value.events })
|
||||
let advancedEvents = ref({ ...targetData.value.events.advancedEvents })
|
||||
// 事件错误标识
|
||||
const errorFlag = ref(false)
|
||||
|
||||
@@ -190,7 +194,7 @@ const validEvents = () => {
|
||||
let message = ''
|
||||
let name = ''
|
||||
|
||||
errorFlag.value = Object.entries(events.value).every(([eventName, str]) => {
|
||||
errorFlag.value = Object.entries(advancedEvents.value).every(([eventName, str]) => {
|
||||
try {
|
||||
// 支持await,验证语法
|
||||
const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor
|
||||
@@ -221,11 +225,14 @@ const saveEvents = () => {
|
||||
window['$message'].error('事件函数错误,无法进行保存')
|
||||
return
|
||||
}
|
||||
if (Object.values(events.value).join('').trim() === '') {
|
||||
if (Object.values(advancedEvents.value).join('').trim() === '') {
|
||||
// 清空事件
|
||||
targetData.value.events = undefined
|
||||
targetData.value.events.advancedEvents = {
|
||||
vnodeBeforeMount: undefined,
|
||||
vnodeMounted: undefined
|
||||
}
|
||||
} else {
|
||||
targetData.value.events = { ...events.value }
|
||||
targetData.value.events.advancedEvents = { ...advancedEvents.value }
|
||||
}
|
||||
closeEvents()
|
||||
}
|
||||
@@ -234,52 +241,12 @@ watch(
|
||||
() => showModal.value,
|
||||
(newData: boolean) => {
|
||||
if (newData) {
|
||||
events.value = { ...targetData.value.events }
|
||||
advancedEvents.value = { ...targetData.value.events.advancedEvents }
|
||||
}
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 外层也要使用 */
|
||||
.func-keyword {
|
||||
color: #b478cf;
|
||||
}
|
||||
|
||||
@include go('chart-data-monaco-editor') {
|
||||
.func-keyNameWord {
|
||||
color: #70c0e8;
|
||||
}
|
||||
.tab-tip {
|
||||
font-size: 12px;
|
||||
}
|
||||
&.n-card.n-modal,
|
||||
.n-card {
|
||||
@extend .go-background-filter;
|
||||
}
|
||||
}
|
||||
@include deep() {
|
||||
.n-layout,
|
||||
.n-layout-sider {
|
||||
background-color: transparent;
|
||||
}
|
||||
.go-editor-area {
|
||||
max-height: 530px;
|
||||
}
|
||||
.checkbox--hidden:checked {
|
||||
& + label {
|
||||
.n-icon {
|
||||
transition: all 0.3s;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
& ~ .go-editor-area {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
// 优化代码换行
|
||||
.n-code > pre {
|
||||
white-space: break-spaces;
|
||||
}
|
||||
}
|
||||
@import '../index.scss';
|
||||
</style>
|
||||
@@ -0,0 +1,3 @@
|
||||
import ChartEventBaseHandle from './index.vue'
|
||||
|
||||
export { ChartEventBaseHandle }
|
||||
@@ -0,0 +1,215 @@
|
||||
<template>
|
||||
<n-collapse-item title="基础事件配置" name="1">
|
||||
<template #header-extra>
|
||||
<n-button type="primary" tertiary size="small" @click.stop="showModal = true">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<pencil-icon />
|
||||
</n-icon>
|
||||
</template>
|
||||
编辑
|
||||
</n-button>
|
||||
</template>
|
||||
<n-card class="collapse-show-box">
|
||||
<!-- 函数体 -->
|
||||
<div v-for="eventName in BaseEvent" :key="eventName">
|
||||
<p>
|
||||
<span class="func-annotate">// {{ EventTypeName[eventName] }}</span>
|
||||
<br />
|
||||
<span class="func-keyword">async {{ eventName }}</span> (mouseEvent) {
|
||||
</p>
|
||||
<p class="go-ml-4">
|
||||
<n-code :code="(targetData.events.baseEvent || {})[eventName] || ''" language="typescript"></n-code>
|
||||
</p>
|
||||
<p>}<span>,</span></p>
|
||||
</div>
|
||||
</n-card>
|
||||
</n-collapse-item>
|
||||
|
||||
<!-- 弹窗 -->
|
||||
<n-modal class="go-chart-data-monaco-editor" v-model:show="showModal" :mask-closable="false">
|
||||
<n-card :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 1200px; height: 700px">
|
||||
<template #header>
|
||||
<n-space>
|
||||
<n-text>基础事件编辑器</n-text>
|
||||
</n-space>
|
||||
</template>
|
||||
|
||||
<template #header-extra> </template>
|
||||
<n-layout has-sider sider-placement="right">
|
||||
<n-layout style="height: 580px; padding-right: 20px">
|
||||
<n-tabs v-model:value="editTab" type="card" tab-style="min-width: 100px;">
|
||||
<!-- 提示 -->
|
||||
<template #suffix>
|
||||
<n-text class="tab-tip" type="warning">提示: ECharts 组件会拦截鼠标事件</n-text>
|
||||
</template>
|
||||
<n-tab-pane
|
||||
v-for="(eventName, index) in BaseEvent"
|
||||
:key="index"
|
||||
:tab="`${EventTypeName[eventName]}-${eventName}`"
|
||||
:name="eventName"
|
||||
>
|
||||
<!-- 函数名称 -->
|
||||
<p class="go-pl-3">
|
||||
<span class="func-keyword">async function </span>
|
||||
<span class="func-keyNameWord">{{ eventName }}(mouseEvent) {</span>
|
||||
</p>
|
||||
<!-- 编辑主体 -->
|
||||
<monaco-editor v-model:modelValue="baseEvent[eventName]" height="480px" language="javascript" />
|
||||
<!-- 函数结束 -->
|
||||
<p class="go-pl-3 func-keyNameWord">}</p>
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
</n-layout>
|
||||
<n-layout-sider
|
||||
:collapsed-width="14"
|
||||
:width="340"
|
||||
show-trigger="bar"
|
||||
collapse-mode="transform"
|
||||
content-style="padding: 12px 12px 0px 12px;margin-left: 3px;"
|
||||
>
|
||||
<n-tabs default-value="1" justify-content="space-evenly" type="segment">
|
||||
<!-- 验证结果 -->
|
||||
<n-tab-pane tab="验证结果" name="1" size="small">
|
||||
<n-scrollbar trigger="none" style="max-height: 505px">
|
||||
<n-collapse class="go-px-3" arrow-placement="right" :default-expanded-names="[1, 2, 3]">
|
||||
<template v-for="error in [validEvents()]" :key="error">
|
||||
<n-collapse-item title="错误函数" :name="1">
|
||||
<n-text depth="3">{{ error.errorFn || '暂无' }}</n-text>
|
||||
</n-collapse-item>
|
||||
<n-collapse-item title="错误信息" :name="2">
|
||||
<n-text depth="3">{{ error.name || '暂无' }}</n-text>
|
||||
</n-collapse-item>
|
||||
<n-collapse-item title="堆栈信息" :name="3">
|
||||
<n-text depth="3">{{ error.message || '暂无' }}</n-text>
|
||||
</n-collapse-item>
|
||||
</template>
|
||||
</n-collapse>
|
||||
</n-scrollbar>
|
||||
</n-tab-pane>
|
||||
<!-- 辅助说明 -->
|
||||
<n-tab-pane tab="变量说明" name="2">
|
||||
<n-scrollbar trigger="none" style="max-height: 505px">
|
||||
<n-collapse class="go-px-3" arrow-placement="right" :default-expanded-names="[1, 2]">
|
||||
<n-collapse-item title="mouseEvent" :name="1">
|
||||
<n-text depth="3">鼠标事件对象</n-text>
|
||||
</n-collapse-item>
|
||||
</n-collapse>
|
||||
</n-scrollbar>
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
</n-layout-sider>
|
||||
</n-layout>
|
||||
|
||||
<template #action>
|
||||
<n-space justify="space-between">
|
||||
<div class="go-flex-items-center">
|
||||
<n-tag :bordered="false" type="primary">
|
||||
<template #icon>
|
||||
<n-icon :component="DocumentTextIcon" />
|
||||
</template>
|
||||
说明
|
||||
</n-tag>
|
||||
<n-text class="go-ml-2" depth="2">编写方式同正常 JavaScript 写法</n-text>
|
||||
</div>
|
||||
|
||||
<n-space>
|
||||
<n-button size="medium" @click="closeEvents">取消</n-button>
|
||||
<n-button size="medium" type="primary" @click="saveEvents">保存</n-button>
|
||||
</n-space>
|
||||
</n-space>
|
||||
</template>
|
||||
</n-card>
|
||||
</n-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, toRefs, toRaw } from 'vue'
|
||||
import { MonacoEditor } from '@/components/Pages/MonacoEditor'
|
||||
import { useTargetData } from '../../../hooks/useTargetData.hook'
|
||||
import { CreateComponentType, BaseEvent } from '@/packages/index.d'
|
||||
import { icon } from '@/plugins'
|
||||
|
||||
const { targetData, chartEditStore } = useTargetData()
|
||||
const { DocumentTextIcon, ChevronDownIcon, PencilIcon } = icon.ionicons5
|
||||
|
||||
const EventTypeName = {
|
||||
[BaseEvent.ON_CLICK]: '单击',
|
||||
[BaseEvent.ON_DBL_CLICK]: '双击',
|
||||
[BaseEvent.ON_MOUSE_ENTER]: '鼠标进入',
|
||||
[BaseEvent.ON_MOUSE_LEAVE]: '鼠标移出'
|
||||
}
|
||||
|
||||
// 受控弹窗
|
||||
const showModal = ref(false)
|
||||
// 编辑区域控制
|
||||
const editTab = ref(BaseEvent.ON_CLICK)
|
||||
// events 函数模板
|
||||
let baseEvent = ref({ ...targetData.value.events.baseEvent })
|
||||
// 事件错误标识
|
||||
const errorFlag = ref(false)
|
||||
|
||||
// 验证语法
|
||||
const validEvents = () => {
|
||||
let errorFn = ''
|
||||
let message = ''
|
||||
let name = ''
|
||||
|
||||
errorFlag.value = Object.entries(baseEvent.value).every(([eventName, str]) => {
|
||||
try {
|
||||
// 支持await,验证语法
|
||||
const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor
|
||||
new AsyncFunction(str)
|
||||
return true
|
||||
} catch (error: any) {
|
||||
message = error.message
|
||||
name = error.name
|
||||
errorFn = eventName
|
||||
return false
|
||||
}
|
||||
})
|
||||
return {
|
||||
errorFn,
|
||||
message,
|
||||
name
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭事件
|
||||
const closeEvents = () => {
|
||||
showModal.value = false
|
||||
}
|
||||
|
||||
// 新增事件
|
||||
const saveEvents = () => {
|
||||
if (validEvents().errorFn) {
|
||||
window['$message'].error('事件函数错误,无法进行保存')
|
||||
return
|
||||
}
|
||||
if (Object.values(baseEvent.value).join('').trim() === '') {
|
||||
// 清空事件
|
||||
targetData.value.events.baseEvent = {
|
||||
[BaseEvent.ON_CLICK]: undefined,
|
||||
[BaseEvent.ON_DBL_CLICK]: undefined,
|
||||
[BaseEvent.ON_MOUSE_ENTER]: undefined,
|
||||
[BaseEvent.ON_MOUSE_LEAVE]: undefined
|
||||
}
|
||||
} else {
|
||||
targetData.value.events.baseEvent = { ...baseEvent.value }
|
||||
}
|
||||
closeEvents()
|
||||
}
|
||||
|
||||
watch(
|
||||
() => showModal.value,
|
||||
(newData: boolean) => {
|
||||
if (newData) {
|
||||
baseEvent.value = { ...targetData.value.events.baseEvent }
|
||||
}
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '../index.scss';
|
||||
</style>
|
||||
@@ -1,3 +0,0 @@
|
||||
import ChartEventMonacoEditor from './index.vue'
|
||||
|
||||
export { ChartEventMonacoEditor }
|
||||
@@ -0,0 +1,51 @@
|
||||
/* 外层也要使用 */
|
||||
.func-keyword {
|
||||
color: #b478cf;
|
||||
}
|
||||
|
||||
.func-annotate {
|
||||
color: #70c0e8;
|
||||
}
|
||||
|
||||
@include go('chart-data-monaco-editor') {
|
||||
.func-keyNameWord {
|
||||
color: #70c0e8;
|
||||
}
|
||||
.tab-tip {
|
||||
font-size: 12px;
|
||||
}
|
||||
&.n-card.n-modal,
|
||||
.n-card {
|
||||
@extend .go-background-filter;
|
||||
}
|
||||
}
|
||||
@include deep() {
|
||||
.n-layout,
|
||||
.n-layout-sider {
|
||||
background-color: transparent;
|
||||
}
|
||||
.collapse-show-box {
|
||||
.n-card__content {
|
||||
padding-left: 20px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
}
|
||||
.go-editor-area {
|
||||
max-height: 530px;
|
||||
}
|
||||
.checkbox--hidden:checked {
|
||||
& + label {
|
||||
.n-icon {
|
||||
transition: all 0.3s;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
& ~ .go-editor-area {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
// 优化代码换行
|
||||
.n-code > pre {
|
||||
white-space: break-spaces;
|
||||
}
|
||||
}
|
||||
@@ -5,20 +5,15 @@
|
||||
组件 id:
|
||||
<n-text>{{ targetData.id }}</n-text>
|
||||
</n-text>
|
||||
<n-collapse-item title="基础事件配置" name="1">
|
||||
<div class="go-event">
|
||||
<n-text depth="3">【单击、双击、移入、移出】在开发中,即将上线!</n-text>
|
||||
<br/>
|
||||
<n-text depth="3">(备注:高级事件模块可自行实现上述功能)</n-text>
|
||||
</div>
|
||||
</n-collapse-item>
|
||||
<chart-event-monaco-editor></chart-event-monaco-editor>
|
||||
<chart-event-base-handle></chart-event-base-handle>
|
||||
<chart-event-advanced-handle></chart-event-advanced-handle>
|
||||
</n-collapse>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { ChartEventMonacoEditor } from './components/ChartEventMonacoEditor'
|
||||
import { ChartEventAdvancedHandle } from './components/ChartEventAdvancedHandle'
|
||||
import { ChartEventBaseHandle } from './components/ChartEventBaseHandle'
|
||||
import { useTargetData } from '../hooks/useTargetData.hook'
|
||||
|
||||
const { targetData } = useTargetData()
|
||||
|
||||
@@ -37,6 +37,7 @@ export const useFile = () => {
|
||||
await updateComponent(fileData, false, true)
|
||||
window['$message'].success('导入成功!')
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
window['$message'].error('组件导入失败,请检查文件完整性!')
|
||||
}
|
||||
},
|
||||
@@ -47,6 +48,7 @@ export const useFile = () => {
|
||||
await updateComponent(fileData, true, true)
|
||||
window['$message'].success('导入成功!')
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
window['$message'].error('组件导入失败,请检查文件完整性!')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import { watch } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { useSync } from '@/views/chart/hooks/useSync.hook'
|
||||
import { ChartEnum } from '@/enums/pageEnum'
|
||||
import { SavePageEnum } from '@/enums/editPageEnum'
|
||||
import { editToJsonInterval } from '@/settings/designSetting'
|
||||
|
||||
const { updateComponent, dataSyncUpdate } = useSync()
|
||||
const chartEditStore = useChartEditStore()
|
||||
|
||||
// 侦听器更新
|
||||
const useSyncUpdateHandle = () => {
|
||||
// 定义侦听器变量
|
||||
let timer: any
|
||||
const updateFn = (e: any) => updateComponent(e!.detail, true, false)
|
||||
const syncData = async () => {
|
||||
dataSyncUpdate && (await dataSyncUpdate())
|
||||
dispatchEvent(new CustomEvent(SavePageEnum.CHART, { detail: chartEditStore.getStorageInfo }))
|
||||
}
|
||||
|
||||
// 开启侦听
|
||||
const use = () => {
|
||||
// // 1、定时同步数据
|
||||
// timer = setInterval(() => {
|
||||
// // 窗口激活并且处于工作台
|
||||
// document.hasFocus() && syncData()
|
||||
// }, editToJsonInterval)
|
||||
// // 1、定时同步数据
|
||||
// timer = setInterval(() => {
|
||||
// // 窗口激活并且处于工作台
|
||||
// document.hasFocus() && syncData()
|
||||
// }, editToJsonInterval)
|
||||
// 2、失焦同步数据
|
||||
addEventListener('blur', syncData)
|
||||
|
||||
// 【监听JSON代码 刷新工作台图表】
|
||||
addEventListener(SavePageEnum.JSON, updateFn)
|
||||
}
|
||||
|
||||
// 关闭侦听
|
||||
const unUse = () => {
|
||||
// clearInterval(timer)
|
||||
// clearInterval(timer)
|
||||
removeEventListener(SavePageEnum.JSON, updateFn)
|
||||
removeEventListener('blur', syncData)
|
||||
}
|
||||
|
||||
// 路由变更时处理
|
||||
const watchHandler = (toName: any, fromName: any) => {
|
||||
if (fromName == ChartEnum.CHART_HOME_NAME) {
|
||||
unUse()
|
||||
}
|
||||
if (toName == ChartEnum.CHART_HOME_NAME) {
|
||||
use()
|
||||
}
|
||||
}
|
||||
|
||||
return watchHandler
|
||||
}
|
||||
|
||||
export const useSyncUpdate = () => {
|
||||
const routerParamsInfo = useRoute()
|
||||
watch(() => routerParamsInfo.name, useSyncUpdateHandle(), { immediate: true })
|
||||
}
|
||||
@@ -62,20 +62,18 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, h, watch } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import { useSettingStore } from '@/store/modules/settingStore/settingStore'
|
||||
import { ToolsStatusEnum } from '@/store/modules/settingStore/settingStore.d'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { fetchPathByName, routerTurnByPath, setSessionStorage, getLocalStorage } from '@/utils'
|
||||
import { editToJsonInterval } from '@/settings/designSetting'
|
||||
import { EditEnum, ChartEnum } from '@/enums/pageEnum'
|
||||
import { fetchRouteParamsLocation, fetchPathByName, routerTurnByPath, setSessionStorage, getLocalStorage } from '@/utils'
|
||||
import { EditEnum } from '@/enums/pageEnum'
|
||||
import { StorageEnum } from '@/enums/storageEnum'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useSync } from '@/views/chart/hooks/useSync.hook'
|
||||
import { SavePageEnum } from '@/enums/editPageEnum'
|
||||
import { GoSystemSet } from '@/components/GoSystemSet/index'
|
||||
import { exportHandle } from './utils'
|
||||
import { useFile } from './hooks/useFile.hooks'
|
||||
import { useSyncUpdate } from './hooks/useSyncUpdate.hook'
|
||||
import { BtnListType, TypeEnum } from './index.d'
|
||||
import { icon } from '@/plugins'
|
||||
|
||||
@@ -83,7 +81,8 @@ const { DownloadIcon, ShareIcon, PawIcon, SettingsSharpIcon, CreateIcon } = icon
|
||||
const settingStore = useSettingStore()
|
||||
const chartEditStore = useChartEditStore()
|
||||
const routerParamsInfo = useRoute()
|
||||
const { updateComponent } = useSync()
|
||||
// 初始化编辑 JSON 模块
|
||||
useSyncUpdate()
|
||||
|
||||
// 鼠标悬停定时器
|
||||
let mouseTime: any = null
|
||||
@@ -138,13 +137,13 @@ const toolsMouseoutHandle = () => {
|
||||
|
||||
// 编辑处理
|
||||
const editHandle = () => {
|
||||
window['$message'].warning('将开启失焦更新与 5 秒同步更新!')
|
||||
window['$message'].warning('将开启失焦更新!')
|
||||
// window['$message'].warning('将开启失焦更新与 5 秒同步更新!')
|
||||
setTimeout(() => {
|
||||
// 获取id路径
|
||||
const path = fetchPathByName(EditEnum.CHART_EDIT_NAME, 'href')
|
||||
if (!path) return
|
||||
let { id } = routerParamsInfo.params as any
|
||||
id = typeof id === 'string' ? id : id[0]
|
||||
const id = fetchRouteParamsLocation()
|
||||
updateToSession(id)
|
||||
routerTurnByPath(path, [id], undefined, true)
|
||||
}, 1000)
|
||||
@@ -170,51 +169,6 @@ const updateToSession = (id: string) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 侦听器更新
|
||||
const useSyncUpdate = () => {
|
||||
// 定义侦听器变量
|
||||
let timer: any
|
||||
const updateFn = (e: any) => updateComponent(e!.detail, true, false)
|
||||
const syncData = () => {
|
||||
if (routerParamsInfo.name == ChartEnum.CHART_HOME_NAME) {
|
||||
dispatchEvent(new CustomEvent(SavePageEnum.CHART, { detail: chartEditStore.getStorageInfo }))
|
||||
}
|
||||
}
|
||||
|
||||
// 开启侦听
|
||||
const use = () => {
|
||||
// 1、定时同步数据
|
||||
timer = setInterval(() => {
|
||||
// 窗口激活并且处于工作台
|
||||
document.hasFocus() && syncData()
|
||||
}, editToJsonInterval)
|
||||
// 2、失焦同步数据
|
||||
addEventListener('blur', syncData)
|
||||
|
||||
// 【监听JSON代码 刷新工作台图表】
|
||||
addEventListener(SavePageEnum.JSON, updateFn)
|
||||
}
|
||||
|
||||
// 关闭侦听
|
||||
const unUse = () => {
|
||||
clearInterval(timer)
|
||||
removeEventListener(SavePageEnum.JSON, updateFn)
|
||||
removeEventListener('blur', syncData)
|
||||
}
|
||||
|
||||
// 路由变更时处理
|
||||
const watchHandler = (toName: any, fromName: any) => {
|
||||
if (fromName == ChartEnum.CHART_HOME_NAME) {
|
||||
unUse()
|
||||
}
|
||||
if (toName == ChartEnum.CHART_HOME_NAME) {
|
||||
use()
|
||||
}
|
||||
}
|
||||
return watchHandler
|
||||
}
|
||||
|
||||
watch(() => routerParamsInfo.name, useSyncUpdate(), { immediate: true })
|
||||
|
||||
// 配置列表
|
||||
const btnList: BtnListType[] = [
|
||||
@@ -234,7 +188,7 @@ const btnList: BtnListType[] = [
|
||||
{
|
||||
key: 'edit',
|
||||
type: TypeEnum.BUTTON,
|
||||
name: '编辑JSON',
|
||||
name: '编辑',
|
||||
icon: CreateIcon,
|
||||
handle: editHandle
|
||||
},
|
||||
|
||||
@@ -152,9 +152,9 @@ const sendHandle = async () => {
|
||||
id: fetchRouteParamsLocation(),
|
||||
// 反过来
|
||||
state: release.value ? -1 : 1,
|
||||
})) as unknown as MyResponseType
|
||||
}))
|
||||
|
||||
if (res.code === ResultEnum.SUCCESS) {
|
||||
if (res && res.code === ResultEnum.SUCCESS) {
|
||||
modelShowHandle()
|
||||
if (!release.value) {
|
||||
copyPreviewPath('发布成功!已复制地址到剪贴板~', '发布成功!')
|
||||
|
||||
@@ -67,8 +67,8 @@ const handleBlur = async () => {
|
||||
const res = (await updateProjectApi({
|
||||
id: fetchRouteParamsLocation(),
|
||||
projectName: title.value
|
||||
})) as unknown as MyResponseType
|
||||
if (res.code === ResultEnum.SUCCESS) {
|
||||
}))
|
||||
if (res && res.code === ResultEnum.SUCCESS) {
|
||||
dataSyncUpdate()
|
||||
} else {
|
||||
httpErrorHandle()
|
||||
|
||||
@@ -142,7 +142,6 @@ $textSize: 10px;
|
||||
/* 选中样式 */
|
||||
&.select {
|
||||
border: 1px solid v-bind('themeColor');
|
||||
/* 需要设置最高级,覆盖 hover 的颜色 */
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -81,12 +81,13 @@ import { LayersGroupListItem } from './components/LayersGroupListItem/index'
|
||||
import { icon } from '@/plugins'
|
||||
|
||||
const { LayersIcon, GridIcon, ListIcon } = icon.ionicons5
|
||||
const { LaptopIcon } = icon.carbon
|
||||
const chartLayoutStore = useChartLayoutStore()
|
||||
const chartEditStore = useChartEditStore()
|
||||
const { handleContextMenu, onClickOutSide } = useContextMenu()
|
||||
|
||||
const layerModeList = [
|
||||
{ label: '缩略图', icon: GridIcon, value: LayerModeEnum.THUMBNAIL },
|
||||
{ label: '缩略图', icon: LaptopIcon, value: LayerModeEnum.THUMBNAIL },
|
||||
{ label: '文本列表', icon: ListIcon, value: LayerModeEnum.TEXT }
|
||||
]
|
||||
|
||||
|
||||
@@ -15,28 +15,79 @@ import { ResultEnum } from '@/enums/httpEnum'
|
||||
import { saveProjectApi, fetchProjectApi, uploadFile, updateProjectApi } from '@/api/path'
|
||||
// 画布枚举
|
||||
import { SyncEnum } from '@/enums/editPageEnum'
|
||||
import { CreateComponentType, CreateComponentGroupType, ConfigType } from '@/packages/index.d'
|
||||
import { BaseEvent, EventLife, CreateComponentType, CreateComponentGroupType, ConfigType } from '@/packages/index.d'
|
||||
import { PublicGroupConfigClass } from '@/packages/public/publicConfig'
|
||||
import merge from 'lodash/merge'
|
||||
|
||||
/**
|
||||
* 合并处理
|
||||
* @param object 模板数据
|
||||
* * 画布-版本升级对旧数据无法兼容的补丁
|
||||
* @param object
|
||||
*/
|
||||
const canvasVersionUpdatePolyfill = (object: any) => {
|
||||
return object
|
||||
}
|
||||
|
||||
/**
|
||||
* * 组件-版本升级对旧数据无法兼容的补丁
|
||||
* @param newObject
|
||||
* @param sources
|
||||
*/
|
||||
const componentVersionUpdatePolyfill = (newObject: any, sources: any) => {
|
||||
try {
|
||||
// 判断是否是组件
|
||||
if (sources.id) {
|
||||
// 处理事件补丁
|
||||
const hasVnodeBeforeMount = 'vnodeBeforeMount' in sources.events
|
||||
const hasVnodeMounted = 'vnodeMounted' in sources.events
|
||||
|
||||
if (hasVnodeBeforeMount) {
|
||||
newObject.events.advancedEvents.vnodeBeforeMount = sources?.events.vnodeBeforeMount
|
||||
}
|
||||
if (hasVnodeMounted) {
|
||||
newObject.events.advancedEvents.vnodeMounted = sources?.events.vnodeMounted
|
||||
}
|
||||
if (hasVnodeBeforeMount || hasVnodeMounted) {
|
||||
sources.events = {
|
||||
baseEvent: {
|
||||
[BaseEvent.ON_CLICK]: undefined,
|
||||
[BaseEvent.ON_DBL_CLICK]: undefined,
|
||||
[BaseEvent.ON_MOUSE_ENTER]: undefined,
|
||||
[BaseEvent.ON_MOUSE_LEAVE]: undefined
|
||||
},
|
||||
advancedEvents: {
|
||||
[EventLife.VNODE_MOUNTED]: undefined,
|
||||
[EventLife.VNODE_BEFORE_MOUNT]: undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
return newObject
|
||||
}
|
||||
} catch (error) {
|
||||
return newObject
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* * 合并处理
|
||||
* @param newObject 新的模板数据
|
||||
* @param sources 新拿到的数据
|
||||
* @returns object
|
||||
*/
|
||||
const componentMerge = (object: any, sources: any, notComponent = false) => {
|
||||
const componentMerge = (newObject: any, sources: any, notComponent = false) => {
|
||||
// 处理组件补丁
|
||||
componentVersionUpdatePolyfill(newObject, sources)
|
||||
|
||||
// 非组件不处理
|
||||
if (notComponent) return merge(object, sources)
|
||||
// 组件排除 options
|
||||
if (notComponent) return merge(newObject, sources)
|
||||
// 组件排除 newObject
|
||||
const option = sources.option
|
||||
if (!option) return merge(object, sources)
|
||||
if (!option) return merge(newObject, sources)
|
||||
|
||||
// 为 undefined 的 sources 来源对象属性将被跳过详见 https://www.lodashjs.com/docs/lodash.merge
|
||||
sources.option = undefined
|
||||
if (option) {
|
||||
return {
|
||||
...merge(object, sources),
|
||||
...merge(newObject, sources),
|
||||
option: option
|
||||
}
|
||||
}
|
||||
@@ -62,6 +113,9 @@ export const useSync = () => {
|
||||
chartHistoryStore.clearBackStack()
|
||||
chartHistoryStore.clearForwardStack()
|
||||
}
|
||||
// 画布补丁处理
|
||||
projectData.editCanvasConfig = canvasVersionUpdatePolyfill(projectData.editCanvasConfig)
|
||||
|
||||
// 列表组件注册
|
||||
projectData.componentList.forEach(async (e: CreateComponentType | CreateComponentGroupType) => {
|
||||
const intComponent = (target: CreateComponentType) => {
|
||||
@@ -132,7 +186,7 @@ export const useSync = () => {
|
||||
// 分组插入到列表
|
||||
chartEditStore.addComponentList(groupClass, false, true)
|
||||
} else {
|
||||
await create(comItem as CreateComponentType)
|
||||
await create(comItem as CreateComponentType)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -170,10 +224,13 @@ export const useSync = () => {
|
||||
|
||||
// * 数据获取
|
||||
const dataSyncFetch = async () => {
|
||||
// FIX:重新执行dataSyncFetch需清空chartEditStore.componentList,否则会导致图层重复
|
||||
// 切换语言等操作会导致重新执行 dataSyncFetch,此时pinia中并未清空chartEditStore.componentList,导致图层重复
|
||||
chartEditStore.componentList = []
|
||||
chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.START)
|
||||
try {
|
||||
const res = await fetchProjectApi({ projectId: fetchRouteParamsLocation() }) as unknown as MyResponseType
|
||||
if (res.code === ResultEnum.SUCCESS) {
|
||||
const res = await fetchProjectApi({ projectId: fetchRouteParamsLocation() })
|
||||
if (res && res.code === ResultEnum.SUCCESS) {
|
||||
if (res.data) {
|
||||
updateStoreInfo(res.data)
|
||||
// 更新全局数据
|
||||
@@ -195,7 +252,7 @@ export const useSync = () => {
|
||||
}
|
||||
|
||||
// * 数据保存
|
||||
const dataSyncUpdate = throttle(async () => {
|
||||
const dataSyncUpdate = throttle(async (updateImg = true) => {
|
||||
if(!fetchRouteParamsLocation()) return
|
||||
|
||||
let projectId = chartEditStore.getProjectInfo[ProjectInfoEnum.PROJECT_ID];
|
||||
@@ -206,34 +263,41 @@ export const useSync = () => {
|
||||
|
||||
chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.START)
|
||||
|
||||
// 获取缩略图片
|
||||
const range = document.querySelector('.go-edit-range') as HTMLElement
|
||||
// 生成图片
|
||||
const canvasImage: HTMLCanvasElement = await html2canvas(range, {
|
||||
backgroundColor: null,
|
||||
allowTaint: true,
|
||||
useCORS: true
|
||||
})
|
||||
// 异常处理:缩略图上传失败不影响JSON的保存
|
||||
try {
|
||||
if (updateImg) {
|
||||
// 获取缩略图片
|
||||
const range = document.querySelector('.go-edit-range') as HTMLElement
|
||||
// 生成图片
|
||||
const canvasImage: HTMLCanvasElement = await html2canvas(range, {
|
||||
backgroundColor: null,
|
||||
allowTaint: true,
|
||||
useCORS: true
|
||||
})
|
||||
|
||||
// 上传预览图
|
||||
let uploadParams = new FormData()
|
||||
uploadParams.append('object', base64toFile(canvasImage.toDataURL(), `${fetchRouteParamsLocation()}_index_preview.png`))
|
||||
const uploadRes = await uploadFile(uploadParams) as unknown as MyResponseType
|
||||
// 保存预览图
|
||||
if(uploadRes.code === ResultEnum.SUCCESS) {
|
||||
await updateProjectApi({
|
||||
id: fetchRouteParamsLocation(),
|
||||
indexImage: `${systemStore.getFetchInfo.OSSUrl}${uploadRes.data.fileName}`
|
||||
})
|
||||
// 上传预览图
|
||||
let uploadParams = new FormData()
|
||||
uploadParams.append('object', base64toFile(canvasImage.toDataURL(), `${fetchRouteParamsLocation()}_index_preview.png`))
|
||||
const uploadRes = await uploadFile(uploadParams)
|
||||
// 保存预览图
|
||||
if(uploadRes && uploadRes.code === ResultEnum.SUCCESS) {
|
||||
await updateProjectApi({
|
||||
id: fetchRouteParamsLocation(),
|
||||
indexImage: `${systemStore.getFetchInfo.OSSUrl}${uploadRes.data.fileName}`
|
||||
})
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
// 保存数据
|
||||
let params = new FormData()
|
||||
params.append('projectId', projectId)
|
||||
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(() => {
|
||||
chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.SUCCESS)
|
||||
|
||||
@@ -38,20 +38,23 @@ import { MonacoEditor } from '@/components/Pages/MonacoEditor'
|
||||
import { SavePageEnum } from '@/enums/editPageEnum'
|
||||
import { getSessionStorageInfo } from '../preview/utils'
|
||||
import type { ChartEditStorageType } from '../preview/index.d'
|
||||
import { setSessionStorage } from '@/utils'
|
||||
import { setSessionStorage, fetchRouteParamsLocation } from '@/utils'
|
||||
import { StorageEnum } from '@/enums/storageEnum'
|
||||
import { icon } from '@/plugins'
|
||||
|
||||
import { useSync } from '@/views/chart/hooks/useSync.hook'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { ProjectInfoEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
|
||||
const chartEditStore = useChartEditStore()
|
||||
const { dataSyncUpdate } = useSync()
|
||||
const { ChevronBackOutlineIcon, DownloadIcon } = icon.ionicons5
|
||||
const showOpenFilePicker: Function = (window as any).showOpenFilePicker
|
||||
let content = ref('')
|
||||
|
||||
const content = ref('')
|
||||
// 从sessionStorage 获取数据
|
||||
function getDataBySession() {
|
||||
const localStorageInfo: ChartEditStorageType = getSessionStorageInfo() as unknown as ChartEditStorageType
|
||||
async function getDataBySession() {
|
||||
const localStorageInfo: ChartEditStorageType = await getSessionStorageInfo() as unknown as ChartEditStorageType
|
||||
content.value = JSON.stringify(localStorageInfo, undefined, 2)
|
||||
}
|
||||
getDataBySession()
|
||||
setTimeout(getDataBySession)
|
||||
|
||||
// 返回父窗口
|
||||
function back() {
|
||||
@@ -86,7 +89,7 @@ document.addEventListener('keydown', function (e) {
|
||||
addEventListener('blur', updateSync)
|
||||
|
||||
// 同步更新
|
||||
function updateSync() {
|
||||
async function updateSync() {
|
||||
if (!window.opener) {
|
||||
return window['$message'].error('源窗口已关闭,视图同步失败')
|
||||
}
|
||||
@@ -94,6 +97,11 @@ function updateSync() {
|
||||
const detail = JSON.parse(content.value)
|
||||
delete detail.id
|
||||
// 保持id不变
|
||||
// 带后端版本额外处理请求
|
||||
if (dataSyncUpdate) {
|
||||
chartEditStore.setProjectInfo(ProjectInfoEnum.PROJECT_ID, fetchRouteParamsLocation())
|
||||
await dataSyncUpdate(false) // JSON界面保存不上传缩略图
|
||||
}
|
||||
window.opener.dispatchEvent(new CustomEvent(SavePageEnum.JSON, { detail }))
|
||||
} catch (e) {
|
||||
window['$message'].error('内容格式有误')
|
||||
|
||||
@@ -207,8 +207,8 @@ const handleSubmit = async (e: Event) => {
|
||||
const res = await loginApi({
|
||||
username,
|
||||
password
|
||||
}) as unknown as MyResponseType
|
||||
if(res.data) {
|
||||
})
|
||||
if(res && res.data) {
|
||||
const { tokenValue, tokenName } = res.data.token
|
||||
const { nickname, username, id } = res.data.userinfo
|
||||
|
||||
@@ -225,6 +225,7 @@ const handleSubmit = async (e: Event) => {
|
||||
window['$message'].success(t('login.login_success'))
|
||||
routerTurnByName(PageEnum.BASE_HOME_NAME, true)
|
||||
}
|
||||
loading.value = false
|
||||
} else {
|
||||
window['$message'].error(t('login.login_message'))
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
>
|
||||
<component
|
||||
:is="item.chartConfig.chartKey"
|
||||
:id="item.id"
|
||||
:chartConfig="item"
|
||||
:themeSetting="themeSetting"
|
||||
:themeColor="themeColor"
|
||||
@@ -29,6 +30,7 @@ import { CreateComponentGroupType } from '@/packages/index.d'
|
||||
import { animationsClass, getFilterStyle, getTransformStyle, getBlendModeStyle } from '@/utils'
|
||||
import { getSizeStyle, getComponentAttrStyle, getStatusStyle } from '../../utils'
|
||||
import { useLifeHandler } from '@/hooks'
|
||||
|
||||
const props = defineProps({
|
||||
groupData: {
|
||||
type: Object as PropType<CreateComponentGroupType>,
|
||||
@@ -52,5 +54,6 @@ const props = defineProps({
|
||||
<style lang="scss" scoped>
|
||||
.chart-item {
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
...getTransformStyle(item.styles),
|
||||
...getStatusStyle(item.status),
|
||||
...getBlendModeStyle(item.styles) as any
|
||||
} as any"
|
||||
}"
|
||||
>
|
||||
<!-- 分组 -->
|
||||
<preview-render-group
|
||||
@@ -25,6 +25,7 @@
|
||||
<component
|
||||
v-else
|
||||
:is="item.chartConfig.chartKey"
|
||||
:id="item.id"
|
||||
:chartConfig="item"
|
||||
:themeSetting="themeSetting"
|
||||
:themeColor="themeColor"
|
||||
@@ -35,7 +36,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PropType, computed } from 'vue'
|
||||
import { PropType, computed, onMounted } from 'vue'
|
||||
import { useChartDataPondFetch } from '@/hooks'
|
||||
import { ChartEditStorageType } from '../../index.d'
|
||||
import { PreviewRenderGroup } from '../PreviewRenderGroup/index'
|
||||
import { CreateComponentGroupType } from '@/packages/index.d'
|
||||
@@ -43,6 +45,10 @@ import { chartColors } from '@/settings/chartThemes/index'
|
||||
import { animationsClass, getFilterStyle, getTransformStyle, getBlendModeStyle } from '@/utils'
|
||||
import { getSizeStyle, getComponentAttrStyle, getStatusStyle } from '../../utils'
|
||||
import { useLifeHandler } from '@/hooks'
|
||||
|
||||
// 初始化数据池
|
||||
const { initDataPond, clearMittDataPondMap } = useChartDataPondFetch()
|
||||
|
||||
const props = defineProps({
|
||||
localStorageInfo: {
|
||||
type: Object as PropType<ChartEditStorageType>,
|
||||
@@ -61,10 +67,17 @@ const themeColor = computed(() => {
|
||||
const chartThemeColor = props.localStorageInfo.editCanvasConfig.chartThemeColor
|
||||
return chartColors[chartThemeColor]
|
||||
})
|
||||
|
||||
// 组件渲染结束初始化数据池
|
||||
clearMittDataPondMap()
|
||||
onMounted(() => {
|
||||
initDataPond(props.localStorageInfo.requestGlobalConfig)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.chart-item {
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -11,15 +11,13 @@ export interface ChartEditStorageType extends ChartEditStorage {
|
||||
// 根据路由 id 获取存储数据的信息
|
||||
export const getSessionStorageInfo = async () => {
|
||||
const id = fetchRouteParamsLocation()
|
||||
const storageList: ChartEditStorageType[] = getSessionStorage(
|
||||
StorageEnum.GO_CHART_STORAGE_LIST
|
||||
)
|
||||
|
||||
const storageList: ChartEditStorageType[] = getSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST)
|
||||
|
||||
// 是否本地预览
|
||||
if (!storageList || storageList.findIndex(e => e.id === id.toString()) === -1) {
|
||||
// 接口调用
|
||||
const res = await fetchProjectApi({ projectId: id }) as unknown as MyResponseType
|
||||
if (res.code === ResultEnum.SUCCESS) {
|
||||
const res = await fetchProjectApi({ projectId: id })
|
||||
if (res && res.code === ResultEnum.SUCCESS) {
|
||||
const { content, state } = res.data
|
||||
if (state === -1) {
|
||||
// 跳转未发布页
|
||||
@@ -37,4 +35,4 @@ export const getSessionStorageInfo = async () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,12 +12,12 @@ import { ref } from 'vue'
|
||||
import Preview from './index.vue'
|
||||
|
||||
let key = ref(Date.now())
|
||||
let localStorageInfo: ChartEditStorageType = getSessionStorageInfo() as unknown as ChartEditStorageType
|
||||
|
||||
// 数据变更 -> 同步sessionStorage -> reload页面 (重新执行Mounted)
|
||||
// 数据变更 -> 组件销毁重建
|
||||
;[SavePageEnum.JSON, SavePageEnum.CHART].forEach((saveEvent: string) => {
|
||||
if (!window.opener) return
|
||||
window.opener.addEventListener(saveEvent, (e: any) => {
|
||||
window.opener.addEventListener(saveEvent, async (e: any) => {
|
||||
const localStorageInfo: ChartEditStorageType = await getSessionStorageInfo() as unknown as ChartEditStorageType
|
||||
setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, [{ ...e.detail, id: localStorageInfo.id }])
|
||||
key.value = Date.now()
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ref, reactive } from 'vue';
|
||||
import { ref, reactive } from 'vue'
|
||||
import { goDialog, httpErrorHandle } from '@/utils'
|
||||
import { DialogEnum } from '@/enums/pluginEnum'
|
||||
import { projectListApi, deleteProjectApi, changeProjectReleaseApi } from '@/api/path'
|
||||
@@ -7,16 +7,15 @@ import { ResultEnum } from '@/enums/httpEnum'
|
||||
|
||||
// 数据初始化
|
||||
export const useDataListInit = () => {
|
||||
|
||||
const loading = ref(true)
|
||||
|
||||
const paginat = reactive({
|
||||
// 当前页数
|
||||
// 当前页数
|
||||
page: 1,
|
||||
// 每页值
|
||||
limit: 12,
|
||||
// 总数
|
||||
count: 10,
|
||||
count: 10
|
||||
})
|
||||
|
||||
const list = ref<ChartList>([])
|
||||
@@ -27,11 +26,11 @@ export const useDataListInit = () => {
|
||||
const res = await projectListApi({
|
||||
page: paginat.page,
|
||||
limit: paginat.limit
|
||||
}) as any
|
||||
if (res.data) {
|
||||
const { count } = res
|
||||
})
|
||||
if (res && res.data) {
|
||||
const { count } = res as any // 这里的count与data平级,不在Response结构中
|
||||
paginat.count = count
|
||||
list.value = res.data.map((e: any) => {
|
||||
list.value = res.data.map(e => {
|
||||
const { id, projectName, state, createTime, indexImage, createUserId } = e
|
||||
return {
|
||||
id: id,
|
||||
@@ -67,11 +66,14 @@ export const useDataListInit = () => {
|
||||
goDialog({
|
||||
type: DialogEnum.DELETE,
|
||||
promise: true,
|
||||
onPositiveCallback: () => new Promise(res => {
|
||||
res(deleteProjectApi({
|
||||
ids: cardData.id
|
||||
}))
|
||||
}),
|
||||
onPositiveCallback: () =>
|
||||
new Promise(res => {
|
||||
res(
|
||||
deleteProjectApi({
|
||||
ids: cardData.id
|
||||
})
|
||||
)
|
||||
}),
|
||||
promiseResCallback: (res: any) => {
|
||||
if (res.code === ResultEnum.SUCCESS) {
|
||||
window['$message'].success(window['$t']('global.r_delete_success'))
|
||||
@@ -90,8 +92,8 @@ export const useDataListInit = () => {
|
||||
id: id,
|
||||
// [-1未发布, 1发布]
|
||||
state: !release ? 1 : -1
|
||||
}) as unknown as MyResponseType
|
||||
if (res.code === ResultEnum.SUCCESS) {
|
||||
})
|
||||
if (res && res.code === ResultEnum.SUCCESS) {
|
||||
list.value = []
|
||||
fetchList()
|
||||
// 发布 -> 未发布
|
||||
|
||||
2
src/views/project/items/index.d.ts
vendored
2
src/views/project/items/index.d.ts
vendored
@@ -1,7 +1,7 @@
|
||||
export type Chartype = {
|
||||
id: number | string
|
||||
title: string // 标题
|
||||
label: string // 标签
|
||||
label?: string // 标签
|
||||
time: string, // 时间
|
||||
image: string, // 预览图地址
|
||||
createId: string, // 创建者
|
||||
|
||||
@@ -96,8 +96,8 @@ const btnHandle = async (key: string) => {
|
||||
remarks: 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'))
|
||||
|
||||
const { id } = res.data
|
||||
|
||||
7
types/global.d.ts
vendored
7
types/global.d.ts
vendored
@@ -11,11 +11,4 @@ interface Window {
|
||||
opener: any
|
||||
}
|
||||
|
||||
|
||||
declare interface MyResponseType {
|
||||
code: number;
|
||||
msg: string;
|
||||
data: any;
|
||||
}
|
||||
|
||||
declare type Recordable<T = any> = Record<string, T>
|
||||
|
||||
Reference in New Issue
Block a user