调试了 第一把 载入一个简单的表格

This commit is contained in:
hawk86104 2024-05-27 18:05:47 +08:00
parent 983ae230b7
commit 5e3d0a0967
523 changed files with 56412 additions and 111 deletions

20
.fes.js
View File

@ -4,10 +4,10 @@
* @Autor: 地虎降天龙
* @Date: 2023-10-16 10:53:09
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-03-25 15:37:42
* @LastEditTime: 2024-05-27 15:50:16
*/
// import { resolve } from 'path';
import { join } from 'path';
import { join } from 'path'
import { defineBuildConfig } from '@fesjs/fes'
import { templateCompilerOptions } from '@tresjs/core'
// eslint-disable-next-line import/no-unresolved
@ -38,13 +38,22 @@ export default defineBuildConfig({
...templateCompilerOptions,
},
viteOption: {
base: "./",
base: './',
plugins: [
UnoCSS({
/* options */
}),
glsl()
glsl(),
],
// 全局 css 注册
css: {
preprocessorOptions: {
scss: {
javascriptEnabled: true,
additionalData: `@import "src/plugins/goView/lib/scss/style.scss";`,
},
},
},
server: {
// host: "0.0.0.0",
// proxy: {
@ -59,5 +68,4 @@ export default defineBuildConfig({
alias: { PLS: join(__dirname, './src/plugins') },
// { find: 'pls', replacement: resolve(__dirname, './src/plugins') },
// { '@': join(__dirname, '/src') }
});
})

View File

@ -45,13 +45,20 @@
"@tresjs/cientos": "3.8.0",
"@tresjs/core": "3.8.0",
"@tweenjs/tween.js": "^23.1.1",
"@vicons/carbon": "^0.12.0",
"@vicons/ionicons5": "^0.12.0",
"axios": "1.6.8",
"cannon-es": "^0.20.0",
"chalk": "^5.3.0",
"color": "^4.2.3",
"compressing": "^1.10.0",
"core-js": "3.36.1",
"d3-geo": "^3.1.1",
"dayjs": "^1.11.11",
"echarts": "^5.5.0",
"echarts-liquidfill": "^3.1.0",
"echarts-stat": "^1.2.0",
"echarts-wordcloud": "^2.1.0",
"file-saver": "^2.0.5",
"gl-matrix": "^3.4.3",
"gsap": "3.12.5",
@ -59,6 +66,7 @@
"jszip": "^3.10.1",
"lamina": "^1.1.23",
"lygia": "^1.1.3",
"naive-ui": "^2.38.2",
"oimophysics": "^1.2.2",
"patch-package": "^8.0.0",
"pinia": "^2.1.7",
@ -72,7 +80,10 @@
"tilebelt-wgs84": "^1.0.4",
"tweakpane": "4.0.3",
"unocss": "0.58.9",
"vue": "3.4.21"
"vue": "3.4.21",
"vue-echarts": "^6.7.2",
"vue3-lazyload": "^0.3.8",
"vue3-sketch-ruler": "^1.3.15"
},
"private": true
}

View File

