Pre Merge pull request !245 from 宝莉/lyw

This commit is contained in:
宝莉 2024-09-10 07:18:41 +00:00 committed by Gitee
commit 8b6a442f65
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
511 changed files with 50825 additions and 5011 deletions

7
.env
View File

@ -2,7 +2,10 @@
VITE_DEV_PORT = '8080' VITE_DEV_PORT = '8080'
# development path # development path
VITE_DEV_PATH = 'https://demo.mtruning.club' # VITE_DEV_PATH = 'http://192.168.0.34:11887'
VITE_DEV_PATH = 'http://192.168.0.34:8025/'
# VITE_DEV_PATH = 'http://192.168.0.120:3001'
VITE_DEV_TOKEN = "197fccbc-0048-4552-aeb3-9b19edb351d6"
# production path # production path
VITE_PRO_PATH = 'https://demo.mtruning.club' # VITE_PRO_PATH = 'http://192.168.0.235:8177'

2
.gitignore vendored
View File

@ -1,6 +1,6 @@
node_modules node_modules
.DS_Store .DS_Store
dist customLargeScreen
dist-ssr dist-ssr
*.local *.local
.vscode .vscode

View File

@ -37,61 +37,61 @@ import axiosInstance from './axios'
import { RequestHttpEnum, ContentTypeEnum } from '@/enums/httpEnum' import { RequestHttpEnum, ContentTypeEnum } from '@/enums/httpEnum'
export const get = (url: string, params?: object) => { export const get = (url: string, params?: object) => {
return axiosInstance({ return axiosInstance({
url: url, url: url,
method: RequestHttpEnum.GET, method: RequestHttpEnum.GET,
params: params, params: params,
}) })
} }
export const post = (url: string, data?: object, headersType?: string) => { export const post = (url: string, data?: object, headersType?: string) => {
return axiosInstance({ return axiosInstance({
url: url, url: url,
method: RequestHttpEnum.POST, method: RequestHttpEnum.POST,
data: data, data: data,
headers: { headers: {
'Content-Type': headersType || ContentTypeEnum.JSON 'Content-Type': headersType || ContentTypeEnum.JSON
} }
}) })
} }
export const put = (url: string, data?: object, headersType?: string) => { export const put = (url: string, data?: object, headersType?: string) => {
return axiosInstance({ return axiosInstance({
url: url, url: url,
method: RequestHttpEnum.PUT, method: RequestHttpEnum.PUT,
data: data, data: data,
headers: { headers: {
'Content-Type': headersType || ContentTypeEnum.JSON 'Content-Type': headersType || ContentTypeEnum.JSON
} }
}) })
} }
export const del = (url: string, params?: object) => { export const del = (url: string, params?: object) => {
return axiosInstance({ return axiosInstance({
url: url, url: url,
method: RequestHttpEnum.DELETE, method: RequestHttpEnum.DELETE,
params params
}) })
} }
// 获取请求函数默认get // 获取请求函数默认get
export const http = (type?: RequestHttpEnum) => { export const http = (type?: RequestHttpEnum) => {
switch (type) { switch (type) {
case RequestHttpEnum.GET: case RequestHttpEnum.GET:
return get return get
case RequestHttpEnum.POST: case RequestHttpEnum.POST:
return post return post
case RequestHttpEnum.PUT: case RequestHttpEnum.PUT:
return put return put
case RequestHttpEnum.DELETE: case RequestHttpEnum.DELETE:
return del return del
default: default:
return get return get
} }
} }
``` ```
@ -109,11 +109,3 @@ export const http = (type?: RequestHttpEnum) => {
* build: 影响项目构建或依赖修改 * build: 影响项目构建或依赖修改
* style: 不影响程序逻辑的代码修改 * style: 不影响程序逻辑的代码修改
* chore: 不属于以上类型的其他类型(日常事务) * chore: 不属于以上类型的其他类型(日常事务)
## 交流
QQ 群1030129384
![QQ群](readme/go-view-qq.png)
![渲染海报](readme/logo-poster.png)

View File

@ -1,5 +1,5 @@
import path from 'path' import path from 'path'
export const OUTPUT_DIR = 'dist' export const OUTPUT_DIR = 'customLargeScreen'
// monaco-editor 路径 // monaco-editor 路径
export const prefix = `monaco-editor/esm/vs` export const prefix = `monaco-editor/esm/vs`

View File

@ -4,13 +4,10 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="renderer" content="webkit" /> <meta name="renderer" content="webkit" />
<meta name="description" content="GoView 是高效、高性能的拖拽式低代码数据可视化开发平台,将页面元素封装为基础组件,无需编写代码即可完成业务需求。"> <meta
<meta name="keywords" content="GoViewgoview低代码可视化"> name="viewport"
<meta name="author" content="奔跑的面条,面条"> content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1,maximum-scale=1,user-scalable=0"> />
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=yes" media="(min-width: 769px)">
<link rel="icon" href="./favicon.ico" />
<title>GoView</title>
<link rel="stylesheet" href="./index.css" /> <link rel="stylesheet" href="./index.css" />
</head> </head>
<body> <body>

10777
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,7 @@
"scripts": { "scripts": {
"dev": "vite --host", "dev": "vite --host",
"build": "vue-tsc --noEmit && vite build", "build": "vue-tsc --noEmit && vite build",
"viteBuild": " vite build",
"preview": "vite preview", "preview": "vite preview",
"new": "plop --plopfile ./plop/plopfile.js", "new": "plop --plopfile ./plop/plopfile.js",
"postinstall": "husky install", "postinstall": "husky install",
@ -21,6 +22,7 @@
"@types/crypto-js": "^4.1.1", "@types/crypto-js": "^4.1.1",
"@types/keymaster": "^1.6.30", "@types/keymaster": "^1.6.30",
"@types/lodash": "^4.14.184", "@types/lodash": "^4.14.184",
"@vicons/fa": "^0.12.0",
"animate.css": "^4.1.1", "animate.css": "^4.1.1",
"axios": "^1.4.0", "axios": "^1.4.0",
"color": "^4.2.3", "color": "^4.2.3",
@ -36,8 +38,10 @@
"iconify-icon": "^1.0.8", "iconify-icon": "^1.0.8",
"keymaster": "^1.6.2", "keymaster": "^1.6.2",
"mitt": "^3.0.0", "mitt": "^3.0.0",
"moment": "^2.29.4",
"monaco-editor": "^0.33.0", "monaco-editor": "^0.33.0",
"naive-ui": "2.34.3", "naive-ui": "2.34.3",
"nanoid": "^5.0.4",
"pinia": "^2.0.13", "pinia": "^2.0.13",
"screenfull": "^6.0.1", "screenfull": "^6.0.1",
"three": "^0.145.0", "three": "^0.145.0",
@ -57,7 +61,10 @@
"@typescript-eslint/eslint-plugin": "^5.18.0", "@typescript-eslint/eslint-plugin": "^5.18.0",
"@typescript-eslint/parser": "^5.18.0", "@typescript-eslint/parser": "^5.18.0",
"@vicons/carbon": "^0.12.0", "@vicons/carbon": "^0.12.0",
"@vicons/fluent": "^0.12.0",
"@vicons/ionicons5": "~0.11.0", "@vicons/ionicons5": "~0.11.0",
"@vicons/material": "^0.12.0",
"@vicons/tabler": "^0.12.0",
"@vitejs/plugin-vue": "^4.2.3", "@vitejs/plugin-vue": "^4.2.3",
"@vitejs/plugin-vue-jsx": "^3.0.1", "@vitejs/plugin-vue-jsx": "^3.0.1",
"@vue/compiler-sfc": "^3.2.31", "@vue/compiler-sfc": "^3.2.31",

7974
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

63
proxyConfig.ts Normal file
View File

@ -0,0 +1,63 @@
import { loadEnv } from 'vite'
// 这里是开发环境的代理配置
const devProxy = (mode:any) => {
return {
// 开发
'/dcim': {
// @ts-ignore
target: loadEnv(mode, process.cwd()).VITE_DEV_PATH,
changeOrigin: true,
ws: true,
secure: true,
},
// 开发首页缩略图
'/data/file': {
// @ts-ignore
target: loadEnv(mode, process.cwd()).VITE_DEV_PATH,
changeOrigin: true,
ws: true,
secure: true,
},
// 开发 图片
'/svgConfig/customLargeScreen': {
// @ts-ignore
target: loadEnv(mode, process.cwd()).VITE_DEV_PATH,
changeOrigin: true,
// rewrite: (path) => path.replace(new RegExp(`^/svgConfig/customLargeScreen`), ''),
ws: true,
secure: true,
},
// 开发
'/dynamic_report': {
// @ts-ignore
target: loadEnv(mode, process.cwd()).VITE_DEV_PATH,
changeOrigin: true,
ws: true,
secure: true,
},
};
}
// 这里是生产环境的代理配置
const prodProxy = (mode:any) => {
return {
/*
// 生产list页缩略图 开发时注释掉
'/svgConfig/customLargeScreen/data/file': {
// @ts-ignore
target: loadEnv(mode, process.cwd()).VITE_PRO_PATH,
// target: window.location.href,
changeOrigin: true,
rewrite: (path:any) => {
console.log(path.replace(new RegExp(`^/svgConfig/customLargeScreen/data/file`), '/data/file'))
return path.replace(new RegExp(`^/svgConfig/customLargeScreen/data/file`), '/data/file')
},
ws: true,
secure: true,
},
*/
}
}
// 根据环境变量导出相应的配置
export const proxyConfig = process.env.NODE_ENV === 'production' ? prodProxy : devProxy;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -18,6 +18,86 @@ import { NConfigProvider } from 'naive-ui'
import { GoAppProvider } from '@/components/GoAppProvider' import { GoAppProvider } from '@/components/GoAppProvider'
import { I18n } from '@/components/I18n' import { I18n } from '@/components/I18n'
import { useSystemInit, useDarkThemeHook, useThemeOverridesHook, useCode, useLang } from '@/hooks' import { useSystemInit, useDarkThemeHook, useThemeOverridesHook, useCode, useLang } from '@/hooks'
import { getToken } from '@/api/path'
import { useRouterStore } from '@/store/modules/routerStore/routerStore'
import { useOriginStore } from '@/store/modules/originStore/originStore'
import { useGetMessageByParent } from '@/utils/utils'
import router from '@/router'
import {useDesignStore} from "@/store/modules/designStore/designStore";
import { AppThemeColorType } from '@/store/modules/designStore/designStore.d'
const {getMessageByParent} = useGetMessageByParent()
// console.log(window.location.origin)
const routerStore = useRouterStore()
getMessageByParent('setCallByParent', (e) => {
if(e.data.type === 'setCallByParent' && e.data.page === 'customLargeScreen') {
const {data}:{data:any} = e
if(data.page === 'customLargeScreen' && data.type === 'setCallByParent') {
routerStore.setCallByParent(data.callByParent)
}
}
})
const originStore = useOriginStore()
getMessageByParent('getStore', (e) => {
if(e.data.type === 'getStore' && e.data.page === 'customLargeScreen') {
originStore.setOriginStore(e.data.data, false)
let map: { [k: string]: AppThemeColorType } = {
blueTheme: {
"CMYK": [75, 41, 0, 0],
"RGB": [65,150,255],
"hex": "#4196ff",
"name": "天蓝",
"pinyin": "tianlan"
},
greenTheme: {
"CMYK": [100, 0, 3, 17],
"RGB": [0,212,206],
"hex": "#00d4ce",
"name": "墨绿",
"pinyin": "molv"
},
simpleTheme: {
"CMYK": [0, 82, 70, 35],
"RGB": [167,30,50],
"hex": "#a71e32",
"name": "简约",
"pinyin": "jianyue"
},
whiteOrangeTheme: {
"CMYK": [0, 50, 100, 7],
"RGB": [238,119,0],
"hex": "#EE7700",
"name": "白橙",
"pinyin": "baicheng"
},
lightSkyBlueTheme: {
"CMYK": [99, 11, 0, 5],
"RGB": [3,216,243],
"hex": "#03D8F3",
"name": "亮天蓝色",
"pinyin": "liangtianlanse"
},
}
let theme = e.data.data.app.theme as string
const designStore = useDesignStore()
designStore.setAppColor(map[theme])
}
})
getMessageByParent('loaded', (e) => {
if(e.data.type === 'changeRoute' && e.data.page === 'customLargeScreen') {
if(import.meta.env.MODE === 'production') {
routerStore.setToken(e.data.token)
}
else {
routerStore.setToken(import.meta.env.VITE_DEV_TOKEN)
}
router.replace(e.data.path ? e.data.path : '/chart/preview/null')
}
})
// getToken()
// //
const darkTheme = useDarkThemeHook() const darkTheme = useDarkThemeHook()

View File

@ -1,5 +1,5 @@
import axios, { AxiosResponse, AxiosRequestConfig, Axios, AxiosError, InternalAxiosRequestConfig } from 'axios' import axios, { AxiosResponse, AxiosRequestConfig, Axios, AxiosError, InternalAxiosRequestConfig } from 'axios'
import { RequestHttpHeaderEnum, ResultEnum, ModuleTypeEnum } from '@/enums/httpEnum' import { RequestHttpHeaderEnum, ResultEnum, ResultErrcode } from '@/enums/httpEnum'
import { PageEnum, ErrorPageNameMap } from '@/enums/pageEnum' import { PageEnum, ErrorPageNameMap } from '@/enums/pageEnum'
import { StorageEnum } from '@/enums/storageEnum' import { StorageEnum } from '@/enums/storageEnum'
import { axiosPre } from '@/settings/httpSetting' import { axiosPre } from '@/settings/httpSetting'
@ -7,11 +7,15 @@ import { SystemStoreEnum, SystemStoreUserInfoEnum } from '@/store/modules/system
import { redirectErrorPage, getLocalStorage, routerTurnByName, isPreview } from '@/utils' import { redirectErrorPage, getLocalStorage, routerTurnByName, isPreview } from '@/utils'
import { fetchAllowList } from './axios.config' import { fetchAllowList } from './axios.config'
import includes from 'lodash/includes' import includes from 'lodash/includes'
import { postMessageToParent } from "@/utils";
export interface MyResponseType<T> { export interface MyResponseType<T> {
code: ResultEnum code: ResultEnum
data: T data: T
message: string message: string
// 兼顾主系统
errcode: string
errmsg: string
} }
export interface MyRequestInstance extends Axios { export interface MyRequestInstance extends Axios {
@ -19,23 +23,24 @@ export interface MyRequestInstance extends Axios {
} }
const axiosInstance = axios.create({ const axiosInstance = axios.create({
baseURL: `${import.meta.env.PROD ? import.meta.env.VITE_PRO_PATH : ''}${axiosPre}`, // baseURL: `${import.meta.env.PROD ? import.meta.env.VITE_PRO_PATH : ''}${axiosPre}`,
baseURL: `${import.meta.env.PROD ? window.location.origin : ''}${axiosPre}`,
timeout: ResultEnum.TIMEOUT timeout: ResultEnum.TIMEOUT
}) as unknown as MyRequestInstance }) as unknown as MyRequestInstance
axiosInstance.interceptors.request.use( axiosInstance.interceptors.request.use(
(config: InternalAxiosRequestConfig) => { (config: InternalAxiosRequestConfig) => {
// 白名单校验 // // 白名单校验
if (includes(fetchAllowList, config.url)) return config // if (includes(fetchAllowList, config.url)) return config
// 获取 token // // 获取 token
const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE) // const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE)
// 重新登录 // // 重新登录
if (!info) { // if (!info) {
routerTurnByName(PageEnum.BASE_LOGIN_NAME) // routerTurnByName(PageEnum.BASE_LOGIN_NAME)
return config // return config
} // }
const userInfo = info[SystemStoreEnum.USER_INFO] // const userInfo = info[SystemStoreEnum.USER_INFO]
config.headers[userInfo[SystemStoreUserInfoEnum.TOKEN_NAME] || 'token'] = userInfo[SystemStoreUserInfoEnum.USER_TOKEN] || '' // config.headers[userInfo[SystemStoreUserInfoEnum.TOKEN_NAME] || 'token'] = userInfo[SystemStoreUserInfoEnum.USER_TOKEN] || ''
return config return config
}, },
(err: AxiosError) => { (err: AxiosError) => {
@ -46,48 +51,79 @@ axiosInstance.interceptors.request.use(
// 响应拦截器 // 响应拦截器
axiosInstance.interceptors.response.use( axiosInstance.interceptors.response.use(
(res: AxiosResponse) => { (res: AxiosResponse) => {
const { code, errcode, errmsg } = res.data as { code: number, errcode: string, errmsg: string }
const logOutCodeList = ['00004', '000012', '000013']
if(logOutCodeList.some(_ => _ === errcode)) {
// window['$message'].error(errmsg)
// setTimeout(() => {
// postMessageToParent({
// type: 'logOut'
// })
// })
// axios加载时 pinia还没加载好 要异步加载拿到pinia
import('@/store/modules/modalStore/modalStore').then(res => {
const modalStore = res.useModalStore()
modalStore.setModalStore({
showModal: true,
title: '提示',
content: errmsg,
positiveText: '重新登录',
positiveClick: () => {
modalStore.clear()
setTimeout(() => {
postMessageToParent({
type: 'logOut'
})
}, 500)
},
})
})
return Promise.resolve(res.data)
}
// 预览页面错误不进行处理 // 预览页面错误不进行处理
if (isPreview()) { if (isPreview()) {
return Promise.resolve(res.data) return Promise.resolve(res.data)
} }
const { code } = res.data as { code: number }
if (code === undefined || code === null) return Promise.resolve(res.data) // if (code === undefined || code === null) return Promise.resolve(res.data)
// 成功 // 成功
if (code === ResultEnum.SUCCESS) { if (errcode === ResultErrcode.SUCCESS) {
return Promise.resolve(res.data) return Promise.resolve(res.data)
} }
// 登录过期 // // 登录过期
if (code === ResultEnum.TOKEN_OVERDUE) { // if (code === ResultEnum.TOKEN_OVERDUE) {
window['$message'].error(window['$t']('http.token_overdue_message')) // window['$message'].error(window['$t']('http.token_overdue_message'))
routerTurnByName(PageEnum.BASE_LOGIN_NAME) // routerTurnByName(PageEnum.BASE_LOGIN_NAME)
return Promise.resolve(res.data) // return Promise.resolve(res.data)
} // }
// 固定错误码重定向 // 固定错误码重定向
if (ErrorPageNameMap.get(code)) { // if (ErrorPageNameMap.get(code)) {
redirectErrorPage(code) // redirectErrorPage(code)
return Promise.resolve(res.data) // return Promise.resolve(res.data)
} // }
// 提示错误 // 统一提示错误
window['$message'].error(window['$t']((res.data as any).msg)) window['$message'].error(errmsg)
return Promise.resolve(res.data) return Promise.resolve(res.data)
}, },
(err: AxiosError) => { (err: AxiosError) => {
const status = err.response?.status Promise.reject(err)
switch (status) { // const status = err.response?.status
case 401: // switch (status) {
routerTurnByName(PageEnum.BASE_LOGIN_NAME) // case 401:
Promise.reject(err) // routerTurnByName(PageEnum.BASE_LOGIN_NAME)
break // Promise.reject(err)
// break
default: //
Promise.reject(err) // default:
break // Promise.reject(err)
} // break
// }
} }
) )

View File

@ -8,6 +8,8 @@ import {
RequestParamsObjType RequestParamsObjType
} from '@/enums/httpEnum' } from '@/enums/httpEnum'
import type { RequestGlobalConfigType, RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d' import type { RequestGlobalConfigType, RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
import moment from "moment";
import {getToken} from "@/api/path";
export const get = <T = any>(url: string, params?: object) => { export const get = <T = any>(url: string, params?: object) => {
return axiosInstance<T>({ return axiosInstance<T>({
@ -139,7 +141,9 @@ export const customizeHttp = (targetParams: RequestConfigType, globalParams: Req
// SQL 请求对象 // SQL 请求对象
requestSQLContent, requestSQLContent,
// 请求内容 params / cookie / header / body: 同 requestParamsBodyType // 请求内容 params / cookie / header / body: 同 requestParamsBodyType
requestParams: targetRequestParams requestParams: targetRequestParams,
// 请求参数body-json预处理
requestBodyJSONPre
} = targetParams } = targetParams
// 静态排除 // 静态排除
@ -172,9 +176,21 @@ export const customizeHttp = (targetParams: RequestConfigType, globalParams: Req
case RequestBodyEnum.JSON: case RequestBodyEnum.JSON:
headers['Content-Type'] = ContentTypeEnum.JSON headers['Content-Type'] = ContentTypeEnum.JSON
//json对象也能使用'javasctipt:'来动态拼接参数 //json对象也能使用'javasctipt:'来动态拼接参数
data = translateStr(targetRequestParams.Body['json']) if(requestBodyJSONPre.enable) {
if(typeof data === 'string') data = JSON.parse(data) const fn = new Function('global', requestBodyJSONPre.handler)
// json 赋值给 data const global = {
moment,
getToken
}
const res = fn(global)
// @ts-ignore
data = JSON.stringify(res, null, 2)
}
else {
data = translateStr(targetRequestParams.Body['json'])
if(typeof data === 'string') data = JSON.parse(data)
// json 赋值给 data
}
break break
case RequestBodyEnum.XML: case RequestBodyEnum.XML:

View File

@ -0,0 +1,65 @@
// import Cookies from 'js-cookie';
import { http } from "@/api/http";
import { RequestHttpEnum } from "@/enums/httpEnum";
import { httpErrorHandle } from '@/utils'
import moment from 'moment'
/*
export function getToken() {
// 为了开发时只单独展示goview 需要localStorage
// const storage_access_token = localStorage.getItem('access_token_obj')
// if(storage_access_token) {
// const obj = JSON.parse(storage_access_token)
// const { access_token, expiration } = obj
// if(expiration >= Number(moment().format('x'))) return access_token
// }
let queryStr = window.location.href
queryStr = queryStr.split('?')[1]
if(queryStr && queryStr.indexOf('#') > -1) queryStr = queryStr.split('#')[0]
let query:{[key:string]: string} = {}
queryStr && queryStr.split('&').forEach((item:string) => {
query[item.split('=')[0]] = item.split('=')[1]
})
// const obj = {
// access_token: query.access_token,
// expiration: 86400000 + Number(moment().format('x'))
// }
// if(query.access_token) localStorage.setItem('access_token_obj', JSON.stringify(obj))
return query.access_token
}
*/
// 初次等待久一点 因为dom加载后才能获取父页面传来的token 才能存入store
export async function getToken() {
return new Promise(resolve => {
let timer = setInterval(() => {
import('@/store/modules/routerStore/routerStore').then(res => {
let routerStore = res.useRouterStore()
if(routerStore.token) {
clearInterval(timer)
resolve(routerStore.token)
}
})
}, 100)
})
}
export const publicInterface = async (paramType:string, interfaceType:string, paramData?:unknown) =>{
try {
let access_token = ''
if(import.meta.env.MODE === 'production') {
access_token = await getToken() as string
}
else {
access_token = import.meta.env.VITE_DEV_TOKEN
}
const res = await http(RequestHttpEnum.POST)<any>(paramType, {
access_token,
type: interfaceType,
data: paramData
})
return res
} catch {
httpErrorHandle()
}
}

0
src/api/path/business.d.ts vendored Normal file
View File

View File

@ -1,2 +1,3 @@
export * from '@/api/path/project.api' export * from '@/api/path/project.api'
export * from '@/api/path/system.api' export * from '@/api/path/system.api'
export * from '@/api/path/business.api'

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 878 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

View File

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 878 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 684 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 840 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 819 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 41.8 47.8" style="enable-background:new 0 0 41.8 47.8;" xml:space="preserve">
<g id="bg">
</g>
<g id="顶栏">
</g>
<g id="楼宇蒙层">
</g>
<g id="内容">
<g>
<ellipse style="opacity:0.5;fill:#F43B42;" cx="20.8" cy="36.8" rx="15.4" ry="7.7"/>
<g>
<ellipse style="fill:none;stroke:#F43B42;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:2.0175,2.0175;" cx="20.8" cy="36.8" rx="20" ry="10"/>
</g>
<g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="3.5071" y1="11.6331" x2="37.1067" y2="11.6331">
<stop offset="0" style="stop-color:#F43B42;stop-opacity:0.15"/>
<stop offset="0.5" style="stop-color:#F43B42"/>
<stop offset="1" style="stop-color:#F43B42;stop-opacity:0.15"/>
</linearGradient>
<polygon style="fill:url(#SVGID_1_);stroke:#F43B42;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" points="
20.3,22.4 3.5,11.6 20.3,0.8 37.1,11.6 "/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="3.5071" y1="24.2332" x2="20.3069" y2="24.2332">
<stop offset="0" style="stop-color:#F43B42;stop-opacity:0.15"/>
<stop offset="0.5" style="stop-color:#F43B42"/>
<stop offset="1" style="stop-color:#F43B42;stop-opacity:0.15"/>
</linearGradient>
<polygon style="fill:url(#SVGID_2_);stroke:#F43B42;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" points="
20.3,22.4 20.3,36.8 3.5,11.6 "/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="20.3069" y1="24.2332" x2="37.1067" y2="24.2332">
<stop offset="0" style="stop-color:#F43B42;stop-opacity:0.15"/>
<stop offset="0.5" style="stop-color:#F43B42"/>
<stop offset="1" style="stop-color:#F43B42;stop-opacity:0.15"/>
</linearGradient>
<polygon style="fill:url(#SVGID_3_);stroke:#F43B42;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" points="
20.3,22.4 20.3,36.8 37.1,11.6 "/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 41.8 47.5" style="enable-background:new 0 0 41.8 47.5;" xml:space="preserve">
<g id="bg">
</g>
<g id="顶栏">
</g>
<g id="楼宇蒙层">
</g>
<g id="内容">
<g>
<ellipse style="opacity:0.5;fill:#4DCA59;" cx="20.9" cy="36.7" rx="15.4" ry="7.7"/>
<g>
<ellipse style="fill:none;stroke:#4DCA59;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:2.0175,2.0175;" cx="20.9" cy="36.7" rx="20" ry="10"/>
</g>
<g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="3.6473" y1="11.4665" x2="37.2469" y2="11.4665">
<stop offset="0" style="stop-color:#4DCA59;stop-opacity:0.15"/>
<stop offset="0.5" style="stop-color:#4DCA59"/>
<stop offset="1" style="stop-color:#4DCA59;stop-opacity:0.15"/>
</linearGradient>
<polygon style="fill:url(#SVGID_1_);stroke:#4DCA59;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" points="
20.4,22.3 3.6,11.5 20.4,0.7 37.2,11.5 "/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="3.6473" y1="24.0666" x2="20.4471" y2="24.0666">
<stop offset="0" style="stop-color:#4DCA59;stop-opacity:0.15"/>
<stop offset="0.5" style="stop-color:#4DCA59"/>
<stop offset="1" style="stop-color:#4DCA59;stop-opacity:0.15"/>
</linearGradient>
<polygon style="fill:url(#SVGID_2_);stroke:#4DCA59;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" points="
20.4,22.3 20.4,36.7 3.6,11.5 "/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="20.4471" y1="24.0666" x2="37.2469" y2="24.0666">
<stop offset="0" style="stop-color:#4DCA59;stop-opacity:0.15"/>
<stop offset="0.5" style="stop-color:#4DCA59"/>
<stop offset="1" style="stop-color:#4DCA59;stop-opacity:0.15"/>
</linearGradient>
<polygon style="fill:url(#SVGID_3_);stroke:#4DCA59;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;" points="
20.4,22.3 20.4,36.7 37.2,11.5 "/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

View File

@ -158,99 +158,111 @@
></n-select> ></n-select>
</setting-item> </setting-item>
</setting-item-box> </setting-item-box>
<setting-item-box name="最小值" alone v-if="'min' in xAxis">
<setting-item name="">
<n-input-number v-model:value="xAxis.min" size="small"/>
</setting-item>
</setting-item-box>
</collapse-item> </collapse-item>
<collapse-item v-if="yAxis" name="Y轴"> <template v-for="(yAxis, i) in yAxisArr" :key="i">
<template #header> <collapse-item v-if="yAxis" :name="`Y轴-${i + 1}`">
<n-switch v-model:value="yAxis.show" size="small"></n-switch> <template #header>
</template> <n-switch v-model:value="yAxis.show" size="small"></n-switch>
<setting-item-box name="单位"> </template>
<setting-item name="名称"> <setting-item-box name="单位">
<n-input v-model:value="yAxis.name" size="small"></n-input> <setting-item name="名称">
</setting-item> <n-input v-model:value="yAxis.name" size="small"></n-input>
<setting-item name="颜色"> </setting-item>
<n-color-picker size="small" v-model:value="yAxis.nameTextStyle.color"></n-color-picker> <setting-item name="颜色">
</setting-item> <n-color-picker size="small" v-model:value="yAxis.nameTextStyle.color"></n-color-picker>
<setting-item name="大小"> </setting-item>
<n-input-number v-model:value="yAxis.nameTextStyle.fontSize" :min="8" size="small"></n-input-number> <setting-item name="大小">
</setting-item> <n-input-number v-model:value="yAxis.nameTextStyle.fontSize" :min="8" size="small"></n-input-number>
<setting-item name="偏移量"> </setting-item>
<n-input-number v-model:value="yAxis.nameGap" :min="5" size="small"></n-input-number> <setting-item name="偏移量">
</setting-item> <n-input-number v-model:value="yAxis.nameGap" :min="5" size="small"></n-input-number>
</setting-item-box> </setting-item>
<setting-item-box name="标签"> </setting-item-box>
<setting-item name="展示"> <setting-item-box name="标签">
<n-space> <setting-item name="展示">
<n-switch v-model:value="yAxis.axisLabel.show" size="small"></n-switch> <n-space>
</n-space> <n-switch v-model:value="yAxis.axisLabel.show" size="small"></n-switch>
</setting-item> </n-space>
<setting-item name="颜色"> </setting-item>
<n-color-picker size="small" v-model:value="yAxis.axisLabel.color"></n-color-picker> <setting-item name="颜色">
</setting-item> <n-color-picker size="small" v-model:value="yAxis.axisLabel.color"></n-color-picker>
<setting-item name="大小"> </setting-item>
<n-input-number v-model:value="yAxis.axisLabel.fontSize" :min="8" size="small"></n-input-number> <setting-item name="大小">
</setting-item> <n-input-number v-model:value="yAxis.axisLabel.fontSize" :min="8" size="small"></n-input-number>
<setting-item name="偏移量"> </setting-item>
<n-input-number v-model:value="yAxis.axisLabel.rotate" :min="-90" :max="90" size="small"></n-input-number> <setting-item name="偏移量">
</setting-item> <n-input-number v-model:value="yAxis.axisLabel.rotate" :min="-90" :max="90" size="small"></n-input-number>
</setting-item-box> </setting-item>
<setting-item-box name="轴线"> </setting-item-box>
<setting-item name="展示"> <setting-item-box name="轴线">
<n-space> <setting-item name="展示">
<n-switch v-model:value="yAxis.axisLine.show" size="small"></n-switch> <n-space>
</n-space> <n-switch v-model:value="yAxis.axisLine.show" size="small"></n-switch>
</setting-item> </n-space>
<setting-item name="颜色"> </setting-item>
<n-color-picker v-model:value="yAxis.axisLine.lineStyle.color" size="small"></n-color-picker> <setting-item name="颜色">
</setting-item> <n-color-picker v-model:value="yAxis.axisLine.lineStyle.color" size="small"></n-color-picker>
<setting-item name="粗细"> </setting-item>
<n-input-number v-model:value="yAxis.axisLine.lineStyle.width" :min="1" size="small"></n-input-number> <setting-item name="粗细">
</setting-item> <n-input-number v-model:value="yAxis.axisLine.lineStyle.width" :min="1" size="small"></n-input-number>
<setting-item name="位置"> </setting-item>
<n-select v-model:value="yAxis.position" size="small" :options="axisConfig.yposition"></n-select> <setting-item name="位置">
</setting-item> <n-select v-model:value="yAxis.position" size="small" :options="axisConfig.yposition"></n-select>
<setting-item name="对齐零"> </setting-item>
<n-space> <setting-item name="对齐零">
<n-switch v-model:value="yAxis.axisLine.onZero" size="small"></n-switch> <n-space>
</n-space> <n-switch v-model:value="yAxis.axisLine.onZero" size="small"></n-switch>
</setting-item> </n-space>
<setting-item name="反向"> </setting-item>
<n-space> <setting-item name="反向">
<n-switch v-model:value="yAxis.inverse" size="small"></n-switch> <n-space>
</n-space> <n-switch v-model:value="yAxis.inverse" size="small"></n-switch>
</setting-item> </n-space>
</setting-item-box> </setting-item>
<setting-item-box name="刻度"> </setting-item-box>
<setting-item name="展示"> <setting-item-box name="刻度">
<n-space> <setting-item name="展示">
<n-switch v-model:value="yAxis.axisTick.show" size="small"></n-switch> <n-space>
</n-space> <n-switch v-model:value="yAxis.axisTick.show" size="small"></n-switch>
</setting-item> </n-space>
<setting-item name="长度"> </setting-item>
<n-input-number v-model:value="yAxis.axisTick.length" :min="1" size="small"></n-input-number> <setting-item name="长度">
</setting-item> <n-input-number v-model:value="yAxis.axisTick.length" :min="1" size="small"></n-input-number>
</setting-item-box> </setting-item>
<setting-item-box name="分割线"> </setting-item-box>
<setting-item name="展示"> <setting-item-box name="分割线">
<n-space> <setting-item name="展示">
<n-switch v-model:value="yAxis.splitLine.show" size="small"></n-switch> <n-space>
</n-space> <n-switch v-model:value="yAxis.splitLine.show" size="small"></n-switch>
</setting-item> </n-space>
<setting-item name="颜色"> </setting-item>
<n-color-picker v-model:value="yAxis.splitLine.lineStyle.color" size="small"></n-color-picker> <setting-item name="颜色">
</setting-item> <n-color-picker v-model:value="yAxis.splitLine.lineStyle.color" size="small"></n-color-picker>
<setting-item name="粗细"> </setting-item>
<n-input-number v-model:value="yAxis.splitLine.lineStyle.width" :min="1" size="small"></n-input-number> <setting-item name="粗细">
</setting-item> <n-input-number v-model:value="yAxis.splitLine.lineStyle.width" :min="1" size="small"></n-input-number>
<setting-item name="类型"> </setting-item>
<n-select <setting-item name="类型">
v-model:value="yAxis.splitLine.lineStyle.type" <n-select
size="small" v-model:value="yAxis.splitLine.lineStyle.type"
:options="axisConfig.splitLint.lineStyle.type" size="small"
></n-select> :options="axisConfig.splitLint.lineStyle.type"
</setting-item> ></n-select>
</setting-item-box> </setting-item>
</collapse-item> </setting-item-box>
<setting-item-box name="最小值" alone v-if="'min' in yAxis">
<setting-item name="">
<n-input-number v-model:value="yAxis.min" size="small"/>
</setting-item>
</setting-item-box>
</collapse-item>
</template>
<collapse-item v-if="legend" name="图例"> <collapse-item v-if="legend" name="图例">
<template #header> <template #header>
@ -271,6 +283,23 @@
<setting-item name="y轴"> <setting-item name="y轴">
<n-select v-model:value="legend.y" size="small" :options="legendConfig.lengendY" /> <n-select v-model:value="legend.y" size="small" :options="legendConfig.lengendY" />
</setting-item> </setting-item>
<setting-item name="上">
<n-input-number
v-model:value="legend.top"
:min="0"
size="small"
placeholder="px"
/>
</setting-item>
<setting-item name="右">
<n-input-number
v-model:value="legend.right"
:min="0"
size="small"
placeholder="px"
/>
</setting-item>
</setting-item-box> </setting-item-box>
<setting-item-box name="图例信息"> <setting-item-box name="图例信息">
<setting-item name="方向"> <setting-item name="方向">
@ -289,6 +318,20 @@
</setting-item> </setting-item>
</setting-item-box> </setting-item-box>
</collapse-item> </collapse-item>
<collapse-item v-if="dataZoom" name="滚动条">
<template #header>
<n-switch v-model:value="dataZoom.show" size="small"></n-switch>
</template>
<setting-item-box name="样式">
<!-- <setting-item name="颜色">
<n-color-picker size="small" v-model:value="dataZoom.backgroundColor"></n-color-picker>
</setting-item> -->
<setting-item name="展示个数">
<n-input-number v-model:value="dataZoom.endValue" :min="1" size="small"></n-input-number>
</setting-item>
</setting-item-box>
</collapse-item>
<collapse-item v-if="visualMap" name="视觉映射"> <collapse-item v-if="visualMap" name="视觉映射">
<template #header> <template #header>
@ -336,7 +379,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { PropType, computed, watch } from 'vue' import { PropType, computed, watch, Ref } from 'vue'
import { GlobalThemeJsonType } from '@/settings/chartThemes/index' import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
import { axisConfig, legendConfig } from '@/packages/chartConfiguration/echarts/index' import { axisConfig, legendConfig } from '@/packages/chartConfiguration/echarts/index'
import { CollapseItem, SettingItemBox, SettingItem, GlobalSettingPosition } from '@/components/Pages/ChartItemSetting' import { CollapseItem, SettingItemBox, SettingItem, GlobalSettingPosition } from '@/components/Pages/ChartItemSetting'
@ -368,17 +411,20 @@ const title = computed(() => {
return props.optionData.title return props.optionData.title
}) })
const xAxis = computed(() => { const xAxis: Ref<any> = computed(() => {
return props.optionData.xAxis return props.optionData.xAxis
}) })
const yAxis = computed(() => { const yAxisArr: Ref<any> = computed(() => {
return props.optionData.yAxis return props.optionData.yAxis
}) })
const legend = computed(() => { const legend = computed(() => {
return props.optionData.legend return props.optionData.legend
}) })
const dataZoom = computed(() => {
return props.optionData.dataZoom
})
const grid = computed(() => { const grid = computed(() => {
return props.optionData.grid return props.optionData.grid

View File

@ -33,13 +33,37 @@
<n-text depth="3"></n-text> <n-text depth="3"></n-text>
</template> </template>
</n-input-number> </n-input-number>
<n-input-number
:value="marginBottom"
@update:value="(v: number) => handleUpdate('y', v)"
:min="0"
size="small"
placeholder="px"
style="margin-top: 5px;"
>
<template #prefix>
<n-text depth="3"></n-text>
</template>
</n-input-number>
<n-input-number
:value="marginRight"
@update:value="(v: number) => handleUpdate('x', v)"
:min="0"
size="small"
placeholder="px"
style="margin-top: 5px;"
>
<template #prefix>
<n-text depth="3"></n-text>
</template>
</n-input-number>
</setting-item-box> </setting-item-box>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { PropType } from 'vue' import { PropType, computed } from 'vue'
import { PickCreateComponentType } from '@/packages/index.d' import { PickCreateComponentType } from '@/packages/index.d'
import { SettingItemBox } from '@/components/Pages/ChartItemSetting' import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { renderIcon } from '@/utils' import { renderIcon } from '@/utils'
import { icon } from '@/plugins/index' import { icon } from '@/plugins/index'
import { EditCanvasConfigType } from '@/store/modules/chartEditStore/chartEditStore.d' import { EditCanvasConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
@ -125,4 +149,25 @@ const positonHandle = (key: string) => {
break break
} }
} }
const marginBottom = computed(() => {
const { h, y } = props.chartAttr
const { height:canvasHeight } = props.canvasConfig
return canvasHeight - h - y
})
const marginRight = computed(() => {
const { w, x } = props.chartAttr
const { width:canvasWidth } = props.canvasConfig
return canvasWidth - w - x
})
const handleUpdate = (type: string, v: number) => {
const { w, h } = props.chartAttr
const { width:canvasWidth, height:canvasHeight } = props.canvasConfig
if(type === 'y') {
props.chartAttr.y = canvasHeight - h - v
}
else if(type === 'x') {
props.chartAttr.x = canvasWidth - w - v
}
}
</script> </script>

View File

@ -48,6 +48,7 @@ $leftWidth: 60px;
text-align: left; text-align: left;
margin-top: 4px; margin-top: 4px;
margin-left: 10px; margin-left: 10px;
margin-right: 4px;
font-size: 12px; font-size: 12px;
} }
.item-right { .item-right {

View File

@ -8,7 +8,7 @@
placeholder="px" placeholder="px"
> >
<template #prefix> <template #prefix>
<n-text depth="3"></n-text> <n-text depth="3"></n-text>
</template> </template>
</n-input-number> </n-input-number>
<n-input-number <n-input-number
@ -19,7 +19,7 @@
placeholder="px" placeholder="px"
> >
<template #prefix> <template #prefix>
<n-text depth="3"></n-text> <n-text depth="3"></n-text>
</template> </template>
</n-input-number> </n-input-number>
</setting-item-box> </setting-item-box>

View File

@ -71,18 +71,27 @@
<!-- 预设滤镜 --> <!-- 预设滤镜 -->
<div v-if="presetImageList.length" class="preset-filter"> <div v-if="presetImageList.length" class="preset-filter">
<n-image <!-- <n-image-->
<!-- class="preset-img"-->
<!-- width="46"-->
<!-- preview-disabled-->
<!-- object-fit="scale-down"-->
<!-- v-for="(item, index) in presetImageList"-->
<!-- :key="index"-->
<!-- :class="{ 'active-preset': item.hueRotate === chartStyles.hueRotate }"-->
<!-- :style="{ filter: `hue-rotate(${item.hueRotate}deg)` }"-->
<!-- :src="item.src"-->
<!-- @click="() => (chartStyles.hueRotate = item.hueRotate)"-->
<!-- ></n-image>-->
<div
class="preset-img" class="preset-img"
width="46" style="width: 46px;height: 38px;background: #3ba4ff;"
preview-disabled
object-fit="scale-down"
v-for="(item, index) in presetImageList" v-for="(item, index) in presetImageList"
:key="index" :key="index"
:class="{ 'active-preset': item.hueRotate === chartStyles.hueRotate }" :class="{ 'active-preset': item.hueRotate === chartStyles.hueRotate }"
:style="{ filter: `hue-rotate(${item.hueRotate}deg)` }" :style="{ filter: `hue-rotate(${item.hueRotate}deg)` }"
:src="item.src"
@click="() => (chartStyles.hueRotate = item.hueRotate)" @click="() => (chartStyles.hueRotate = item.hueRotate)"
></n-image> ></div>
</div> </div>
<!-- 混合模式 --> <!-- 混合模式 -->
@ -169,7 +178,7 @@ import { ref, PropType } from 'vue'
import { PickCreateComponentType, BlendModeEnumList } from '@/packages/index.d' import { PickCreateComponentType, BlendModeEnumList } from '@/packages/index.d'
import { SettingItemBox, SettingItem, CollapseItem } from '@/components/Pages/ChartItemSetting' import { SettingItemBox, SettingItem, CollapseItem } from '@/components/Pages/ChartItemSetting'
import { icon } from '@/plugins' import { icon } from '@/plugins'
import logoImg from '@/assets/logo.png' // import logoImg from '@/assets/logo.png'
import { useDesignStore } from '@/store/modules/designStore/designStore' import { useDesignStore } from '@/store/modules/designStore/designStore'
const props = defineProps({ const props = defineProps({
@ -210,7 +219,7 @@ const presetImageList = ref([] as presetImageData[])
for (let i = 1; i <= 12; i++) { for (let i = 1; i <= 12; i++) {
presetImageList.value.push({ presetImageList.value.push({
index: i, index: i,
src: logoImg, src: '',
hueRotate: i * 30 hueRotate: i * 30
}) })
} }

View File

@ -0,0 +1,22 @@
<template>
<n-modal
v-model:show="modalStore.showModal"
preset="dialog"
:title="modalStore.title"
:content="modalStore.content"
:positiveText="modalStore.positiveText"
:negativeText="modalStore.negativeText"
@positive-click="modalStore.positiveClick"
@negative-click="modalStore.negativeClick"
/>
</template>
<script setup lang="ts">
import {useModalStore} from '@/store/modules/modalStore/modalStore'
const modalStore = useModalStore()
</script>
<style lang="scss" scoped>
</style>

View File

@ -46,6 +46,12 @@ export enum MenuEnum {
GROUP = 'group', GROUP = 'group',
// 解组 // 解组
UN_GROUP = 'unGroup', UN_GROUP = 'unGroup',
// 水平对齐
H_ALIGN = 'hAlign',
// 垂直对齐
V_ALIGN = 'vAlign',
// 水平平均分布
// 垂直平均分布
// 后退 // 后退
BACK = 'back', BACK = 'back',
FORWORD = 'forward', FORWORD = 'forward',

View File

@ -50,7 +50,9 @@ export const excludeParseEventKeyList = [
BaseEvent.ON_MOUSE_ENTER, BaseEvent.ON_MOUSE_ENTER,
BaseEvent.ON_MOUSE_LEAVE, BaseEvent.ON_MOUSE_LEAVE,
//过滤器 //过滤器
'filter' 'filter',
//body-json处理
'handler',
] ]
// 内置字符串函数键值列表 // 内置字符串函数键值列表
export const excludeParseEventValueList = [ export const excludeParseEventValueList = [

View File

@ -7,4 +7,7 @@ export enum FileTypeEnum {
PNG = 'image/png', PNG = 'image/png',
JPEG = 'image/jpeg', JPEG = 'image/jpeg',
GIF = 'image/gif', GIF = 'image/gif',
// 视频
MP4 = 'video/mp4',
WEBM = 'video/webm',
} }

View File

@ -14,6 +14,9 @@ export enum ResultEnum {
TOKEN_OVERDUE = 886, TOKEN_OVERDUE = 886,
TIMEOUT = 60000, TIMEOUT = 60000,
} }
export enum ResultErrcode {
SUCCESS = '00000'
}
// 数据相关 // 数据相关
export enum RequestDataTypeEnum { export enum RequestDataTypeEnum {

View File

@ -0,0 +1,40 @@
{
"dimensions": ["product", "data1", "data2"],
"source": [
{
"product": "Mon",
"data1": 120,
"data2": 130
},
{
"product": "Tue",
"data1": 200,
"data2": 130
},
{
"product": "Wed",
"data1": 150,
"data2": 312
},
{
"product": "Thu",
"data1": 80,
"data2": 268
},
{
"product": "Fri",
"data1": 70,
"data2": 155
},
{
"product": "Sat",
"data1": 110,
"data2": 117
},
{
"product": "Sun",
"data1": 130,
"data2": 160
}
]
}

View File

@ -0,0 +1,7 @@
{
"name": "",
"status": null,
"time": "",
"unit": "",
"value": 0
}

View File

@ -0,0 +1,40 @@
import { publicInterface } from "@/api/path";
import { CreateComponentType } from '@/packages/index.d'
import { ResultErrcode } from "@/enums/httpEnum";
import { AlarmTrendType } from '@/store/modules/chartEditStore/chartEditStore.d'
import dataJson from "./data.json";
import {useGlobalQueryParamsStore} from '@/store/modules/globalQueryParamsStore/globalQueryParamsStore'
export const handleAlarmTrend =async (targetComponent: CreateComponentType) => {
console.log(targetComponent.commonData,'targetComponent.commonData');
const globalQueryParamsStore = useGlobalQueryParamsStore()
const obj = targetComponent.commonData[targetComponent.commonData.currentSource] as AlarmTrendType
let { enable, signal_ids,alarmConfirmStatus,alarmRecoveryStatus,level} = obj
if(!enable) return {
errcode: ResultErrcode.SUCCESS,
data: { ...dataJson },
errmsg: ''
}
const queryParams = {
signal_ids:signal_ids.length?signal_ids.split(','):[],
alarmConfirmStatus,
alarmRecoveryStatus,
level
}
const res = await publicInterface('/dcim/dems/devie_history_alarm', 'trend_chart', queryParams)
if (res && res.data) {
console.log(res,'res_handleAlarmTrend');
// res.data = {
// // dimensions: res?.data.brand_count.map((item: {})=>Object.keys(item).join('')),
// dimensions: ['名称','温度值'],
// source:res?.data.map((item: any)=>{
// return {
// '名称':`${item.node_name}-${item.dems_device_point.node_name}`,
// '温度值':item.dems_device_point.node_value,
// }
// })
// }
return res
}
}

View File

@ -0,0 +1,39 @@
import { publicInterface } from "@/api/path";
import { CreateComponentType } from '@/packages/index.d'
import { ResultErrcode } from "@/enums/httpEnum";
import { AreaDevCountType } from '@/store/modules/chartEditStore/chartEditStore.d'
import dataJson from "./data.json";
import {useGlobalQueryParamsStore} from '@/store/modules/globalQueryParamsStore/globalQueryParamsStore'
export const handleAreaDevCountClass =async (targetComponent: CreateComponentType) => {
const globalQueryParamsStore = useGlobalQueryParamsStore()
const obj = targetComponent.commonData[targetComponent.commonData.currentSource] as AreaDevCountType
// targetComponent?.option.series.forEach((item,index)=>{
// item.encode = { y:index===0? 'dev_count':'it_dev_count', x: 'space' }
// })
const queryParams = {
device_codes: obj.device_codes?.length
? obj.device_codes.split(',')
: [],
...globalQueryParamsStore.getAreaDevCountQueryParams,
space_type:'station'
}
// 处理数据
const res = await publicInterface('/dcim/dems/device','get_area_dev_count', queryParams)
res!.data = {
// dimensions: res?.data.brand_count.map((item: {})=>Object.keys(item).join('')),
dimensions: ['区域','配电设备总数','IT设备总数'],
source:res?.data.map((item: any)=>{
return {
'区域':item?.space?.label,
'配电设备总数':item?.dev_count,
'IT设备总数':item?.it_dev_count,
complete_id:item?.space?.complete_id,
complete_name:item?.space.complete_name
}
})
}
return res
}

View File

@ -0,0 +1,56 @@
import { publicInterface } from "@/api/path";
import { CreateComponentType } from '@/packages/index.d'
import { ResultErrcode } from "@/enums/httpEnum";
import { AssetsClassType } from '@/store/modules/chartEditStore/chartEditStore.d'
import dataJson from "./data.json";
import {useGlobalQueryParamsStore} from '@/store/modules/globalQueryParamsStore/globalQueryParamsStore'
export const handleAssetsClass =async (targetComponent: CreateComponentType) => {
const globalQueryParamsStore = useGlobalQueryParamsStore()
const obj = targetComponent.commonData[targetComponent.commonData.currentSource] as AssetsClassType
let { enable, dataSource,device_codes } = obj
if(!enable) return {
errcode: ResultErrcode.SUCCESS,
data: { ...dataJson },
errmsg: ''
}
const query = {
device_codes:device_codes?.length
? device_codes.split(',')
: [],
...globalQueryParamsStore.getGlobalQueryParams
}
// 处理数据
if(dataSource==='IT'){
const res = await publicInterface('/dcim/asset','get_asset_overview_page_info_new', query)
res!.data = {
// dimensions: res?.data.brand_count.map((item: {})=>Object.keys(item).join('')),
dimensions: ['品牌','data'],
source:res?.data?.brand_count? res?.data?.brand_count.map((item: {})=>{
return {
'品牌':Object.keys(item)[0]||'未知品牌',
data:Object.values(item)[0],
}
}):[{'品牌':'品牌',data:'0'}]
}
return res
}else{
const res = await publicInterface('/dcim/dems/device','get_dev_brand_count', query)
res!.data = {
// dimensions: res?.data.brand_count.map((item: {})=>Object.keys(item).join('')),
dimensions: ['品牌','data'],
source:res!.data.length? res?.data.map((item: any)=>{
return {
'品牌':item?.name||'未知品牌',
data:item?.count||'0',
}
}):[{'品牌':'品牌',data:'0'}]
}
console.log(res,'调用了吗11')
return res
}
}

View File

@ -0,0 +1,39 @@
import moment from "moment";
import { publicInterface } from "@/api/path";
import { DateTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
import { commonDataType, CategoryBrandCountTableType } from '@/store/modules/chartEditStore/chartEditStore.d'
import { CreateComponentType } from '@/packages/index.d'
import { ResultErrcode } from '@/enums/httpEnum'
import dataJson from './data.json'
import {useGlobalQueryParamsStore} from '@/store/modules/globalQueryParamsStore/globalQueryParamsStore'
export const handleCategoryBrandCountTable =async (targetComponent: CreateComponentType) => {
let { currentSource, enable,device_codes } = (targetComponent.commonData as commonDataType).categoryBrandCountTable as CategoryBrandCountTableType
if(!enable) return {
errcode: ResultErrcode.SUCCESS,
data: { ...dataJson },
errmsg: ''
}
const globalQueryParamsStore = useGlobalQueryParamsStore()
const queryParams = {
device_codes:device_codes?.length
? device_codes.split(',')
: [],
...globalQueryParamsStore.getGlobalQueryParams
}
const res = await publicInterface(currentSource==='IT'?'/dcim/asset':'/dcim/dems/device',currentSource==='IT'?'get_category_brand_count': 'get_dev_category_brand_count', queryParams)
const top = ['TOP1','TOP2','TOP3']
res!.data = {
dimensions: ['分类名',...top],
source:res?.data.map((item: any)=>{
let obj:any = {'分类名':item.name,}
item.brand.forEach((v:any,index:number)=>{
obj[top[index]] = v.Brand
})
return obj
})
}
return res
}

View File

@ -0,0 +1,70 @@
import { publicInterface } from '@/api/path'
import { CreateComponentType } from '@/packages/index.d'
import { ResultErrcode } from '@/enums/httpEnum'
import { CompanyTempTopType } from '@/store/modules/chartEditStore/chartEditStore.d'
import dataJson from './data.json'
export const handleCompanyTempTop = async (targetComponent: CreateComponentType) => {
console.log(targetComponent, 'targetComponent_targetComponent')
const option = targetComponent.option as any
const obj = targetComponent.commonData[targetComponent.commonData.currentSource] as CompanyTempTopType
let { enable, space_complete_id, signal_ids,spaceLevel } = obj
if (!enable)
return {
errcode: ResultErrcode.SUCCESS,
data: { ...dataJson },
errmsg: ''
}
option.tooltip.formatter = (value:any)=>{
const item = value[0].data
// 将字符串按照 '/' 分割成数组
const parts = item.space_complete_name.split('/');
// 从数组开头开始,截取指定层级及以后的部分
const space_complete_name = parts.slice(spaceLevel, parts.length );
return `
${space_complete_name.join('/')}/${item.device_name}</br>
${item['名称']}&nbsp;&nbsp;&nbsp;&nbsp;${item['温度值']}°C
`
}
const res: any = await publicInterface('/dcim/dems/device_point', 'temp_list_dashboard', {
signal_ids: [signal_ids],
space_complete_id
})
if (res && res.data) {
// option.yAxis[0].data = res?.data.slice(0, 10).map((item: any) => item.dems_device_point.node_value)
// option.xAxis.data = res?.data.slice(0, 10).map((item: any) => item.node_name)
res.data = {
dimensions: ['uid', '温度值',],
source: res?.data.slice(0, 10).map((item: any) => {
return {
uid: item.dems_device_point.uid,
: `${item.dems_device_point.node_name}`,
温度值: item.dems_device_point.node_value,
space_complete_name:item.space_complete_name,
device_name:item.node_name
}
}),
encode: {
x: '名称',
y: '温度值'
}
}
return res
} else {
// 后端没有给errcode,前端重置
res.errcode = '00000'
res.data = {
dimensions: [],
source: []
}
return res
}
}

Some files were not shown because too many files have changed in this diff Show More