├── .browserslistrc
├── .npmignore
├── public
├── favicon.ico
└── index.html
├── postcss.config.js
├── preview
├── favicon.ico
├── static
│ ├── img
│ │ ├── ve-bar.fc0a17e5.png
│ │ ├── ve-map.ccf2219e.png
│ │ ├── ve-pie.987b8426.png
│ │ ├── ve-line.75126573.png
│ │ ├── ve-radar.2f5b69a2.png
│ │ └── ve-histogram.0683a6c8.png
│ ├── fonts
│ │ ├── iconfont.2b3196f7.ttf
│ │ ├── iconfont.abe346b2.eot
│ │ ├── iconfont.ac59ffae.woff
│ │ ├── element-icons.535877f5.woff
│ │ └── element-icons.732389de.ttf
│ └── js
│ │ ├── chunk-2d0c4a47.0e8656d7.js
│ │ ├── chunk-95354e52.42529e2d.js
│ │ └── app.6a3a718f.js
└── index.html
├── src
├── assets
│ └── images
│ │ ├── dot.png
│ │ ├── ve-bar.png
│ │ ├── ve-map.png
│ │ ├── ve-pie.png
│ │ ├── ve-line.png
│ │ ├── ve-radar.png
│ │ └── ve-histogram.png
├── utils
│ ├── deepClone.js
│ ├── render.js
│ ├── defaultColors.js
│ ├── db.js
│ ├── arr-utils.js
│ ├── formatData.js
│ ├── geoCoordMap.js
│ └── database.js
├── App.vue
├── components
│ ├── board
│ │ ├── options
│ │ │ ├── gui-colors.vue
│ │ │ ├── gui-inline.vue
│ │ │ ├── gui-field.vue
│ │ │ ├── gui-group.vue
│ │ │ └── gui-wrap.vue
│ │ ├── header
│ │ │ └── index.vue
│ │ ├── canvas
│ │ │ ├── components
│ │ │ │ └── edit-slider.vue
│ │ │ └── index.vue
│ │ ├── coverage
│ │ │ └── index.vue
│ │ ├── index.vue
│ │ └── context-menu
│ │ │ └── index.vue
│ ├── drop
│ │ └── drop-panel.vue
│ ├── preview
│ │ └── preview-box.vue
│ ├── drag
│ │ ├── DragList.vue
│ │ └── DragItem.vue
│ └── charts
│ │ └── charts-factory.vue
├── styles
│ ├── index.styl
│ ├── modules
│ │ ├── preview.styl
│ │ ├── home.styl
│ │ └── admin.styl
│ ├── common
│ │ ├── base.styl
│ │ └── var.styl
│ └── board
│ │ ├── context-menu.styl
│ │ ├── canvas.styl
│ │ ├── edit-slider.styl
│ │ ├── coverage.styl
│ │ ├── header-box.styl
│ │ ├── options.styl
│ │ └── transform-block.styl
├── store
│ ├── index.js
│ ├── getters.js
│ └── modules
│ │ ├── app.js
│ │ └── canvasMaps.js
├── router
│ ├── routes.js
│ └── index.js
├── api
│ ├── app
│ │ └── app-request.js
│ ├── canvasMaps
│ │ └── canvas-maps-request.js
│ ├── api_request.js
│ └── datastore.js
├── main.js
├── config
│ ├── board.js
│ ├── components
│ │ ├── line.json
│ │ └── test.json
│ └── navigate.js
└── views
│ ├── home.vue
│ ├── screen.vue
│ └── admin.vue
├── docs
├── .vuepress
│ ├── public
│ │ ├── hero.jpg
│ │ └── favicon.png
│ ├── styles
│ │ └── palette.styl
│ └── config.js
├── README.md
└── guide
│ └── index.md
├── .editorconfig
├── babel.config.js
├── .gitignore
├── .eslintrc.js
├── README.md
├── vue.config.js
├── LICENSE
└── package.json
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .*
2 | *.md
3 | *.yml
4 | build/
5 | node_modules/
6 | test/
7 | gulpfile.js
8 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangbin3162/bin-data/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | autoprefixer: {}
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/preview/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangbin3162/bin-data/HEAD/preview/favicon.ico
--------------------------------------------------------------------------------
/src/assets/images/dot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangbin3162/bin-data/HEAD/src/assets/images/dot.png
--------------------------------------------------------------------------------
/src/assets/images/ve-bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangbin3162/bin-data/HEAD/src/assets/images/ve-bar.png
--------------------------------------------------------------------------------
/src/assets/images/ve-map.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangbin3162/bin-data/HEAD/src/assets/images/ve-map.png
--------------------------------------------------------------------------------
/src/assets/images/ve-pie.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangbin3162/bin-data/HEAD/src/assets/images/ve-pie.png
--------------------------------------------------------------------------------
/src/utils/deepClone.js:
--------------------------------------------------------------------------------
1 | export function deepClone (obj) {
2 | return JSON.parse(JSON.stringify(obj))
3 | }
4 |
--------------------------------------------------------------------------------
/docs/.vuepress/public/hero.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangbin3162/bin-data/HEAD/docs/.vuepress/public/hero.jpg
--------------------------------------------------------------------------------
/src/assets/images/ve-line.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangbin3162/bin-data/HEAD/src/assets/images/ve-line.png
--------------------------------------------------------------------------------
/src/assets/images/ve-radar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangbin3162/bin-data/HEAD/src/assets/images/ve-radar.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangbin3162/bin-data/HEAD/docs/.vuepress/public/favicon.png
--------------------------------------------------------------------------------
/src/assets/images/ve-histogram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangbin3162/bin-data/HEAD/src/assets/images/ve-histogram.png
--------------------------------------------------------------------------------
/preview/static/img/ve-bar.fc0a17e5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangbin3162/bin-data/HEAD/preview/static/img/ve-bar.fc0a17e5.png
--------------------------------------------------------------------------------
/preview/static/img/ve-map.ccf2219e.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangbin3162/bin-data/HEAD/preview/static/img/ve-map.ccf2219e.png
--------------------------------------------------------------------------------
/preview/static/img/ve-pie.987b8426.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangbin3162/bin-data/HEAD/preview/static/img/ve-pie.987b8426.png
--------------------------------------------------------------------------------
/preview/static/img/ve-line.75126573.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangbin3162/bin-data/HEAD/preview/static/img/ve-line.75126573.png
--------------------------------------------------------------------------------
/preview/static/img/ve-radar.2f5b69a2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangbin3162/bin-data/HEAD/preview/static/img/ve-radar.2f5b69a2.png
--------------------------------------------------------------------------------
/preview/static/fonts/iconfont.2b3196f7.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangbin3162/bin-data/HEAD/preview/static/fonts/iconfont.2b3196f7.ttf
--------------------------------------------------------------------------------
/preview/static/fonts/iconfont.abe346b2.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangbin3162/bin-data/HEAD/preview/static/fonts/iconfont.abe346b2.eot
--------------------------------------------------------------------------------
/preview/static/fonts/iconfont.ac59ffae.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangbin3162/bin-data/HEAD/preview/static/fonts/iconfont.ac59ffae.woff
--------------------------------------------------------------------------------
/preview/static/img/ve-histogram.0683a6c8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangbin3162/bin-data/HEAD/preview/static/img/ve-histogram.0683a6c8.png
--------------------------------------------------------------------------------
/preview/static/fonts/element-icons.535877f5.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangbin3162/bin-data/HEAD/preview/static/fonts/element-icons.535877f5.woff
--------------------------------------------------------------------------------
/preview/static/fonts/element-icons.732389de.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangbin3162/bin-data/HEAD/preview/static/fonts/element-icons.732389de.ttf
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.{js,jsx,ts,tsx,vue}]
2 | indent_style = space
3 | indent_size = 2
4 | trim_trailing_whitespace = true
5 | insert_final_newline = true
6 |
--------------------------------------------------------------------------------
/docs/.vuepress/styles/palette.styl:
--------------------------------------------------------------------------------
1 | // showing default values
2 | $accentColor = #409EFF
3 | $textColor = #2c3e50
4 | $borderColor = #eaecef
5 | $codeBgColor = #282c34
6 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
12 |
--------------------------------------------------------------------------------
/src/components/board/options/gui-colors.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
10 |
--------------------------------------------------------------------------------
/src/styles/index.styl:
--------------------------------------------------------------------------------
1 | // 样式引入,所有前缀遵循dv- 及data view缩写,样式单独引入后期可方便打包
2 | @import "./common/base.styl"
3 | @import "./modules/home.styl"
4 | @import "./modules/admin.styl"
5 | @import "./modules/preview.styl"
6 |
--------------------------------------------------------------------------------
/src/utils/render.js:
--------------------------------------------------------------------------------
1 | export default {
2 | name: 'RenderCell',
3 | functional: true,
4 | props: {
5 | render: Function
6 | },
7 | render: (h, ctx) => {
8 | return ctx.props.render(h)
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/app'
4 | ],
5 | plugins: [
6 | [
7 | 'component',
8 | {
9 | 'libraryName': 'element-ui',
10 | 'styleLibraryName': 'theme-chalk'
11 | }
12 | ]
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/src/utils/defaultColors.js:
--------------------------------------------------------------------------------
1 | export const DEFAULT_COLORS = [
2 | '#60b8f6', '#55da8d', '#ffcc41',
3 | '#ba5eed', '#ff6e8c', '#1f9bff',
4 | '#e1017e', '#e7641c', '#c1df05',
5 | '#00acc5', '#de0029', '#02af3b',
6 | '#c23531', '#2f4554', '#ca8622',
7 | '#7ec720', '#3c117c', '#0168b3'
8 | ]
9 |
--------------------------------------------------------------------------------
/src/styles/modules/preview.styl:
--------------------------------------------------------------------------------
1 | .dv-screen {
2 | height: 100%;
3 | width: 100%;
4 | .canvas-panel {
5 | position: relative;
6 | .preview-box {
7 | position: absolute;
8 | }
9 | }
10 | }
11 |
12 | .dv-screen .bin-scrollbar__wrap {
13 | overflow-x: hidden;
14 | }
15 |
--------------------------------------------------------------------------------
/src/components/board/options/gui-inline.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
15 |
--------------------------------------------------------------------------------
/src/styles/common/base.styl:
--------------------------------------------------------------------------------
1 | @import "var.styl"
2 | #app {
3 | height: 100%;
4 | color: $color-text-primary;
5 | font-size: 14px;
6 | background-color: $color-main;
7 | }
8 | * {
9 | margin: 0;
10 | padding: 0;
11 | border: 0;
12 | font-size: 100%;
13 | vertical-align: baseline;
14 | }
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw*
22 |
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 | import app from './modules/app'
4 | import canvasMaps from './modules/canvasMaps'
5 | import getters from './getters'
6 |
7 | Vue.use(Vuex)
8 |
9 | export default new Vuex.Store({
10 | modules: {
11 | app, canvasMaps
12 | },
13 | getters
14 | })
15 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | home: true
3 | heroImage: /hero.jpg
4 | actionText: 快速上手 →
5 | actionLink: /guide/
6 | features:
7 | - title: 业务提炼
8 | details: 对业务进行封装,提炼基础功能
9 | - title: 组件
10 | details: 简洁的代码、目录、格式,封装部分可复用组件
11 | - title: 技术栈
12 | details: 使用 vue/vuex/vue-router/bin-ui 等前端技术
13 | footer: MIT Licensed | Copyright © 2019-present wang bin
14 | ---
15 |
--------------------------------------------------------------------------------
/src/components/board/options/gui-field.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{label}}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
17 |
--------------------------------------------------------------------------------
/src/utils/db.js:
--------------------------------------------------------------------------------
1 | import low from 'lowdb'
2 | import LocalStorage from 'lowdb/adapters/LocalStorage'
3 | import database from './database'
4 |
5 | const adapter = new LocalStorage('bin-data')
6 | const db = low(adapter)
7 |
8 | db
9 | .defaults(database)
10 | .write()
11 |
12 | // db.set('canvasMaps', database.canvasMaps).write()
13 |
14 | export default db
15 |
--------------------------------------------------------------------------------
/src/components/board/options/gui-group.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{groupName}}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
17 |
--------------------------------------------------------------------------------
/src/store/getters.js:
--------------------------------------------------------------------------------
1 | const getters = {
2 | pageSettings: state => state.app.pageSettings,
3 | // 画布缩放
4 | canvasRange: state => state.app.canvasRange,
5 | // 参数面板展开
6 | optionsExpand: state => state.app.optionsExpand,
7 | // 画布映射数组
8 | canvasMap: state => state.canvasMaps.canvasMap,
9 | // 当前选中的
10 | currentSelected: state => state.canvasMaps.singleSelected,
11 | // 右键菜单信息
12 | contextMenuInfo: state => state.canvasMaps.contextMenuInfo
13 | }
14 |
15 | export default getters
16 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | 'extends': [
7 | 'plugin:vue/essential',
8 | '@vue/standard'
9 | ],
10 | rules: {
11 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
12 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
13 | 'indent': 'off',
14 | 'space-before-function-paren': 'off',
15 | 'no-unused-vars': 'off'
16 | },
17 | parserOptions: {
18 | parser: 'babel-eslint'
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/router/routes.js:
--------------------------------------------------------------------------------
1 | import Home from '../views/home'
2 |
3 | let routes = [
4 | {
5 | path: '/',
6 | redirect: '/home',
7 | component: Home,
8 | children: [{
9 | path: 'home',
10 | name: 'home',
11 | component: Home
12 | }]
13 | },
14 | {
15 | path: '/admin/:id',
16 | name: 'admin',
17 | component: () => import('../views/admin')
18 | },
19 | {
20 | path: '/screen/:id',
21 | name: 'screen',
22 | component: () => import('../views/screen')
23 | }
24 | ]
25 |
26 | export default routes
27 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueRouter from 'vue-router'
3 | import store from '../store/index'
4 | // 路由数据
5 | import routes from './routes'
6 |
7 | import BinUI from 'bin-ui'
8 |
9 | Vue.use(BinUI)
10 |
11 | Vue.use(VueRouter)
12 |
13 | // 导出路由 在 main.js 里使用
14 | const router = new VueRouter({
15 | base: process.env.BASE_URL,
16 | routes
17 | })
18 |
19 | router.beforeEach((to, from, next) => {
20 | BinUI.LoadingBar.start()
21 | store.dispatch('SingleSelected', null)
22 | next()
23 | })
24 | router.afterEach(() => {
25 | BinUI.LoadingBar.done()
26 | })
27 |
28 | export default router
29 |
--------------------------------------------------------------------------------
/src/styles/common/var.styl:
--------------------------------------------------------------------------------
1 | // 定义基本色系
2 | $color-main = #171b22
3 | $color-primary = #00baff
4 | $color-blue = #1a8ae4
5 | $color-text-primary = #ffffff
6 | $color-text-info = #bcc9d4
7 | $color-linear-gradient = #00baff
8 |
9 | $color-admin-main = #222528
10 | $color-admin-ctrl = #1b1f25
11 | $color-admin-ctrl-header = #2e343c
12 | $color-admin-options-dark = #0e1013
13 | $color-admin-options-hover = #212631
14 | $color-admin-options-bg = #1b1f25
15 | $color-admin-canvas = #2a2e33
16 |
17 | $color-admin-context-menu = #27343e
18 | $color-admin-context-menu-color = #bcc9d4
19 |
20 | //指示线
21 | $color-navigator-line = #05ddff
22 |
--------------------------------------------------------------------------------
/src/api/app/app-request.js:
--------------------------------------------------------------------------------
1 | // import request from '../api_request'
2 | import * as api from '../datastore'
3 |
4 | // 获取页面参数信息
5 | export function getPageSettings () {
6 | return api.getPageSettings()
7 | // return request({
8 | // url: '/getPageSettings',
9 | // method: 'get'
10 | // })
11 | }
12 |
13 | // 设置页面参数信息
14 | export function setPageSettings (setting) {
15 | return api.setPageSettings(setting)
16 | }
17 |
18 | // 重置页面参数配置
19 | export function resetPageSettings () {
20 | return api.resetPageSettings()
21 | }
22 |
23 | // 初始化所有参数配置
24 | export function initLocalData () {
25 | return api.initLocalData()
26 | }
27 |
--------------------------------------------------------------------------------
/docs/guide/index.md:
--------------------------------------------------------------------------------
1 | # 入门
2 |
3 | 本项目是基于 Vue2.6,配合使用 [bin-ui](https://github.com/wangbin3162/bin-ui/) 作为组件库来进行搭建,
4 | 参考阿里DataV来实现的一套数据可视化配置系统,主要实现对百度地图的多拽生成和动态配置。
5 |
6 | 现已实现一版简易版,包括折线图,中国地图,柱状图,饼状图,条形图,雷达图等6个图标的样式配置和数据配置,后续继续进行完善补充,现发布第一版
7 | 文档及预览,后续持续更新...
8 |
9 | ## 功能概述
10 |
11 | - lowdb实现本地数据配置,后续实现持久化更新
12 | - 初始化数据库后可进行拖拽移动
13 | - 图表可以动态进行样式设置和数据设置
14 |
15 |
16 | 注:仅列举部分组件和功能
17 |
18 |
19 | ## 安装
20 |
21 | ```bash
22 | # 克隆项目
23 | git clone https://github.com/wangbin3162/bin-data.git
24 |
25 | # 安装依赖
26 | npm install
27 |
28 | # 本地开发 启动项目
29 | npm run serve
30 | # OR vue ui 图形化界面启动
31 | vue ui
32 | ```
33 |
34 | 文档持续更新中...
35 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # bin-data
2 |
3 | [预览](https://wangbin3162.github.io/bin-data/)
4 |
5 | # 入门
6 |
7 | 本项目是基于 Vue2.6,配合使用 [bin-ui](https://github.com/wangbin3162/bin-ui/) 作为组件库来进行搭建,
8 | 参考阿里DataV来实现的一套数据可视化配置系统,主要实现对百度地图的多拽生成和动态配置。
9 |
10 | 现已实现一版简易版,包括折线图,中国地图,柱状图,饼状图,条形图,雷达图等6个图标的样式配置和数据配置,后续继续进行完善补充,现发布第一版
11 | 文档及预览,后续持续更新...
12 |
13 | ## 功能概述
14 |
15 | - lowdb实现本地数据配置,后续实现持久化更新
16 | - 初始化数据库后可进行拖拽移动
17 | - 图表可以动态进行样式设置和数据设置
18 |
19 |
20 | 注:仅列举部分组件和功能
21 |
22 |
23 | ## 安装
24 |
25 | ```bash
26 | # 克隆项目
27 | git clone https://github.com/wangbin3162/bin-data.git
28 |
29 | # 安装依赖
30 | npm install
31 |
32 | # 本地开发 启动项目
33 | npm run serve
34 | # OR vue ui 图形化界面启动
35 | vue ui
36 | ```
37 |
38 | 文档持续更新中...
39 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 | import router from './router'
4 | import store from './store'
5 | import { Button, ColorPicker, Select, Option } from 'element-ui'
6 | import BinUI from 'bin-ui'
7 | import VCharts from 'v-charts'
8 | import 'bin-ui/lib/styles/index.css'
9 | import './styles/index.styl'
10 |
11 | // element-ui 局部引用
12 | Vue.use(Button)
13 | Vue.use(ColorPicker)
14 | Vue.use(Select)
15 | Vue.use(Option)
16 |
17 | Vue.use(BinUI)
18 | Vue.use(VCharts)
19 |
20 | Vue.prototype.$EventBus = new Vue()
21 | Vue.prototype.$base = process.env.NODE_ENV === 'production' ? '/bin-data-site' : ''
22 |
23 | new Vue({
24 | router,
25 | store,
26 | render: h => h(App)
27 | }).$mount('#app')
28 |
--------------------------------------------------------------------------------
/src/config/board.js:
--------------------------------------------------------------------------------
1 | // 画板默认布局配置
2 | export default {
3 | // 编辑器功能:头部组件
4 | header: {
5 | // 标题配置
6 | title: {
7 | text: '当前工作空间'
8 | },
9 | // 该功能数据源
10 | data: [],
11 | // 初始化数据
12 | initData: []
13 | },
14 | // 左侧功能栏
15 | coverage: {
16 | // 是否启用该功能,true: 启用 false: 不启用
17 | enable: true,
18 | // 标题配置
19 | title: {
20 | enable: true,
21 | text: '图层'
22 | },
23 | // 样式
24 | style: {
25 | width: '180px',
26 | flex: '0 0 180px'
27 | }
28 | },
29 | // 表单元素配置组件
30 | options: {
31 | // 标题配置
32 | title: {
33 | enable: true,
34 | text: '页面设置'
35 | },
36 | style: {
37 | width: '300px'
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/styles/board/context-menu.styl:
--------------------------------------------------------------------------------
1 | @import "../common/var.styl"
2 | .dv-context-menu {
3 | position: fixed;
4 | z-index: 9999;
5 | background: $color-admin-context-menu;
6 | color: $color-admin-context-menu-color;
7 | user-select: none;
8 | .context-menu-item {
9 | padding: 0 6px;
10 | line-height: 28px;
11 | height: 28px;
12 | border-left: 2px solid transparent;
13 | cursor: pointer;
14 | overflow: hidden;
15 | padding-right: 3em;
16 | display: flex;
17 | .iconfont {
18 | margin-right: 3px;
19 | line-height: 28px;
20 | width: 16px;
21 | }
22 | &:hover {
23 | background-color: #1d262e;
24 | color: #00baff;
25 | border-left: 2px solid #00baff;
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | // 配置路径别名
2 | var path = require('path')
3 |
4 | function resolve (dir) {
5 | return path.join(__dirname, dir)
6 | }
7 |
8 | module.exports = {
9 | // 配置基础链接地址,根据发布环境添加
10 | publicPath: process.env.NODE_ENV === 'production'
11 | ? ''
12 | : '/',
13 | outputDir: 'preview',
14 | // dev跨域问题
15 | // devServer: {
16 | // proxy: {
17 | // '/admin': { target: 'http://localhost:8088/cms' }
18 | // }
19 | // },
20 | productionSourceMap: false,
21 | lintOnSave: process.env.NODE_ENV !== 'production',
22 | assetsDir: 'static',
23 | filenameHashing: true, // 发布打包文件是否有哈希后缀
24 | chainWebpack: config => {
25 | config.resolve.alias
26 | .set('@', resolve('src')) // key,value自行定义,比如.set('@@', resolve('src/components'))
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/utils/arr-utils.js:
--------------------------------------------------------------------------------
1 | export function toFirst (fieldData, index) {
2 | let arr = [...fieldData]
3 | if (index !== 0) {
4 | arr.unshift(arr.splice(index, 1)[0])
5 | }
6 | return arr
7 | }
8 |
9 | export function toLast (fieldData, index) {
10 | let arr = [...fieldData]
11 | if (index !== arr.length - 1) {
12 | arr.push(arr.shift())
13 | }
14 | return arr
15 | }
16 |
17 | export function upGo (fieldData, index) {
18 | let arr = [...fieldData]
19 | if (index !== 0) {
20 | arr[index] = arr.splice(index - 1, 1, arr[index])[0]
21 | }
22 | return arr
23 | }
24 |
25 | export function downGo (fieldData, index) {
26 | let arr = [...fieldData]
27 | if (index !== arr.length - 1) {
28 | arr[index] = arr.splice(index + 1, 1, arr[index])[0]
29 | }
30 | return arr
31 | }
32 |
--------------------------------------------------------------------------------
/src/store/modules/app.js:
--------------------------------------------------------------------------------
1 | const app = {
2 | state: {
3 | pageSettings: { width: 1920, height: 1080, backgroundColor: '#0d2a42', gridStep: 1 },
4 | // 状态数据
5 | canvasRange: 0, // 画布缩放
6 | optionsExpand: true // 参数面板打开关闭
7 | },
8 | mutations: {
9 | SET_CANVAS_RANGE: (state, val) => {
10 | state.canvasRange = val
11 | },
12 | SET_OPTIONS_EXPAND: (state) => {
13 | state.optionsExpand = !state.optionsExpand
14 | },
15 | SET_PAGE_SETTING: (state, setting) => {
16 | state.pageSettings = { ...setting }
17 | }
18 | },
19 | actions: {
20 | SetCanvasRange: ({ commit }, val) => {
21 | commit('SET_CANVAS_RANGE', val)
22 | },
23 | ToggleOptionsExpand: ({ commit }) => {
24 | commit('SET_OPTIONS_EXPAND')
25 | },
26 | SetPageSettings: ({ commit }, setting) => {
27 | commit('SET_PAGE_SETTING', setting)
28 | }
29 | }
30 | }
31 |
32 | export default app
33 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | bin-data
9 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/styles/board/canvas.styl:
--------------------------------------------------------------------------------
1 | .canvas-main {
2 | position: relative;
3 | width: 100%;
4 | height: 100%;
5 | overflow: hidden;
6 | user-select: none;
7 | background: #26282d url('../assets/images/dot.png') repeat;
8 | .canvas-panel-wrap {
9 | width: 100%;
10 | height: calc(100% - 30px);
11 | overflow: hidden;
12 | position: relative;
13 | .screen-shot {
14 | position: relative;
15 | .canvas-panel {
16 | position: absolute;
17 | transform-origin: 0 0;
18 | top: 60px;
19 | left: 60px;
20 | transition: .2s all ease-in-out;
21 | background-size: cover, contain;
22 | background-position: center, right bottom;
23 | background-repeat: no-repeat, no-repeat;
24 | box-shadow: rgba(0, 0, 0, .5) 0 0 30px 0;
25 | .drop-panel {
26 | width: 100%;
27 | height: 100%;
28 | }
29 | }
30 | }
31 | }
32 | }
33 |
34 | // 需要覆盖bin-ui的样式
35 | .canvas-panel-wrap .bin-scrollbar__wrap {
36 | overflow-x: hidden;
37 | }
38 |
--------------------------------------------------------------------------------
/docs/.vuepress/config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | title: '[bin-data]说明文档',
3 | description: '基于bin-ui echarts的数据可视化平台',
4 | // 注入到当前页面的 HTML 中的标签
5 | head: [
6 | ['link', { rel: 'icon', href: '/favicon.png' }], // 增加一个自定义的 favicon(网页标签的图标)
7 | ],
8 | base: '/docs/bin-data/',
9 | markdown: {
10 | lineNumbers: true // 代码块显示行号
11 | },
12 | themeConfig: {
13 | sidebarDepth: 2, // e'b将同时提取markdown中h2 和 h3 标题,显示在侧边栏上。
14 | lastUpdated: 'Last Updated', // 文档更新时间:每个文件git最后提交的时间
15 | nav: [
16 | { text: '指南', link: '/guide/' },
17 | { text: 'bin-ui', link: 'https://wangbin3162.github.io/docs/bin-ui/' },
18 | { text: '预览', link: 'https://wangbin3162.github.io/preview/bin-data/' },
19 | { text: 'GitHub', link: 'https://github.com/wangbin3162/bin-data' }
20 | ],
21 | sidebar: {
22 | // 第一组侧边栏
23 | '/guide/': [
24 | {
25 | collapsable: false,
26 | children: [
27 | ['/guide/', '入门']
28 | ]
29 | }
30 | ]
31 | }
32 | }
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/src/components/drop/drop-panel.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
11 |
39 |
--------------------------------------------------------------------------------
/src/config/components/line.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "x": "1/1",
4 | "y": 375,
5 | "s": "系列1"
6 | },
7 | {
8 | "x": "1/1",
9 | "y": 123,
10 | "s": "系列2"
11 | },
12 | {
13 | "x": "1/2",
14 | "y": 200,
15 | "s": "系列1"
16 | },
17 | {
18 | "x": "1/2",
19 | "y": 122,
20 | "s": "系列2"
21 | },
22 | {
23 | "x": "1/3",
24 | "y": 25,
25 | "s": "系列1"
26 | },
27 | {
28 | "x": "1/3",
29 | "y": 231,
30 | "s": "系列2"
31 | },
32 | {
33 | "x": "1/4",
34 | "y": 190,
35 | "s": "系列1"
36 | },
37 | {
38 | "x": "1/4",
39 | "y": 11,
40 | "s": "系列2"
41 | },
42 | {
43 | "x": "1/5",
44 | "y": 90,
45 | "s": "系列1"
46 | },
47 | {
48 | "x": "1/5",
49 | "y": 134,
50 | "s": "系列2"
51 | },
52 | {
53 | "x": "1/6",
54 | "y": 233,
55 | "s": "系列1"
56 | },
57 | {
58 | "x": "1/6",
59 | "y": 155,
60 | "s": "系列2"
61 | },
62 | {
63 | "x": "1/7",
64 | "y": 120,
65 | "s": "系列1"
66 | },
67 | {
68 | "x": "1/7",
69 | "y": 333,
70 | "s": "系列2"
71 | }
72 | ]
73 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | Copyright (c) 2019 bin-data/wang bin
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of
5 | this software and associated documentation files (the “Software”), to deal in the
6 | Software without restriction, including without limitation the rights to use,
7 | copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8 | the Software, and to permit persons to whom the Software is furnished to do so,
9 | subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in all
12 | copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
18 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
19 | THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/src/components/preview/preview-box.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
49 |
--------------------------------------------------------------------------------
/src/styles/board/edit-slider.styl:
--------------------------------------------------------------------------------
1 | @import "../common/var.styl"
2 | // 下方缩放条
3 | .board-edit-slider {
4 | background: $color-admin-main;
5 | height: 30px;
6 | width: 100%;
7 | display: flex;
8 | align-items: center;
9 | justify-content: flex-end;
10 | position: absolute;
11 | right: 0;
12 | bottom: 0;
13 | z-index: 99;
14 | .label {
15 | font-size: 12px;
16 | line-height: 18px;
17 | padding: 0 5px;
18 | color: $color-text-info;
19 | }
20 | .data-slider {
21 | display: flex;
22 | right: 4px;
23 | align-items: center;
24 | .input-range {
25 | cursor: pointer;
26 | height: 2px;
27 | -webkit-appearance: none;
28 | box-sizing: border-box;
29 | outline: 0;
30 | margin: 0;
31 | display: inline-block;
32 | &::-webkit-slider-thumb {
33 | -webkit-appearance: none; /*清除系统默认样式*/
34 | height: 12px; /*拖动块高度*/
35 | width: 12px; /*拖动块宽度*/
36 | background: #fff; /*拖动块背景*/
37 | border: solid 1px #202020; /*设置边框*/
38 | }
39 | }
40 | .iconfont {
41 | color: $color-text-info;
42 | font-size: 18px;
43 | margin: 0 8px;
44 | &.zoom-out {
45 | cursor: zoom-out;
46 | }
47 | &.zoom-in {
48 | cursor: zoom-in;
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/utils/formatData.js:
--------------------------------------------------------------------------------
1 | // 处理图表数据源,换算为v-charts数据结构
2 | import { geoCoordMap } from './geoCoordMap'
3 |
4 | export function formatData (source) {
5 | const apiData = {
6 | columns: [],
7 | rows: []
8 | }
9 | const map = new Map()
10 |
11 | source.forEach(item => {
12 | let obj = {}
13 | if (item.x) {
14 | apiData.columns[0] = 'x'
15 | obj['x'] = item.x
16 | }
17 | // 如果系列值存在且column中不包含这个系列则增加一个系列
18 | if (item.s) {
19 | if (!apiData.columns.includes(item.s)) {
20 | apiData.columns.push(item.s)
21 | }
22 | obj[item.s] = item.y
23 | } else {
24 | apiData.columns[1] = 's'
25 | obj['s'] = item.y
26 | }
27 | if (map.has(item.x)) {
28 | let temp = Object.assign(map.get(item.x), obj)
29 | map.set(item.x, temp)
30 | } else {
31 | map.set(item.x, obj)
32 | }
33 | })
34 | apiData.rows = [...map.values()]
35 | return apiData
36 | }
37 |
38 | export function convertData (data) {
39 | let res = []
40 | for (let i = 0; i < data.length; i++) {
41 | let geoCoord = geoCoordMap[data[i].name]
42 | if (geoCoord) {
43 | res.push({
44 | name: data[i].name,
45 | value: geoCoord.concat(data[i].value),
46 | selected: false
47 | })
48 | }
49 | }
50 | return res
51 | }
52 |
--------------------------------------------------------------------------------
/preview/index.html:
--------------------------------------------------------------------------------
1 | bin-data
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bin-data",
3 | "version": "0.1.0",
4 | "description": "大数据基础框架",
5 | "keywords": [
6 | "bin-ui",
7 | "bin",
8 | "ui",
9 | "vue",
10 | "vue",
11 | "components"
12 | ],
13 | "author": "wang bin",
14 | "files": [
15 | "lib",
16 | "src"
17 | ],
18 | "private": false,
19 | "license": "MIT",
20 | "scripts": {
21 | "serve": "vue-cli-service serve",
22 | "build": "vue-cli-service build",
23 | "lint": "vue-cli-service lint",
24 | "dev:doc": "vuepress dev docs",
25 | "build:doc": "vuepress build docs"
26 | },
27 | "dependencies": {
28 | "axios": "^0.19.0",
29 | "bin-ui": "^2.0.2",
30 | "core-js": "^2.6.5",
31 | "echarts": "^4.2.1",
32 | "element-ui": "^2.9.1",
33 | "lodash": "^4.17.11",
34 | "lowdb": "^1.0.0",
35 | "qs": "^6.7.0",
36 | "v-charts": "^1.19.0",
37 | "vue": "^2.6.10",
38 | "vue-router": "^3.0.3",
39 | "vuex": "^3.0.1"
40 | },
41 | "devDependencies": {
42 | "@vue/cli-plugin-babel": "^3.8.0",
43 | "@vue/cli-plugin-eslint": "^3.8.0",
44 | "@vue/cli-service": "^3.8.0",
45 | "@vue/eslint-config-standard": "^4.0.0",
46 | "babel-eslint": "^10.0.1",
47 | "babel-plugin-component": "^1.1.1",
48 | "eslint": "^5.16.0",
49 | "eslint-plugin-vue": "^5.0.0",
50 | "stylus": "^0.54.5",
51 | "stylus-loader": "^3.0.2",
52 | "vue-template-compiler": "^2.5.21",
53 | "vuepress": "^1.0.2"
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/views/home.vue:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
48 |
--------------------------------------------------------------------------------
/src/api/canvasMaps/canvas-maps-request.js:
--------------------------------------------------------------------------------
1 | // import request from '../api_request'
2 | import * as api from '../datastore'
3 | import { deepClone } from '../../utils/deepClone'
4 |
5 | // 获取所有的maps
6 | export function getCanvasMaps () {
7 | return api.getCanvasMaps()
8 | // return request({
9 | // url: '/getPageSettings',
10 | // method: 'get'
11 | // })
12 | }
13 |
14 | // 修改当前的map
15 | export function setBaseProperty (currentMaps) {
16 | return api.setBaseProperty(currentMaps)
17 | }
18 |
19 | // 增加一个canvasmap
20 | export function addCanvasMap (map) {
21 | return api.addCanvasMap(map)
22 | }
23 |
24 | // 置顶一个canvasmap
25 | export function topCanvasMap (map) {
26 | return api.topCanvasMap(map)
27 | }
28 |
29 | // 置底一个canvasmap
30 | export function bottomCanvasMap (map) {
31 | return api.bottomCanvasMap(map)
32 | }
33 |
34 | // 置底一个canvasmap
35 | export function upCanvasMap (map) {
36 | return api.upCanvasMap(map)
37 | }
38 |
39 | // 置底一个canvasmap
40 | export function downCanvasMap (map) {
41 | return api.downCanvasMap(map)
42 | }
43 |
44 | // copy一个canvasmap
45 | export function copyCanvasMap (map) {
46 | let newMap = deepClone(map)// 深拷贝一个对象并修改默认信息,
47 | newMap.id = 'node-' + ((new Date()).getTime()) // 修改生成的id
48 | // 修改复制出来的位置信息
49 | newMap.packageJson.view.x += 20
50 | newMap.packageJson.view.y += 20
51 | return api.addCanvasMap(newMap)
52 | }
53 |
54 | // 删除一个canvasmap
55 | export function removeCanvasMap (map) {
56 | return api.removeCanvasMap(map)
57 | }
58 |
--------------------------------------------------------------------------------
/src/styles/modules/home.styl:
--------------------------------------------------------------------------------
1 | @import "../common/var.styl"
2 | .dv-home {
3 | header {
4 | height: 60px;
5 | line-height: 60px;
6 | box-sizing: border-box;
7 | padding: 0 30px;
8 | border-bottom: 1px solid $color-blue;
9 | background: linear-gradient(180deg, transparent, #171b22);
10 | .head-title {
11 | font-size: 24px;
12 | font-weight: 600;
13 | color: $color-blue;
14 | background-image: -webkit-gradient(linear, left 0, right 0, from($color-primary), to($color-blue));
15 | -webkit-background-clip: text;
16 | }
17 | }
18 | .dv-container {
19 | width: 100%;
20 | height: calc(100vh - 60px);
21 | overflow: hidden;
22 | .dv-ctrl {
23 | padding: 40px;
24 | text-align: center;
25 | display: flex;
26 | justify-content: center;
27 | align-items: center;
28 | .btn {
29 | display: flex;
30 | justify-content: center;
31 | align-items: center;
32 | height: 184px;
33 | width: 258px;
34 | margin: 16px;
35 | border: 1px solid #00baff;
36 | font-size: 18px;
37 | color: #8eeeff;
38 | text-decoration: none;
39 | transition: all .3s;
40 | background-image: linear-gradient(-90deg, rgba(0, 222, 255, .39) 0, rgba(0, 174, 255, .19) 100%);
41 | box-shadow: 0 0 10px 0 rgba(55, 224, 255, .3);
42 | cursor: pointer;
43 | &:hover {
44 | font-size: 20px;
45 | }
46 | }
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/components/board/header/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
27 |
28 |
29 |
49 |
--------------------------------------------------------------------------------
/src/components/board/canvas/components/edit-slider.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ range }}
4 |
5 |
6 |
8 |
9 |
10 |
11 |
12 |
13 |
53 |
--------------------------------------------------------------------------------
/src/components/board/options/gui-wrap.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{label}}
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
60 |
--------------------------------------------------------------------------------
/src/styles/modules/admin.styl:
--------------------------------------------------------------------------------
1 | @import "../common/var.styl"
2 | @import "../board/header-box.styl"
3 | @import "../board/coverage.styl"
4 | @import "../board/edit-slider.styl"
5 | @import "../board/canvas.styl"
6 | @import "../board/transform-block.styl"
7 | @import "../board/options.styl"
8 | @import "../board/context-menu.styl"
9 | // 主体布局
10 | .dv-admin {
11 | width: 100%;
12 | height: 100%;
13 | overflow: hidden;
14 | .board-layout {
15 | position: relative;
16 | width: 100%;
17 | height: 100%;
18 | display: inline-block;
19 | background: #ffffff;
20 | overflow: hidden;
21 | cursor: default;
22 | user-select: none;
23 | font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
24 | -webkit-font-smoothing: antialiased;
25 | -moz-osx-font-smoothing: grayscale;
26 | box-sizing: border-box;
27 | .center-box {
28 | position: relative;
29 | height: 100%;
30 | padding-top: 40px;
31 | .board-center {
32 | position: absolute;
33 | top: 40px;
34 | left: 0;
35 | right: 300px;
36 | bottom: 0;
37 | transition: right .3s;
38 | }
39 | }
40 | }
41 | }
42 |
43 | .delete-dialog {
44 | .bin-modal-content {
45 | background: #27343e;
46 | }
47 | .bin-modal-footer {
48 | border-top: 1px solid #3a4659;
49 | }
50 | .delete-dialog-inner {
51 | text-align: center;
52 | padding-top: 30px;
53 | .iconfont {
54 | color: #ff4f43;
55 | }
56 | p {
57 | padding: 10px;
58 | font-size: 14px;
59 | color: #fff;
60 | }
61 | }
62 | }
63 |
64 | // 覆盖样式
65 | .bin-modal-mask {
66 | background-color: rgba(0, 0, 0, .35);
67 | }
68 |
69 |
--------------------------------------------------------------------------------
/src/styles/board/coverage.styl:
--------------------------------------------------------------------------------
1 | @import "../common/var.styl"
2 | // 左侧图层列表
3 | .board-coverage {
4 | background: $color-admin-ctrl;
5 | .header-title {
6 | height: 30px;
7 | line-height: 30px;
8 | padding-left: 10px;
9 | background: $color-admin-ctrl-header;
10 | font-size: 12px;
11 | color: $color-text-info;
12 | }
13 | .control {
14 | display: flex;
15 | justify-content: center;
16 | align-items: center;
17 | height: 30px;
18 | border-bottom: 2px solid #282f3a;
19 | opacity: .3;
20 | .iconfont {
21 | padding: 2px;
22 | font-size: 14px;
23 | background-color: #282f3a;
24 | color: #8cc7ff;
25 | margin: 0 8px;
26 | }
27 | &.selected {
28 | opacity: 1;
29 | .iconfont {
30 | cursor: pointer;
31 | &:hover {
32 | color: #fff;
33 | background-color: #2d8cf0;
34 | }
35 | }
36 | }
37 | }
38 | .control-body {
39 | width: 100%;
40 | height: 100%;
41 | overflow: hidden;
42 | .body-wrap {
43 | width: 100%;
44 | height: 100%;
45 | padding: 5px;
46 | .list-item {
47 | position: relative;
48 | padding: 0 6px;
49 | line-height: 26px;
50 | cursor: pointer;
51 | transition: all 0.2s ease-in-out;
52 | color: $color-text-info;
53 | span {
54 | display: inline-block;
55 | vertical-align: middle;
56 | text-indent: 7px;
57 | font-size: 12px;
58 | }
59 | &.hovered {
60 | background-color: rgba(143, 255, 255, .1);
61 | }
62 | &.selected {
63 | background-color: $color-blue;
64 | }
65 | }
66 | }
67 | }
68 | }
69 |
70 | // 需要覆盖bin-ui的样式
71 | .body-wrap .bin-scrollbar__wrap {
72 | overflow-x: hidden;
73 | }
74 |
--------------------------------------------------------------------------------
/src/views/screen.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
55 |
--------------------------------------------------------------------------------
/src/components/board/coverage/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
62 |
--------------------------------------------------------------------------------
/src/components/board/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
64 |
--------------------------------------------------------------------------------
/preview/static/js/chunk-2d0c4a47.0e8656d7.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0c4a47"],{"3c67":function(t,a,e){"use strict";e.r(a);var n=function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("div",{staticClass:"dv-screen"},[e("b-scrollbar",{staticStyle:{height:"100%"}},[e("div",{staticClass:"canvas-panel",style:t.canvasPanelStyle},[t._l(t.canvasMap,function(t){return[e("preview-box",{key:t.id,attrs:{item:t}},[e("charts-factory",{attrs:{"type-name":t.packageJson.name,config:t.packageJson.config,"api-data":t.packageJson.api_data,apis:t.packageJson.apis}})],1)]})],2)])],1)},s=[],c=e("cebc"),i=e("2f62"),r=e("c15d"),o=e("549b"),p=e("0324"),h=function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("div",{staticClass:"preview-box",style:t.contentStyles},[e("div",{staticClass:"preview-wrap",style:t.dvWrapperStyles},[t._t("default")],2)])},l=[],d={props:{item:{type:Object,required:!0}},created:function(){this.transformData=Object(c["a"])({},this.item.packageJson.view)},watch:{item:{handler:function(t){t&&(this.transformData=Object(c["a"])({},t.packageJson.view))},deep:!0}},computed:{contentStyles:function(){return{width:this.transformData.width+"px",height:this.transformData.height+"px",transform:"translate3d(".concat(this.transformData.x,"px,").concat(this.transformData.y,"px,0)")}},dvWrapperStyles:function(){return{transform:"translateZ(0)",width:this.transformData.width+"px",height:this.transformData.height+"px",padding:"10px 0"}}}},u=d,f=e("2877"),g=Object(f["a"])(u,h,l,!1,null,null,null),v=g.exports,m={name:"screen",components:{ChartsFactory:p["a"],PreviewBox:v},data:function(){return{}},computed:Object(c["a"])({},Object(i["c"])(["canvasMap","pageSettings"]),{canvasPanelStyle:function(){return{width:"".concat(this.pageSettings.width,"px"),height:"".concat(this.pageSettings.height,"px"),backgroundColor:this.pageSettings.backgroundColor}}}),created:function(){var t=this;Object(r["a"])().then(function(a){t.$store.dispatch("SetPageSettings",a.data),console.log(a.data)}),Object(o["e"])().then(function(a){t.$store.dispatch("InitCanvasMaps",a.data)})}},w=m,b=Object(f["a"])(w,n,s,!1,null,null,null);a["default"]=b.exports}}]);
--------------------------------------------------------------------------------
/src/components/drag/DragList.vue:
--------------------------------------------------------------------------------
1 |
2 |
33 |
34 |
35 |
67 |
--------------------------------------------------------------------------------
/src/config/components/test.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "ml-area-basic_rny2b",
3 | "packageJson": {
4 | "api_data": {
5 | "source": [
6 | {
7 | "x": "2010/01/01 00:00:00",
8 | "y": 666
9 | },
10 | {
11 | "x": "2010/02/01 00:00:00",
12 | "y": 200
13 | },
14 | {
15 | "x": "2010/03/01 00:00:00",
16 | "y": 555
17 | },
18 | {
19 | "x": "2010/04/01 00:00:00",
20 | "y": 190
21 | },
22 | {
23 | "x": "2010/05/01 00:00:00",
24 | "y": 90
25 | },
26 | {
27 | "x": "2010/06/01 00:00:00",
28 | "y": 237
29 | }
30 | ]
31 | },
32 | "apis": {
33 | "source": {
34 | "description": "区域图接口",
35 | "fields": {
36 | "s": {
37 | "description": "系列(可选)",
38 | "optional": true
39 | },
40 | "x": {
41 | "description": "类目"
42 | },
43 | "y": {
44 | "description": "值"
45 | }
46 | },
47 | "handler": "render"
48 | }
49 | },
50 | "cn_name": "区域图",
51 | "config": {
52 | "chart": {
53 | "emptyData": true,
54 | "fontFamily": "Microsoft Yahei",
55 | "loadAmount": 2000,
56 | "margin": {
57 | "top": 0,
58 | "right": 0,
59 | "bottom": 0,
60 | "left": 0
61 | }
62 | },
63 | "title": {
64 | "content": "主标题",
65 | "textStyle": {
66 | "color": "rgba(255,255,255,0.6)",
67 | "fontSize": 20,
68 | "fontWeight": "normal"
69 | }
70 | },
71 | "animation": {
72 | "animationDuration": 1000,
73 | "animationDurationUpdate": 300,
74 | "animationEasing": "cubicInOut",
75 | "animationUpdateFromPrevious": true,
76 | "show": true
77 | }
78 | },
79 | "icon": "",
80 | "level": 0,
81 | "name": "ml-area-basic",
82 | "protocol": 2,
83 | "type": [
84 | "regular_area"
85 | ],
86 | "validate": {},
87 | "view": {
88 | "height": 200,
89 | "width": 300,
90 | "zIndex": 1010
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/components/board/context-menu/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
15 |
16 |
17 |
18 |
72 |
--------------------------------------------------------------------------------
/src/api/api_request.js:
--------------------------------------------------------------------------------
1 | /**
2 | *创建axios服务实例
3 | */
4 | import httpRequest from 'axios'
5 | import Qs from 'qs'
6 | import { messages } from 'bin-ui'
7 |
8 | let baseUrl = process.env.NODE_ENV !== 'production' ? '/' : '/admin'
9 | const service = httpRequest.create({
10 | baseURL: baseUrl,
11 | headers: {
12 | 'X-Requested-With': 'XMLHttpRequest'
13 | },
14 | timeout: 60000 // 请求超时时间
15 | })
16 | /**
17 | * respone拦截器
18 | */
19 | service.interceptors.response.use(
20 | response => {
21 | return response
22 | },
23 | error => {
24 | if (error.response) {
25 | messages({ content: error.response.data, type: 'danger', duration: 5 })
26 | } else {
27 | messages({ content: error.message, type: 'danger', duration: 5 })
28 | }
29 | return Promise.reject(error)
30 | }
31 | )
32 |
33 | export default service
34 |
35 | /**
36 | * get请求
37 | * @param url
38 | * @param data
39 | */
40 | export function requestGetNoData (url) {
41 | return service({
42 | url: url,
43 | method: 'get'
44 | })
45 | }
46 |
47 | export function requestGet (url, data) {
48 | return service({
49 | url: url,
50 | method: 'get',
51 | params: data
52 | })
53 | }
54 |
55 | /**
56 | * post请求
57 | * @param url
58 | * @param data
59 | */
60 | export function requestPost (url, data) {
61 | return service({
62 | url: url,
63 | method: 'post',
64 | transformRequest: [function (data) {
65 | data = Qs.stringify(data)
66 | return data
67 | }],
68 | headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
69 | data: data
70 | })
71 | }
72 |
73 | /**
74 | * post请求
75 | * @param url
76 | * @param data
77 | */
78 | export function requestPost2 (url, data) {
79 | return service({
80 | url: url,
81 | method: 'post',
82 | data: data
83 | })
84 | }
85 |
86 | /**
87 | * post请求
88 | * @param url
89 | * @param formData
90 | */
91 | export function requestPostFormData (url, data) {
92 | return service({
93 | url: url,
94 | method: 'post',
95 | headers: { 'Content-Type': 'multipart/form-data' },
96 | data: data
97 | })
98 | }
99 |
100 | /**
101 | * 向formData中添加新的项,如果值为null则跳过
102 | * @param formData FormData
103 | * @param name 参数名
104 | * @param value 参数值
105 | */
106 | export function appendFormData (formData, name, value) {
107 | if (value != null) {
108 | formData.append(name, value)
109 | }
110 | }
111 |
112 | export function getBaseUrl () {
113 | return baseUrl
114 | }
115 |
116 | export function requestGet2 (url, data, downloadProcess) {
117 | return service({
118 | timeout: 10000 * 60, // 请求超时时间
119 | url: url,
120 | method: 'get',
121 | params: data,
122 | headers: { 'Content-Type': 'application/octet-stream;charset=utf-8' },
123 | responseType: 'arraybuffer',
124 | onDownloadProgress: downloadProcess
125 | })
126 | }
127 |
--------------------------------------------------------------------------------
/src/components/board/canvas/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
99 |
--------------------------------------------------------------------------------
/src/components/charts/charts-factory.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ config.title.content }}
5 |
6 |
11 |
12 |
13 |
14 |
138 |
--------------------------------------------------------------------------------
/src/store/modules/canvasMaps.js:
--------------------------------------------------------------------------------
1 | import {
2 | addCanvasMap,
3 | bottomCanvasMap,
4 | copyCanvasMap, downCanvasMap,
5 | removeCanvasMap,
6 | topCanvasMap, upCanvasMap
7 | } from '../../api/canvasMaps/canvas-maps-request'
8 |
9 | const canvasMaps = {
10 | state: {
11 | canvasMap: [], // 画布中的组件,默认插入一个用于调试可动态添加,暂时写死,后期用lowdb缓存
12 | singleSelected: null, // 单选选中的可拖拽组件
13 | contextMenuInfo: { x: 0, y: 0, isShow: false }
14 | },
15 | mutations: {
16 | SET_CANVAS_MAPS (state, maps) {
17 | state.canvasMap = [...maps]
18 | },
19 | ADD_CANVAS_MAP (state, nodeInfo) {
20 | state.canvasMap.push(nodeInfo)
21 | },
22 | // 单选组件
23 | SINGLE_SELECT (state, item) {
24 | if (state.singleSelected === item) return
25 | state.singleSelected = item
26 | if (state.singleSelected) {
27 | console.warn('===single select===' + item.id)
28 | }
29 | },
30 | // 设置右键菜单信息
31 | SET_CONTEXT_MENU_INFO (state, info) {
32 | state.contextMenuInfo = info
33 | },
34 | // 设置当前选中的基本属性
35 | SET_CURRENT_BASE_PROPERTY (state, transformData) {
36 | state.singleSelected.packageJson.view = { ...transformData }
37 | let current = state.canvasMap.find(item => {
38 | return item.id === state.singleSelected.id
39 | })
40 | if (current) {
41 | current.packageJson.view = { ...transformData }
42 | }
43 | },
44 | // 设置当前选中的自有属性
45 | SET_CURRENT_SELF (state, { data, property }) {
46 | state.singleSelected.packageJson[property] = { ...data }
47 | let current = state.canvasMap.find(item => {
48 | return item.id === state.singleSelected.id
49 | })
50 | if (current) {
51 | current.packageJson[property] = { ...data }
52 | }
53 | }
54 | },
55 | actions: {
56 | InitCanvasMaps ({ commit }, maps) {
57 | commit('SET_CANVAS_MAPS', maps)
58 | },
59 | AddCanvasMap ({ commit }, nodeInfo) {
60 | addCanvasMap(nodeInfo).then(() => {
61 | commit('ADD_CANVAS_MAP', nodeInfo)
62 | })
63 | },
64 | SingleSelected ({ commit }, selectItem) {
65 | commit('SINGLE_SELECT', selectItem)
66 | },
67 | ToggleContextMenu ({ commit }, info) {
68 | let menuInfo = info ? Object.assign({}, info, { isShow: true }) : { x: 0, y: 0, isShow: false }
69 | commit('SET_CONTEXT_MENU_INFO', menuInfo)
70 | },
71 | HideContextMenu ({ commit }) {
72 | commit('SET_CONTEXT_MENU_INFO', { x: 0, y: 0, isShow: false })
73 | },
74 | ContextMenuCommand ({ commit, state }, order) {
75 | commit('SET_CONTEXT_MENU_INFO', { x: 0, y: 0, isShow: false })
76 | switch (order) {
77 | case 'top':
78 | // 如果是置顶
79 | topCanvasMap(state.singleSelected).then(res => {
80 | commit('SET_CANVAS_MAPS', res.data)
81 | })
82 | break
83 | case 'bottom':
84 | // 如果是置顶
85 | bottomCanvasMap(state.singleSelected).then(res => {
86 | commit('SET_CANVAS_MAPS', res.data)
87 | })
88 | break
89 | case 'up':
90 | upCanvasMap(state.singleSelected).then(res => {
91 | commit('SET_CANVAS_MAPS', res.data)
92 | })
93 | break
94 | case 'down':
95 | downCanvasMap(state.singleSelected).then(res => {
96 | commit('SET_CANVAS_MAPS', res.data)
97 | })
98 | break
99 | case 'copy':
100 | // 如果是复制操作,则传入当前选中的值
101 | copyCanvasMap(state.singleSelected).then(res => {
102 | let last = res.data[res.data.length - 1]
103 | commit('SET_CANVAS_MAPS', res.data)
104 | commit('SINGLE_SELECT', last)
105 | })
106 | break
107 | case 'remove':
108 | // 如果是删除操作,则需要删除并更新当前的canvasMaps,并默认设置当前选中为空
109 | removeCanvasMap(state.singleSelected).then(res => {
110 | commit('SET_CANVAS_MAPS', res.data)
111 | commit('SINGLE_SELECT', null)
112 | })
113 | break
114 | }
115 | },
116 | SetBaseProperty ({ commit, state }, transformData) {
117 | if (state.singleSelected) {
118 | commit('SET_CURRENT_BASE_PROPERTY', transformData)
119 | }
120 | },
121 | SetSelfProperty ({ commit, state }, config) {
122 | if (state.singleSelected) {
123 | commit('SET_CURRENT_SELF', { data: config, property: 'config' })
124 | }
125 | },
126 | SetApis ({ commit, state }, apis) {
127 | if (state.singleSelected) {
128 | commit('SET_CURRENT_SELF', { data: apis, property: 'apis' })
129 | }
130 | },
131 | SetSelfDataSource ({ commit, state }, source) {
132 | if (state.singleSelected) {
133 | commit('SET_CURRENT_SELF', { data: source, property: 'api_data' })
134 | }
135 | }
136 | }
137 | }
138 | export default canvasMaps
139 |
--------------------------------------------------------------------------------
/src/api/datastore.js:
--------------------------------------------------------------------------------
1 | import db from '../utils/db'
2 | import database from '../utils/database'
3 | import { toFirst, toLast, upGo, downGo } from '../utils/arr-utils'
4 |
5 | // 初始化所有本地数据
6 | export function initLocalData () {
7 | return new Promise((resolve, reject) => {
8 | try {
9 | db.set('app', database.app).write()
10 | db.set('canvasMaps', database.canvasMaps).write()
11 | resolve({ message: '初始化数据库成功' })
12 | } catch (err) {
13 | return reject(err)
14 | }
15 | })
16 | }
17 |
18 | // pageSetting配置数据
19 | export function getPageSettings () {
20 | return new Promise((resolve, reject) => {
21 | try {
22 | resolve({ data: db.get('app').cloneDeep().value() })
23 | } catch (err) {
24 | return reject(err)
25 | }
26 | })
27 | }
28 |
29 | export function setPageSettings (setting) {
30 | return new Promise((resolve, reject) => {
31 | try {
32 | db.set('app', setting).write()
33 | resolve({ data: db.get('app').cloneDeep().value() })
34 | } catch (err) {
35 | return reject(err)
36 | }
37 | })
38 | }
39 |
40 | export function resetPageSettings () {
41 | return setPageSettings(database.app)
42 | }
43 |
44 | // 画布db数据
45 | export function getCanvasMaps () {
46 | return new Promise((resolve, reject) => {
47 | try {
48 | resolve({ data: db.get('canvasMaps').cloneDeep().value() })
49 | } catch (err) {
50 | return reject(err)
51 | }
52 | })
53 | }
54 |
55 | export function setBaseProperty (currentMaps) {
56 | return new Promise((resolve, reject) => {
57 | try {
58 | db.get('canvasMaps')
59 | .find({ id: currentMaps.id })
60 | .assign(currentMaps)
61 | .write()
62 | resolve({ data: db.get('canvasMaps').cloneDeep().value() })
63 | } catch (err) {
64 | return reject(err)
65 | }
66 | })
67 | }
68 |
69 | export function addCanvasMap (map) {
70 | return new Promise((resolve, reject) => {
71 | try {
72 | db.get('canvasMaps')
73 | .push(map)
74 | .write()
75 | resolve({ data: db.get('canvasMaps').cloneDeep().value() })
76 | } catch (err) {
77 | return reject(err)
78 | }
79 | })
80 | }
81 |
82 | export function removeCanvasMap (map) {
83 | return new Promise((resolve, reject) => {
84 | try {
85 | db.get('canvasMaps')
86 | .remove({ id: map.id })
87 | .write()
88 | resolve({ data: db.get('canvasMaps').cloneDeep().value() })
89 | } catch (err) {
90 | return reject(err)
91 | }
92 | })
93 | }
94 |
95 | // 置顶一个数据
96 | export function topCanvasMap (map) {
97 | return new Promise((resolve, reject) => {
98 | try {
99 | let arr = db.get('canvasMaps').cloneDeep().value()
100 | let index = arr.findIndex(item => {
101 | return item.id === map.id
102 | })
103 | if (index !== arr.length - 1) {
104 | let newArr = toLast(arr, index)
105 | db.set('canvasMaps', newArr).write()
106 | }
107 | resolve({ data: db.get('canvasMaps').cloneDeep().value() })
108 | } catch (err) {
109 | return reject(err)
110 | }
111 | })
112 | }
113 |
114 | // 置底一个数据 即将数组元素排至开头位置
115 | export function bottomCanvasMap (map) {
116 | return new Promise((resolve, reject) => {
117 | try {
118 | let arr = db.get('canvasMaps').cloneDeep().value()
119 | let index = arr.findIndex(item => {
120 | return item.id === map.id
121 | })
122 | if (index !== 0) {
123 | let newArr = toFirst(arr, index)
124 | db.set('canvasMaps', newArr).write()
125 | }
126 | resolve({ data: db.get('canvasMaps').cloneDeep().value() })
127 | } catch (err) {
128 | return reject(err)
129 | }
130 | })
131 | }
132 |
133 | // up
134 | export function upCanvasMap (map) {
135 | return new Promise((resolve, reject) => {
136 | try {
137 | let arr = db.get('canvasMaps').cloneDeep().value()
138 | let index = arr.findIndex(item => {
139 | return item.id === map.id
140 | })
141 | if (index !== arr.length - 1) {
142 | let newArr = downGo(arr, index)
143 | db.set('canvasMaps', newArr).write()
144 | }
145 | resolve({ data: db.get('canvasMaps').cloneDeep().value() })
146 | } catch (err) {
147 | return reject(err)
148 | }
149 | })
150 | }
151 |
152 | // down
153 | export function downCanvasMap (map) {
154 | return new Promise((resolve, reject) => {
155 | try {
156 | let arr = db.get('canvasMaps').cloneDeep().value()
157 | let index = arr.findIndex(item => {
158 | return item.id === map.id
159 | })
160 | if (index !== 0) {
161 | let newArr = upGo(arr, index)
162 | db.set('canvasMaps', newArr).write()
163 | }
164 | resolve({ data: db.get('canvasMaps').cloneDeep().value() })
165 | } catch (err) {
166 | return reject(err)
167 | }
168 | })
169 | }
170 |
--------------------------------------------------------------------------------
/src/styles/board/header-box.styl:
--------------------------------------------------------------------------------
1 | @import "../common/var.styl"
2 | // 画板顶部
3 | .board-header {
4 | position: absolute;
5 | top: 0;
6 | right: 0;
7 | left: 0;
8 | width: 100%;
9 | height: 40px;
10 | line-height: 40px;
11 | z-index: 205;
12 | background: $color-admin-main;
13 | transition: all .5s ease-in .1s;
14 | .header-title {
15 | width: 200px;
16 | height: 40px;
17 | display: inline-block;
18 | .iconfont {
19 | display: inline-block;
20 | vertical-align: top;
21 | height: 100%;
22 | line-height: 40px;
23 | cursor: pointer;
24 | color: $color-blue;
25 | padding: 0 5px;
26 | }
27 | span {
28 | display: inline-block;
29 | vertical-align: top;
30 | font-size: 14px;
31 | line-height: 40px;
32 | color: $color-blue;
33 | padding-left: 20px;
34 | }
35 | }
36 | .control {
37 | padding-left: 30px;
38 | height: 40px;
39 | line-height: 40px;
40 | .drag-list-menu {
41 | height: 100%;
42 | .list-group {
43 | position: relative;
44 | width: 56px;
45 | height: 100%;
46 | text-align: center;
47 | .list-group-header {
48 | position: relative;
49 | box-sizing: border-box;
50 | font-size: 14px;
51 | color: $color-text-info;
52 | cursor: pointer;
53 | &:before {
54 | content: ''
55 | position: absolute;
56 | top: 0;
57 | left: 0;
58 | right: 0;
59 | border-top: 2px solid transparent;
60 | }
61 | }
62 | &.hovered {
63 | .list-group-header {
64 | color: $color-primary;
65 | &:before {
66 | border-top: 2px solid $color-primary;
67 | }
68 | }
69 | }
70 | .list-group-body {
71 | position: absolute;
72 | top: 40px;
73 | left: 0;
74 | width: 555px;
75 | height: 333px;
76 | background-color: #1c1f25;
77 | .left {
78 | width: 60px;
79 | background-color: #2b2e36;
80 | }
81 | .right {
82 | flex: 1;
83 | text-align: left;
84 | padding: 20px 0 0 20px;
85 | .list-item {
86 | position: relative;
87 | display: inline-block;
88 | width: 138px;
89 | height: 100px;
90 | cursor: pointer;
91 | transition: all 0.2s ease-in-out;
92 | color: $color-text-info;
93 | background-color: #282a30;
94 | box-sizing: border-box;
95 | border: 1px solid transparent;
96 | margin-right: 20px;
97 | margin-bottom: 20px;
98 | .img {
99 | position: absolute;
100 | width: 100%;
101 | height: 100%;
102 | background-repeat: no-repeat;
103 | background-size: 100% 100%;
104 | background-position: 0 0;
105 | &.ve-line {
106 | background-image: url("../assets/images/ve-line.png")
107 | }
108 | &.ve-histogram {
109 | background-image: url("../assets/images/ve-histogram.png")
110 | }
111 | &.ve-bar {
112 | background-image: url("../assets/images/ve-bar.png")
113 | }
114 | &.ve-pie {
115 | background-image: url("../assets/images/ve-pie.png")
116 | }
117 | &.ve-radar {
118 | background-image: url("../assets/images/ve-radar.png")
119 | }
120 | &.ve-map {
121 | background-image: url("../assets/images/ve-map.png")
122 | }
123 | }
124 | .front {
125 | position: absolute;
126 | width: 100%;
127 | height: 30px;
128 | bottom: 0;
129 | margin-bottom: -30px;
130 | line-height: 30px;
131 | span {
132 | display: inline-block;
133 | vertical-align: middle;
134 | text-indent: 7px;
135 | font-size: 12px;
136 | }
137 | }
138 | &:hover {
139 | border: 1px solid $color-primary;
140 | }
141 | }
142 | }
143 | }
144 | }
145 | }
146 | }
147 | .right-box {
148 | width: 300px;
149 | height: 40px;
150 | line-height: 40px;
151 | display: inline-block;
152 | text-align: center;
153 | .iconfont {
154 | cursor: pointer;
155 | width: 65px;
156 | font-size: 18px;
157 | transition: .3s;
158 | &:hover {
159 | color: $color-primary;
160 | }
161 | }
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/src/views/admin.vue:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
16 |
17 |
18 |
19 | {{ transform.packageJson.config.title.content}}
20 |
21 | {{ transform.packageJson.title }}
22 |
23 |
24 |
25 |
26 |
27 |
34 |
38 |
39 |
40 |
41 |
42 |
44 |
45 |
46 |
47 |
48 |
是否删除选中的1个组件
49 |
50 |
51 |
52 |
53 |
54 |
143 |
--------------------------------------------------------------------------------
/src/utils/geoCoordMap.js:
--------------------------------------------------------------------------------
1 | export const geoCoordMap = {
2 | '海门': [121.15, 31.89],
3 | '鄂尔多斯': [109.781327, 39.608266],
4 | '招远': [120.38, 37.35],
5 | '舟山': [122.207216, 29.985295],
6 | '齐齐哈尔': [123.97, 47.33],
7 | '盐城': [120.13, 33.38],
8 | '赤峰': [118.87, 42.28],
9 | '青岛': [120.33, 36.07],
10 | '乳山': [121.52, 36.89],
11 | '金昌': [102.188043, 38.520089],
12 | '泉州': [118.58, 24.93],
13 | '莱西': [120.53, 36.86],
14 | '日照': [119.46, 35.42],
15 | '胶南': [119.97, 35.88],
16 | '南通': [121.05, 32.08],
17 | '拉萨': [91.11, 29.97],
18 | '云浮': [112.02, 22.93],
19 | '梅州': [116.1, 24.55],
20 | '文登': [122.05, 37.2],
21 | '上海': [121.48, 31.22],
22 | '攀枝花': [101.718637, 26.582347],
23 | '威海': [122.1, 37.5],
24 | '承德': [117.93, 40.97],
25 | '厦门': [118.1, 24.46],
26 | '汕尾': [115.375279, 22.786211],
27 | '潮州': [116.63, 23.68],
28 | '丹东': [124.37, 40.13],
29 | '太仓': [121.1, 31.45],
30 | '曲靖': [103.79, 25.51],
31 | '烟台': [121.39, 37.52],
32 | '福州': [119.3, 26.08],
33 | '瓦房店': [121.979603, 39.627114],
34 | '即墨': [120.45, 36.38],
35 | '抚顺': [123.97, 41.97],
36 | '玉溪': [102.52, 24.35],
37 | '张家口': [114.87, 40.82],
38 | '阳泉': [113.57, 37.85],
39 | '莱州': [119.942327, 37.177017],
40 | '湖州': [120.1, 30.86],
41 | '汕头': [116.69, 23.39],
42 | '昆山': [120.95, 31.39],
43 | '宁波': [121.56, 29.86],
44 | '湛江': [110.359377, 21.270708],
45 | '揭阳': [116.35, 23.55],
46 | '荣成': [122.41, 37.16],
47 | '连云港': [119.16, 34.59],
48 | '葫芦岛': [120.836932, 40.711052],
49 | '常熟': [120.74, 31.64],
50 | '东莞': [113.75, 23.04],
51 | '河源': [114.68, 23.73],
52 | '淮安': [119.15, 33.5],
53 | '泰州': [119.9, 32.49],
54 | '南宁': [108.33, 22.84],
55 | '营口': [122.18, 40.65],
56 | '惠州': [114.4, 23.09],
57 | '江阴': [120.26, 31.91],
58 | '蓬莱': [120.75, 37.8],
59 | '韶关': [113.62, 24.84],
60 | '嘉峪关': [98.289152, 39.77313],
61 | '广州': [113.23, 23.16],
62 | '延安': [109.47, 36.6],
63 | '太原': [112.53, 37.87],
64 | '清远': [113.01, 23.7],
65 | '中山': [113.38, 22.52],
66 | '昆明': [102.73, 25.04],
67 | '寿光': [118.73, 36.86],
68 | '盘锦': [122.070714, 41.119997],
69 | '长治': [113.08, 36.18],
70 | '深圳': [114.07, 22.62],
71 | '珠海': [113.52, 22.3],
72 | '宿迁': [118.3, 33.96],
73 | '咸阳': [108.72, 34.36],
74 | '铜川': [109.11, 35.09],
75 | '平度': [119.97, 36.77],
76 | '佛山': [113.11, 23.05],
77 | '海口': [110.35, 20.02],
78 | '江门': [113.06, 22.61],
79 | '章丘': [117.53, 36.72],
80 | '肇庆': [112.44, 23.05],
81 | '大连': [121.62, 38.92],
82 | '临汾': [111.5, 36.08],
83 | '吴江': [120.63, 31.16],
84 | '石嘴山': [106.39, 39.04],
85 | '沈阳': [123.38, 41.8],
86 | '苏州': [120.62, 31.32],
87 | '茂名': [110.88, 21.68],
88 | '嘉兴': [120.76, 30.77],
89 | '长春': [125.35, 43.88],
90 | '胶州': [120.03336, 36.264622],
91 | '银川': [106.27, 38.47],
92 | '张家港': [120.555821, 31.875428],
93 | '三门峡': [111.19, 34.76],
94 | '锦州': [121.15, 41.13],
95 | '南昌': [115.89, 28.68],
96 | '柳州': [109.4, 24.33],
97 | '三亚': [109.511909, 18.252847],
98 | '自贡': [104.778442, 29.33903],
99 | '吉林': [126.57, 43.87],
100 | '阳江': [111.95, 21.85],
101 | '泸州': [105.39, 28.91],
102 | '西宁': [101.74, 36.56],
103 | '宜宾': [104.56, 29.77],
104 | '呼和浩特': [111.65, 40.82],
105 | '成都': [104.06, 30.67],
106 | '大同': [113.3, 40.12],
107 | '镇江': [119.44, 32.2],
108 | '桂林': [110.28, 25.29],
109 | '张家界': [110.479191, 29.117096],
110 | '宜兴': [119.82, 31.36],
111 | '北海': [109.12, 21.49],
112 | '西安': [108.95, 34.27],
113 | '金坛': [119.56, 31.74],
114 | '东营': [118.49, 37.46],
115 | '牡丹江': [129.58, 44.6],
116 | '遵义': [106.9, 27.7],
117 | '绍兴': [120.58, 30.01],
118 | '扬州': [119.42, 32.39],
119 | '常州': [119.95, 31.79],
120 | '潍坊': [119.1, 36.62],
121 | '重庆': [106.54, 29.59],
122 | '台州': [121.420757, 28.656386],
123 | '南京': [118.78, 32.04],
124 | '滨州': [118.03, 37.36],
125 | '贵阳': [106.71, 26.57],
126 | '无锡': [120.29, 31.59],
127 | '本溪': [123.73, 41.3],
128 | '克拉玛依': [84.77, 45.59],
129 | '渭南': [109.5, 34.52],
130 | '马鞍山': [118.48, 31.56],
131 | '宝鸡': [107.15, 34.38],
132 | '焦作': [113.21, 35.24],
133 | '句容': [119.16, 31.95],
134 | '北京': [116.46, 39.92],
135 | '徐州': [117.2, 34.26],
136 | '衡水': [115.72, 37.72],
137 | '包头': [110, 40.58],
138 | '绵阳': [104.73, 31.48],
139 | '乌鲁木齐': [87.68, 43.77],
140 | '枣庄': [117.57, 34.86],
141 | '杭州': [120.19, 30.26],
142 | '淄博': [118.05, 36.78],
143 | '鞍山': [122.85, 41.12],
144 | '溧阳': [119.48, 31.43],
145 | '库尔勒': [86.06, 41.68],
146 | '安阳': [114.35, 36.1],
147 | '开封': [114.35, 34.79],
148 | '济南': [117, 36.65],
149 | '德阳': [104.37, 31.13],
150 | '温州': [120.65, 28.01],
151 | '九江': [115.97, 29.71],
152 | '邯郸': [114.47, 36.6],
153 | '临安': [119.72, 30.23],
154 | '兰州': [103.73, 36.03],
155 | '沧州': [116.83, 38.33],
156 | '临沂': [118.35, 35.05],
157 | '南充': [106.110698, 30.837793],
158 | '天津': [117.2, 39.13],
159 | '富阳': [119.95, 30.07],
160 | '泰安': [117.13, 36.18],
161 | '诸暨': [120.23, 29.71],
162 | '郑州': [113.65, 34.76],
163 | '哈尔滨': [126.63, 45.75],
164 | '聊城': [115.97, 36.45],
165 | '芜湖': [118.38, 31.33],
166 | '唐山': [118.02, 39.63],
167 | '平顶山': [113.29, 33.75],
168 | '邢台': [114.48, 37.05],
169 | '德州': [116.29, 37.45],
170 | '济宁': [116.59, 35.38],
171 | '荆州': [112.239741, 30.335165],
172 | '宜昌': [111.3, 30.7],
173 | '义乌': [120.06, 29.32],
174 | '丽水': [119.92, 28.45],
175 | '洛阳': [112.44, 34.7],
176 | '秦皇岛': [119.57, 39.95],
177 | '株洲': [113.16, 27.83],
178 | '石家庄': [114.48, 38.03],
179 | '莱芜': [117.67, 36.19],
180 | '常德': [111.69, 29.05],
181 | '保定': [115.48, 38.85],
182 | '湘潭': [112.91, 27.87],
183 | '金华': [119.64, 29.12],
184 | '岳阳': [113.09, 29.37],
185 | '长沙': [113, 28.21],
186 | '衢州': [118.88, 28.97],
187 | '廊坊': [116.7, 39.53],
188 | '菏泽': [115.480656, 35.23375],
189 | '合肥': [117.27, 31.86],
190 | '武汉': [114.31, 30.52],
191 | '大庆': [125.03, 46.58]
192 | }
193 |
--------------------------------------------------------------------------------
/src/styles/board/options.styl:
--------------------------------------------------------------------------------
1 | @import "../common/var.styl"
2 | // 右侧参数配置页面
3 | .board-options {
4 | position: absolute;
5 | top: 40px;
6 | right: 0;
7 | bottom: 0;
8 | box-sizing: border-box;
9 | z-index: 200;
10 | background: #ffffff;
11 | box-shadow: -2px 0 2px 0 rgba(0, 0, 0, 0.1);
12 | transition: all .3s;
13 | transform: translate3d(100%, 0, 0)
14 | .header-title {
15 | height: 30px;
16 | line-height: 30px;
17 | text-align: center;
18 | background: $color-admin-ctrl-header;
19 | }
20 | .tabs {
21 | width: 100%;
22 | display: flex;
23 | height: 30px;
24 | line-height: 27px;
25 | .tab-item {
26 | flex: 1;
27 | height: 100%;
28 | display: inline-block;
29 | text-align: center;
30 | background: #27343e;
31 | transition: .2s;
32 | outline: 0;
33 | color: #bcc9d4;
34 | font-size: 12px;
35 | cursor: pointer;
36 | border-top: 2px solid transparent;
37 | &.active {
38 | background: $color-admin-options-bg;
39 | color: $color-primary;
40 | border-top: 2px solid $color-primary;
41 | }
42 | .iconfont {
43 | font-size: 16px;
44 | }
45 | }
46 | }
47 | .options-body {
48 | background: $color-admin-options-bg;
49 | height: calc(100% - 30px);
50 | }
51 | .expand-hover {
52 | position: absolute;
53 | top: 50%;
54 | left: 0;
55 | width: 16px;
56 | height: 160px;
57 | margin-top: -80px;
58 | margin-left: -16px;
59 | cursor: pointer;
60 | .inner {
61 | position: relative;
62 | width: 100%;
63 | height: 100%;
64 | background: $color-admin-options-hover;
65 | opacity: 0;
66 | transition: all .2s;
67 | i {
68 | position: absolute;
69 | width: 18px;
70 | height: 18px;
71 | font-size: 18px;
72 | top: 50%;
73 | margin-top: -9px;
74 | &:hover {
75 | color: #2d8cf0;
76 | }
77 | }
78 | &:before, &:after {
79 | content: ''
80 | position: absolute
81 | left: 0;
82 | }
83 | &:before {
84 | top: 0;
85 | margin-top: -16px;
86 | border-top: 16px solid transparent;
87 | border-right: 16px solid $color-admin-options-hover;
88 | }
89 | &:after {
90 | bottom: 0;
91 | margin-bottom: -16px;
92 | border-left: 16px solid transparent;
93 | border-top: 16px solid $color-admin-options-hover;
94 | }
95 | }
96 | &:hover .inner {
97 | opacity: 1;
98 | }
99 | }
100 | &.is-expand {
101 | transform: translate3d(0, 0, 0)
102 | }
103 | }
104 | // 页面设置
105 | .page-config, .block-config {
106 | padding-top: 10px;
107 | .gui-field {
108 | display: flex;
109 | justify-content: space-between;
110 | padding: 6px 13px;
111 | min-height: 24px;
112 | color: $color-text-info;
113 | font-size: 12px;
114 | .gui-field-name {
115 | padding-right: 5px;
116 | line-height: 28px;
117 | }
118 | .gui-field-container {
119 | min-height: 24px;
120 | display: flex;
121 | width: 175px;
122 | font-size: 12px;
123 | align-items: center;
124 | .gui-inline {
125 | display: inline-block;
126 | width: 85px;
127 | .label {
128 | color: #647279;
129 | white-space: nowrap;
130 | overflow: hidden;
131 | text-overflow: ellipsis;
132 | font-size: 12px;
133 | line-height: 18px;
134 | text-align: left;
135 | }
136 | &:first-child {
137 | margin-right: 5px;
138 | }
139 | }
140 | }
141 | }
142 | .gui-wrap {
143 | position: relative;
144 | padding-left: 13px;
145 | &.disable {
146 | color: #647279;
147 | }
148 | .wrap-name {
149 | line-height: 40px;
150 | span {
151 | display: inline-block;
152 | vertical-align: middle;
153 | }
154 | .wrap-arrow {
155 | transition: .3s
156 | &.show {
157 | transform: rotate(90deg)
158 | }
159 | &.simple {
160 | cursor: pointer;
161 | }
162 | }
163 | .wrap-label {
164 | padding: 0 5px 0 2px;
165 | }
166 | .wrap-toggle {
167 | cursor: pointer;
168 | }
169 | .iconfont {
170 | line-height: normal;
171 | }
172 | }
173 | .gui-field {
174 | padding-left: 18px;
175 | }
176 | &:after {
177 | content: ''
178 | position: absolute;
179 | top: 40px;
180 | left: 18px;
181 | bottom: 0;
182 | border-left: 1px solid #282f3a;
183 | }
184 | }
185 | .gui-group {
186 | .gui-group-name {
187 | border-bottom: 1px solid #282f3a;
188 | line-height: 26px;
189 | cursor: pointer;
190 | padding: 4px 5px 6px 18px;
191 | text-align: left;
192 | font-size: 12px;
193 | }
194 | .gui-group-content {
195 | background: #15171c;
196 | padding: 5px 0;
197 | .gui-field {
198 | padding-left: 20px;
199 | }
200 | }
201 | }
202 | .gui-color {
203 | display: inline-block;
204 | margin: 0 4px 4px 0
205 | }
206 | .group-title {
207 | padding: 0 10px;
208 | }
209 | }
210 |
211 | // 需要覆盖bin-ui的样式
212 | .options-body .bin-scrollbar__wrap {
213 | overflow-x: hidden;
214 | }
215 | .options-body .bin-collapse-simple {
216 | background-color: $color-admin-options-bg;
217 | }
218 |
219 | // 折叠菜单
220 | .options-body .bin-collapse > .bin-collapse-item > .bin-collapse-header {
221 | color: #fff;
222 | padding-left: 5px;
223 | font-size: 12px;
224 | i {
225 | margin-right: 0;
226 | }
227 | }
228 | .options-body .bin-collapse-content {
229 | background-color: $color-admin-options-dark;
230 | color: $color-text-info;
231 | padding: 0;
232 | .bin-collapse-content-box {
233 | padding-top: 6px;
234 | padding-bottom: 6px;
235 | font-size: 12px;
236 | }
237 | }
238 |
239 | .options-body .bin-collapse > .bin-collapse-item.bin-collapse-item-active > .bin-collapse-header {
240 | border-bottom: 1px solid #282f3a;
241 | }
242 | .options-body .bin-collapse {
243 | border-top: 1px solid #282f3a;
244 | border-bottom: 1px solid #282f3a;
245 | }
246 | .options-body .bin-collapse > .bin-collapse-item {
247 | border-top: 1px solid #282f3a;
248 | }
249 | .options-body .bin-collapse > .bin-collapse-item:first-child {
250 | border-top: none;
251 | }
252 | // 数字输入框样式覆盖
253 | .options-body .bin-input-number {
254 | width: 85px;
255 | }
256 | .options-body .bin-input-number-input {
257 | background-color: $color-admin-options-dark;
258 | color: $color-text-info;
259 | }
260 | .options-body .bin-input-number-handler-wrap {
261 | background-color: $color-admin-options-dark;
262 | }
263 | // 输入框样式
264 | .options-body .bin-input {
265 | background-color: $color-admin-options-dark;
266 | color: $color-text-info;
267 | }
268 |
269 |
270 | // 覆盖element-ui
271 | .options-body {
272 | .el-color-picker {
273 | vertical-align: middle;
274 | height: 26px;
275 | .el-color-picker__trigger {
276 | height: 26px;
277 | width: 26px;
278 | padding: 2px;
279 | }
280 | .el-color-picker__color {
281 | overflow: hidden;
282 | border: none;
283 | }
284 | }
285 |
286 | .el-input__inner {
287 | color: $color-text-info;
288 | background-color: $color-admin-options-dark;
289 | }
290 | .el-select {
291 | .el-input__suffix {
292 | right: 0
293 | }
294 | .el-input__inner {
295 | padding: 0 15px;
296 | }
297 | }
298 | }
299 |
300 |
301 |
--------------------------------------------------------------------------------
/src/styles/board/transform-block.styl:
--------------------------------------------------------------------------------
1 | @import "../common/var.styl"
2 | * {
3 | outline: 0;
4 | }
5 | .dv-transform {
6 | position: absolute;
7 | top: 0;
8 | left: 0;
9 | will-change: transform;
10 | .dv-com {
11 | outline: 0;
12 | transform-origin: 50% 50%;
13 | width: 100%;
14 | height: 100%;
15 | box-sizing: border-box
16 | &.hovered {
17 | background: rgba(0, 231, 255, .11);
18 | }
19 | .dv-wrapper {
20 | pointer-events: none !important;
21 | }
22 | }
23 | .transform-handler {
24 | width: 100%;
25 | height: 100%;
26 | box-sizing: border-box;
27 | cursor: move;
28 | }
29 | &.selected {
30 | z-index: 1;
31 | .dv-com {
32 | background: rgba(0, 231, 255, .11);
33 | }
34 | .dv-scale::after {
35 | z-index: -1;
36 | content: "";
37 | position: absolute;
38 | top: 0;
39 | bottom: 0;
40 | left: 0;
41 | right: 0;
42 | border: 1px dashed #05ddff;
43 | }
44 | }
45 | }
46 | // 导航线条
47 | .navigator-line {
48 | width: 100%;
49 | height: 100%;
50 | position: absolute;
51 | top: 0;
52 | left: 0;
53 | pointer-events: none;
54 | box-sizing: content-box;
55 | .navigator-line-left {
56 | position: absolute;
57 | border-top: 1px dashed $color-navigator-line;
58 | height: 0;
59 | top: 0;
60 | font-size: 12px;
61 | transform: translateX(-100%);
62 | box-sizing: border-box;
63 | }
64 | .navigator-line-top {
65 | position: absolute;
66 | border-left: 1px dashed $color-navigator-line;
67 | width: 0;
68 | left: 0;
69 | font-size: 12px;
70 | transform: translateY(-100%);
71 | box-sizing: border-box;
72 | }
73 | .navigator-line-account {
74 | position: absolute;
75 | transform: translate(-100%, -100%);
76 | color: $color-navigator-line;
77 | text-shadow: 1px 1px 1px #222;
78 | white-space: nowrap;
79 | }
80 | }
81 | // scale-面板
82 | .dv-scale {
83 | transform-origin: 0 0;
84 | width: 100%;
85 | height: 100%;
86 | position: absolute;
87 | }
88 |
89 | .dv-wrapper {
90 | box-sizing: border-box;
91 | }
92 |
93 | //resize-bar
94 | .dv-transform.selected .transform-handler .bottom-handler,
95 | .dv-transform.selected .transform-handler .left-handler,
96 | .dv-transform.selected .transform-handler .right-handler,
97 | .dv-transform.selected .transform-handler .top-handler {
98 | display: flex !important;
99 | }
100 | .transform-handler {
101 | .top-handler {
102 | display: flex;
103 | justify-content: center;
104 | align-items: center;
105 | position: absolute;
106 | top: -5px;
107 | width: 100%;
108 | height: 11px;
109 | .control-point {
110 | display: flex;
111 | justify-content: center;
112 | align-items: center;
113 | height: 20px;
114 | width: 20px;
115 | z-index: 2;
116 | &::after {
117 | content: '';
118 | height: 6px;
119 | width: 6px;
120 | border-radius: 100%;
121 | background: #fff;
122 | }
123 | }
124 | &::after {
125 | content: "";
126 | height: 1px;
127 | background: #05ddff;
128 | width: 100%;
129 | position: absolute;
130 | z-index: 1;
131 | }
132 | }
133 | .bottom-handler {
134 | display: flex;
135 | justify-content: center;
136 | align-items: center;
137 | position: absolute;
138 | bottom: -5px;
139 | width: 100%;
140 | height: 11px;
141 | .control-point {
142 | display: flex;
143 | justify-content: center;
144 | align-items: center;
145 | height: 20px;
146 | width: 20px;
147 | z-index: 2;
148 | &::after {
149 | content: '';
150 | height: 6px;
151 | width: 6px;
152 | border-radius: 100%;
153 | background: #fff;
154 | }
155 | }
156 | &::after {
157 | content: "";
158 | height: 1px;
159 | background: #05ddff;
160 | width: 100%;
161 | position: absolute;
162 | z-index: 1;
163 | }
164 | }
165 | .left-handler {
166 | display: flex;
167 | justify-content: center;
168 | align-items: center;
169 | position: absolute;
170 | top: 0;
171 | left: -5px;
172 | width: 11px;
173 | height: 100%;
174 | .control-point {
175 | display: flex;
176 | justify-content: center;
177 | align-items: center;
178 | height: 20px;
179 | width: 20px;
180 | z-index: 2;
181 | &::after {
182 | content: '';
183 | height: 6px;
184 | width: 6px;
185 | border-radius: 100%;
186 | background: #fff;
187 | }
188 | }
189 | &::after {
190 | content: "";
191 | width: 1px;
192 | background: #05ddff;
193 | height: 100%;
194 | position: absolute;
195 | z-index: 1;
196 | }
197 | }
198 | .right-handler {
199 | display: flex;
200 | justify-content: center;
201 | align-items: center;
202 | position: absolute;
203 | top: 0;
204 | right: -5px;
205 | width: 11px;
206 | height: 100%;
207 | .control-point {
208 | display: flex;
209 | justify-content: center;
210 | align-items: center;
211 | height: 20px;
212 | width: 20px;
213 | z-index: 2;
214 | &::after {
215 | content: '';
216 | height: 6px;
217 | width: 6px;
218 | border-radius: 100%;
219 | background: #fff;
220 | }
221 | }
222 | &::after {
223 | content: "";
224 | width: 1px;
225 | background: #05ddff;
226 | height: 100%;
227 | position: absolute;
228 | z-index: 1;
229 | }
230 | }
231 | .top-left-handler {
232 | display: flex;
233 | justify-content: center;
234 | align-items: center;
235 | position: absolute;
236 | left: -5px;
237 | top: -5px;
238 | height: 11px;
239 | width: 11px;
240 | .control-point {
241 | display: flex;
242 | justify-content: center;
243 | align-items: center;
244 | height: 20px;
245 | width: 20px;
246 | z-index: 2;
247 | &::after {
248 | content: '';
249 | height: 6px;
250 | width: 6px;
251 | border-radius: 100%;
252 | background: #fff;
253 | }
254 | }
255 | }
256 | .top-right-handler {
257 | display: flex;
258 | justify-content: center;
259 | align-items: center;
260 | position: absolute;
261 | right: -5px;
262 | top: -5px;
263 | height: 11px;
264 | width: 11px;
265 | .control-point {
266 | display: flex;
267 | justify-content: center;
268 | align-items: center;
269 | height: 20px;
270 | width: 20px;
271 | z-index: 2;
272 | &::after {
273 | content: '';
274 | height: 6px;
275 | width: 6px;
276 | border-radius: 100%;
277 | background: #fff;
278 | }
279 | }
280 | }
281 | .bottom-left-handler {
282 | display: flex;
283 | justify-content: center;
284 | align-items: center;
285 | position: absolute;
286 | bottom: -5px;
287 | left: -5px;
288 | height: 11px;
289 | width: 11px;
290 | .control-point {
291 | display: flex;
292 | justify-content: center;
293 | align-items: center;
294 | height: 20px;
295 | width: 20px;
296 | z-index: 2;
297 | &::after {
298 | content: '';
299 | height: 6px;
300 | width: 6px;
301 | border-radius: 100%;
302 | background: #fff;
303 | }
304 | }
305 | }
306 | .bottom-right-handler {
307 | display: flex;
308 | justify-content: center;
309 | align-items: center;
310 | position: absolute;
311 | bottom: -5px;
312 | right: -5px;
313 | height: 11px;
314 | width: 11px;
315 | .control-point {
316 | display: flex;
317 | justify-content: center;
318 | align-items: center;
319 | height: 20px;
320 | width: 20px;
321 | z-index: 2;
322 | &::after {
323 | content: '';
324 | height: 6px;
325 | width: 6px;
326 | border-radius: 100%;
327 | background: #fff;
328 | }
329 | }
330 | }
331 | }
332 |
333 | .transform-handler.hide > .transform-bg,
334 | .transform-handler.hide > i[class$="-handler"],
335 | .transform-handler.hide > i[class$="-handler"] .control-point {
336 | display: none;
337 | }
338 |
339 | // 悬停显示
340 | .dv-com.hovered {
341 | .transform-handler > i[class$="-handler"] {
342 | display: flex !important;
343 | }
344 | .transform-handler > i[class$="-handler"] .control-point {
345 | display: none;
346 | }
347 | .top-handler {
348 | &::after {
349 | content: "";
350 | height: 1px;
351 | background: #05ddff;
352 | width: 100%;
353 | position: absolute;
354 | z-index: 1;
355 | }
356 | }
357 | .bottom-handler {
358 | &::after {
359 | content: "";
360 | height: 1px;
361 | background: #05ddff;
362 | width: 100%;
363 | position: absolute;
364 | z-index: 1;
365 | }
366 | }
367 | .left-handler {
368 | &::after {
369 | content: "";
370 | width: 1px;
371 | background: #05ddff;
372 | height: 100%;
373 | position: absolute;
374 | z-index: 1;
375 | }
376 | }
377 | .right-handler {
378 | &::after {
379 | content: "";
380 | width: 1px;
381 | background: #05ddff;
382 | height: 100%;
383 | position: absolute;
384 | z-index: 1;
385 | }
386 | }
387 | }
388 |
389 | // 选中显示
390 | .dv-transform.selected {
391 | .dv-com {
392 | .transform-handler > i[class$="-handler"] .control-point {
393 | display: flex !important;
394 | }
395 | }
396 | }
397 |
--------------------------------------------------------------------------------
/src/components/drag/DragItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
53 |
54 |
55 |
333 |
--------------------------------------------------------------------------------
/preview/static/js/chunk-95354e52.42529e2d.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-95354e52"],{"02f4":function(t,e,n){var i=n("4588"),r=n("be13");t.exports=function(t){return function(e,n){var c,o,s=String(r(e)),a=i(n),u=s.length;return a<0||a>=u?t?"":void 0:(c=s.charCodeAt(a),c<55296||c>56319||a+1===u||(o=s.charCodeAt(a+1))<56320||o>57343?t?s.charAt(a):c:t?s.slice(a,a+2):o-56320+(c-55296<<10)+65536)}}},"0324":function(t,e,n){"use strict";var i=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{ref:"wrap",staticClass:"dv-charts",staticStyle:{width:"100%",height:"100%"}},[t.config.title?n("div",{ref:"titles",staticClass:"titles",style:t.titleStyle},[n("span",[t._v(t._s(t.config.title.content))])]):t._e(),n(t.typeName,{ref:"chart",tag:"component",attrs:{data:t.chartData,width:t.width,height:t.height,"legend-visible":t.legendVisible,"after-config":t.afterConfig,extend:t.chartExtend,options:t.chartOptions,settings:t.chartSettings}})],1)},r=[],c=n("75fc"),o=n("cebc"),s=n("fbe2"),a=(n("7f7f"),n("6762"),n("2fdb"),n("ac6a"),n("5df3"),n("f400"),{"海门":[121.15,31.89],"鄂尔多斯":[109.781327,39.608266],"招远":[120.38,37.35],"舟山":[122.207216,29.985295],"齐齐哈尔":[123.97,47.33],"盐城":[120.13,33.38],"赤峰":[118.87,42.28],"青岛":[120.33,36.07],"乳山":[121.52,36.89],"金昌":[102.188043,38.520089],"泉州":[118.58,24.93],"莱西":[120.53,36.86],"日照":[119.46,35.42],"胶南":[119.97,35.88],"南通":[121.05,32.08],"拉萨":[91.11,29.97],"云浮":[112.02,22.93],"梅州":[116.1,24.55],"文登":[122.05,37.2],"上海":[121.48,31.22],"攀枝花":[101.718637,26.582347],"威海":[122.1,37.5],"承德":[117.93,40.97],"厦门":[118.1,24.46],"汕尾":[115.375279,22.786211],"潮州":[116.63,23.68],"丹东":[124.37,40.13],"太仓":[121.1,31.45],"曲靖":[103.79,25.51],"烟台":[121.39,37.52],"福州":[119.3,26.08],"瓦房店":[121.979603,39.627114],"即墨":[120.45,36.38],"抚顺":[123.97,41.97],"玉溪":[102.52,24.35],"张家口":[114.87,40.82],"阳泉":[113.57,37.85],"莱州":[119.942327,37.177017],"湖州":[120.1,30.86],"汕头":[116.69,23.39],"昆山":[120.95,31.39],"宁波":[121.56,29.86],"湛江":[110.359377,21.270708],"揭阳":[116.35,23.55],"荣成":[122.41,37.16],"连云港":[119.16,34.59],"葫芦岛":[120.836932,40.711052],"常熟":[120.74,31.64],"东莞":[113.75,23.04],"河源":[114.68,23.73],"淮安":[119.15,33.5],"泰州":[119.9,32.49],"南宁":[108.33,22.84],"营口":[122.18,40.65],"惠州":[114.4,23.09],"江阴":[120.26,31.91],"蓬莱":[120.75,37.8],"韶关":[113.62,24.84],"嘉峪关":[98.289152,39.77313],"广州":[113.23,23.16],"延安":[109.47,36.6],"太原":[112.53,37.87],"清远":[113.01,23.7],"中山":[113.38,22.52],"昆明":[102.73,25.04],"寿光":[118.73,36.86],"盘锦":[122.070714,41.119997],"长治":[113.08,36.18],"深圳":[114.07,22.62],"珠海":[113.52,22.3],"宿迁":[118.3,33.96],"咸阳":[108.72,34.36],"铜川":[109.11,35.09],"平度":[119.97,36.77],"佛山":[113.11,23.05],"海口":[110.35,20.02],"江门":[113.06,22.61],"章丘":[117.53,36.72],"肇庆":[112.44,23.05],"大连":[121.62,38.92],"临汾":[111.5,36.08],"吴江":[120.63,31.16],"石嘴山":[106.39,39.04],"沈阳":[123.38,41.8],"苏州":[120.62,31.32],"茂名":[110.88,21.68],"嘉兴":[120.76,30.77],"长春":[125.35,43.88],"胶州":[120.03336,36.264622],"银川":[106.27,38.47],"张家港":[120.555821,31.875428],"三门峡":[111.19,34.76],"锦州":[121.15,41.13],"南昌":[115.89,28.68],"柳州":[109.4,24.33],"三亚":[109.511909,18.252847],"自贡":[104.778442,29.33903],"吉林":[126.57,43.87],"阳江":[111.95,21.85],"泸州":[105.39,28.91],"西宁":[101.74,36.56],"宜宾":[104.56,29.77],"呼和浩特":[111.65,40.82],"成都":[104.06,30.67],"大同":[113.3,40.12],"镇江":[119.44,32.2],"桂林":[110.28,25.29],"张家界":[110.479191,29.117096],"宜兴":[119.82,31.36],"北海":[109.12,21.49],"西安":[108.95,34.27],"金坛":[119.56,31.74],"东营":[118.49,37.46],"牡丹江":[129.58,44.6],"遵义":[106.9,27.7],"绍兴":[120.58,30.01],"扬州":[119.42,32.39],"常州":[119.95,31.79],"潍坊":[119.1,36.62],"重庆":[106.54,29.59],"台州":[121.420757,28.656386],"南京":[118.78,32.04],"滨州":[118.03,37.36],"贵阳":[106.71,26.57],"无锡":[120.29,31.59],"本溪":[123.73,41.3],"克拉玛依":[84.77,45.59],"渭南":[109.5,34.52],"马鞍山":[118.48,31.56],"宝鸡":[107.15,34.38],"焦作":[113.21,35.24],"句容":[119.16,31.95],"北京":[116.46,39.92],"徐州":[117.2,34.26],"衡水":[115.72,37.72],"包头":[110,40.58],"绵阳":[104.73,31.48],"乌鲁木齐":[87.68,43.77],"枣庄":[117.57,34.86],"杭州":[120.19,30.26],"淄博":[118.05,36.78],"鞍山":[122.85,41.12],"溧阳":[119.48,31.43],"库尔勒":[86.06,41.68],"安阳":[114.35,36.1],"开封":[114.35,34.79],"济南":[117,36.65],"德阳":[104.37,31.13],"温州":[120.65,28.01],"九江":[115.97,29.71],"邯郸":[114.47,36.6],"临安":[119.72,30.23],"兰州":[103.73,36.03],"沧州":[116.83,38.33],"临沂":[118.35,35.05],"南充":[106.110698,30.837793],"天津":[117.2,39.13],"富阳":[119.95,30.07],"泰安":[117.13,36.18],"诸暨":[120.23,29.71],"郑州":[113.65,34.76],"哈尔滨":[126.63,45.75],"聊城":[115.97,36.45],"芜湖":[118.38,31.33],"唐山":[118.02,39.63],"平顶山":[113.29,33.75],"邢台":[114.48,37.05],"德州":[116.29,37.45],"济宁":[116.59,35.38],"荆州":[112.239741,30.335165],"宜昌":[111.3,30.7],"义乌":[120.06,29.32],"丽水":[119.92,28.45],"洛阳":[112.44,34.7],"秦皇岛":[119.57,39.95],"株洲":[113.16,27.83],"石家庄":[114.48,38.03],"莱芜":[117.67,36.19],"常德":[111.69,29.05],"保定":[115.48,38.85],"湘潭":[112.91,27.87],"金华":[119.64,29.12],"岳阳":[113.09,29.37],"长沙":[113,28.21],"衢州":[118.88,28.97],"廊坊":[116.7,39.53],"菏泽":[115.480656,35.23375],"合肥":[117.27,31.86],"武汉":[114.31,30.52],"大庆":[125.03,46.58]});function u(t){var e={columns:[],rows:[]},n=new Map;return t.forEach(function(t){var i={};if(t.x&&(e.columns[0]="x",i["x"]=t.x),t.s?(e.columns.includes(t.s)||e.columns.push(t.s),i[t.s]=t.y):(e.columns[1]="s",i["s"]=t.y),n.has(t.x)){var r=Object.assign(n.get(t.x),i);n.set(t.x,r)}else n.set(t.x,i)}),e.rows=Object(c["a"])(n.values()),e}function f(t){for(var e=[],n=0;n1?arguments[1]:void 0)}})},5147:function(t,e,n){var i=n("2b4c")("match");t.exports=function(t){var e=/./;try{"/./"[t](e)}catch(n){try{return e[i]=!1,!"/./"[t](e)}catch(r){}}return!0}},"5dbc":function(t,e,n){var i=n("d3f4"),r=n("8b97").set;t.exports=function(t,e,n){var c,o=e.constructor;return o!==n&&"function"==typeof o&&(c=o.prototype)!==n.prototype&&i(c)&&r&&r(t,c),t}},"5df3":function(t,e,n){"use strict";var i=n("02f4")(!0);n("01f9")(String,"String",function(t){this._t=String(t),this._i=0},function(){var t,e=this._t,n=this._i;return n>=e.length?{value:void 0,done:!0}:(t=i(e,n),this._i+=t.length,{value:t,done:!1})})},6762:function(t,e,n){"use strict";var i=n("5ca1"),r=n("c366")(!0);i(i.P,"Array",{includes:function(t){return r(this,t,arguments.length>1?arguments[1]:void 0)}}),n("9c6c")("includes")},"67ab":function(t,e,n){var i=n("ca5a")("meta"),r=n("d3f4"),c=n("69a8"),o=n("86cc").f,s=0,a=Object.isExtensible||function(){return!0},u=!n("79e5")(function(){return a(Object.preventExtensions({}))}),f=function(t){o(t,i,{value:{i:"O"+ ++s,w:{}}})},l=function(t,e){if(!r(t))return"symbol"==typeof t?t:("string"==typeof t?"S":"P")+t;if(!c(t,i)){if(!a(t))return"F";if(!e)return"E";f(t)}return t[i].i},h=function(t,e){if(!c(t,i)){if(!a(t))return!0;if(!e)return!1;f(t)}return t[i].w},d=function(t){return u&&p.NEED&&a(t)&&!c(t,i)&&f(t),t},p=t.exports={KEY:i,NEED:!1,fastKey:l,getWeak:h,onFreeze:d}},"7f7f":function(t,e,n){var i=n("86cc").f,r=Function.prototype,c=/^\s*function ([^ (]*)/,o="name";o in r||n("9e1e")&&i(r,o,{configurable:!0,get:function(){try{return(""+this).match(c)[1]}catch(t){return""}}})},"8b97":function(t,e,n){var i=n("d3f4"),r=n("cb7c"),c=function(t,e){if(r(t),!i(e)&&null!==e)throw TypeError(e+": can't set as prototype!")};t.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(t,e,i){try{i=n("9b43")(Function.call,n("11e9").f(Object.prototype,"__proto__").set,2),i(t,[]),e=!(t instanceof Array)}catch(r){e=!0}return function(t,n){return c(t,n),e?t.__proto__=n:i(t,n),t}}({},!1):void 0),check:c}},aae3:function(t,e,n){var i=n("d3f4"),r=n("2d95"),c=n("2b4c")("match");t.exports=function(t){var e;return i(t)&&(void 0!==(e=t[c])?!!e:"RegExp"==r(t))}},ac6a:function(t,e,n){for(var i=n("cadf"),r=n("0d58"),c=n("2aba"),o=n("7726"),s=n("32e9"),a=n("84f2"),u=n("2b4c"),f=u("iterator"),l=u("toStringTag"),h=a.Array,d={CSSRuleList:!0,CSSStyleDeclaration:!1,CSSValueList:!1,ClientRectList:!1,DOMRectList:!1,DOMStringList:!1,DOMTokenList:!0,DataTransferItemList:!1,FileList:!1,HTMLAllCollection:!1,HTMLCollection:!1,HTMLFormElement:!1,HTMLSelectElement:!1,MediaList:!0,MimeTypeArray:!1,NamedNodeMap:!1,NodeList:!0,PaintRequestList:!1,Plugin:!1,PluginArray:!1,SVGLengthList:!1,SVGNumberList:!1,SVGPathSegList:!1,SVGPointList:!1,SVGStringList:!1,SVGTransformList:!1,SourceBufferList:!1,StyleSheetList:!0,TextTrackCueList:!1,TextTrackList:!1,TouchList:!1},p=r(d),_=0;_1?arguments[1]:void 0,3);while(n=n?n.n:this._f){i(n.v,n.k,this);while(n&&n.r)n=n.p}},has:function(t){return!!v(p(this,e),t)}}),h&&i(f.prototype,"size",{get:function(){return p(this,e)[_]}}),f},def:function(t,e,n){var i,r,c=v(t,e);return c?c.v=n:(t._l=c={i:r=d(e,!0),k:e,v:n,p:i=t._l,n:void 0,r:!1},t._f||(t._f=c),i&&(i.n=c),t[_]++,"F"!==r&&(t._i[r]=c)),t},getEntry:v,setStrong:function(t,e,n){u(t,e,function(t,n){this._t=p(t,e),this._k=n,this._l=void 0},function(){var t=this,e=t._k,n=t._l;while(n&&n.r)n=n.p;return t._t&&(t._l=n=n?n.n:t._t._f)?f(0,"keys"==e?n.k:"values"==e?n.v:[n.k,n.v]):(t._t=void 0,f(1))},n?"entries":"values",!n,!0),l(e)}}},d2c8:function(t,e,n){var i=n("aae3"),r=n("be13");t.exports=function(t,e,n){if(i(e))throw TypeError("String#"+n+" doesn't accept regex!");return String(r(t))}},e0b8:function(t,e,n){"use strict";var i=n("7726"),r=n("5ca1"),c=n("2aba"),o=n("dcbc"),s=n("67ab"),a=n("4a59"),u=n("f605"),f=n("d3f4"),l=n("79e5"),h=n("5cc5"),d=n("7f20"),p=n("5dbc");t.exports=function(t,e,n,_,v,g){var b=i[t],y=b,S=v?"set":"add",x=y&&y.prototype,m={},w=function(t){var e=x[t];c(x,t,"delete"==t?function(t){return!(g&&!f(t))&&e.call(this,0===t?0:t)}:"has"==t?function(t){return!(g&&!f(t))&&e.call(this,0===t?0:t)}:"get"==t?function(t){return g&&!f(t)?void 0:e.call(this,0===t?0:t)}:"add"==t?function(t){return e.call(this,0===t?0:t),this}:function(t,n){return e.call(this,0===t?0:t,n),this})};if("function"==typeof y&&(g||x.forEach&&!l(function(){(new y).entries().next()}))){var L=new y,O=L[S](g?{}:-0,1)!=L,E=l(function(){L.has(1)}),j=h(function(t){new y(t)}),T=!g&&l(function(){var t=new y,e=5;while(e--)t[S](e,e);return!t.has(-0)});j||(y=e(function(e,n){u(e,y,t);var i=p(new b,e,y);return void 0!=n&&a(n,v,i[S],i),i}),y.prototype=x,x.constructor=y),(E||T)&&(w("delete"),w("has"),v&&w("get")),(T||O)&&w(S),g&&x.clear&&delete x.clear}else y=_.getConstructor(e,t,v,S),o(y.prototype,n),s.NEED=!0;return d(y,t),m[t]=y,r(r.G+r.W+r.F*(y!=b),m),g||_.setStrong(y,t,v),y}},f400:function(t,e,n){"use strict";var i=n("c26b"),r=n("b39a"),c="Map";t.exports=n("e0b8")(c,function(t){return function(){return t(this,arguments.length>0?arguments[0]:void 0)}},{get:function(t){var e=i.getEntry(r(this,c),t);return e&&e.v},set:function(t,e){return i.def(r(this,c),0===t?0:t,e)}},i,!0)},fbe2:function(t,e,n){"use strict";n.d(e,"a",function(){return o}),n.d(e,"b",function(){return s});var i=n("6dd8");const r="undefined"===typeof window,c=function(t){for(let e of t){const t=e.target.__resizeListeners__||[];t.length&&t.forEach(t=>{t()})}},o=function(t,e){r||(t.__resizeListeners__||(t.__resizeListeners__=[],t.__ro__=new i["default"](c),t.__ro__.observe(t)),t.__resizeListeners__.push(e))},s=function(t,e){t&&t.__resizeListeners__&&(t.__resizeListeners__.splice(t.__resizeListeners__.indexOf(e),1),t.__resizeListeners__.length||t.__ro__.disconnect())}}}]);
--------------------------------------------------------------------------------
/preview/static/js/app.6a3a718f.js:
--------------------------------------------------------------------------------
1 | (function(e){function t(t){for(var o,c,r=t[0],s=t[1],f=t[2],l=0,p=[];l