@ -4,7 +4,7 @@
* @Autor: 地虎降天龙
* @Date: 2023-10-16 10:53:09
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-05-24 09:58:10
* @LastEditTime: 2024-05-27 17:52:17
*/
import { defineRuntimeConfig, useModel } from '@fesjs/fes'
import { FMenu } from '@fesjs/fes-design'
@ -55,6 +55,8 @@ export function layout(layoutConfig) {
export function onAppCreated ({ app }) {
app.use(FMenu)
app.use(Tres)
window['$vue'] = app
// if (process.env.FES_APP_PLUGINS === 'true') {
console.log(chalk.hex('#1c86e5')(`

View File

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

View File

@ -0,0 +1,76 @@
<!--
* @Description:
* @Version: 1.668
* @Autor: 地虎降天龙
* @Date: 2024-05-27 17:55:27
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-05-27 18:04:17
-->
<template>
<div
:class="animationsClass(groupData.styles.animations)"
:style="{
...getSizeStyle(groupData.attr),
...getFilterStyle(groupData.styles),
}"
>
<div
class="chart-item"
v-for="item in groupData.groupList"
:class="animationsClass(item.styles.animations)"
:key="item.id"
:style="{
...getComponentAttrStyle(item.attr, groupIndex),
...getStatusStyle(item.status),
...getPreviewConfigStyle(item.preview),
...getBlendModeStyle(item.styles) as any
}"
>
<component
:is="item.chartConfig.chartKey"
:id="item.id"
:chartConfig="item"
:themeSetting="themeSetting"
:themeColor="themeColor"
:style="{
...getSizeStyle(item.attr),
...getFilterStyle(item.styles),
...getTransformStyle(item.styles),
}"
v-on="useLifeHandler(item)"
></component>
</div>
</div>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import { animationsClass, getFilterStyle, getTransformStyle, getBlendModeStyle } from 'PLS/goView/lib/utils'
import { getSizeStyle, getComponentAttrStyle, getStatusStyle, getPreviewConfigStyle } from 'PLS/goView/lib/utils'
import { useLifeHandler } from 'PLS/goView/lib/gHooks'
const props = defineProps({
groupData: {
type: Object as PropType<any>,
required: true,
},
themeSetting: {
type: Object,
required: true,
},
themeColor: {
type: Object,
required: true,
},
groupIndex: {
type: Number,
required: true,
},
})
</script>
<style lang="scss" scoped>
.chart-item {
position: absolute;
}
</style>

View File

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

View File

@ -0,0 +1,85 @@
<!--
* @Description:
* @Version: 1.668
* @Autor: 地虎降天龙
* @Date: 2024-05-27 17:55:27
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-05-27 17:59:05
-->
<template>
<div
class="chart-item"
v-for="(item, index) in chartEditStore.componentList"
:class="animationsClass(item.styles.animations)"
:key="item.id"
:style="{
...getComponentAttrStyle(item.attr, index),
...getTransformStyle(item.styles),
...getStatusStyle(item.status),
...getPreviewConfigStyle(item.preview),
...getBlendModeStyle(item.styles) as any,
...getSizeStyle(item.attr)
}"
>
<!-- 分组 -->
<preview-render-group
v-if="item.isGroup"
:groupData="(item as any)"
:groupIndex="index"
:themeSetting="themeSetting"
:themeColor="themeColor"
></preview-render-group>
<!-- 单组件 -->
<component
v-else
:is="item.chartConfig.chartKey"
:id="item.id"
:chartConfig="item"
:themeSetting="themeSetting"
:themeColor="themeColor"
:style="{
...getSizeStyle(item.attr),
...getFilterStyle(item.styles),
}"
v-on="useLifeHandler(item)"
></component>
</div>
</template>
<script setup lang="ts">
import { computed, onMounted } from 'vue'
import { useChartDataPondFetch, useLifeHandler } from 'PLS/goView/lib/gHooks'
import { PreviewRenderGroup } from '../PreviewRenderGroup/index'
import { useChartEditStore } from 'PLS/goView/stores/chartEditStore'
import { animationsClass, getFilterStyle, getTransformStyle, getBlendModeStyle, colorCustomMerge } from 'PLS/goView/lib/utils'
import { getSizeStyle, getComponentAttrStyle, getStatusStyle, getPreviewConfigStyle } from 'PLS/goView/lib/utils'
//
const { initDataPond, clearMittDataPondMap } = useChartDataPondFetch()
const chartEditStore = useChartEditStore()
//
const themeSetting = computed(() => {
const chartThemeSetting = chartEditStore.editCanvasConfig.chartThemeSetting
return chartThemeSetting
})
//
const themeColor = computed(() => {
const colorCustomMergeData = colorCustomMerge(chartEditStore.editCanvasConfig.chartCustomThemeColorInfo)
return colorCustomMergeData[chartEditStore.editCanvasConfig.chartThemeColor]
})
//
clearMittDataPondMap()
onMounted(() => {
initDataPond(useChartEditStore)
})
</script>
<style lang="scss" scoped>
.chart-item {
position: absolute;
}
</style>

View File

@ -0,0 +1,86 @@
// 鼠标点击左右键
export enum MouseEventButton {
LEFT = 1,
RIGHT = 2
}
// 页面拖拽键名
export enum DragKeyEnum {
DRAG_KEY = 'ChartData'
}
// 不同页面保存操作
export enum SavePageEnum {
CHART = 'SaveChart',
CHART_TO_PREVIEW = 'ChartToPreview',
JSON = 'SaveJSON',
CLOSE = 'close'
}
// 操作枚举
export enum MenuEnum {
// 移动
ARROW_UP = 'up',
ARROW_RIGHT = 'right',
ARROW_DOWN = 'down',
ARROW_LEFT = 'left',
// 删除
DELETE = 'delete',
// 复制
COPY = 'copy',
// 剪切
CUT = 'cut',
// 粘贴
PARSE = 'parse',
// 置顶
TOP = 'top',
// 置底
BOTTOM = 'bottom',
// 上移
UP = 'up',
// 下移
DOWN = 'down',
// 清空剪贴板
CLEAR = 'clear',
// 成组
GROUP = 'group',
// 解组
UN_GROUP = 'unGroup',
// 后退
BACK = 'back',
// 前进
FORWORD = 'forward',
// 保存
SAVE = 'save',
// 锁定
LOCK = 'lock',
// 解除锁定
UNLOCK = 'unLock',
// 隐藏
HIDE = 'hide',
// 显示
SHOW = 'show'
}
// Win 键盘枚举
export enum WinKeyboard {
CTRL = 'ctrl',
SHIFT = 'shift',
ALT = ' alt',
CTRL_SOURCE_KEY = 'control',
SHIFT_SOURCE_KEY = 'shift',
ALT_SOURCE_KEY = 'alt',
SPACE = 'Space'
}
// Mac 键盘枚举
export enum MacKeyboard {
// 还是用 Command 吧
CTRL = '⌘',
SHIFT = '⇧',
ALT = '⌥',
CTRL_SOURCE_KEY = '⌘',
SHIFT_SOURCE_KEY = '⇧',
ALT_SOURCE_KEY = '⌥',
SPACE = 'Space'
}

View File

@ -0,0 +1,59 @@
// 基础事件类型(vue不加 on)
export enum BaseEvent {
// 点击
ON_CLICK = 'click',
// 双击
ON_DBL_CLICK = 'dblclick',
// 移入
ON_MOUSE_ENTER = 'mouseenter',
// 移出
ON_MOUSE_LEAVE = 'mouseleave'
}
// 组件交互回调事件
export enum InteractEvents {
INTERACT_ON = 'interactOn',
INTERACT_COMPONENT_ID = 'interactComponentId',
INTERACT_FN = 'interactFn'
}
// 全局组件交互回调事件触发的类型(当然可以自定义名称)
export enum InteractEventOn {
CLICK = 'click',
CHANGE = 'change'
}
// 确定交互组件触发类型 key名称
export const COMPONENT_INTERACT_EVENT_KET = 'componentInteractEventKey'
// 交互式组件的触发配置
export type InteractActionsType = {
interactType: InteractEventOn
interactName: string
componentEmitEvents: { [T: string]: { value: any; label: string }[] }
}
// vue3 生命周期事件
export enum EventLife {
// 渲染之后
VNODE_MOUNTED = 'vnodeMounted',
// 渲染之前
VNODE_BEFORE_MOUNT = 'vnodeBeforeMount'
}
// 内置字符串函数对象列表
export const excludeParseEventKeyList = [
EventLife.VNODE_BEFORE_MOUNT,
EventLife.VNODE_MOUNTED,
BaseEvent.ON_CLICK,
BaseEvent.ON_DBL_CLICK,
BaseEvent.ON_MOUSE_ENTER,
BaseEvent.ON_MOUSE_LEAVE,
//过滤器
'filter'
]
// 内置字符串函数键值列表
export const excludeParseEventValueList = [
// 请求里的函数语句
'javascript:'
]

View File

@ -0,0 +1,10 @@
// 文件上传时的格式映射
export enum FileTypeEnum {
// 文档
TXT = 'text/plain',
JSON = 'application/json',
// 图片
PNG = 'image/png',
JPEG = 'image/jpeg',
GIF = 'image/gif',
}

View File

@ -0,0 +1,128 @@
/**
* @description:
*/
export enum ResultEnum {
DATA_SUCCESS = 0,
SUCCESS = 200,
SERVER_ERROR = 500,
SERVER_FORBIDDEN = 403,
NOT_FOUND = 404,
TIMEOUT = 60000
}
// 数据相关
export enum RequestDataTypeEnum {
// 静态数据
STATIC = 0,
// 请求数据
AJAX = 1,
// 数据池
Pond = 2
}
// 请求主体类型
export enum RequestContentTypeEnum {
// 普通请求
DEFAULT = 0,
// SQL请求
SQL = 1
}
/**
* @description:
*/
export enum RequestHttpEnum {
GET = 'get',
POST = 'post',
PATCH = 'patch',
PUT = 'put',
DELETE = 'delete'
}
/**
* @description:
*/
export enum RequestHttpIntervalEnum {
// 秒
SECOND = 'second',
// 分
MINUTE = 'minute',
// 时
HOUR = 'hour',
// 天
DAY = 'day'
}
/**
* @description:
*/
export const SelectHttpTimeNameObj = {
[RequestHttpIntervalEnum.SECOND]: '秒',
[RequestHttpIntervalEnum.MINUTE]: '分',
[RequestHttpIntervalEnum.HOUR]: '时',
[RequestHttpIntervalEnum.DAY]: '天'
}
/**
* @description:
*/
export enum RequestBodyEnum {
NONE = 'none',
FORM_DATA = 'form-data',
X_WWW_FORM_URLENCODED = 'x-www-form-urlencoded',
JSON = 'json',
XML = 'xml'
}
/**
* @description:
*/
export const RequestBodyEnumList = [
RequestBodyEnum.NONE,
RequestBodyEnum.FORM_DATA,
RequestBodyEnum.X_WWW_FORM_URLENCODED,
RequestBodyEnum.JSON,
RequestBodyEnum.XML
]
/**
* @description:
*/
export enum RequestParamsTypeEnum {
PARAMS = 'Params',
BODY = 'Body',
HEADER = 'Header',
}
/**
* @description:
*/
export type RequestParamsObjType = {
[T: string]: string
}
export type RequestParams = {
[RequestParamsTypeEnum.PARAMS]: RequestParamsObjType
[RequestParamsTypeEnum.HEADER]: RequestParamsObjType
[RequestParamsTypeEnum.BODY]: {
[RequestBodyEnum.FORM_DATA]: RequestParamsObjType
[RequestBodyEnum.X_WWW_FORM_URLENCODED]: RequestParamsObjType
[RequestBodyEnum.JSON]: string
[RequestBodyEnum.XML]: string
}
}
/**
* @description: contentTyp类型
*/
export enum ContentTypeEnum {
// json
JSON = 'application/json;charset=UTF-8',
// text
TEXT = 'text/plain;charset=UTF-8',
// xml
XML = 'application/xml;charset=UTF-8',
// application/x-www-form-urlencoded 一般配合qs
FORM_URLENCODED = 'application/x-www-form-urlencoded;charset=UTF-8',
// form-data 上传
FORM_DATA = 'multipart/form-data;charset=UTF-8'
}

View File

@ -0,0 +1,59 @@
import { ResultEnum } from 'PLS/goView/lib/enums/httpEnum'
export enum ChartEnum {
// 图表创建
CHART_HOME = '/chart/home/:id(.*)*',
CHART_HOME_NAME = 'ChartHome',
}
export enum PreviewEnum {
// 图表预览
CHART_PREVIEW = '/chart/preview/:id(.*)*',
CHART_PREVIEW_NAME = 'ChartPreview',
}
export enum EditEnum {
// 图表JSON编辑
CHART_EDIT = '/chart/edit/:id(.*)*',
CHART_EDIT_NAME = 'ChartEdit',
}
export enum PageEnum {
// 登录
BASE_LOGIN = '/login',
BASE_LOGIN_NAME = 'Login',
//重定向
REDIRECT = '/redirect',
REDIRECT_NAME = 'Redirect',
RELOAD = '/reload',
RELOAD_NAME = 'Reload',
// 首页
BASE_HOME = '/project',
BASE_HOME_NAME = 'Project',
// 我的项目
BASE_HOME_ITEMS = '/project/items',
BASE_HOME_ITEMS_NAME = 'Project-Items',
// 我的模板
BASE_HOME_TEMPLATE = '/project/my-template',
BASE_HOME_TEMPLATE_NAME = 'Project-My-Template',
// 模板市场
BASE_HOME_TEMPLATE_MARKET = '/project/template-market',
BASE_HOME_TEMPLATE_MARKET_NAME = 'Project-Template-Market',
// 错误
ERROR_PAGE_NAME_403 = 'ErrorPage403',
ERROR_PAGE_NAME_404 = 'ErrorPage404',
ERROR_PAGE_NAME_500 = 'ErrorPage500'
}
export const ErrorPageNameMap = new Map([
[ResultEnum.NOT_FOUND, PageEnum.ERROR_PAGE_NAME_404],
[ResultEnum.SERVER_FORBIDDEN, PageEnum.ERROR_PAGE_NAME_403],
[ResultEnum.SERVER_ERROR, PageEnum.ERROR_PAGE_NAME_500]
])

View File

@ -0,0 +1,6 @@
export enum DialogEnum {
DELETE = 'delete',
WARNING = 'warning',
ERROR = 'error',
SUCCESS = 'success'
}

View File

@ -0,0 +1,18 @@
export enum StorageEnum {
// 全局设置
GO_SYSTEM_SETTING_STORE = 'GO_SYSTEM_SETTING',
// token 等信息
GO_ACCESS_TOKEN_STORE = 'GO_ACCESS_TOKEN',
// 登录信息
GO_LOGIN_INFO_STORE = 'GO_LOGIN_INFO',
// 语言
GO_LANG_STORE = 'GO_LANG',
// 当前选择的主题
GO_DESIGN_STORE = 'GO_DESIGN',
// 工作台布局配置
GO_CHART_LAYOUT_STORE = 'GO_CHART_LAYOUT',
// 工作台需要保存的数据
GO_CHART_STORAGE_LIST = 'GO_CHART_STORAGE_LIST',
// 用户存储的图片媒体
GO_USER_MEDIA_PHOTOS = 'GO_USER_MEDIA_PHOTOS'
}

View File

@ -0,0 +1,19 @@
// 主题
export enum ThemeEnum {
DARK = 'dark',
LIGHT = 'light'
}
// 语言
export enum LangEnum {
ZH = 'ZH',
EN = 'EN'
}
// 预览展示
export enum PreviewScaleEnum {
FIT = 'fit',
SCROLL_Y = 'scrollY',
SCROLL_X = 'scrollX',
FULL = 'full'
}

View File

@ -0,0 +1,14 @@
import { ModuleTypeEnum } from 'PLS/goView/lib/enums/httpEnum'
// 接口白名单(免登录)
export const fetchAllowList = [
// 登录
`${ModuleTypeEnum.SYSTEM}/login`,
// 获取 OSS 接口
`${ModuleTypeEnum.SYSTEM}/getOssInfo`,
// 预览获取数据
`${ModuleTypeEnum.PROJECT}/getData`,
]
// 接口黑名单
export const fetchBlockList = []

View File

@ -0,0 +1,35 @@
import axios, { AxiosResponse, InternalAxiosRequestConfig, AxiosError } from 'axios'
import { ResultEnum } from "PLS/goView/lib/enums/httpEnum"
import { ErrorPageNameMap } from "PLS/goView/lib/enums/pageEnum"
import { redirectErrorPage } from 'PLS/goView/lib/utils'
const axiosInstance = axios.create({
baseURL: import.meta.env.DEV ? import.meta.env.VITE_DEV_PATH : import.meta.env.VITE_PRO_PATH,
timeout: ResultEnum.TIMEOUT,
})
axiosInstance.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
return config
},
(error: AxiosError) => {
Promise.reject(error)
}
)
// 响应拦截器
axiosInstance.interceptors.response.use(
(res: AxiosResponse) => {
const { code } = res.data as { code: number }
if (code === undefined || code === null) return Promise.resolve(res.data)
if (code === ResultEnum.DATA_SUCCESS) return Promise.resolve(res.data)
// 重定向
if (ErrorPageNameMap.get(code)) redirectErrorPage(code)
return Promise.resolve(res.data)
},
(err: AxiosResponse) => {
Promise.reject(err)
}
)
export default axiosInstance

View File

@ -0,0 +1,226 @@
import axiosInstance from './axios'
import {
RequestHttpEnum,
ContentTypeEnum,
RequestBodyEnum,
RequestDataTypeEnum,
RequestContentTypeEnum,
RequestParamsObjType
} from 'PLS/goView/lib/enums/httpEnum'
import type { RequestGlobalConfigType, RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
export const get = <T = any>(url: string, params?: object) => {
return axiosInstance<T>({
url: url,
method: RequestHttpEnum.GET,
params: params,
})
}
export const post = <T = any>(url: string, data?: object, headersType?: string) => {
return axiosInstance<T>({
url: url,
method: RequestHttpEnum.POST,
data: data,
headers: {
'Content-Type': headersType || ContentTypeEnum.JSON
}
})
}
export const patch = <T = any>(url: string, data?: object, headersType?: string) => {
return axiosInstance<T>({
url: url,
method: RequestHttpEnum.PATCH,
data: data,
headers: {
'Content-Type': headersType || ContentTypeEnum.JSON
}
})
}
export const put = <T = any>(url: string, data?: object, headersType?: ContentTypeEnum) => {
return axiosInstance<T>({
url: url,
method: RequestHttpEnum.PUT,
data: data,
headers: {
'Content-Type': headersType || ContentTypeEnum.JSON
}
})
}
export const del = <T = any>(url: string, params?: object) => {
return axiosInstance<T>({
url: url,
method: RequestHttpEnum.DELETE,
params
})
}
// 获取请求函数默认get
export const http = (type?: RequestHttpEnum) => {
switch (type) {
case RequestHttpEnum.GET:
return get
case RequestHttpEnum.POST:
return post
case RequestHttpEnum.PATCH:
return patch
case RequestHttpEnum.PUT:
return put
case RequestHttpEnum.DELETE:
return del
default:
return get
}
}
const prefix = 'javascript:'
// 对输入字符进行转义处理
export const translateStr = (target: string | Record<any, any>) => {
if (typeof target === 'string') {
if (target.startsWith(prefix)) {
const funcStr = target.split(prefix)[1]
let result
try {
result = new Function(`${funcStr}`)()
} catch (error) {
console.log(error)
window['$message'].error('js内容解析有误')
}
return result
} else {
return target
}
}
for (const key in target) {
if (Object.prototype.hasOwnProperty.call(target, key)) {
const subTarget = target[key]
target[key] = translateStr(subTarget)
}
}
return target
}
/**
* *
* @param targetParams
* @param globalParams
*/
export const customizeHttp = (targetParams: RequestConfigType, globalParams: RequestGlobalConfigType) => {
if (!targetParams || !globalParams) {
return
}
// 全局
const {
// 全局请求源地址
requestOriginUrl,
// 全局请求内容
requestParams: globalRequestParams
} = globalParams
// 目标组件(优先级 > 全局组件)
const {
// 请求地址
requestUrl,
// 普通 / sql
requestContentType,
// 获取数据的方式
requestDataType,
// 请求方式 get/post/del/put/patch
requestHttpType,
// 请求体类型 none / form-data / x-www-form-urlencoded / json /xml
requestParamsBodyType,
// SQL 请求对象
requestSQLContent,
// 请求内容 params / cookie / header / body: 同 requestParamsBodyType
requestParams: targetRequestParams
} = targetParams
// 静态排除
if (requestDataType === RequestDataTypeEnum.STATIC) return
if (!requestUrl) {
return
}
// 处理头部
let headers: RequestParamsObjType = {
...globalRequestParams.Header,
...targetRequestParams.Header
}
headers = translateStr(headers)
// data 参数
let data: RequestParamsObjType | FormData | string = {}
// params 参数
let params: RequestParamsObjType = { ...targetRequestParams.Params }
params = translateStr(params)
// form 类型处理
let formData: FormData = new FormData()
// 类型处理
switch (requestParamsBodyType) {
case RequestBodyEnum.NONE:
break
case RequestBodyEnum.JSON:
headers['Content-Type'] = ContentTypeEnum.JSON
//json对象也能使用'javasctipt:'来动态拼接参数
data = translateStr(targetRequestParams.Body['json'])
if(typeof data === 'string') data = JSON.parse(data)
// json 赋值给 data
break
case RequestBodyEnum.XML:
headers['Content-Type'] = ContentTypeEnum.XML
// xml 字符串赋值给 data
data = translateStr(targetRequestParams.Body['xml'])
break
case RequestBodyEnum.X_WWW_FORM_URLENCODED: {
headers['Content-Type'] = ContentTypeEnum.FORM_URLENCODED
const bodyFormData = targetRequestParams.Body['x-www-form-urlencoded']
for (const i in bodyFormData) formData.set(i, translateStr(bodyFormData[i]))
// FormData 赋值给 data
data = formData
break
}
case RequestBodyEnum.FORM_DATA: {
headers['Content-Type'] = ContentTypeEnum.FORM_DATA
const bodyFormUrlencoded = targetRequestParams.Body['form-data']
for (const i in bodyFormUrlencoded) {
formData.set(i, translateStr(bodyFormUrlencoded[i]))
}
// FormData 赋值给 data
data = formData
break
}
}
// sql 处理
if (requestContentType === RequestContentTypeEnum.SQL) {
headers['Content-Type'] = ContentTypeEnum.JSON
data = requestSQLContent
}
try {
const url = (new Function("return `" + `${requestOriginUrl}${requestUrl}`.trim() + "`"))();
return axiosInstance({
url,
method: requestHttpType,
data,
params,
headers
})
} catch (error) {
console.log(error)
window['$message'].error('URL地址格式有误')
}
}

View File

@ -0,0 +1,100 @@
{
"nodes": [
{
"id": "0",
"name": "Myriel",
"symbolSize": "@integer(0, 50)",
"x": -266.82776,
"y": 299.6904,
"value": "@integer(0, 50)",
"category": 3
},
{
"id": "1",
"name": "Napoleon",
"symbolSize": "@integer(0, 50)",
"x": -418.08344,
"y": 446.8853,
"value": "@integer(0, 50)",
"category": 5
},
{
"id": "2",
"name": "MlleBaptistine",
"symbolSize": "@integer(0, 50)",
"x": -212.76357,
"y": 245.29176,
"value": "@integer(0, 50)",
"category": 1
},
{
"id": "3",
"name": "MmeMagloire",
"symbolSize": "@integer(0, 50)",
"x": -242.82404,
"y": 235.26283,
"value": "@integer(0, 50)",
"category": 1
},
{
"id": "4",
"name": "CountessDeLo",
"symbolSize": "@integer(0, 50)",
"x": -379.30386,
"y": 429.06424,
"value": "@integer(0, 50)",
"category": 0
}
],
"links": [
{
"source": "1",
"target": "@integer(2, 4)"
},
{
"source": "2",
"target": "@integer(3, 4)"
},
{
"source": "3",
"target": "@integer(0, 2)"
},
{
"source": "3",
"target": "@integer(0, 1)"
},
{
"source": "4",
"target": "@integer(0, 3)"
}
],
"categories": [
{
"name": "A"
},
{
"name": "B"
},
{
"name": "C"
},
{
"name": "D"
},
{
"name": "E"
},
{
"name": "F"
},
{
"name": "G"
},
{
"name": "H"
},
{
"name": "I"
}
]
}

View File

@ -0,0 +1,199 @@
{
"xAxis": [
"12a",
"1a",
"2a",
"3a",
"4a",
"5a",
"6a",
"7a",
"8a",
"9a",
"10a",
"11a",
"12p",
"1p",
"2p",
"3p",
"4p",
"5p",
"6p",
"7p",
"8p",
"9p",
"10p",
"11p"
],
"yAxis": ["Saturday", "Friday", "Thursday", "Wednesday", "Tuesday", "Monday", "Sunday"],
"seriesData": [
[0, 0, "@integer(0, 10)"],
[1, 0, "@integer(0, 10)"],
[2, 0, "-"],
[3, 0, "-"],
[4, 0, "-"],
[5, 0, "-"],
[6, 0, "-"],
[7, 0, "-"],
[8, 0, "-"],
[9, 0, "-"],
[10, 0, "-"],
[11, 0, "@integer(0, 10)"],
[12, 0, "@integer(0, 10)"],
[13, 0, "@integer(0, 10)"],
[14, 0, "@integer(0, 10)"],
[15, 0, "@integer(0, 10)"],
[16, 0, "@integer(0, 10)"],
[17, 0, "@integer(0, 10)"],
[18, 0, "@integer(0, 10)"],
[19, 0, "@integer(0, 10)"],
[20, 0, "@integer(0, 10)"],
[21, 0, "@integer(0, 10)"],
[22, 0, "@integer(0, 10)"],
[23, 0, "@integer(0, 10)"],
[0, 1, 7],
[1, 1, "-"],
[2, 1, "-"],
[3, 1, "-"],
[4, 1, "-"],
[5, 1, "-"],
[6, 1, "-"],
[7, 1, "-"],
[8, 1, "-"],
[9, 1, "-"],
[10, 1, "@integer(0, 10)"],
[11, 1, "@integer(0, 10)"],
[12, 1, "@integer(0, 10)"],
[13, 1, "@integer(0, 10)"],
[14, 1, "@integer(0, 10)"],
[15, 1, "@integer(0, 10)"],
[16, 1, "@integer(0, 10)"],
[17, 1, "@integer(0, 10)"],
[18, 1, "@integer(0, 10)"],
[19, 1, "@integer(0, 10)"],
[20, 1, "@integer(0, 10)"],
[21, 1, "@integer(0, 10)"],
[22, 1, "@integer(0, 10)"],
[23, 1, "@integer(0, 10)"],
[0, 2, 1],
[1, 2, 1],
[2, 2, "-"],
[3, 2, "-"],
[4, 2, "-"],
[5, 2, "-"],
[6, 2, "-"],
[7, 2, "-"],
[8, 2, "-"],
[9, 2, "-"],
[10, 2, "@integer(0, 10)"],
[11, 2, "@integer(0, 10)"],
[12, 2, "@integer(0, 10)"],
[13, 2, "@integer(0, 10)"],
[14, 2, "@integer(0, 10)"],
[15, 2, "@integer(0, 10)"],
[16, 2, "@integer(0, 10)"],
[17, 2, "@integer(0, 10)"],
[18, 2, "@integer(0, 10)"],
[19, 2, "@integer(0, 10)"],
[20, 2, "@integer(0, 10)"],
[21, 2, "@integer(0, 10)"],
[22, 2, "@integer(0, 10)"],
[23, 2, "@integer(0, 10)"],
[0, 3, 7],
[1, 3, 3],
[2, 3, "-"],
[3, 3, "-"],
[4, 3, "-"],
[5, 3, "-"],
[6, 3, "-"],
[7, 3, "-"],
[8, 3, 1],
[9, 3, "-"],
[10, 3, "@integer(0, 10)"],
[11, 3, "@integer(0, 10)"],
[12, 3, "@integer(0, 10)"],
[13, 3, "@integer(0, 10)"],
[14, 3, "@integer(0, 10)"],
[15, 3, "@integer(0, 10)"],
[16, 3, "@integer(0, 10)"],
[17, 3, "@integer(0, 10)"],
[18, 3, "@integer(0, 10)"],
[19, 3, "@integer(0, 10)"],
[20, 3, "@integer(0, 10)"],
[21, 3, "@integer(0, 10)"],
[22, 3, "@integer(0, 10)"],
[23, 3, "@integer(0, 10)"],
[0, 4, "@integer(0, 10)"],
[1, 4, "@integer(0, 10)"],
[2, 4, "-"],
[3, 4, "-"],
[4, 4, "-"],
[5, 4, "@integer(0, 10)"],
[6, 4, "-"],
[7, 4, "-"],
[8, 4, "-"],
[9, 4, "@integer(0, 10)"],
[10, 4, "@integer(0, 10)"],
[11, 4, "@integer(0, 10)"],
[12, 4, "@integer(0, 10)"],
[13, 4, "@integer(0, 10)"],
[14, 4, "@integer(0, 10)"],
[15, 4, "@integer(0, 10)"],
[16, 4, "@integer(0, 10)"],
[17, 4, "@integer(0, 10)"],
[18, 4, "@integer(0, 10)"],
[19, 4, "@integer(0, 10)"],
[20, 4, "@integer(0, 10)"],
[21, 4, "@integer(0, 10)"],
[22, 4, "@integer(0, 10)"],
[23, 4, "-"],
[0, 5, "@integer(0, 10)"],
[1, 5, "@integer(0, 10)"],
[2, 5, "-"],
[3, 5, "@integer(0, 10)"],
[4, 5, "-"],
[5, 5, "-"],
[6, 5, "-"],
[7, 5, "-"],
[8, 5, "@integer(0, 10)"],
[9, 5, "-"],
[10, 5, "@integer(0, 10)"],
[11, 5, "@integer(0, 10)"],
[12, 5, "@integer(0, 10)"],
[13, 5, "@integer(0, 10)"],
[14, 5, "@integer(0, 10)"],
[15, 5, "@integer(0, 10)"],
[16, 5, "@integer(0, 10)"],
[17, 5, "@integer(0, 10)"],
[18, 5, "-"],
[19, 5, "@integer(0, 10)"],
[20, 5, "@integer(0, 10)"],
[21, 5, "@integer(0, 10)"],
[22, 5, "@integer(0, 10)"],
[23, 5, "-"],
[0, 6, "@integer(0, 10)"],
[1, 6, "-"],
[2, 6, "-"],
[3, 6, "-"],
[4, 6, "-"],
[5, 6, "-"],
[6, 6, "-"],
[7, 6, "-"],
[8, 6, "-"],
[9, 6, "-"],
[10, 6, "@integer(0, 10)"],
[11, 6, "-"],
[12, 6, "@integer(0, 10)"],
[13, 6, "@integer(0, 10)"],
[14, 6, "@integer(0, 10)"],
[15, 6, "@integer(0, 10)"],
[16, 6, "-"],
[17, 6, "-"],
[18, 6, "-"],
[19, 6, "-"],
[20, 6, "@integer(0, 10)"],
[21, 6, "@integer(0, 10)"],
[22, 6, "@integer(0, 10)"],
[23, 6, "@integer(0, 10)"]
]
}

View File

@ -0,0 +1,120 @@
import test from './test.mock'
import { MockMethod } from 'vite-plugin-mock'
import { RequestHttpEnum } from 'PLS/goView/lib/enums/httpEnum'
// 单个X数据
export const chartDataUrl = '/mock/chartData'
export const chartSingleDataUrl = '/mock/chartSingleData'
export const numberFloatUrl = '/mock/number/float'
export const numberIntUrl = '/mock/number/int'
export const textUrl = '/mock/text'
export const imageUrl = '/mock/image'
export const rankListUrl = '/mock/rankList'
export const scrollBoardUrl = '/mock/scrollBoard'
export const radarUrl = '/mock/radarData'
export const heatMapUrl = '/mock/heatMapData'
export const scatterBasicUrl = '/mock/scatterBasic'
export const mapUrl = '/mock/map'
export const capsuleUrl = '/mock/capsule'
export const wordCloudUrl = '/mock/wordCloud'
export const treemapUrl = '/mock/treemap'
export const threeEarth01Url = '/mock/threeEarth01Data'
export const sankeyUrl = '/mock/sankey'
export const graphUrl = '/mock/graphData'
const mockObject: MockMethod[] = [
{
// 正则
// url: /\/mock\/mockData(|\?\S*)$/,
url: chartDataUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchMockData
},
{
url: chartSingleDataUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchMockSingleData
},
{
url: numberFloatUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchNumberFloat
},
{
url: numberIntUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchNumberInt
},
{
url: textUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchText
},
{
url: imageUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchImage(Math.round(Math.random() * 10))
},
{
url: rankListUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchRankList
},
{
url: scrollBoardUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchScrollBoard
},
{
url: radarUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchRadar
},
{
url: heatMapUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchHeatmap
},
{
url: scatterBasicUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchScatterBasic
},
{
url: mapUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchMap
},
{
url: capsuleUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchCapsule
},
{
url: wordCloudUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchWordCloud
},
{
url: treemapUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchTreemap
},
{
url: threeEarth01Url,
method: RequestHttpEnum.GET,
response: () => test.threeEarth01Data
},
{
url: sankeyUrl,
method: RequestHttpEnum.GET,
response: () => test.fetchSankey
},
{
url: graphUrl,
method: RequestHttpEnum.GET,
response: () => test.graphData
},
]
export default mockObject

View File

@ -0,0 +1,9 @@
{
"markers|50": [
{
"name": "某某地市",
"value": "@integer(2, 20)",
"position": ["@float(115, 117, 1, 6)", "@float(38, 40, 1, 6)"]
}
]
}

View File

@ -0,0 +1,86 @@
{
"label": [
{
"name": "a"
},
{
"name": "b"
},
{
"name": "a1"
},
{
"name": "a2"
},
{
"name": "b1"
},
{
"name": "b2"
}
],
"links": [
{
"source": "a",
"target": "a1",
"value": "@integer(0, 10)"
},
{
"source": "a",
"target": "a2",
"value": "@integer(0, 10)"
},
{
"source": "b",
"target": "b1",
"value": "@integer(0, 10)"
},
{
"source": "a",
"target": "b1",
"value": "@integer(0, 10)"
},
{
"source": "b1",
"target": "a1",
"value": "@integer(0, 10)"
},
{
"source": "b1",
"target": "b2",
"value": "@integer(0, 10)"
}
],
"levels": [
{
"depth": 0,
"itemStyle": {
"color": "#decbe4"
},
"lineStyle": {
"color": "source",
"opacity": 0.9
}
},
{
"depth": 1,
"itemStyle": {
"color": "#b3cde3"
},
"lineStyle": {
"color": "source",
"opacity": 0.6
}
},
{
"depth": 2,
"itemStyle": {
"color": "#ccebc5"
},
"lineStyle": {
"color": "source",
"opacity": 0.6
}
}
]
}

View File

@ -0,0 +1,56 @@
[
{
"dimensions": ["data1"],
"source": [
[10.0, "@integer(0, 100)"],
[8.07, "@integer(0, 100)"],
[13.0, "@integer(0, 100)"],
[9.05, "@integer(0, 100)"],
[11.0, "@integer(0, 100)"],
[14.0, "@integer(0, 100)"],
[13.4, "@integer(0, 100)"],
[10.0, "@integer(0, 100)"],
[14.0, "@integer(0, 100)"],
[12.5, "@integer(0, 100)"],
[9.15, "@integer(0, 100)"],
[11.5, "@integer(0, 100)"],
[3.03, "@integer(0, 100)"],
[12.2, "@integer(0, 100)"],
[2.02, "@integer(0, 100)"],
[1.05, "@integer(0, 100)"],
[4.05, "@integer(0, 100)"],
[6.03, "@integer(0, 100)"],
[12.0, "@integer(0, 100)"],
[12.0, "@integer(0, 100)"],
[7.08, "@integer(0, 100)"],
[5.02, "@integer(0, 100)"]
]
},
{
"dimensions": ["data2"],
"source": [
[10.0, "@integer(0, 70)"],
[8.07, "@integer(0, 70)"],
[13.0, "@integer(0, 70)"],
[9.05, "@integer(0, 70)"],
[11.0, "@integer(0, 70)"],
[14.0, "@integer(0, 70)"],
[13.4, "@integer(0, 70)"],
[10.0, "@integer(0, 70)"],
[14.0, "@integer(0, 70)"],
[12.5, "@integer(0, 70)"],
[9.15, "@integer(0, 70)"],
[11.5, "@integer(0, 70)"],
[3.03, "@integer(0, 70)"],
[12.2, "@integer(0, 70)"],
[2.02, "@integer(0, 70)"],
[1.05, "@integer(0, 70)"],
[4.05, "@integer(0, 70)"],
[6.03, "@integer(0, 70)"],
[12.0, "@integer(0, 70)"],
[12.0, "@integer(0, 70)"],
[7.08, "@integer(0, 70)"],
[5.02, "@integer(0, 70)"]
]
}
]

View File

@ -0,0 +1,239 @@
import heatmapJson from './heatMapData.json'
import scatterJson from './scatter.json'
import mapJson from './map.json'
import tTreemapJson from './treemap.json'
import sankeyJson from './sankey.json'
import graphDataJson from './graph.json'
export default {
// 单图表
fetchMockSingleData: {
code: 0,
status: 200,
msg: '请求成功',
data: {
dimensions: ['product', 'dataOne'],
'source|20': [
{
product: '@name',
'dataOne|0-900': 3
}
]
}
},
// 胶囊图
fetchCapsule: {
code: 0,
status: 200,
msg: '请求成功',
data: {
dimensions: ['name', 'value'],
"source|2-5": [
{ 'name|+1': ["厦门","福州","北京","上海","新疆","郑州","湖南","内蒙古"], 'value|0-40': 20 },
]
}
},
// 图表
fetchMockData: {
code: 0,
status: 200,
msg: '请求成功',
data: {
dimensions: ['product', 'dataOne', 'dataTwo', 'dataThree'],
'source|20': [
{
product: '@name',
'dataOne|100-900': 3,
'dataTwo|100-900': 3,
'dataThree|100-900': 3
}
]
}
},
// 排名列表
fetchRankList: {
code: 0,
status: 200,
msg: '请求成功',
'data|50': [{ name: '@name', 'value|100-900': 5 }]
},
// 轮播表格
fetchScrollBoard: {
code: 0,
status: 200,
msg: '请求成功',
data: [
['行1列1', '行1列2', '1'],
['行2列1', '行2列2', '2'],
['行3列1', '行3列2', '3'],
['行4列1', '行4列2', '4'],
['行5列1', '行5列2', '5'],
['行6列1', '行6列2', '6'],
['行7列1', '行7列2', '行7列3'],
['行8列1', '行8列2', '行8列3'],
['行9列1', '行9列2', '行9列3'],
['行10列1', '行10列2', '行10列3']
]
},
// 获取数字-浮点型
fetchNumberFloat: {
code: 0,
status: 200,
msg: '请求成功',
data: '@float(0, 0.99, 1, 4)'
},
// 获取数字-整型
fetchNumberInt: {
code: 0,
status: 200,
msg: '请求成功',
data: '@integer(0, 100)'
},
// 文字
fetchText: {
code: 0,
status: 200,
msg: '请求成功',
data: '@paragraph(1, 10)'
},
// 图片
fetchImage: (num: number) => ({
code: 0,
status: 200,
msg: '请求成功',
data: `https://robohash.org/${num}`
}),
// 雷达
fetchRadar: {
code: 0,
status: 200,
msg: '请求成功',
data: {
radarIndicator: [
{ name: '@name', max: 10000 },
{ name: '@name', max: 10000 },
{ name: '@name', max: 10000 },
{ name: '@name', max: 10000 },
{ name: '@name', max: 10000 },
{ name: '@name', max: 10000 }
],
seriesData: [
{
value: [
'@integer(0, 10000)',
'@integer(0, 10000)',
'@integer(0, 10000)',
'@integer(0, 10000)',
'@integer(0, 10000)',
'@integer(0, 10000)'
],
name: 'data1'
},
{
value: [
'@integer(0, 10000)',
'@integer(0, 10000)',
'@integer(0, 10000)',
'@integer(0, 10000)',
'@integer(0, 10000)',
'@integer(0, 10000)'
],
name: 'data2'
}
]
}
},
// 热力图
fetchHeatmap: {
code: 0,
status: 200,
msg: '请求成功',
data: heatmapJson
},
// 散点图
fetchScatterBasic: {
code: 0,
status: 200,
msg: '请求成功',
data: scatterJson
},
// 中国地图
fetchMap: {
code: 0,
status: 200,
msg: '请求成功',
data: mapJson
},
// 词云
fetchWordCloud: {
code: 0,
status: 200,
msg: '请求成功',
data: [
{
name: '@name',
value: 8000,
textStyle: {
color: '#78fbb2'
},
emphasis: {
textStyle: {
color: 'red'
}
}
},
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' },
{ name: '@name', value: '@integer(10, 8000)' }
]
},
// 树图
fetchTreemap: {
code: 0,
status: 200,
msg: '请求成功',
data: tTreemapJson
},
// 三维地球
threeEarth01Data: {
code: 0,
status: 200,
msg: '请求成功',
data: [
{
startArray: { name: '@name', N: '@integer(10, 100)', E: '@integer(10, 100)' },
'endArray|10': [{ name: '@name', N: '@integer(10, 100)', E: '@integer(10, 100)' }]
}
]
},
// 桑基图
fetchSankey: {
code: 0,
status: 200,
msg: '请求成功',
data: sankeyJson
},
// 关系图
graphData: {
code: 0,
status: 200,
msg: '请求成功',
data: graphDataJson
},
}

View File

@ -0,0 +1,50 @@
[
{
"name": "@name",
"value": "@integer(0, 1000)",
"children": [
{
"name": "@name",
"value": "@integer(0, 500)"
},
{
"name": "@name",
"value": "@integer(0, 500)"
}
]
},
{
"name": "@name",
"value": "@integer(0, 1000)",
"children": [
{
"name": "@name",
"value": "@integer(0, 00)"
},
{
"name": "@name",
"value": "@integer(0, 500)"
}
]
},
{
"name": "@name",
"value": "@integer(0, 1000)",
"children": [
{
"name": "@name",
"value": "@integer(0, 1000)"
}
]
},
{
"name": "@name",
"value": "@integer(0, 1000)",
"children": [
{
"name": "@name",
"value": "@integer(0, 1000)"
}
]
}
]

View File

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

View File

@ -0,0 +1,99 @@
import { http } from 'PLS/goView/lib/gApi/http'
import { httpErrorHandle } from 'PLS/goView/lib/utils'
import { ContentTypeEnum, RequestHttpEnum, ModuleTypeEnum } from 'PLS/goView/lib/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()
}
}

View File

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

View File

@ -0,0 +1,39 @@
import { http } from 'PLS/goView/lib/gApi/http'
import { httpErrorHandle } from 'PLS/goView/lib/utils'
import { RequestHttpEnum, ModuleTypeEnum } from 'PLS/goView/lib/enums/httpEnum'
import { LoginResult } from './system'
// * 登录
export const loginApi = async (data: object) => {
try {
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()
}
}
// * 获取 oss 上传接口
export const ossUrlApi = async (data: object) => {
try {
const res = await http(RequestHttpEnum.GET)<{
/**
* bucket
*/
bucketURL?: string
}>(`${ModuleTypeEnum.SYSTEM}/getOssInfo`, data)
return res
} catch (err) {
httpErrorHandle()
}
}

View File

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

View File

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

View File

@ -0,0 +1,34 @@
<template>
<iconify-icon
:icon="icon"
:rotate="`${rotate}deg`"
:width="width"
:style="{
color: color
}"
></iconify-icon>
</template>
<script setup lang="ts">
defineProps({
icon: {
type: String,
required: true
},
color: {
type: String,
default: '#999999',
required: false
},
width: {
type: [String, Number],
default: '20',
required: false
},
rotate: {
type: [String, Number],
default: '0',
required: false
}
})
</script>

View File

@ -0,0 +1,6 @@
<template>
<div>
<!-- 骨架图 -->
<go-skeleton :repeat="3" :show="true"></go-skeleton>
</div>
</template>

View File

@ -0,0 +1,17 @@
import type { App } from 'vue'
import GoLoading from './index.vue'
import AsyncLoading from './index.vue'
import AsyncSkeletonLoading from './LoadingSkeleton.vue'
// 正常组件
export { GoLoading }
// 异步
AsyncLoading.install = (app: App): void => {
app.component('AsyncLoading', AsyncLoading)
}
AsyncSkeletonLoading.install = (app: App): void => {
app.component('AsyncSkeletonLoading', AsyncSkeletonLoading)
}
export { AsyncLoading, AsyncSkeletonLoading }

View File

@ -0,0 +1,24 @@
<!--
* @Description:
* @Version: 1.668
* @Autor: 地虎降天龙
* @Date: 2024-05-27 17:02:50
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-05-27 17:13:46
-->
<template>
<!-- svg加载图 -->
<div class="go-loading-svg go-flex-center">
<img src=" " alt="" />
</div>
</template>
<style lang="scss" scoped>
@include go('loading-svg') {
width: 100%;
height: 100%;
background-color: transparent;
img {
height: 50px;
}
}
</style>

View File

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

View File

@ -0,0 +1,39 @@
<template>
<div v-show="load" class="go-skeleton">
<div v-show="repeat == 1">
<n-skeleton class="item" v-bind="$attrs"></n-skeleton>
</div>
<div v-show="repeat == 2">
<n-skeleton class="item" v-bind="$attrs"></n-skeleton>
<n-skeleton class="item" v-bind="$attrs" style="width: 60%;"></n-skeleton>
</div>
<div v-show="repeat > 2">
<n-skeleton class="item" v-bind="$attrs" :repeat="repeat - 2"></n-skeleton>
<n-skeleton class="item" v-bind="$attrs" style="width: 60%;"></n-skeleton>
<n-skeleton class="item" v-bind="$attrs" style="width: 50%;"></n-skeleton>
</div>
</div>
</template>
<script lang="ts" setup>
defineProps({
repeat: {
type: Number,
default: 1
},
load: {
type: Boolean,
default: true
}
})
</script>
<style lang="scss" scoped>
@include go("skeleton") {
.item {
margin-top: 5px;
margin-left: 5px;
}
padding-bottom: 5px;
}
</style>

View File

@ -0,0 +1,8 @@
export * from 'PLS/goView/lib/gHooks/useTheme.hook'
export * from 'PLS/goView/lib/gHooks/usePreviewScale.hook'
export * from 'PLS/goView/lib/gHooks/useCode.hook'
export * from 'PLS/goView/lib/gHooks/useChartDataFetch.hook'
export * from 'PLS/goView/lib/gHooks/useChartDataPondFetch.hook'
export * from 'PLS/goView/lib/gHooks/useLifeHandler.hook'
export * from 'PLS/goView/lib/gHooks/useLang.hook'
export * from 'PLS/goView/lib/gHooks/useChartInteract.hook'

View File

@ -0,0 +1,27 @@
import { inject, type Ref } from 'vue'
import { EchartsRenderer } from 'PLS/goView/lib/gSettings/chartThemes'
import { SCALE_KEY } from 'PLS/goView/lib/hooks/useScale.hook'
import { use } from 'echarts/core'
import { CanvasRenderer, SVGRenderer } from 'echarts/renderers'
use([CanvasRenderer, SVGRenderer])
type InitOptions = {
renderer: EchartsRenderer
devicePixelRatio?: number
}
// 获取需要给当前echarts组件设置什么初始值
export function useCanvasInitOptions(option: any, themeSetting: any) {
const renderer = option.renderer || themeSetting.renderer
const initOptions: InitOptions = { renderer }
const scaleRef = inject<Ref<{ width: number; height: number }>>(SCALE_KEY) || { value: { width: 1, height: 1 } }
if (renderer === 'canvas') {
initOptions.devicePixelRatio = Math.ceil(
Math.max(window.devicePixelRatio, scaleRef.value.width, scaleRef.value.height)
)
}
return initOptions
}

View File

@ -0,0 +1,130 @@
import { ref, toRefs, toRaw, watch } from 'vue'
import type VChart from 'vue-echarts'
import { customizeHttp } from 'PLS/goView/lib/gApi/http'
import { useChartDataPondFetch } from 'PLS/goView/lib/gHooks/'
import { CreateComponentType, ChartFrameEnum } from 'PLS/goView/lib/packages/index.d'
import { useChartEditStore } from 'PLS/goView/stores/chartEditStore'
import { RequestDataTypeEnum } from 'PLS/goView/lib/enums/httpEnum'
import { isPreview, newFunctionHandle, intervalUnitHandle } from 'PLS/goView/lib/utils/global'
import { setOption } from 'PLS/goView/lib/packages/public/chart'
import { isNil } from 'lodash'
// 获取类型
type ChartEditStoreType = typeof useChartEditStore
/**
* setdata
* @param targetComponent
* @param useChartEditStore
* @param updateCallback
*/
export const useChartDataFetch = (
targetComponent: CreateComponentType,
useChartEditStore: ChartEditStoreType,
updateCallback?: (...args: any) => any
) => {
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) {
setOption(vChartRef.value, { dataset: dataset })
}
}
}
const requestIntervalFn = () => {
const chartEditStore = useChartEditStore()
// 全局数据
const {
requestOriginUrl,
requestIntervalUnit: globalUnit,
requestInterval: globalRequestInterval
} = toRefs(chartEditStore.getRequestGlobalConfig)
// 目标组件
const {
requestDataType,
requestUrl,
requestIntervalUnit: targetUnit,
requestInterval: targetInterval
} = toRefs(targetComponent.request)
// 非请求类型
if (requestDataType.value !== RequestDataTypeEnum.AJAX) return
try {
// 处理地址
// @ts-ignore
if (requestUrl?.value) {
// requestOriginUrl 允许为空
const completePath = requestOriginUrl && requestOriginUrl.value + requestUrl.value
if (!completePath) return
clearInterval(fetchInterval)
const fetchFn = async () => {
const res = await customizeHttp(toRaw(targetComponent.request), toRaw(chartEditStore.getRequestGlobalConfig))
if (res) {
try {
const filter = targetComponent.filter
const { data } = res
echartsUpdateHandle(newFunctionHandle(data, res, filter))
// 更新回调函数
if (updateCallback) {
updateCallback(newFunctionHandle(data, res, filter))
}
} catch (error) {
console.error(error)
}
}
}
// 普通初始化与组件交互处理监听
watch(
() => targetComponent.request.requestParams,
() => {
fetchFn()
},
{
immediate: true,
deep: true
}
)
// 定时时间
const time = targetInterval && !isNil(targetInterval.value) ? targetInterval.value : globalRequestInterval.value
// 单位
const unit = targetInterval && !isNil(targetInterval.value) ? targetUnit.value : globalUnit.value
// 开启轮询
if (time) {
fetchInterval = setInterval(fetchFn, intervalUnitHandle(time, unit))
}
}
// eslint-disable-next-line no-empty
} catch (error) {
console.log(error)
}
}
if (isPreview()) {
targetComponent.request.requestDataType === RequestDataTypeEnum.Pond
? addGlobalDataInterface(targetComponent, useChartEditStore, (newData: any) => {
echartsUpdateHandle(newData)
if (updateCallback) updateCallback(newData)
})
: requestIntervalFn()
} else {
requestIntervalFn()
}
return { vChartRef }
}

View File

@ -0,0 +1,130 @@
import { toRaw, watch, computed, ComputedRef } from 'vue'
import { customizeHttp } from 'PLS/goView/lib/gApi/http'
import { CreateComponentType } from 'PLS/goView/lib/packages/index.d'
import { useChartEditStore } from 'PLS/goView/stores/chartEditStore'
import { RequestGlobalConfigType, RequestDataPondItemType } from 'PLS/goView/stores/chartEditStore.d'
import { newFunctionHandle, intervalUnitHandle } from 'PLS/goView/lib/utils/global'
// 获取类型
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: ComputedRef<RequestDataPondItemType>,
dataPondMapItem?: DataPondMapType[]
) => {
if (!dataPondMapItem) return
let fetchInterval: any = 0
clearInterval(fetchInterval)
// 请求
const fetchFn = async () => {
try {
const res = await customizeHttp(toRaw(requestDataPondItem.value.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
}
}
watch(
() => requestDataPondItem.value.dataPondRequestConfig.requestParams.Params,
() => {
fetchFn()
},
{
immediate: false,
deep: true
}
)
// 立即调用
fetchFn()
const targetInterval = requestDataPondItem.value.dataPondRequestConfig.requestInterval
const targetUnit = requestDataPondItem.value.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 = (useChartEditStore: ChartEditStoreType) => {
const { requestGlobalConfig } = useChartEditStore()
const chartEditStore = useChartEditStore()
// 根据 mapId 查找对应的数据池配置
for (let pondKey of mittDataPondMap.keys()) {
const requestDataPondItem = computed(() => {
return requestGlobalConfig.requestDataPond.find(item => item.dataPondId === pondKey)
}) as ComputedRef<RequestDataPondItemType>
if (requestDataPondItem) {
newPondItemInterval(chartEditStore.requestGlobalConfig, requestDataPondItem, mittDataPondMap.get(pondKey))
}
}
}
return {
addGlobalDataInterface,
clearMittDataPondMap,
initDataPond
}
}

View File

@ -0,0 +1,59 @@
import { toRefs } from 'vue'
import { isPreview } from 'PLS/goView/lib/utils/global'
import { CreateComponentType } from 'PLS/goView/lib/packages/index.d'
import { useChartEditStore } from 'PLS/goView/stores/chartEditStore'
// 获取类型
type ChartEditStoreType = typeof useChartEditStore
// Params 参数修改触发 api 更新图表请求
export const useChartInteract = (
chartConfig: CreateComponentType,
useChartEditStore: ChartEditStoreType,
param: { [T: string]: any },
interactEventOn: string
) => {
if (!isPreview()) return
const chartEditStore = useChartEditStore()
const { interactEvents } = chartConfig.events
const fnOnEvent = interactEvents.filter(item => {
return item.interactOn === interactEventOn
})
if (fnOnEvent.length === 0) return
fnOnEvent.forEach(item => {
const globalConfigPindAprndex = chartEditStore.requestGlobalConfig.requestDataPond.findIndex(cItem =>
cItem.dataPondId === item.interactComponentId
)
if (globalConfigPindAprndex !== -1) {
const { Params, Header } = toRefs(chartEditStore.requestGlobalConfig.requestDataPond[globalConfigPindAprndex].dataPondRequestConfig.requestParams)
Object.keys(item.interactFn).forEach(key => {
if (key in Params.value) {
Params.value[key] = param[item.interactFn[key]]
}
if (key in Header.value) {
Header.value[key] = param[item.interactFn[key]]
}
})
} else {
const index = chartEditStore.fetchTargetIndex(item.interactComponentId)
if (index === -1) return
const { Params, Header } = toRefs(chartEditStore.componentList[index].request.requestParams)
Object.keys(item.interactFn).forEach(key => {
if (key in Params.value) {
Params.value[key] = param[item.interactFn[key]]
}
if (key in Header.value) {
Header.value[key] = param[item.interactFn[key]]
}
})
}
})
}
// 联动事件触发的 type 变更时,清除当前绑定内容
export const clearInteractEvent = (chartConfig: CreateComponentType) => {
}

View File

@ -0,0 +1,10 @@
import hljs from 'highlight.js/lib/core'
import json from 'highlight.js/lib/languages/json'
import typescript from 'highlight.js/lib/languages/typescript'
// * code 展示
export const useCode = () => {
hljs.registerLanguage('json', json)
hljs.registerLanguage('typescript', typescript)
return hljs
}

View File

@ -0,0 +1,33 @@
/*
* @Description:
* @Version: 1.668
* @Autor:
* @Date: 2024-05-22 20:54:09
* @LastEditors:
* @LastEditTime: 2024-05-27 17:06:18
*/
import { computed } from 'vue'
import { LangEnum } from 'PLS/goView/lib/enums/styleEnum'
import { zhCN, enUS, dateEnUS, dateZhCN } from 'naive-ui'
type LangStoreType = typeof useLangStore
// 语言切换
export const useLang = () => {
const lang = {
getLang : LangEnum.ZH
}
const locale = computed(() => {
return lang.getLang === LangEnum.ZH ? zhCN : enUS
})
const dateLocale = computed(() => {
return lang.getLang === LangEnum.ZH ? dateZhCN : dateEnUS
})
return {
locale,
dateLocale
}
}

View File

@ -0,0 +1,79 @@
import { CreateComponentType, CreateComponentGroupType } from 'PLS/goView/lib/packages/index.d'
import { EventLife } from 'PLS/goView/lib/enums/eventEnum'
import * as echarts from 'echarts'
// 所有图表组件集合对象
const components: { [K in string]?: any } = {}
// 项目提供的npm 包变量
export const npmPkgs = { echarts }
// 组件事件处理 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.VNODE_BEFORE_MOUNT](e: any) {
// 存储组件
components[chartConfig.id] = e.component
const fnStr = (events[EventLife.VNODE_BEFORE_MOUNT] || '').trim()
generateFunc(fnStr, e)
},
[EventLife.VNODE_MOUNTED](e: any) {
const fnStr = (events[EventLife.VNODE_MOUNTED] || '').trim()
generateFunc(fnStr, e)
}
}
return { ...baseEvent, ...lifeEvents }
}
/**
*
* @param fnStr
* @param event
*/
export function generateBaseFunc(fnStr: string) {
try {
return new Function(`
return (
async function(components,mouseEvent){
${fnStr}
}
)`)().bind(undefined,components)
} catch (error) {
console.error(error)
}
}
/**
*
* @param fnStr
* @param e
*/
function generateFunc(fnStr: string, e: any) {
try {
// npmPkgs 便于拷贝 echarts 示例时设置option 的formatter等相关内容
Function(`
"use strict";
return (
async function(e, components, node_modules){
const {${Object.keys(npmPkgs).join()}} = node_modules;
${fnStr}
}
)`)().bind(e?.component)(e, components, npmPkgs)
} catch (error) {
console.error(error)
}
}

View File

@ -0,0 +1,218 @@
import throttle from 'lodash/throttle'
// 拆出来是为了更好的分离单独复用
// * 屏幕缩放适配(两边留白)
export const usePreviewFitScale = (
width: number,
height: number,
scaleDom: HTMLElement | null,
callback?: (scale: {
width: number;
height: number;
}) => void
) => {
// * 画布尺寸px
const baseWidth = width
const baseHeight = height
// * 默认缩放值
const scale = {
width: 1,
height: 1,
}
// * 需保持的比例
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
const calcRate = () => {
// 当前屏幕宽高比
const currentRate = parseFloat(
(window.innerWidth / window.innerHeight).toFixed(5)
)
if (scaleDom) {
if (currentRate > baseProportion) {
// 表示更宽
scale.width = parseFloat(((window.innerHeight * baseProportion) / baseWidth).toFixed(5))
scale.height = parseFloat((window.innerHeight / baseHeight).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
} else {
// 表示更高
scale.height = parseFloat(((window.innerWidth / baseProportion) / baseHeight).toFixed(5))
scale.width = parseFloat((window.innerWidth / baseWidth).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
}
if (callback) callback(scale)
}
}
const resize = throttle(() => {
calcRate()
}, 200)
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize)
}
// * 卸载监听
const unWindowResize = () => {
window.removeEventListener('resize', resize)
}
return {
calcRate,
windowResize,
unWindowResize,
}
}
// * X轴撑满Y轴滚动条
export const usePreviewScrollYScale = (
width: number,
height: number,
scaleDom: HTMLElement | null,
callback?: (scale: {
width: number;
height: number;
}) => void
) => {
// * 画布尺寸px
const baseWidth = width
const baseHeight = height
// * 默认缩放值
const scale = {
width: 1,
height: 1,
}
// * 需保持的比例
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
const calcRate = () => {
if (scaleDom) {
scale.height = parseFloat(((window.innerWidth / baseProportion) / baseHeight).toFixed(5))
scale.width = parseFloat((window.innerWidth / baseWidth).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
if (callback) callback(scale)
}
}
const resize = throttle(() => {
calcRate()
}, 200)
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize)
}
// * 卸载监听
const unWindowResize = () => {
window.removeEventListener('resize', resize)
}
return {
calcRate,
windowResize,
unWindowResize,
}
}
// * Y轴撑满X轴滚动条
export const usePreviewScrollXScale = (
width: number,
height: number,
scaleDom: HTMLElement | null,
callback?: (scale: {
width: number;
height: number;
}) => void
) => {
// * 画布尺寸px
const baseWidth = width
const baseHeight = height
// * 默认缩放值
const scale = {
height: 1,
width: 1,
}
// * 需保持的比例
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
const calcRate = () => {
if (scaleDom) {
scale.width = parseFloat(((window.innerHeight * baseProportion) / baseWidth).toFixed(5))
scale.height = parseFloat((window.innerHeight / baseHeight).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
if (callback) callback(scale)
}
}
const resize = throttle(() => {
calcRate()
}, 200)
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize)
}
// * 卸载监听
const unWindowResize = () => {
window.removeEventListener('resize', resize)
}
return {
calcRate,
windowResize,
unWindowResize,
}
}
// * 变形内容,宽高铺满
export const usePreviewFullScale = (
width: number,
height: number,
scaleDom: HTMLElement | null,
callback?: (scale: {
width: number;
height: number;
}) => void
) => {
// * 默认缩放值
const scale = {
width: 1,
height: 1,
}
const calcRate = () => {
if (scaleDom) {
scale.width = parseFloat((window.innerWidth / width).toFixed(5))
scale.height = parseFloat((window.innerHeight / height).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
if (callback) callback(scale)
}
}
const resize = throttle(() => {
calcRate()
}, 200)
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize)
}
// * 卸载监听
const unWindowResize = () => {
window.removeEventListener('resize', resize)
}
return {
calcRate,
windowResize,
unWindowResize,
}
}

View File

@ -0,0 +1,50 @@
import { computed, toRefs } from 'vue'
import { darkTheme, GlobalThemeOverrides } from 'naive-ui'
import { useDesignStore } from 'PLS/goView/stores/designStore/designStore'
import { borderRadius } from 'PLS/goView/lib/gSettings/designSetting'
import { alpha, lighten } from 'PLS/goView/lib/utils/global'
/**
* *
*/
export const useThemeOverridesHook = () => {
const designStore = useDesignStore()
const { getAppTheme } = toRefs(designStore)
const darkTheme = computed(
(): GlobalThemeOverrides => {
// 通用
const commonObj = {
common: {
primaryColor: getAppTheme.value,
primaryColorHover: lighten(alpha(getAppTheme.value), 0.1),
primaryColorPressed: lighten(alpha(getAppTheme.value), 0.1),
primaryColorSuppl: getAppTheme.value,
borderRadius
}
}
// 亮色主题
const lightObject = {
common: {
...commonObj.common
}
}
// 暗色主题
const dartObject = {
common: {
...commonObj.common
},
LoadingBar: {
colorLoading: getAppTheme.value
}
}
return designStore.getDarkTheme ? dartObject : lightObject
}
)
return darkTheme
}
// 返回暗黑主题
export const useDarkThemeHook = () => {
const designStore = useDesignStore()
return computed(() => (designStore.getDarkTheme ? darkTheme : undefined))
}

View File

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

View File

@ -0,0 +1,31 @@
<template>
<img class="list-img" v-lazy="imageInfo" alt="图表图片" />
</template>
<script setup lang="ts">
import { ref, PropType, watch } from 'vue'
import { fetchImages } from '@/packages'
import { ConfigType } from 'PLS/goView/lib/packages/index.d'
const props = defineProps({
chartConfig: {
type: Object as PropType<ConfigType>,
required: true,
},
})
const imageInfo = ref('')
//
const fetchImageUrl = async () => {
imageInfo.value = await fetchImages(props.chartConfig)
}
watch(
() => props.chartConfig.key,
() => fetchImageUrl(),
{
immediate: true,
},
)
</script>

View File

@ -0,0 +1,36 @@
<template>
<n-divider style="margin: 10px 0;"></n-divider>
<n-collapse arrow-placement="right" :default-expanded-names="expanded ? name : null" accordion>
<!-- 右侧 -->
<template #header-extra>
<div @click="click">
<slot name="header"></slot>
</div>
</template>
<n-collapse-item :title="name" :name="name">
<slot></slot>
</n-collapse-item>
</n-collapse>
</template>
<script setup lang="ts">
defineProps({
name: {
type: String,
required: true
},
expanded: {
type: Boolean,
required: false,
default: false
}
})
// const name = new Date().getTime()
const click = (e:MouseEvent) => {
e.preventDefault()
e.stopPropagation()
}
</script>

View File

@ -0,0 +1,45 @@
<template>
<n-radio-group :value="props.modelValue || INHERIT_VALUE" @update:value="handleChange">
<n-space>
<n-tooltip :show-arrow="false" trigger="hover" v-for="item in rendererList" :key="item.value">
<template #trigger>
<n-radio :value="item.value">
{{ item.value }}
</n-radio>
</template>
{{ item.desc }}
</n-tooltip>
</n-space>
</n-radio-group>
</template>
<script setup lang="ts">
import { type EchartsRenderer } from 'PLS/goView/lib/gSettings/chartThemes'
const props = defineProps<{ modelValue?: EchartsRenderer; includeInherit?: boolean }>()
const emits = defineEmits(['update:modelValue'])
const INHERIT_VALUE = 'inherit'
const handleChange = (val: EchartsRenderer & typeof INHERIT_VALUE) => {
emits('update:modelValue', val === INHERIT_VALUE ? undefined : val)
}
const rendererList = [
{
value: 'svg',
desc: '在缩放场景下具有更好的表现',
},
{
value: 'canvas',
desc: '数据量较大(经验判断 > 1k、较多交互时建议选择',
},
...(props.includeInherit
? [
{
value: INHERIT_VALUE,
desc: '默认继承全局配置',
},
]
: []),
]
</script>

View File

@ -0,0 +1,400 @@
<template>
<collapse-item name="渲染器">
<setting-item-box :alone="true">
<template #name>
<n-text>全局</n-text>
<n-tooltip trigger="hover">
<template #trigger>
<n-icon size="21" :depth="3">
<help-outline-icon></help-outline-icon>
</n-icon>
</template>
<n-text>所有echarts图表组件默认都将采用所选的渲染器进行渲染</n-text>
</n-tooltip>
</template>
<EchartsRendererSetting v-model="themeSetting.renderer" />
</setting-item-box>
<setting-item-box :alone="true">
<template #name>
<n-text>当前</n-text>
<n-tooltip trigger="hover">
<template #trigger>
<n-icon size="21" :depth="3">
<help-outline-icon></help-outline-icon>
</n-icon>
</template>
<n-text>仅当前组件采用指定渲染器渲染</n-text>
</n-tooltip>
</template>
<EchartsRendererSetting v-model="optionData.renderer" includeInherit />
</setting-item-box>
</collapse-item>
<collapse-item v-if="title" name="标题">
<template #header>
<n-switch v-model:value="title.show" size="small"></n-switch>
</template>
<setting-item-box name="标题">
<setting-item name="颜色">
<n-color-picker v-model:value="title.textStyle.color" size="small"></n-color-picker>
</setting-item>
<setting-item name="大小">
<n-input-number v-model:value="title.textStyle.fontSize" :min="1" size="small"></n-input-number>
</setting-item>
</setting-item-box>
<setting-item-box name="副标题">
<setting-item name="颜色">
<n-color-picker size="small" v-model:value="title.subtextStyle.color"></n-color-picker>
</setting-item>
<setting-item name="大小">
<n-input-number v-model:value="title.subtextStyle.fontSize" :min="1" size="small"></n-input-number>
</setting-item>
</setting-item-box>
</collapse-item>
<collapse-item v-if="grid" name="容器">
<setting-item-box name="距离">
<setting-item name="左侧距离">
<n-input v-model:value="grid.left" size="small"></n-input>
</setting-item>
<setting-item name="右侧距离">
<n-input v-model:value="grid.right" size="small"></n-input>
</setting-item>
<setting-item name="上侧距离">
<n-input v-model:value="grid.top" size="small"></n-input>
</setting-item>
<setting-item name="下侧距离">
<n-input v-model:value="grid.bottom" size="small"></n-input>
</setting-item>
</setting-item-box>
</collapse-item>
<collapse-item v-if="xAxis" name="X轴">
<template #header>
<n-switch v-model:value="xAxis.show" size="small"></n-switch>
</template>
<setting-item-box name="单位">
<setting-item name="名称">
<n-input v-model:value="xAxis.name" size="small"></n-input>
</setting-item>
<setting-item name="颜色">
<n-color-picker size="small" v-model:value="xAxis.nameTextStyle.color"></n-color-picker>
</setting-item>
<setting-item name="大小">
<n-input-number v-model:value="xAxis.nameTextStyle.fontSize" :min="12" size="small"></n-input-number>
</setting-item>
<setting-item name="偏移量">
<n-input-number v-model:value="xAxis.nameGap" :min="5" size="small"></n-input-number>
</setting-item>
</setting-item-box>
<setting-item-box name="标签">
<setting-item name="展示">
<n-space>
<n-switch v-model:value="xAxis.axisLabel.show" size="small"></n-switch>
</n-space>
</setting-item>
<setting-item name="颜色">
<n-color-picker size="small" v-model:value="xAxis.axisLabel.color"></n-color-picker>
</setting-item>
<setting-item name="大小">
<n-input-number v-model:value="xAxis.axisLabel.fontSize" :min="8" size="small"></n-input-number>
</setting-item>
<setting-item name="偏移量">
<n-input-number v-model:value="xAxis.axisLabel.rotate" :min="-90" :max="90" size="small"></n-input-number>
</setting-item>
</setting-item-box>
<setting-item-box name="轴线">
<setting-item name="展示">
<n-space>
<n-switch v-model:value="xAxis.axisLine.show" size="small"></n-switch>
</n-space>
</setting-item>
<setting-item name="颜色">
<n-color-picker v-model:value="xAxis.axisLine.lineStyle.color" size="small"></n-color-picker>
</setting-item>
<setting-item name="粗细">
<n-input-number v-model:value="xAxis.axisLine.lineStyle.width" :min="1" size="small"></n-input-number>
</setting-item>
<setting-item name="位置">
<n-select v-model:value="xAxis.position" size="small" :options="axisConfig.xposition"></n-select>
</setting-item>
<setting-item name="对齐零">
<n-space>
<n-switch v-model:value="xAxis.axisLine.onZero" size="small"></n-switch>
</n-space>
</setting-item>
<setting-item name="反向">
<n-space>
<n-switch v-model:value="xAxis.inverse" size="small"></n-switch>
</n-space>
</setting-item>
</setting-item-box>
<setting-item-box name="刻度">
<setting-item name="展示">
<n-space>
<n-switch v-model:value="xAxis.axisTick.show" size="small"></n-switch>
</n-space>
</setting-item>
<setting-item name="长度">
<n-input-number v-model:value="xAxis.axisTick.length" :min="1" size="small"></n-input-number>
</setting-item>
</setting-item-box>
<setting-item-box name="分割线">
<setting-item name="展示">
<n-space>
<n-switch v-model:value="xAxis.splitLine.show" size="small"></n-switch>
</n-space>
</setting-item>
<setting-item name="颜色">
<n-color-picker v-model:value="xAxis.splitLine.lineStyle.color" size="small"></n-color-picker>
</setting-item>
<setting-item name="粗细">
<n-input-number v-model:value="xAxis.splitLine.lineStyle.width" :min="1" size="small"></n-input-number>
</setting-item>
<setting-item name="类型">
<n-select v-model:value="xAxis.splitLine.lineStyle.type" size="small" :options="axisConfig.splitLint.lineStyle.type"></n-select>
</setting-item>
</setting-item-box>
</collapse-item>
<collapse-item v-if="yAxis" name="Y轴">
<template #header>
<n-switch v-model:value="yAxis.show" size="small"></n-switch>
</template>
<setting-item-box name="单位">
<setting-item name="名称">
<n-input v-model:value="yAxis.name" size="small"></n-input>
</setting-item>
<setting-item name="颜色">
<n-color-picker size="small" v-model:value="yAxis.nameTextStyle.color"></n-color-picker>
</setting-item>
<setting-item name="大小">
<n-input-number v-model:value="yAxis.nameTextStyle.fontSize" :min="8" size="small"></n-input-number>
</setting-item>
<setting-item name="偏移量">
<n-input-number v-model:value="yAxis.nameGap" :min="5" size="small"></n-input-number>
</setting-item>
</setting-item-box>
<setting-item-box name="标签">
<setting-item name="展示">
<n-space>
<n-switch v-model:value="yAxis.axisLabel.show" size="small"></n-switch>
</n-space>
</setting-item>
<setting-item name="颜色">
<n-color-picker size="small" v-model:value="yAxis.axisLabel.color"></n-color-picker>
</setting-item>
<setting-item name="大小">
<n-input-number v-model:value="yAxis.axisLabel.fontSize" :min="8" size="small"></n-input-number>
</setting-item>
<setting-item name="偏移量">
<n-input-number v-model:value="yAxis.axisLabel.rotate" :min="-90" :max="90" size="small"></n-input-number>
</setting-item>
</setting-item-box>
<setting-item-box name="轴线">
<setting-item name="展示">
<n-space>
<n-switch v-model:value="yAxis.axisLine.show" size="small"></n-switch>
</n-space>
</setting-item>
<setting-item name="颜色">
<n-color-picker v-model:value="yAxis.axisLine.lineStyle.color" size="small"></n-color-picker>
</setting-item>
<setting-item name="粗细">
<n-input-number v-model:value="yAxis.axisLine.lineStyle.width" :min="1" size="small"></n-input-number>
</setting-item>
<setting-item name="位置">
<n-select v-model:value="yAxis.position" size="small" :options="axisConfig.yposition"></n-select>
</setting-item>
<setting-item name="对齐零">
<n-space>
<n-switch v-model:value="yAxis.axisLine.onZero" size="small"></n-switch>
</n-space>
</setting-item>
<setting-item name="反向">
<n-space>
<n-switch v-model:value="yAxis.inverse" size="small"></n-switch>
</n-space>
</setting-item>
</setting-item-box>
<setting-item-box name="刻度">
<setting-item name="展示">
<n-space>
<n-switch v-model:value="yAxis.axisTick.show" size="small"></n-switch>
</n-space>
</setting-item>
<setting-item name="长度">
<n-input-number v-model:value="yAxis.axisTick.length" :min="1" size="small"></n-input-number>
</setting-item>
</setting-item-box>
<setting-item-box name="分割线">
<setting-item name="展示">
<n-space>
<n-switch v-model:value="yAxis.splitLine.show" size="small"></n-switch>
</n-space>
</setting-item>
<setting-item name="颜色">
<n-color-picker v-model:value="yAxis.splitLine.lineStyle.color" size="small"></n-color-picker>
</setting-item>
<setting-item name="粗细">
<n-input-number v-model:value="yAxis.splitLine.lineStyle.width" :min="1" size="small"></n-input-number>
</setting-item>
<setting-item name="类型">
<n-select v-model:value="yAxis.splitLine.lineStyle.type" size="small" :options="axisConfig.splitLint.lineStyle.type"></n-select>
</setting-item>
</setting-item-box>
</collapse-item>
<collapse-item v-if="legend" name="图例">
<template #header>
<n-switch v-model:value="legend.show" size="small"></n-switch>
</template>
<setting-item-box name="图例文字">
<setting-item name="颜色">
<n-color-picker size="small" v-model:value="legend.textStyle.color"></n-color-picker>
</setting-item>
<setting-item name="大小">
<n-input-number v-model:value="legend.textStyle.fontSize" :min="1" size="small"></n-input-number>
</setting-item>
</setting-item-box>
<setting-item-box name="图例位置">
<setting-item name="x轴">
<n-select v-model:value="legend.x" size="small" :options="legendConfig.lengendX" />
</setting-item>
<setting-item name="y轴">
<n-select v-model:value="legend.y" size="small" :options="legendConfig.lengendY" />
</setting-item>
</setting-item-box>
<setting-item-box name="图例信息">
<setting-item name="方向">
<n-select v-model:value="legend.orient" size="small" :options="legendConfig.orient" />
</setting-item>
<setting-item name="形状">
<n-select v-model:value="legend.icon" size="small" :options="legendConfig.shape" />
</setting-item>
</setting-item-box>
<setting-item-box name="图例大小">
<setting-item name="宽">
<n-input-number v-model:value="legend.itemWidth" :min="1" size="small"></n-input-number>
</setting-item>
<setting-item name="高">
<n-input-number v-model:value="legend.itemHeight" :min="1" size="small"></n-input-number>
</setting-item>
</setting-item-box>
</collapse-item>
<collapse-item v-if="visualMap" name="视觉映射">
<template #header>
<n-switch v-model:value="visualMap.show" size="small"></n-switch>
</template>
<setting-item-box name="范围">
<setting-item name="最小值">
<n-input-number v-model:value="visualMap.min" size="small"></n-input-number>
</setting-item>
<setting-item name="最大值">
<n-input-number v-model:value="visualMap.max" size="small"></n-input-number>
</setting-item>
</setting-item-box>
<setting-item-box name="颜色">
<setting-item :name="`层级-${index + 1}`" v-for="(item, index) in visualMap.inRange.color" :key="index">
<n-color-picker v-model:value="visualMap.inRange.color[index]" size="small"></n-color-picker>
</setting-item>
</setting-item-box>
<setting-item-box name="控制块">
<setting-item name="放置方向">
<n-select v-model:value="visualMap.orient" size="small" :options="axisConfig.visualMap.orient"></n-select>
</setting-item>
<setting-item name="宽度">
<n-input-number v-model:value="visualMap.itemWidth" :min="5" size="small"></n-input-number>
</setting-item>
<setting-item name="高度">
<n-input-number v-model:value="visualMap.itemHeight" :min="5" size="small"></n-input-number>
</setting-item>
<setting-item name="反转">
<n-space>
<n-switch v-model:value="visualMap.inverse" size="small"></n-switch>
</n-space>
</setting-item>
<setting-item name="拖拽组件实时更新">
<n-space>
<n-switch v-model:value="visualMap.realtime" size="small"></n-switch>
</n-space>
</setting-item>
</setting-item-box>
<global-setting-position :targetData="visualMap"></global-setting-position>
</collapse-item>
</template>
<script setup lang="ts">
import { PropType, computed, watch } from 'vue'
import { GlobalThemeJsonType } from 'PLS/goView/lib/gSettings/chartThemes/index'
import { axisConfig, legendConfig } from 'PLS/goView/lib/packages/chartConfiguration/echarts/index'
import { CollapseItem, SettingItemBox, SettingItem, GlobalSettingPosition } from 'PLS/goView/lib/gPages/ChartItemSetting'
import { icon } from 'PLS/goView/lib/gPlugins/'
import { useChartEditStore } from 'PLS/goView/stores/chartEditStore'
import EchartsRendererSetting from './EchartsRendererSetting.vue'
const { HelpOutlineIcon } = icon.ionicons5
const props = defineProps({
optionData: {
type: Object as PropType<GlobalThemeJsonType>,
required: true,
},
inChart: {
type: Boolean,
required: false,
default: false,
},
})
const chartEditStore = useChartEditStore()
const themeSetting = computed(() => {
const chartThemeSetting = chartEditStore.getEditCanvasConfig.chartThemeSetting
return chartThemeSetting
})
const title = computed(() => {
return props.optionData.title
})
const xAxis = computed(() => {
return props.optionData.xAxis
})
const yAxis = computed(() => {
return props.optionData.yAxis
})
const legend = computed(() => {
return props.optionData.legend
})
const grid = computed(() => {
return props.optionData.grid
})
const visualMap = computed(() => {
return props.optionData.visualMap
})
// legend colortype = scroll
watch(
() => legend.value && legend.value.textStyle.color,
(newVal) => {
if (legend.value && newVal) {
if (!legend.value.pageTextStyle) {
legend.value.pageTextStyle = { color: newVal }
} else {
legend.value.pageTextStyle.color = newVal
}
}
},
{
immediate: true,
deep: true,
},
)
</script>

View File

@ -0,0 +1,29 @@
<template>
<setting-item-box v-if="targetData" name="位置">
<setting-item :name="`偏移 X${targetData.left || 0}px`">
<n-input-number v-model:value="targetData.left" size="small" step="10"></n-input-number>
</setting-item>
<setting-item :name="`偏移 Y${targetData.top || 0}px`">
<n-input-number v-model:value="targetData.top" size="small" step="10"></n-input-number>
</setting-item>
</setting-item-box>
</template>
<script setup lang="ts">
import { PropType, reactive } from 'vue'
import { CollapseItem, SettingItemBox, SettingItem } from 'PLS/goView/lib/gPages/ChartItemSetting'
type positionType = {
top?: number | string | null
left?: number | string | null
right?: number | string | null
bottom?: number | string | null
}
const props = defineProps({
targetData: {
type: Object as PropType<positionType>,
required: true,
},
})
</script>

View File

@ -0,0 +1,42 @@
<template>
<setting-item-box name="名称" :alone="true">
<n-input
type="text"
maxlength="12"
minlength="1"
placeholder="请输入图表名称"
size="small"
clearable
show-count
v-model:value="chartConfig.title"
@focus="handleFocus"
@blur="handleBlur"
></n-input>
</setting-item-box>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import { SettingItemBox } from 'PLS/goView/lib/gPages/ChartItemSetting'
import { ConfigType } from 'PLS/goView/lib/packages/index.d'
const props = defineProps({
chartConfig: {
type: Object as PropType<ConfigType>,
required: true,
},
})
let valueCatch = ''
const handleFocus = () => {
valueCatch = props.chartConfig.title
}
const handleBlur = () => {
if (!props.chartConfig.title.length) {
window['$message'].warning('请输入至少一个字符!')
props.chartConfig.title = valueCatch
}
}
</script>

View File

@ -0,0 +1,107 @@
<template>
<n-divider style="margin: 10px 0"></n-divider>
<n-space :size="8" justify="space-between" style="margin-top: 10px">
<n-button secondary v-for="item in positionList" :key="item.key" @click="positonHandle(item.key)">
<template #icon>
<component :is="item.icon"></component>
</template>
</n-button>
</n-space>
<setting-item-box name="位置">
<n-input-number v-model:value="chartAttr.y" :min="0" size="small" placeholder="px">
<template #prefix>
<n-text depth="3"></n-text>
</template>
</n-input-number>
<n-input-number v-model:value="chartAttr.x" :min="0" size="small" placeholder="px">
<template #prefix>
<n-text depth="3"></n-text>
</template>
</n-input-number>
</setting-item-box>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import { PickCreateComponentType } from 'PLS/goView/lib/packages/index.d'
import { SettingItemBox } from 'PLS/goView/lib/gPages/ChartItemSetting'
import { renderIcon } from 'PLS/goView/lib/utils/global'
import { icon } from 'PLS/goView/lib/gPlugins//index'
import { EditCanvasConfigType } from 'PLS/goView/stores/chartEditStore.d'
const { AlignHorizontalLeftIcon, AlignVerticalCenterIcon, AlignVerticalTopIcon, AlignHorizontalCenterIcon, AlignHorizontalRightIcon, AlignVerticalBottomIcon } =
icon.carbon
const positionList = [
{
key: 'AlignHorizontalLeftIcon',
lable: '局左',
icon: renderIcon(AlignHorizontalLeftIcon),
},
{
key: 'AlignVerticalCenterIcon',
lable: 'X轴居中',
icon: renderIcon(AlignVerticalCenterIcon),
},
{
key: 'AlignHorizontalRightIcon',
lable: '局右',
icon: renderIcon(AlignHorizontalRightIcon),
},
{
key: 'AlignVerticalTopIcon',
lable: '顶部',
icon: renderIcon(AlignVerticalTopIcon),
},
{
key: 'AlignHorizontalCenterIcon',
lable: 'Y轴居中',
icon: renderIcon(AlignHorizontalCenterIcon),
},
{
key: 'AlignVerticalBottomIcon',
lable: '底部',
icon: renderIcon(AlignVerticalBottomIcon),
},
]
const props = defineProps({
canvasConfig: {
type: Object as PropType<EditCanvasConfigType>,
required: true,
},
chartAttr: {
type: Object as PropType<PickCreateComponentType<'attr'>>,
required: true,
},
})
const positonHandle = (key: string) => {
switch (key) {
//
case positionList[0]['key']:
props.chartAttr.x = 0
break
// X
case positionList[1]['key']:
props.chartAttr.y = (props.canvasConfig.height - props.chartAttr.h) / 2
break
//
case positionList[2]['key']:
props.chartAttr.x = props.canvasConfig.width - props.chartAttr.w
break
//
case positionList[3]['key']:
props.chartAttr.y = 0
break
// Y
case positionList[4]['key']:
props.chartAttr.x = (props.canvasConfig.width - props.chartAttr.w) / 2
break
//
case positionList[5]['key']:
props.chartAttr.y = props.canvasConfig.height - props.chartAttr.h
break
}
}
</script>

View File

@ -0,0 +1,32 @@
<template>
<div class="go-setting-item" :style="{ width: width + 'px' }">
<slot ></slot>
<n-text class="name" depth="3">{{ name }}</n-text>
</div>
</template>
<script setup lang="ts">
defineProps({
name: {
type: String,
required: false
},
width: {
type: Number,
required: false
}
})
</script>
<style lang="scss" scoped>
@include go(setting-item) {
display: flex;
flex-direction: column;
min-width: 110px;
text-align: start;
margin-bottom: 5px;
.name {
margin-top: 2px;
}
}
</style>

View File

@ -0,0 +1,59 @@
<template>
<div class="go-config-item-box">
<n-text class="item-left" depth="2">
{{ name }}
<n-space :size="5">
<slot name="name"></slot>
</n-space>
</n-text>
<div
class="item-right"
:style="{
gridTemplateColumns: alone ? '1fr' : '1fr 1fr',
...itemRightStyle
}"
>
<slot></slot>
</div>
</div>
</template>
<script setup lang="ts">
defineProps({
name: {
type: String,
required: false
},
alone: {
type: Boolean,
default: false,
required: false
},
itemRightStyle: {
type: Object,
default: () => {},
required: false
}
})
</script>
<style lang="scss" scoped>
$leftWidth: 60px;
@include go('config-item-box') {
position: relative;
display: flex;
margin: 20px 0;
.item-left {
width: $leftWidth;
text-align: left;
margin-top: 4px;
margin-left: 10px;
font-size: 12px;
}
.item-right {
display: grid;
grid-column-gap: 10px;
width: calc(100% - #{$leftWidth});
}
}
</style>

View File

@ -0,0 +1,31 @@
<template>
<setting-item-box name="尺寸">
<n-input-number v-model:value="chartAttr.w" :min="50" :disabled="isGroup" size="small" placeholder="px">
<template #prefix>
<n-text depth="3">宽度</n-text>
</template>
</n-input-number>
<n-input-number v-model:value="chartAttr.h" :min="50" :disabled="isGroup" size="small" placeholder="px">
<template #prefix>
<n-text depth="3">高度</n-text>
</template>
</n-input-number>
</setting-item-box>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import { PickCreateComponentType } from 'PLS/goView/lib/packages/index.d'
import { SettingItemBox } from 'PLS/goView/lib/gPages/ChartItemSetting'
const props = defineProps({
chartAttr: {
type: Object as PropType<Omit<PickCreateComponentType<'attr'>, 'node' | 'conNode'>>,
required: true,
},
isGroup: {
type: Boolean,
required: false,
},
})
</script>

View File

@ -0,0 +1,180 @@
<template>
<div v-show="isGroup">
<n-divider n-divider style="margin: 10px 0"></n-divider>
<n-tag type="warning"> 解散分组 {{ isCanvas ? '滤镜' : '滤镜 / 变换' }} 也将消失!</n-tag>
</div>
<collapse-item :name="isCanvas ? '滤镜' : '滤镜 / 变换'">
<template #header>
<n-switch v-model:value="chartStyles.filterShow" size="small"></n-switch>
</template>
<setting-item-box name="色相" :alone="true">
<setting-item :name="`值:${chartStyles.hueRotate}deg`">
<!-- 透明度 -->
<n-slider v-model:value="chartStyles.hueRotate" :step="3" :min="0" :max="360" :format-tooltip="degFormatTooltip"></n-slider>
</setting-item>
</setting-item-box>
<setting-item-box name="饱和度" :alone="true">
<setting-item :name="`值:${(parseFloat(String(chartStyles.saturate)) * 100).toFixed(0)}%`">
<!-- 透明度 -->
<n-slider v-model:value="chartStyles.saturate" :step="0.1" :min="0" :max="2" :format-tooltip="sliderFormatTooltip"></n-slider>
</setting-item>
</setting-item-box>
<setting-item-box name="对比度" :alone="true">
<setting-item :name="`值:${(parseFloat(String(chartStyles.contrast)) * 100).toFixed(0)}%`">
<!-- 透明度 -->
<n-slider v-model:value="chartStyles.contrast" :step="0.1" :min="0" :max="2" :format-tooltip="sliderFormatTooltip"></n-slider>
</setting-item>
</setting-item-box>
<setting-item-box name="亮度" :alone="true">
<setting-item :name="`值:${(parseFloat(String(chartStyles.brightness)) * 100).toFixed(0)}%`">
<!-- 透明度 -->
<n-slider v-model:value="chartStyles.brightness" :step="0.1" :min="0" :max="2" :format-tooltip="sliderFormatTooltip"></n-slider>
</setting-item>
</setting-item-box>
<setting-item-box name="透明度" :alone="true">
<setting-item :name="`值:${(parseFloat(String(chartStyles.opacity)) * 100).toFixed(0)}%`">
<!-- 透明度 -->
<n-slider v-model:value="chartStyles.opacity" :step="0.1" :min="0" :max="1" :format-tooltip="sliderFormatTooltip"></n-slider>
</setting-item>
</setting-item-box>
<!-- 预设滤镜 -->
<div v-if="presetImageList.length" class="preset-filter">
<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>
<!-- 混合模式 -->
<setting-item-box v-if="!isCanvas" :alone="true">
<template #name>
<n-text>混合</n-text>
<n-tooltip trigger="hover">
<template #trigger>
<n-icon size="21" :depth="3">
<help-outline-icon></help-outline-icon>
</n-icon>
</template>
<n-text>视频组件需要底色透明一般选中滤色</n-text>
</n-tooltip>
</template>
<setting-item>
<n-select v-model:value="chartStyles.blendMode" size="small" filterable :options="BlendModeEnumList"></n-select>
</setting-item>
</setting-item-box>
<!-- 变换 -->
<setting-item-box v-if="!isCanvas" name="旋转°">
<setting-item name="Z轴(平面) - 旋转">
<!-- 透明度 -->
<n-input-number v-model:value="chartStyles.rotateZ" :min="0" :max="360" size="small" placeholder="角度"></n-input-number>
</setting-item>
<setting-item name="X轴 - 旋转">
<!-- 透明度 -->
<n-input-number v-model:value="chartStyles.rotateX" :min="0" :max="360" size="small" placeholder="角度"></n-input-number>
</setting-item>
<setting-item name="Y轴 - 旋转">
<!-- 透明度 -->
<n-input-number v-model:value="chartStyles.rotateY" :min="0" :max="360" size="small" placeholder="角度"></n-input-number>
</setting-item>
</setting-item-box>
<!-- 倾斜 -->
<setting-item-box v-if="!isCanvas" name="倾斜°">
<setting-item name="X轴 - 倾斜">
<n-input-number v-model:value="chartStyles.skewX" :min="0" :max="360" size="small" placeholder="角度"></n-input-number>
</setting-item>
<setting-item name="Y轴 - 倾斜">
<n-input-number v-model:value="chartStyles.skewY" :min="0" :max="360" size="small" placeholder="角度"></n-input-number>
</setting-item>
</setting-item-box>
<!-- 提示 -->
<n-tag type="warning"> 若预览时大屏模糊可以尝试关闭滤镜进行修复 </n-tag>
</collapse-item>
</template>
<script setup lang="ts">
import { ref, PropType } from 'vue'
import { PickCreateComponentType, BlendModeEnumList } from 'PLS/goView/lib/packages/index.d'
import { SettingItemBox, SettingItem, CollapseItem } from 'PLS/goView/lib/gPages/ChartItemSetting'
import { icon } from 'PLS/goView/lib/gPlugins/'
import { useDesignStore } from 'PLS/goView/stores/designStore/designStore'
const props = defineProps({
isGroup: {
type: Boolean,
required: false,
},
isCanvas: {
type: Boolean,
default: false,
},
chartStyles: {
type: Object as PropType<Omit<PickCreateComponentType<'styles'>, 'animations'>>,
required: true,
},
})
const { HelpOutlineIcon } = icon.ionicons5
// person
const sliderFormatTooltip = (v: string) => {
return `${(parseFloat(v) * 100).toFixed(0)}%`
}
//
const degFormatTooltip = (v: string) => {
return `${v}deg`
}
//
interface presetImageData {
index: number
src: string
hueRotate: number
}
const presetImageList = ref([] as presetImageData[])
for (let i = 1; i <= 12; i++) {
presetImageList.value.push({
index: i,
src: '',
hueRotate: i * 30,
})
}
</script>
<style lang="scss" scoped>
//
.preset-filter {
margin: 20px 0 10px 0;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.preset-img {
margin-bottom: 10px;
padding: 2px;
border-radius: 6px;
transition: 0.2s all;
cursor: pointer;
&:hover {
box-shadow: 0 0 0 2px #66a9c9;
}
}
.active-preset {
box-shadow: 0 0 0 2px #66a9c9;
}
}
</style>

View File

@ -0,0 +1,20 @@
// 设置项布局
import SettingItem from './SettingItem.vue'
import SettingItemBox from './SettingItemBox.vue'
import CollapseItem from './CollapseItem.vue'
// 全局配置属性
import GlobalSetting from './GlobalSetting.vue'
// 全局配置属性-位置
import GlobalSettingPosition from './GlobalSettingPosition.vue'
// 名称
import NameSetting from './NameSetting.vue'
// 方向
import PositionSetting from './PositionSetting.vue'
// 尺寸
import SizeSetting from './SizeSetting.vue'
// 样式
import StylesSetting from './StylesSetting.vue'
export { CollapseItem, SettingItemBox, SettingItem, GlobalSetting, GlobalSettingPosition, NameSetting, PositionSetting, SizeSetting, StylesSetting }

View File

@ -0,0 +1,5 @@
import Flipper from './index.vue'
type FlipType = 'up' | 'down'
export { Flipper, FlipType }

View File

@ -0,0 +1,245 @@
<template>
<div class="go-flipper" :class="[flipType, { go: isFlipping }]">
<div class="digital front" :data-front="frontTextFromData"></div>
<div class="digital back" :data-back="backTextFromData"></div>
</div>
</template>
<script lang="ts" setup>
import { ref, PropType, watch, nextTick } from 'vue'
import { FlipType } from './index'
const props = defineProps({
flipType: {
type: String as PropType<FlipType>,
default: () => {
return 'down'
}
},
count: {
type: [Number, String],
default: 0
},
duration: {
type: Number,
default: 600
},
width: {
type: Number,
default: 60
},
height: {
type: Number,
default: 100
},
radius: {
type: Number,
default: 10
},
frontColor: {
type: String,
default: '#ffffff'
},
backColor: {
type: String,
default: '#000000'
},
borderWidth: {
type: Number,
default: 2
}
})
const isFlipping = ref(false)
const frontTextFromData = ref(props.count || 0)
const backTextFromData = ref(props.count || 0)
let timeoutID: any = 0
//
const flip = async (front: string | number, back: string | number) => {
//
if (isFlipping.value) {
isFlipping.value = false //
clearTimeout(timeoutID) //
await nextTick()
await flip(front, back) //
return
}
//
backTextFromData.value = back
frontTextFromData.value = front
// true
isFlipping.value = true
//
timeoutID = setTimeout(() => {
isFlipping.value = false // false
frontTextFromData.value = back
}, props.duration)
}
watch(
() => props.count,
(newVal, oldVal) => {
flip(oldVal as string | number, newVal as string | number)
},
{
immediate: true
}
)
</script>
<style lang="scss" scoped>
$frontColor: v-bind('props.frontColor');
$backColor: v-bind('props.backColor');
$radius: v-bind('`${props.radius}px`');
$width: v-bind('`${props.width}px`');
$height: v-bind('`${props.height}px`');
$perspective: v-bind('`${props.height * 2}px`');
$borderWidth: v-bind('`${props.borderWidth * 2}px`');
$speed: v-bind('`${props.duration / 1000}s`');
$shadowColor: #000000;
$lineColor: #4a9ef8;
// #region
@keyframes frontFlipDown {
0% {
transform: perspective($perspective) rotateX(0deg);
}
100% {
transform: perspective($perspective) rotateX(-180deg);
}
}
@keyframes backFlipDown {
0% {
transform: perspective($perspective) rotateX(180deg);
}
100% {
transform: perspective($perspective) rotateX(0deg);
}
}
@keyframes frontFlipUp {
0% {
transform: perspective($perspective) rotateX(0deg);
}
100% {
transform: perspective($perspective) rotateX(180deg);
}
}
@keyframes backFlipUp {
0% {
transform: perspective($perspective) rotateX(-180deg);
}
100% {
transform: perspective($perspective) rotateX(0deg);
}
}
// #endregion
.go-flipper {
display: inline-block;
position: relative;
width: $width;
height: $height;
line-height: $height;
border-radius: $radius;
background: $frontColor;
font-size: $width;
color: $frontColor;
box-shadow: 0 0 6px rgba($color: $shadowColor, $alpha: 0.5); //
text-align: center;
// font-family: 'Helvetica Neue';
&::after {
content: '';
position: absolute;
z-index: 10;
left: 0;
top: 0;
right: 0;
bottom: 0;
box-shadow: inset 0 0 $borderWidth 0 $frontColor; //
border-radius: $radius;
}
.digital:before,
.digital:after {
content: '';
position: absolute;
left: 0;
right: 0;
background: $backColor;
overflow: hidden;
box-sizing: border-box;
}
.digital.front:before,
.digital.front:after {
content: attr(data-front) !important;
}
.digital.back:before,
.digital.back:after {
content: attr(data-back) !important;
}
.digital:before {
top: 0;
bottom: 50%;
border-radius: $radius $radius 0 0;
border-bottom: solid 1px rgba($color: $lineColor, $alpha: 0.3); // 线
}
.digital:after {
top: 50%;
bottom: 0;
border-radius: 0 0 $radius $radius;
line-height: 0;
}
/*向下翻*/
&.down .front:before {
z-index: 3;
}
&.down .back:after {
z-index: 2;
transform-origin: 50% 0%;
transform: perspective($perspective) rotateX(180deg);
}
&.down .front:after,
&.down .back:before {
z-index: 1;
}
&.down.go .front:before {
transform-origin: 50% 100%;
animation: frontFlipDown $speed ease-in-out both;
box-shadow: 0 -2px $borderWidth 0 $frontColor;
backface-visibility: hidden;
}
&.down.go .back:after {
animation: backFlipDown $speed ease-in-out both;
box-shadow: 0 2px $borderWidth 0 $frontColor;
backface-visibility: hidden;
}
/*向上翻*/
&.up .front:after {
z-index: 3;
}
&.up .back:before {
z-index: 2;
transform-origin: 50% 100%;
transform: perspective($perspective) rotateX(-180deg);
}
&.up .front:before,
&.up .back:after {
z-index: 1;
}
&.up.go .front:after {
transform-origin: 50% 0;
animation: frontFlipUp $speed ease-in-out both;
box-shadow: 0 2px $borderWidth 0 $frontColor;
backface-visibility: hidden;
}
&.up.go .back:before {
animation: backFlipUp $speed ease-in-out both;
box-shadow: 0 -2px $borderWidth 0 $frontColor;
backface-visibility: hidden;
}
}
</style>

View File

@ -0,0 +1,110 @@
<template>
<div class="content-left">
<div
class="content-left-item go-transition-quick go-mb-0"
span="12 1000:6 1400:4 1800:4 2200:2"
v-for="(item, index) in designColorRecommend"
:key="index"
@click="colorSelectHandle(item)"
>
<n-space>
<div class="content-left-item-color" :style="{ backgroundColor: item.hex }"></div>
<n-space vertical>
<n-space>
<span :style="{ color: item.hex }">{{ item.name }}</span>
<span class="Pinyin-upper">{{ item.pinyin.toUpperCase() }}</span>
</n-space>
<n-text>
{{ item.hex }}
<n-divider vertical></n-divider>
{{ `rgb(${item.RGB[0]}, ${item.RGB[1]}, ${item.RGB[2]})` }}
</n-text>
</n-space>
</n-space>
</div>
<n-divider></n-divider>
<div
class="content-left-item go-transition-quick"
span="12 1000:6 1400:4 1800:4 2200:2"
v-for="(item, index) in designColor"
:key="index"
@click="colorSelectHandle(item)"
>
<n-space>
<div class="content-left-item-color" :style="{ backgroundColor: item.hex }"></div>
<n-space vertical>
<n-space>
<span :style="{ color: item.hex }">{{ item.name }}</span>
<span class="Pinyin-upper">{{ item.pinyin.toUpperCase() }}</span>
</n-space>
<n-text>
{{ item.hex }}
<n-divider vertical></n-divider>
{{ `rgb(${item.RGB[0]}, ${item.RGB[1]}, ${item.RGB[2]})` }}
</n-text>
</n-space>
</n-space>
</div>
</div>
</template>
<script lang="ts" setup>
import { PropType } from 'vue'
import { AppThemeColorType } from 'PLS/goView/stores/designStore/designStore.d'
import designColorRecommend from 'PLS/goView/lib/gSettings/designColorRecommend.json'
const emits = defineEmits(['colorSelectHandle'])
defineProps({
designColor: {
type: Object as PropType<AppThemeColorType[]>,
required: true,
},
})
const colorSelectHandle = (color: AppThemeColorType) => {
emits('colorSelectHandle', color)
}
</script>
<style lang="scss" scoped>
.content-left {
display: flex;
flex-wrap: wrap;
margin-right: 200px;
.content-left-item {
position: relative;
display: flex;
margin-bottom: 10px;
margin-right: 10px;
padding: 10px 20px;
min-width: 300px;
border-radius: 5px;
cursor: pointer;
border: 1px solid rgba(0, 0, 0, 0);
&:hover {
@include hover-border-color('background-color5');
}
&::after {
content: '';
z-index: -1;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0.7;
overflow: hidden;
border-radius: 5px;
@extend .go-background-filter-shallow;
backdrop-filter: none;
}
&-color {
width: 8px;
height: 40px;
border-radius: 2px;
}
.Pinyin-upper {
font-size: 8px;
}
}
}
</style>

View File

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

View File

@ -0,0 +1,160 @@
<template>
<n-button quaternary @click="modelShow = true" title="颜色">
<n-icon size="20" :depth="1">
<color-wand-icon></color-wand-icon>
</n-icon>
</n-button>
<n-modal v-model:show="modelShow">
<div class="go-system-color-setting">
<n-space justify="space-between">
<n-h3 class="title">主题颜色选择</n-h3>
<n-icon size="20" class="go-cursor-pointer" @click="modelShow = false">
<close-icon></close-icon>
</n-icon>
</n-space>
<n-divider></n-divider>
<div class="model-content" ref="contentLeftRef">
<div class="content-left" v-if="modelShow">
<color-list :designColor="designColorSplit" @colorSelectHandle="colorSelectHandle"></color-list>
</div>
<div class="content-right">
<div class="color-name-detail">
<n-text v-if="appThemeDetail" class="color-name">{{ appThemeDetail.name }}</n-text>
<n-text v-else class="color-name">中国色</n-text>
<n-text v-if="appThemeDetail" class="color-name-Pinyin">{{ appThemeDetail.pinyin.toUpperCase() }}</n-text>
<div v-if="appThemeDetail" class="select-color" :style="{ backgroundColor: designStore.appTheme }"></div>
</div>
<img src="" />
</div>
</div>
<div class="model-footer">
中国色列表来自于
<n-a href="http://zhongguose.com" target="_blank">http://zhongguose.com</n-a>
</div>
</div>
</n-modal>
</template>
<script lang="ts" setup>
import { ref, computed, watch, toRefs } from 'vue'
import { useDesignStore } from 'PLS/goView/stores/designStore/designStore'
import { AppThemeColorType } from 'PLS/goView/stores/designStore/designStore.d'
import { icon } from 'PLS/goView/lib/gPlugins/'
import { loadAsyncComponent } from 'PLS/goView/lib/utils/global'
import { useScroll } from '@vueuse/core'
import designColor from 'PLS/goView/lib/gSettings/designColor.json'
const ColorList = loadAsyncComponent(() => import('./components/ColorList.vue'))
const { ColorWandIcon, CloseIcon } = icon.ionicons5
let splitNumber = 50
const designStore = useDesignStore()
const modelShow = ref(false)
const contentLeftRef = ref<HTMLElement | null>(null)
const designColorSplit = ref(designColor.slice(0, splitNumber))
const { arrivedState } = useScroll(contentLeftRef, {
offset: { bottom: 200 },
})
const { bottom } = toRefs(arrivedState)
const appThemeDetail = computed(() => {
return designStore.getAppThemeDetail
})
const colorSelectHandle = (color: AppThemeColorType) => {
designStore.setAppColor(color)
}
watch(
() => bottom.value,
(newData: boolean) => {
if (newData) {
splitNumber = splitNumber + 50
designColorSplit.value = designColor.slice(0, splitNumber)
}
},
)
watch(
() => modelShow.value,
(modelShow: boolean) => {
if (!modelShow) {
splitNumber = 50
}
},
)
</script>
<style lang="scss" scoped>
$height: 85vh;
@include go('system-color-setting') {
position: relative;
display: flex;
flex-direction: column;
width: 90%;
min-width: 1000px;
padding: 20px 25px;
height: $height;
border-radius: 15px;
overflow: hidden;
@extend .go-background-filter;
@include hover-border-color('background-color5');
.title {
margin: 0;
}
.model-content {
flex: 1;
height: calc(#{$height} - 40px - 48px - 36px);
overflow: auto;
/* 右侧 */
.content-right {
position: absolute;
display: flex;
align-items: center;
justify-content: flex-end;
width: 300px;
height: 100%;
right: 50px;
top: 0px;
.color-name-detail {
display: flex;
flex-direction: column;
align-items: center;
margin-right: 40px;
.go-flex-items-center {
flex-direction: column;
}
.select-color {
margin-top: 20px;
width: 100px;
height: 20px;
border-radius: 3px;
background-image: url('');
}
.color-name {
font-family: serif;
font-size: 80px;
color: #fff;
margin: 0 auto;
display: block;
width: 110px;
text-align: center;
background-position: center top;
background-repeat: no-repeat;
}
.color-name-Pinyin {
text-align: center;
font-family: Georgia;
font-size: 16px;
}
}
}
}
.model-footer {
z-index: 1;
text-align: end;
}
}
</style>

View File

@ -0,0 +1,14 @@
import type { App } from 'vue'
import { GoSkeleton } from 'PLS/goView/lib/gComponents/GoSkeleton'
import { GoLoading } from 'PLS/goView/lib/gComponents/GoLoading'
import { SketchRule } from 'vue3-sketch-ruler'
/**
*
* @param app
*/
export function setupCustomComponents(app: App) {
app.component('GoSkeleton', GoSkeleton)
app.component('GoLoading', GoLoading)
app.component('SketchRule', SketchRule)
}

View File

@ -0,0 +1,27 @@
/*
* @Description:
* @Version: 1.668
* @Autor:
* @Date: 2024-05-27 16:29:51
* @LastEditors:
* @LastEditTime: 2024-05-27 17:24:45
*/
import { App } from 'vue';
import VueLazyLoad from 'vue3-lazyload'
// import { requireErrorImg } from 'PLS/goView/lib/utils'
export const requireErrorImg = () => {
return ''
}
// import { x } from '@/directives';
/**
*
* @param app
*/
export function setupDirectives(app: App) {
// 图片懒加载
app.use(VueLazyLoad, {
error: requireErrorImg(),
})
// app.directive('x', x);
}

View File

@ -0,0 +1,308 @@
import {
Add as AddIcon,
Close as CloseIcon,
Remove as RemoveIcon,
Resize as ResizeIcon,
EllipsisHorizontalSharp as EllipsisHorizontalCircleSharpIcon,
CopyOutline as CopyIcon,
Trash as TrashIcon,
Pencil as PencilIcon,
HammerOutline as HammerIcon,
DesktopOutline as DesktopOutlineIcon,
Download as DownloadIcon,
DownloadOutline as DownloadOutlineIcon,
Share as ShareIcon,
Send as SendIcon,
InformationCircleOutline as InformationCircleIcon,
Grid as GridIcon,
TvOutline as TvOutlineIcon,
DocumentText as DocumentTextIcon,
Language as LanguageIcon,
Moon as MoonIcon,
Sunny as SunnyIcon,
Person as PersonIcon,
PersonOutline as PersonOutlineIcon,
LogOutOutline as LogOutOutlineIcon,
ChatboxEllipses as ChatboxEllipsesIcon,
LockOpenOutline as LockOpenOutlineIcon,
LockClosedOutline as LockClosedOutlineIcon,
HelpCircleOutline as HelpOutlineIcon,
CodeSlash as CodeSlashIcon,
Create as CreateIcon,
Rocket as RocketIcon,
Duplicate as DuplicateIcon,
DuplicateOutline as DuplicateOutlineIcon,
Fish as FishIcon,
BarChart as BarChartIcon,
Layers as LayersIcon,
Prism as PrismIcon,
Construct as ConstructIcon,
ChevronBackOutline as ChevronBackOutlineIcon,
Flash as FlashIcon,
SettingsSharp as SettingsSharpIcon,
Home as HomeIcon,
Card as CardIcon,
ChevronUp as ChevronUpIcon,
ChevronDown as ChevronDownIcon,
ClipboardOutline as ClipboardOutlineIcon,
BrowsersOutline as BrowsersOutlineIcon,
Cut as CutIcon,
Square as SquareIcon,
ColorPalette as ColorPaletteIcon,
Leaf as LeafIcon,
ColorWand as ColorWandIcon,
ArrowBack as ArrowBackIcon,
ArrowForward as ArrowForwardIcon,
ArrowDown as ArrowDownIcon,
Planet as PawIcon,
Search as SearchIcon,
ChevronUpOutline as ChevronUpOutlineIcon,
ChevronDownOutline as ChevronDownOutlineIcon,
Pulse as PulseIcon,
Folder as FolderIcon,
FolderOpen as FolderOpenIcon,
ImageOutline as ImageIcon,
Images as ImagesIcon,
List as ListIcon,
EyeOutline as EyeOutlineIcon,
EyeOffOutline as EyeOffOutlineIcon,
Albums as AlbumsIcon,
Analytics as AnalyticsIcon,
AirplaneOutline as AirPlaneOutlineIcon
} from '@vicons/ionicons5'
import {
TableSplit as TableSplitIcon,
Roadmap as RoadmapIcon,
SpellCheck as SpellCheckIcon,
GraphicalDataFlow as GraphicalDataFlowIcon,
Store as StoreIcon,
Devices as DevicesIcon,
ObjectStorage as ObjectStorageIcon,
DicomOverlay as DicomOverlayIcon,
UpToTop as UpToTopIcon,
DownToBottom as DownToBottomIcon,
StackedMove as StackedMoveIcon,
PaintBrush as PaintBrushIcon,
ComposerEdit as ZAxisIcon,
AlignHorizontalLeft as AlignHorizontalLeftIcon,
AlignVerticalCenter as AlignVerticalCenterIcon,
AlignVerticalTop as AlignVerticalTopIcon,
AlignHorizontalCenter as AlignHorizontalCenterIcon,
AlignHorizontalRight as AlignHorizontalRightIcon,
AlignVerticalBottom as AlignVerticalBottomIcon,
DocumentAdd as DocumentAddIcon,
DocumentDownload as DocumentDownloadIcon,
Scale as ScaleIcon,
FitToScreen as FitToScreenIcon,
FitToHeight as FitToHeightIcon,
FitToWidth as FitToWidthIcon,
Carbon3DCursor as Carbon3DCursorIcon,
Carbon3DSoftware as Carbon3DSoftwareIcon,
Filter as FilterIcon,
FilterEdit as FilterEditIcon,
Laptop as LaptopIcon
} from '@vicons/carbon'
const ionicons5 = {
// 新增
AddIcon,
// 帮助(问号)
HelpOutlineIcon,
// 添加
DuplicateIcon,
// 添加 Outline
DuplicateOutlineIcon,
// 代码
CodeSlashIcon,
// 修改代码
CreateIcon,
// 事件(火箭)
RocketIcon,
// 退出
LogOutOutlineIcon,
// 锁
LockOpenOutlineIcon,
LockClosedOutlineIcon,
// 人
PersonIcon,
// 人2
PersonOutlineIcon,
// 更多(省略号)
ChatboxEllipsesIcon,
// 月亮
MoonIcon,
// 太阳
SunnyIcon,
// 关闭
CloseIcon,
// 移除(最小化)
RemoveIcon,
// 调整(最大化)
ResizeIcon,
// 省略号
EllipsisHorizontalCircleSharpIcon,
// 复制
CopyIcon,
// 删除(垃圾桶)
TrashIcon,
// 编辑1
PencilIcon,
// 编辑2锤子
HammerIcon,
// 电脑
DesktopOutlineIcon,
// 下载
DownloadIcon,
DownloadOutlineIcon,
// 导出
ShareIcon,
// 导出
SendIcon,
// 信息
InformationCircleIcon,
// 项目
GridIcon,
// 电脑1
TvOutlineIcon,
// 预览,浏览器
BrowsersOutlineIcon,
// 文档
DocumentTextIcon,
// 语言
LanguageIcon,
// 新项目(鱼)
FishIcon,
// 图表
BarChartIcon,
// 图层
LayersIcon,
// 组件详情设置(三棱镜)
PrismIcon,
// 正方体
ConstructIcon,
// 折叠/回退
ChevronBackOutlineIcon,
// 后端数据(闪电)
FlashIcon,
// 设置(齿轮)
SettingsSharpIcon,
// 回退
HomeIcon,
// 控件(卡片)
CardIcon,
// 上移
ChevronUpIcon,
// 下移
ChevronDownIcon,
// 剪贴板
ClipboardOutlineIcon,
// 剪贴
CutIcon,
// 正方形
SquareIcon,
// 色彩选择
ColorPaletteIcon,
ZAxisIcon,
// 气球
LeafIcon,
// 颜色
ColorWandIcon,
// 撤回
ArrowBackIcon,
// 前进
ArrowForwardIcon,
// 向下
ArrowDownIcon,
// 狗爪
PawIcon,
// 搜索(放大镜)
SearchIcon,
// 过滤器
FilterIcon,
// 向上
ChevronUpOutlineIcon,
// 向下
ChevronDownOutlineIcon,
// 脉搏
PulseIcon,
// 文件夹
FolderIcon,
// 文件夹打开
FolderOpenIcon,
// 图片
ImageIcon,
// 多个图片
ImagesIcon,
// 列表
ListIcon,
// 眼睛
EyeOutlineIcon,
EyeOffOutlineIcon,
// 图表列表
AlbumsIcon,
// 分析
AnalyticsIcon,
// 飞机
AirPlaneOutlineIcon
}
const carbon = {
// 图表
RoadmapIcon,
// 信息
SpellCheckIcon,
// 表格
TableSplitIcon,
// 装饰
GraphicalDataFlowIcon,
// 项目
DevicesIcon,
// 模板市场
StoreIcon,
// 我的模板
ObjectStorageIcon,
// 键盘
DicomOverlayIcon,
// 置顶
UpToTopIcon,
// 置底
DownToBottomIcon,
// 移动
StackedMoveIcon,
// 清空剪切板(刷子)
PaintBrushIcon,
// 坐标轴
ZAxisIcon,
AlignHorizontalLeftIcon,
AlignVerticalCenterIcon,
AlignVerticalTopIcon,
AlignHorizontalCenterIcon,
AlignHorizontalRightIcon,
AlignVerticalBottomIcon,
// 添加文件
DocumentAddIcon,
// 下载文件
DocumentDownloadIcon,
// 预览展示方式
ScaleIcon,
FitToScreenIcon,
FitToHeightIcon,
FitToWidthIcon,
// 成组
Carbon3DCursorIcon,
// 解组
Carbon3DSoftwareIcon,
// 过滤器
FilterIcon,
FilterEditIcon,
// 图层
LaptopIcon
}
// https://www.xicons.org/#/ 还有很多
export const icon = {
ionicons5,
carbon
}

View File

@ -0,0 +1,5 @@
export { setupNaive } from 'PLS/goView/lib/gPlugins//naive'
export { setupDirectives } from 'PLS/goView/lib/gPlugins//directives'
export { setupCustomComponents } from 'PLS/goView/lib/gPlugins//customComponents'
export { icon } from 'PLS/goView/lib/gPlugins//icon'
export { initFunction } from 'PLS/goView/lib/gPlugins//initFunction'

View File

@ -0,0 +1,9 @@
/**
* *
*/
export const initFunction = async () => {
// 捕获全局错误
window.addEventListener("unhandledrejection", event => {
console.warn(`UNHANDLED PROMISE REJECTION: ${event.reason}`);
});
}

View File

@ -0,0 +1,213 @@
import type { App } from 'vue'
import {
create,
NA,
NP,
NH1,
NH2,
NH3,
NH4,
NH5,
NCode,
NCountdown,
NText,
NTime,
NEllipsis,
NConfigProvider,
NMessageProvider,
NDialogProvider,
NGradientText,
NInput,
NImage,
NButton,
NButtonGroup,
NForm,
NFormItem,
NCheckboxGroup,
NCheckbox,
NIcon,
NLayout,
NLayoutHeader,
NLayoutContent,
NLayoutFooter,
NLayoutSider,
NMenu,
NBreadcrumb,
NBreadcrumbItem,
NDropdown,
NSpace,
NTooltip,
NAvatar,
NTabs,
NTab,
NTabPane,
NCard,
NRow,
NCol,
NDrawer,
NDrawerContent,
NDivider,
NSwitch,
NBadge,
NAlert,
NElement,
NTag,
NNotificationProvider,
NNumberAnimation,
NProgress,
NDatePicker,
NGrid,
NGi,
NGridItem,
NList,
NListItem,
NThing,
NDataTable,
NPopover,
NPagination,
NSelect,
NSlider,
NRadioGroup,
NRadio,
NSteps,
NStep,
NInputGroup,
NInputGroupLabel,
NResult,
NDescriptions,
NDescriptionsItem,
NTable,
NInputNumber,
NLoadingBarProvider,
NModal,
NUpload,
NUploadFileList,
NUploadTrigger,
NUploadDragger,
NTree,
NSpin,
NTimeline,
NTimelineItem,
NTimePicker,
NBackTop,
NSkeleton,
NStatistic,
NCarousel,
NScrollbar,
NPopselect,
NCollapse,
NCollapseItem,
NColorPicker,
NWatermark,
NEmpty,
NCollapseTransition
} from 'naive-ui'
const naive = create({
components: [
NA,
NP,
NH1,
NH2,
NH3,
NH4,
NH5,
NCode,
NCountdown,
NText,
NTime,
NEllipsis,
NMessageProvider,
NDialogProvider,
NConfigProvider,
NGradientText,
NInput,
NButton,
NButtonGroup,
NForm,
NFormItem,
NCheckboxGroup,
NCheckbox,
NIcon,
NImage,
NLayout,
NLayoutHeader,
NLayoutContent,
NLayoutFooter,
NLayoutSider,
NMenu,
NBreadcrumb,
NBreadcrumbItem,
NDropdown,
NSpace,
NTooltip,
NAvatar,
NTabs,
NTab,
NTabPane,
NCard,
NRow,
NCol,
NDrawer,
NDrawerContent,
NDivider,
NSwitch,
NBadge,
NAlert,
NElement,
NTag,
NNotificationProvider,
NNumberAnimation,
NProgress,
NDatePicker,
NGrid,
NGi,
NGridItem,
NList,
NListItem,
NThing,
NDataTable,
NPopover,
NPagination,
NSlider,
NSelect,
NRadioGroup,
NRadio,
NSteps,
NStep,
NInputGroup,
NInputGroupLabel,
NResult,
NDescriptions,
NDescriptionsItem,
NTable,
NInputNumber,
NLoadingBarProvider,
NModal,
NUpload,
NUploadFileList,
NUploadTrigger,
NUploadDragger,
NTree,
NSpin,
NTimeline,
NTimelineItem,
NTimePicker,
NBackTop,
NSkeleton,
NStatistic,
NCarousel,
NScrollbar,
NPopselect,
NCollapse,
NCollapseItem,
NColorPicker,
NWatermark,
NEmpty,
NCollapseTransition
]
})
export function setupNaive(app: App<Element>) {
app.use(naive)
}

View File

@ -0,0 +1,57 @@
export const animations = [
{
label: '强调动画',
children: [
{ label: '弹跳', value: 'bounce' },
{ label: '闪烁', value: 'flash' },
{ label: '放大缩小', value: 'pulse' },
{ label: '放大缩小弹簧', value: 'rubberBand' },
{ label: '左右晃动', value: 'headShake' },
{ label: '左右扇形摇摆', value: 'swing' },
{ label: '放大晃动缩小', value: 'tada' },
{ label: '扇形摇摆', value: 'wobble' },
{ label: '左右上下晃动', value: 'jello' },
]
},
{
label: '移入动画',
children: [
{ label: '渐显', value: 'fadeIn' },
{ label: '向右进入', value: 'fadeInLeft' },
{ label: '向左进入', value: 'fadeInRight' },
{ label: '向上进入', value: 'fadeInUp' },
{ label: '向下进入', value: 'fadeInDown' },
{ label: '向右长距进入', value: 'fadeInLeftBig' },
{ label: '向左长距进入', value: 'fadeInRightBig' },
{ label: '向上长距进入', value: 'fadeInUpBig' },
{ label: '向下长距进入', value: 'fadeInDownBig' },
{ label: '旋转进入', value: 'rotateIn' },
{ label: '左顺时针旋转', value: 'rotateInDownLeft' },
{ label: '右逆时针旋转', value: 'rotateInDownRight' },
{ label: '左逆时针旋转', value: 'rotateInUpLeft' },
{ label: '右逆时针旋转', value: 'rotateInUpRight' },
{ label: '弹入', value: 'bounceIn' },
{ label: '向右弹入', value: 'bounceInLeft' },
{ label: '向左弹入', value: 'bounceInRight' },
{ label: '向上弹入', value: 'bounceInUp' },
{ label: '向下弹入', value: 'bounceInDown' },
{ label: '光速从右进入', value: 'lightSpeedInRight' },
{ label: '光速从左进入', value: 'lightSpeedInLeft' },
{ label: '光速从右退出', value: 'lightSpeedOutRight' },
{ label: '光速从左退出', value: 'lightSpeedOutLeft' },
{ label: 'Y轴旋转', value: 'flip' },
{ label: '中心X轴旋转', value: 'flipInX' },
{ label: '中心Y轴旋转', value: 'flipInY' },
{ label: '左长半径旋转', value: 'rollIn' },
{ label: '由小变大进入', value: 'zoomIn' },
{ label: '左变大进入', value: 'zoomInLeft' },
{ label: '右变大进入', value: 'zoomInRight' },
{ label: '向上变大进入', value: 'zoomInUp' },
{ label: '向下变大进入', value: 'zoomInDown' },
{ label: '向右滑动展开', value: 'slideInLeft' },
{ label: '向左滑动展开', value: 'slideInRight' },
{ label: '向上滑动展开', value: 'slideInUp' },
{ label: '向下滑动展开', value: 'slideInDown' }
]
}
]

View File

@ -0,0 +1,111 @@
{
"title": {
"show": true,
"textStyle": {
"color": "#BFBFBF",
"fontSize": 18
},
"subtextStyle": {
"color": "#A2A2A2",
"fontSize": 14
}
},
"xAxis": {
"show": true,
"name": "",
"nameGap": 15,
"nameTextStyle": {
"color": "#B9B8CE",
"fontSize": 12
},
"inverse": false,
"axisLabel": {
"show": true,
"fontSize": 12,
"color": "#B9B8CE",
"rotate": 0
},
"position": "bottom",
"axisLine": {
"show": true,
"lineStyle": {
"color": "#B9B8CE",
"width": 1
},
"onZero": true
},
"axisTick": {
"show": true,
"length": 5
},
"splitLine": {
"show": false,
"lineStyle": {
"color": "#484753",
"width": 1,
"type": "solid"
}
}
},
"yAxis": {
"show": true,
"name": "",
"nameGap": 15,
"nameTextStyle": {
"color": "#B9B8CE",
"fontSize": 12
},
"inverse": false,
"axisLabel": {
"show": true,
"fontSize": 12,
"color": "#B9B8CE",
"rotate": 0
},
"position": "left",
"axisLine": {
"show": true,
"lineStyle": {
"color": "#B9B8CE",
"width": 1
},
"onZero": true
},
"axisTick": {
"show": true,
"length": 5
},
"splitLine": {
"show": true,
"lineStyle": {
"color": "#484753",
"width": 1,
"type": "solid"
}
}
},
"legend": {
"show": true,
"type": "scroll",
"x": "center",
"y": "top",
"icon": "circle",
"orient": "horizontal",
"textStyle": {
"color": "#B9B8CE",
"fontSize": 18
},
"itemHeight": 15,
"itemWidth": 15,
"pageTextStyle": {
"color": "#B9B8CE"
}
},
"grid": {
"show": false,
"left": "10%",
"top": "60",
"right": "10%",
"bottom": "60"
}
}

View File

@ -0,0 +1,76 @@
import customed from './themes/customed.json'
import dark from './themes/dark.json'
import chalk from './themes/chalk.json'
import essos from './themes/essos.json'
import macarons from './themes/macarons.json'
import purplePassion from './themes/purple-passion.json'
import roma from './themes/roma.json'
import shine from './themes/shine.json'
import vintage from './themes/vintage.json'
import walden from './themes/walden.json'
import westeros from './themes/westeros.json'
import wonderland from './themes/wonderland.json'
// 默认主题详细配置
import themeJson from './global.theme.json'
export const chartColors = {
dark,
customed,
macarons,
walden,
purplePassion,
vintage,
chalk,
westeros,
wonderland,
essos,
shine,
roma
}
// 默认主题
export const defaultTheme = 'dark'
// 默认展示的选择器颜色列表
export const swatchesColors = ['#232324', '#2a2a2b', '#313132', '#373739', '#757575', '#e0e0e0', '#eeeeee', '#fafafa']
// 自定义颜色
export type CustomColorsType = {
id: string,
name: string,
color: string[]
}
// 主题色列表, 自定义的颜色使用的是 UUID 作为标识,因为两者数据结构不一致
export type ChartColorsNameType = keyof typeof chartColors
// 渐变主题色列表主色1、主色2、阴影、渐变1、渐变2
export const chartColorsSearch = {
dark: ['#4992ff', '#7cffb2', 'rgba(68, 181, 226, 0.3)', 'rgba(73, 146, 255, 0.5)', 'rgba(124, 255, 178, 0.5)'],
customed: ['#5470c6', '#91cc75', 'rgba(84, 112, 198, 0.5)', 'rgba(84, 112, 198, 0.5)', 'rgba(145, 204, 117, 0.5)'],
macarons: ['#2ec7c9', '#b6a2de', 'rgba(182, 162, 222, 0.3)', 'rgba(46, 199, 201, 0.5)', 'rgba(182, 162, 222, 0.5)'],
walden: ['#3fb1e3', '#6be6c1', 'rgba(68, 181, 226, 0.3)', 'rgba(63, 177, 227, 0.5)', 'rgba(107, 230, 193, 0.5)'],
purplePassion: ['#9b8bba', '#e098c7', 'rgba(182, 162, 222, 0.3)', 'rgba(155, 139, 186, 0.5)', 'rgba(237, 175, 218, 0.5)'],
vintage: ['#d87c7c', '#919e8b', 'rgba(182, 162, 222, 0.3)', 'rgba(216, 124, 124, 0.5)', 'rgba(145, 158, 139, 0.5)'],
chalk: ['#fc97af', '#87f7cf', 'rgba(135, 247, 207, 0.3)', 'rgba(252, 151, 175, 0.5)', 'rgba(135, 247, 207, 0.5)'],
westeros: ['#516b91', '#edafda', 'rgba(81, 107, 145, 0.3)', 'rgba(81, 107, 145, 0.5)', 'rgba(89, 196, 230, 0.5)'],
wonderland: ['#4ea397', '#22c3aa', 'rgba(68, 181, 226, 0.3)', 'rgba(78, 163, 151, 0.5)', 'rgba(34, 195, 170, 0.5)'],
essos: ['#893448', '#d95850', 'rgba(137, 52, 72, 0.3)', 'rgba(137, 52, 72, 0.5)', 'rgba(217, 88, 80, 0.5)'],
shine: ['#c12e34', '#0098d9', 'rgba(137, 52, 72, 0.3)', 'rgba(193, 46, 52, 0.5)', 'rgba(230, 182, 0, 0.5)'],
roma: ['#e01f54', '#5e4ea5', 'rgba(137, 52, 72, 0.3)', 'rgba(224, 31, 84, 0.5)', 'rgba(94, 78, 165, 0.5)'],
}
export type EchartsRenderer = 'svg' | 'canvas';
// 默认主题详细配置
type ThemeJsonType = typeof themeJson
export interface GlobalThemeJsonType extends Partial<ThemeJsonType> {
dataset?: any,
renderer?: EchartsRenderer,
[T:string]: any
}
export const globalThemeJson = {...themeJson, dataset: null, renderer: 'svg' as const }

View File

@ -0,0 +1,13 @@
{
"color": [
"#fc97af",
"#87f7cf",
"#f7f494",
"#72ccff",
"#f7c5a0",
"#d4a4eb",
"#d2f5a6",
"#76f2f2"
],
"name": "粉青"
}

View File

@ -0,0 +1,14 @@
{
"color": [
"#5470c6",
"#91cc75",
"#fac858",
"#ee6666",
"#73c0de",
"#3ba272",
"#fc8452",
"#9a60b4",
"#ea7ccc"
],
"name": "暗淡"
}

View File

@ -0,0 +1,14 @@
{
"color": [
"#4992ff",
"#7cffb2",
"#fddd60",
"#ff6e76",
"#58d9f9",
"#05c091",
"#ff8a45",
"#8d48e3",
"#dd79ff"
],
"name": "明亮"
}

View File

@ -0,0 +1,11 @@
{
"color": [
"#893448",
"#d95850",
"#eb8146",
"#ffb248",
"#f2d643",
"#ebdba4"
],
"name": "橘红"
}

View File

@ -0,0 +1,25 @@
{
"color": [
"#2ec7c9",
"#b6a2de",
"#5ab1ef",
"#ffb980",
"#d87a80",
"#8d98b3",
"#e5cf0d",
"#97b552",
"#95706d",
"#dc69aa",
"#07a2a4",
"#9a7fd1",
"#588dd5",
"#f5994e",
"#c05050",
"#59678c",
"#c9ab00",
"#7eb00a",
"#6f5553",
"#c14089"
],
"name": "马卡龙"
}

View File

@ -0,0 +1,11 @@
{
"color": [
"#9b8bba",
"#e098c7",
"#8fd3e8",
"#71669e",
"#cc70af",
"#7cb4cc"
],
"name": "深紫"
}

View File

@ -0,0 +1,25 @@
{
"color": [
"#e01f54",
"#5e4ea5",
"#f5e8c8",
"#b8d2c7",
"#c6b38e",
"#a4d8c2",
"#f3d999",
"#d3758f",
"#dcc392",
"#2e4783",
"#82b6e9",
"#ff6347",
"#a092f1",
"#0a915d",
"#eaf889",
"#6699FF",
"#ff6666",
"#3cb371",
"#d5b158",
"#38b6b6"
],
"name": "罗马红"
}

View File

@ -0,0 +1,13 @@
{
"color": [
"#c12e34",
"#e6b600",
"#0098d9",
"#2b821d",
"#005eaa",
"#339ca8",
"#cda819",
"#32a487"
],
"name": "深色"
}

View File

@ -0,0 +1,15 @@
{
"color": [
"#d87c7c",
"#919e8b",
"#d7ab82",
"#6e7074",
"#61a0a8",
"#efa18d",
"#787464",
"#cc7e63",
"#724e58",
"#4b565b"
],
"name": "复古"
}

View File

@ -0,0 +1,11 @@
{
"color": [
"#3fb1e3",
"#6be6c1",
"#626c91",
"#a0a7e6",
"#c4ebad",
"#96dee8"
],
"name": "蓝绿"
}

View File

@ -0,0 +1,11 @@
{
"color": [
"#516b91",
"#59c4e6",
"#edafda",
"#93b7e3",
"#a5e7f0",
"#cbb0e3"
],
"name": "灰粉"
}

View File

@ -0,0 +1,11 @@
{
"color": [
"#4ea397",
"#22c3aa",
"#7bd9a5",
"#d0648a",
"#f58db2",
"#f2b3c9"
],
"name": "青草"
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,30 @@
[
{
"CMYK": [62, 0, 21, 16],
"RGB": [81, 214, 169],
"hex": "#51d6a9",
"name": "碧空绿",
"pinyin": "bikonlv"
},
{
"CMYK": [73, 17, 20, 1],
"RGB": [102, 169, 201],
"hex": "#66a9c9",
"name": "涧石蓝",
"pinyin": "jianshilan"
},
{
"CMYK": [4, 13, 67, 0],
"RGB": [248, 223, 114],
"hex": "#f8df72",
"name": "茉莉黄",
"pinyin": "molihuang"
},
{
"CMYK": [76, 51, 0, 0],
"RGB": [60, 126, 255],
"hex": "#3c7eff",
"name": "深海蓝",
"pinyin": "shenhailan"
}
]

View File

@ -0,0 +1,74 @@
import { LangEnum, PreviewScaleEnum } from 'PLS/goView/lib/enums/styleEnum'
import { RequestHttpIntervalEnum } from 'PLS/goView/lib/enums/httpEnum'
import designColor from './designColor.json'
// 默认语言
export const lang = LangEnum.ZH
// 水印文字
export const watermarkText = "GoView 低代码平台"
// 分组名称
export const groupTitle = "分组"
// 主题配置
export const theme = {
// 默认是否开启深色主题
darkTheme: true,
//默认主题色
appTheme: '#51d6a9',
appThemeDetail: null,
}
// 图表初始配置(px)
export const chartInitConfig = {
x: 50,
y: 50,
w: 500,
h: 300,
// 不建议动 offset
offsetX: 0,
offsetY: 0,
}
// dialog 图标的大小
export const dialogIconSize = '20'
// 侧边栏宽度
export const asideWidth = '270'
// 侧边栏折叠后的宽度,支持全部折叠会覆盖为 0
export const asideCollapsedWidth = 60
// 弹窗是否可以通过点击遮罩关闭
export const maskClosable = false
// 全局边框圆角
export const borderRadius = '4px'
// 轮播间隔
export const carouselInterval = 4000
// 工作台大屏背景图片大小限制5M
export const backgroundImageSize = 5
// 预览展示方式
export const previewScaleType = PreviewScaleEnum.FIT
// 编辑工作台同步到 JSON 的轮询间隔5S
export const editToJsonInterval = 5000
// 数据请求间隔
export const requestInterval = 30
// 数据请求间隔单位
export const requestIntervalUnit = RequestHttpIntervalEnum.SECOND
// 工作区域历史记录存储最大数量
export const editHistoryMax = 100
// 拖拽时蒙层的 z-index需比所有图表高
export const canvasModelIndex = 9999
// 框选时蒙层的 z-index需比所有图表高
export const selectBoxIndex = canvasModelIndex + 10

View File

@ -0,0 +1,10 @@
// * 外部路径地址
// 项目文档地址
export const docPath = "https://www.mtruning.club/"
// 项目源码
export const giteeSourceCodePath = "https://gitee.com/dromara/go-view"
// 赞助
export const sponsorPath = "https://www.mtruning.club/sponsor/"

View File

@ -0,0 +1,19 @@
import { SettingStoreEnums, ToolsStatusEnum } from '@/store/modules/settingStore/settingStore.d'
// * 用户配置项
export const systemSetting = {
// 侧边栏折叠是否隐藏全部
[SettingStoreEnums.ASIDE_ALL_COLLAPSED]: true,
// 拖拽页面左侧表单分类只有一项的时候是否隐藏
[SettingStoreEnums.HIDE_PACKAGE_ONE_CATEGORY]: true,
// 切换语言是否进行路由刷新
[SettingStoreEnums.CHANGE_LANG_RELOAD]: false,
// 图表移动时按方向键移动的距离
[SettingStoreEnums.CHART_MOVE_DISTANCE]: 5,
// 图表拖拽时的吸附距离px
[SettingStoreEnums.CHART_ALIGN_RANGE]: 10,
// 图表工具栏状态(侧边工具状态)
[SettingStoreEnums.CHART_TOOLS_STATUS]: ToolsStatusEnum.ASIDE,
// 图表工具栏状态隐藏(刚开始不隐藏)
[SettingStoreEnums.CHART_TOOLS_STATUS_HIDE]: false,
}

View File

@ -0,0 +1,34 @@
import { ref } from 'vue'
import { fetchChartComponent } from '../packages/index'
export const useComInstall = (localStorageInfo: any) => {
const show = ref(false)
// 注册组件(一开始无法获取window['$vue'])
const intervalTiming = setInterval(() => {
if (window['$vue'].component) {
clearInterval(intervalTiming)
const intComponent = (target: any) => {
if (!window['$vue'].component(target.chartConfig.chartKey)) {
window['$vue'].component(target.chartConfig.chartKey, fetchChartComponent(target.chartConfig))
}
}
localStorageInfo.componentList.forEach(async (e: any) => {
if (e.isGroup) {
e.groupList.forEach(groupItem => {
intComponent(groupItem)
})
} else {
intComponent(e)
}
})
show.value = true
}
}, 200)
return {
show
}
}

View File

@ -0,0 +1,218 @@
import throttle from 'lodash/throttle'
// 拆出来是为了更好的分离单独复用
// * 屏幕缩放适配(两边留白)
export const usePreviewFitScale = (
width: number,
height: number,
scaleDom: HTMLElement | null,
callback?: (scale: {
width: number;
height: number;
}) => void
) => {
// * 画布尺寸px
const baseWidth = width
const baseHeight = height
// * 默认缩放值
const scale = {
width: 1,
height: 1,
}
// * 需保持的比例
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
const calcRate = () => {
// 当前屏幕宽高比
const currentRate = parseFloat(
(window.innerWidth / window.innerHeight).toFixed(5)
)
if (scaleDom) {
if (currentRate > baseProportion) {
// 表示更宽
scale.width = parseFloat(((window.innerHeight * baseProportion) / baseWidth).toFixed(5))
scale.height = parseFloat((window.innerHeight / baseHeight).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
} else {
// 表示更高
scale.height = parseFloat(((window.innerWidth / baseProportion) / baseHeight).toFixed(5))
scale.width = parseFloat((window.innerWidth / baseWidth).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
}
if (callback) callback(scale)
}
}
const resize = throttle(() => {
calcRate()
}, 200)
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize)
}
// * 卸载监听
const unWindowResize = () => {
window.removeEventListener('resize', resize)
}
return {
calcRate,
windowResize,
unWindowResize,
}
}
// * X轴撑满Y轴滚动条
export const usePreviewScrollYScale = (
width: number,
height: number,
scaleDom: HTMLElement | null,
callback?: (scale: {
width: number;
height: number;
}) => void
) => {
// * 画布尺寸px
const baseWidth = width
const baseHeight = height
// * 默认缩放值
const scale = {
width: 1,
height: 1,
}
// * 需保持的比例
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
const calcRate = () => {
if (scaleDom) {
scale.height = parseFloat(((window.innerWidth / baseProportion) / baseHeight).toFixed(5))
scale.width = parseFloat((window.innerWidth / baseWidth).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
if (callback) callback(scale)
}
}
const resize = throttle(() => {
calcRate()
}, 200)
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize)
}
// * 卸载监听
const unWindowResize = () => {
window.removeEventListener('resize', resize)
}
return {
calcRate,
windowResize,
unWindowResize,
}
}
// * Y轴撑满X轴滚动条
export const usePreviewScrollXScale = (
width: number,
height: number,
scaleDom: HTMLElement | null,
callback?: (scale: {
width: number;
height: number;
}) => void
) => {
// * 画布尺寸px
const baseWidth = width
const baseHeight = height
// * 默认缩放值
const scale = {
height: 1,
width: 1,
}
// * 需保持的比例
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
const calcRate = () => {
if (scaleDom) {
scale.width = parseFloat(((window.innerHeight * baseProportion) / baseWidth).toFixed(5))
scale.height = parseFloat((window.innerHeight / baseHeight).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
if (callback) callback(scale)
}
}
const resize = throttle(() => {
calcRate()
}, 200)
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize)
}
// * 卸载监听
const unWindowResize = () => {
window.removeEventListener('resize', resize)
}
return {
calcRate,
windowResize,
unWindowResize,
}
}
// * 变形内容,宽高铺满
export const usePreviewFullScale = (
width: number,
height: number,
scaleDom: HTMLElement | null,
callback?: (scale: {
width: number;
height: number;
}) => void
) => {
// * 默认缩放值
const scale = {
width: 1,
height: 1,
}
const calcRate = () => {
if (scaleDom) {
scale.width = parseFloat((window.innerWidth / width).toFixed(5))
scale.height = parseFloat((window.innerHeight / height).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
if (callback) callback(scale)
}
}
const resize = throttle(() => {
calcRate()
}, 200)
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize)
}
// * 卸载监听
const unWindowResize = () => {
window.removeEventListener('resize', resize)
}
return {
calcRate,
windowResize,
unWindowResize,
}
}

View File

@ -0,0 +1,144 @@
import { ref, provide, onMounted, onUnmounted } from 'vue'
import { usePreviewFitScale, usePreviewScrollYScale, usePreviewScrollXScale, usePreviewFullScale } from './usePreviewScale.hook'
import { PreviewScaleEnum } from '../enums/styleEnum'
export const SCALE_KEY = 'scale-value'
export const useScale = (localStorageInfo: any) => {
const entityRef = ref()
const previewRef = ref()
const width = ref(localStorageInfo.editCanvasConfig.width)
const height = ref(localStorageInfo.editCanvasConfig.height)
const scaleRef = ref({ width: 1, height: 1 })
provide(SCALE_KEY, scaleRef)
// 监听鼠标滚轮 +ctrl 键
const useAddWheelHandle = (removeEvent: Function) => {
addEventListener(
'wheel',
(e: any) => {
if (window?.$KeyboardActive?.ctrl) {
e.preventDefault()
e.stopPropagation()
removeEvent()
const transform = previewRef.value?.style.transform
const regRes = transform.match(/scale\((\d+\.?\d*)*/) as RegExpMatchArray
const width = regRes[1]
const previewBoxDom = document.querySelector('.go-preview') as HTMLElement
const entityDom = document.querySelector('.go-preview-entity') as HTMLElement
if (previewBoxDom) {
previewBoxDom.style.overflow = 'unset'
previewBoxDom.style.position = 'absolute'
}
if (entityDom) {
entityDom.style.overflow = 'unset'
}
if (e.wheelDelta > 0) {
const resNum = parseFloat(Number(width).toFixed(2))
previewRef.value.style.transform = `scale(${resNum > 5 ? 5 : resNum + 0.1})`
} else {
const resNum = parseFloat(Number(width).toFixed(2))
previewRef.value.style.transform = `scale(${resNum < 0.2 ? 0.2 : resNum - 0.1})`
}
}
},
{ passive: false }
)
}
const updateScaleRef = (scale: { width: number; height: number }) => {
// 这里需要解构保证赋值给scaleRef的为一个新对象
// 因为scale始终为同一引用
scaleRef.value = { ...scale }
}
// 屏幕适配
onMounted(() => {
switch (localStorageInfo.editCanvasConfig.previewScaleType) {
case PreviewScaleEnum.FIT:
;(() => {
const { calcRate, windowResize, unWindowResize } = usePreviewFitScale(
width.value as number,
height.value as number,
previewRef.value,
updateScaleRef
)
calcRate()
windowResize()
useAddWheelHandle(unWindowResize)
onUnmounted(() => {
unWindowResize()
})
})()
break
case PreviewScaleEnum.SCROLL_Y:
;(() => {
const { calcRate, windowResize, unWindowResize } = usePreviewScrollYScale(
width.value as number,
height.value as number,
previewRef.value,
scale => {
const dom = entityRef.value
dom.style.width = `${width.value * scale.width}px`
dom.style.height = `${height.value * scale.height}px`
updateScaleRef(scale)
}
)
calcRate()
windowResize()
useAddWheelHandle(unWindowResize)
onUnmounted(() => {
unWindowResize()
})
})()
break
case PreviewScaleEnum.SCROLL_X:
;(() => {
const { calcRate, windowResize, unWindowResize } = usePreviewScrollXScale(
width.value as number,
height.value as number,
previewRef.value,
scale => {
const dom = entityRef.value
dom.style.width = `${width.value * scale.width}px`
dom.style.height = `${height.value * scale.height}px`
updateScaleRef(scale)
}
)
calcRate()
windowResize()
useAddWheelHandle(unWindowResize)
onUnmounted(() => {
unWindowResize()
})
})()
break
case PreviewScaleEnum.FULL:
;(() => {
const { calcRate, windowResize, unWindowResize } = usePreviewFullScale(
width.value as number,
height.value as number,
previewRef.value,
updateScaleRef
)
calcRate()
windowResize()
useAddWheelHandle(unWindowResize)
onUnmounted(() => {
unWindowResize()
})
})()
break
}
})
return {
entityRef,
previewRef,
scaleRef
}
}

View File

@ -0,0 +1,8 @@
import { useChartEditStore } from '../../stores/chartEditStore'
const REQUEST_GLOBAL_CONFIG = 'requestGlobalConfig'
// store 相关
export const useStore = (localStorageInfo: any) => {
const chartEditStore = useChartEditStore()
chartEditStore.requestGlobalConfig = localStorageInfo[REQUEST_GLOBAL_CONFIG]
}

View File

@ -0,0 +1,56 @@
export const axisConfig = {
// X轴位置
xposition: [
{
label: '顶部',
value: 'top'
},
{
label: '底部',
value: 'bottom'
}
],
// Y轴位置
yposition: [
{
label: '左侧',
value: 'left'
},
{
label: '右侧',
value: 'right'
}
],
// 线条
splitLint: {
lineStyle: {
type: [
{
label: '实线',
value: 'solid'
},
{
label: '虚线',
value: 'dashed'
},
{
label: '点线',
value: 'dotted'
}
]
}
},
// 视觉映射
visualMap: {
orient: [
{
label: '竖直',
value: 'vertical'
},
{
label: '水平',
value: 'horizontal'
}
]
}
}

View File

@ -0,0 +1,4 @@
export * from './axis'
export * from './line'
export * from './label'
export * from './legend'

View File

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

View File

@ -0,0 +1,70 @@
export const legendConfig = {
// X轴位置
lengendX: [
{
label: '靠左',
value: 'left'
},
{
label: '居中',
value: 'center'
},
{
label: '靠右',
value: 'right'
}
],
// y轴位置
lengendY: [
{
label: '靠上',
value: 'top'
},
{
label: '居中',
value: 'center'
},
{
label: '靠下',
value: 'bottom'
}
],
// 排列方向
orient: [
{
label: '水平',
value: 'horizontal'
},
{
label: '垂直',
value: 'vertical'
}
],
// 形状
shape: [
{
label: '圆形',
value: 'circle'
},
{
label: '方形',
value: 'rect'
},
{
label: '圆角方形',
value: 'roundRect'
},
{
label: '三角形',
value: 'triangle'
},
{
label: '钢笔形',
value: 'pin'
},
{
label: '箭头形',
value: 'arrow'
}
]
}

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