大屏设计器,先这样。。。。
qianlishi 3 years ago
parent be936e481f
commit d03af19e96

@ -54,6 +54,18 @@
<div class="content unicode" style="display: block;"> <div class="content unicode" style="display: block;">
<ul class="icon_lists dib-box"> <ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont">&#xe60d;</span>
<div class="name">恢复备份</div>
<div class="code-name">&amp;#xe60d;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe60e;</span>
<div class="name">撤销</div>
<div class="code-name">&amp;#xe60e;</div>
</li>
<li class="dib"> <li class="dib">
<span class="icon iconfont">&#xe7af;</span> <span class="icon iconfont">&#xe7af;</span>
<div class="name">词云图</div> <div class="name">词云图</div>
@ -792,9 +804,9 @@
<pre><code class="language-css" <pre><code class="language-css"
>@font-face { >@font-face {
font-family: 'iconfont'; font-family: 'iconfont';
src: url('iconfont.woff2?t=1643094287456') format('woff2'), src: url('iconfont.woff2?t=1646807984187') format('woff2'),
url('iconfont.woff?t=1643094287456') format('woff'), url('iconfont.woff?t=1646807984187') format('woff'),
url('iconfont.ttf?t=1643094287456') format('truetype'); url('iconfont.ttf?t=1646807984187') format('truetype');
} }
</code></pre> </code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3> <h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
@ -820,6 +832,24 @@
<div class="content font-class"> <div class="content font-class">
<ul class="icon_lists dib-box"> <ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont iconhuifubeifen"></span>
<div class="name">
恢复备份
</div>
<div class="code-name">.iconhuifubeifen
</div>
</li>
<li class="dib">
<span class="icon iconfont iconundo"></span>
<div class="name">
撤销
</div>
<div class="code-name">.iconundo
</div>
</li>
<li class="dib"> <li class="dib">
<span class="icon iconfont iconciyuntu"></span> <span class="icon iconfont iconciyuntu"></span>
<div class="name"> <div class="name">
@ -1927,6 +1957,22 @@
<div class="content symbol"> <div class="content symbol">
<ul class="icon_lists dib-box"> <ul class="icon_lists dib-box">
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#iconhuifubeifen"></use>
</svg>
<div class="name">恢复备份</div>
<div class="code-name">#iconhuifubeifen</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#iconundo"></use>
</svg>
<div class="name">撤销</div>
<div class="code-name">#iconundo</div>
</li>
<li class="dib"> <li class="dib">
<svg class="icon svg-icon" aria-hidden="true"> <svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#iconciyuntu"></use> <use xlink:href="#iconciyuntu"></use>

@ -1,8 +1,8 @@
@font-face { @font-face {
font-family: "iconfont"; /* Project id 1513211 */ font-family: "iconfont"; /* Project id 1513211 */
src: url('iconfont.woff2?t=1643094287456') format('woff2'), src: url('iconfont.woff2?t=1646807984187') format('woff2'),
url('iconfont.woff?t=1643094287456') format('woff'), url('iconfont.woff?t=1646807984187') format('woff'),
url('iconfont.ttf?t=1643094287456') format('truetype'); url('iconfont.ttf?t=1646807984187') format('truetype');
} }
.iconfont { .iconfont {
@ -13,6 +13,14 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.iconhuifubeifen:before {
content: "\e60d";
}
.iconundo:before {
content: "\e60e";
}
.iconciyuntu:before { .iconciyuntu:before {
content: "\e7af"; content: "\e7af";
} }

File diff suppressed because one or more lines are too long

@ -5,6 +5,20 @@
"css_prefix_text": "icon", "css_prefix_text": "icon",
"description": "", "description": "",
"glyphs": [ "glyphs": [
{
"icon_id": "15047024",
"name": "恢复备份",
"font_class": "huifubeifen",
"unicode": "e60d",
"unicode_decimal": 58893
},
{
"icon_id": "19657550",
"name": "撤销",
"font_class": "undo",
"unicode": "e60e",
"unicode_decimal": 58894
},
{ {
"icon_id": "23043843", "icon_id": "23043843",
"name": "词云图", "name": "词云图",

@ -0,0 +1,237 @@
.layout {
width: 100%;
height: 100%;
background: #242a30;
color: #fff;
.layout-bar {
height: 40px;
line-height: 40px;
font-size: 12px;
padding: 0 10px;
display: flex;
flex-direction: row;
overflow: hidden;
.bar-item {
margin-right: 20px;
cursor: pointer;
.iconfont {
font-size: 12px;
margin-right: 4px;
}
.el-dropdown-link {
color: #fff;
cursor: pointer;
}
}
}
.layout-container {
width: 100%;
height: calc(100vh - 40px);
display: flex;
flex-direction: row;
justify-content: space-between;
overflow: hidden;
.layout-left {
width: 200px;
background: #242a30;
overflow-x: hidden;
overflow-y: auto;
.chart-type {
display: flex;
flex-direction: row;
overflow: hidden;
.type-left {
width: 100%;
height: calc(100vh - 80px);
text-align: center;
/deep/.el-tabs__header {
width: 30%;
margin-right: 0;
.el-tabs__nav-wrap {
&::after {
background: transparent;
}
.el-tabs__item {
text-align: center;
width: 100%;
color: #fff;
padding: 0;
}
}
}
/deep/.el-tabs__content {
width: 70%;
}
}
}
//
.tools-item {
display: flex;
position: relative;
width: 100%;
height: 48px;
align-items: center;
-webkit-box-align: center;
padding: 0 6px;
cursor: pointer;
font-size: 12px;
margin-bottom: 1px;
.tools-item-icon {
color: #409eff;
margin-right: 10px;
width: 53px;
height: 30px;
line-height: 30px;
text-align: center;
display: block;
border: 1px solid #3a4659;
background: #282a30;
}
.tools-item-text {
}
}
/deep/.el-tabs__content {
padding: 0;
}
}
.layout-middle {
// display: flex;
position: relative;
//width: calc(100% - 445px);
height: 100%;
background-color: rgb(36, 42, 48);
box-sizing: border-box;
-webkit-box-sizing: border-box;
border: 1px solid rgb(36, 42, 48);
align-items: center;
vertical-align: middle;
text-align: center;
.workbench-container {
position: relative;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
margin: 0;
padding: 0;
.vueRuler {
width: 100%;
padding: 18px 0px 0px 18px;
}
.workbench {
background-color: #1e1e1e;
position: relative;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
margin: 0;
padding: 0;
}
.bg-grid {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-size: 30px 30px, 30px 30px;
background-image: linear-gradient(
hsla(0, 0%, 100%, 0.1) 1px,
transparent 0
),
linear-gradient(90deg, hsla(0, 0%, 100%, 0.1) 1px, transparent 0);
// z-index: 2;
}
}
}
.layout-right {
width: 300px;
}
/deep/ .el-tabs--border-card {
border: 0;
.el-tabs__header {
background: transparent;
.el-tabs__nav {
width: 100%;
.el-tabs__item {
background-color: #242f3b;
border: 0px;
font-size: 12px;
width: 50%;
.icon {
margin-right: 4px;
}
}
.el-tabs__item.is-active {
background-color: #31455d;
}
}
}
.el-tabs__content {
background-color: #242a30;
height: calc(100vh - 80px);
overflow-x: hidden;
overflow-y: auto;
.el-tab-pane {
color: #bfcbd9;
}
&::-webkit-scrollbar {
width: 5px;
height: 14px;
}
&::-webkit-scrollbar-track,
&::-webkit-scrollbar-thumb {
border-radius: 1px;
border: 0 solid transparent;
}
&::-webkit-scrollbar-track-piece {
/*修改滚动条的背景和圆角*/
background: #29405c;
-webkit-border-radius: 7px;
}
&::-webkit-scrollbar-track {
box-shadow: 1px 1px 5px rgba(116, 148, 170, 0.5) inset;
}
&::-webkit-scrollbar-thumb {
min-height: 20px;
background-clip: content-box;
box-shadow: 0 0 0 5px rgba(116, 148, 170, 0.5) inset;
}
&::-webkit-scrollbar-corner {
background: transparent;
}
/*修改垂直滚动条的样式*/
&::-webkit-scrollbar-thumb:vertical {
background-color: #00113a;
-webkit-border-radius: 7px;
}
/*修改水平滚动条的样式*/
&::-webkit-scrollbar-thumb:horizontal {
background-color: #00113a;
-webkit-border-radius: 7px;
}
}
}
}
}
/deep/.el-dropdown-menu__item {
max-width: none;
}

@ -260,6 +260,12 @@ export const constantRouterMap = [
requireAuth: true requireAuth: true
} }
}, },
// 重写大屏
{
path: '/screenDesigner',
component: () => import('@/views/screenDesigner/index'),
name: 'screenDesigner',
},
{ {
path: '/404', path: '/404',
component: () => import('@/views/404'), component: () => import('@/views/404'),

@ -288,7 +288,7 @@ import draggable from "vuedraggable";
import VueRulerTool from "vue-ruler-tool"; // import VueRulerTool from "vue-ruler-tool"; //
import contentMenu from "./components/contentMenu"; import contentMenu from "./components/contentMenu";
import { getToken } from "@/utils/auth"; import { getToken } from "@/utils/auth";
import { Revoke } from '@/utils/revoke' // 2022-02-22 import { Revoke } from "@/utils/revoke"; // 2022-02-22
export default { export default {
name: "Login", name: "Login",
@ -425,15 +425,15 @@ export default {
this.handlerLayerWidget(val); this.handlerLayerWidget(val);
// //
this.$nextTick(() => { this.$nextTick(() => {
this.revoke.push(this.widgets) this.revoke.push(this.widgets);
}) });
}, },
deep: true deep: true
} }
}, },
created() { created() {
/* 以下是记录历史的 */ /* 以下是记录历史的 */
this.revoke = new Revoke() this.revoke = new Revoke();
}, },
mounted() { mounted() {
// //
@ -450,11 +450,11 @@ export default {
* @return {*} * @return {*}
*/ */
handleUndo() { handleUndo() {
const record = this.revoke.undo() const record = this.revoke.undo();
if (!record) { if (!record) {
return false return false;
} }
this.widgets = record this.widgets = record;
}, },
/** /**
* @description: 重做 * @description: 重做
@ -462,11 +462,11 @@ export default {
* @return {*} * @return {*}
*/ */
handleRedo() { handleRedo() {
const record = this.revoke.redo() const record = this.revoke.redo();
if (!record) { if (!record) {
return false return false;
} }
this.widgets = record this.widgets = record;
}, },
handlerLayerWidget(val) { handlerLayerWidget(val) {
const layerWidgetArr = []; const layerWidgetArr = [];
@ -712,9 +712,9 @@ export default {
//20220222 //20220222
widgetJsonValue.value.position.left = widgetJsonValue.value.position.left =
x - widgetJsonValue.value.position.width / 2 x - widgetJsonValue.value.position.width / 2;
widgetJsonValue.value.position.top = widgetJsonValue.value.position.top =
y - widgetJsonValue.value.position.height / 2 y - widgetJsonValue.value.position.height / 2;
// //
this.widgets.push(this.deepClone(widgetJsonValue)); this.widgets.push(this.deepClone(widgetJsonValue));

@ -4,7 +4,7 @@
* @Author: qianlishi * @Author: qianlishi
* @Date: 2021-08-29 06:43:07 * @Date: 2021-08-29 06:43:07
* @LastEditors: qianlishi * @LastEditors: qianlishi
* @LastEditTime: 2021-12-13 10:22:37 * @LastEditTime: 2022-03-11 10:35:35
*/ */
import { widgetTool } from "./main" import { widgetTool } from "./main"
const screenConfig = { const screenConfig = {
@ -81,5 +81,5 @@ const getToolByCode = function (code) {
}) })
return item return item
} }
console.log(widgetTools)
export {widgetTools, getToolByCode} export {widgetTools, getToolByCode}

@ -0,0 +1,71 @@
<template>
<el-input
clearable
v-model="colorValue"
placeholder="请输入颜色"
size="mini"
@change="changeColor"
>
<template slot="append">
<el-color-picker
v-model="colorValue"
:predefine="predefineColors"
show-alpha
size="mini"
@change="changeColor"
/>
</template>
</el-input>
</template>
<script>
export default {
name: "ColorPicker",
model: {
prop: "value",
event: "input"
},
props: {
value: {
type: [String],
default: ""
}
},
data() {
return {
predefineColors: [
"#ff4500",
"#ff8c00",
"#ffd700",
"#90ee90",
"#00ced1",
"#1e90ff",
"#c71585"
],
colorValue: ""
};
},
watch: {
value(val) {
this.colorValue = val || "";
}
},
mounted() {
this.colorValue = this.value;
},
methods: {
changeColor(val) {
this.colorValue = val || "";
this.$emit("input", this.colorValue);
this.$emit("change", this.colorValue);
}
}
};
</script>
<style lang="scss" scoped>
/deep/.el-color-picker--mini,
/deep/.el-color-picker--mini .el-color-picker__trigger {
width: 23px;
height: 23px;
}
</style>

@ -0,0 +1,106 @@
<template>
<div v-show="visible" class="contentmenu" :style="styleObj">
<div class="contentmenu__item" @click="deleteLayer">
<i class="iconfont iconguanbi"></i> 删除图层
</div>
<div class="contentmenu__item" @click="copyLayer">
<i class="iconfont iconfuzhi1"></i> 复制图层
</div>
<div class="contentmenu__item" @click="istopLayer">
<i class="iconfont iconjinlingyingcaiwangtubiao01"></i> 置顶图层
</div>
<div class="contentmenu__item" @click="setlowLayer">
<i class="iconfont iconleft-copy"></i> 置底图层
</div>
<div class="contentmenu__item" @click="moveupLayer">
<i class="iconfont iconjinlingyingcaiwangtubiao01"></i> 上移一层
</div>
<div class="contentmenu__item" @click="movedownLayer">
<i class="iconfont iconleft-copy"></i> 下移一层
</div>
</div>
</template>
<script>
export default {
props: {
styleObj: Object,
visible: Boolean
},
data() {
return {};
},
watch: {
visible(value) {
if (value) {
document.body.addEventListener("click", this.closeMenu);
} else {
document.body.removeEventListener("click", this.closeMenu);
}
}
},
methods: {
closeMenu() {
this.$emit("update:visible", false);
},
deleteLayer() {
this.$confirm("是否删除所选图层?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.$emit("deletelayer");
this.$message({
type: "success",
message: "删除成功!"
});
})
.catch(() => {
this.$message({
type: "info",
message: "已取消删除"
});
});
},
copyLayer() {
this.$emit("copylayer");
},
istopLayer() {
this.$emit("istopLayer");
},
setlowLayer() {
this.$emit("setlowLayer");
},
moveupLayer() {
this.$emit("moveupLayer");
},
movedownLayer() {
this.$emit("movedownLayer");
}
}
};
</script>
<style lang="scss" scoped>
.contentmenu {
width: 160px;
position: fixed;
z-index: 99999;
list-style: none;
-webkit-box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
padding: 0;
background: #27343e;
color: #bcc9d4;
.contentmenu__item {
z-index: 10000;
list-style: none;
padding: 8px 12px;
cursor: pointer;
position: relative;
font-size: 12px;
}
.iconfont {
font-size: 12px;
}
}
</style>

@ -0,0 +1,191 @@
<template>
<div>
<el-button
type="primary"
size="mini"
icon="el-icon-plus"
plain
@click="handleAddClick"
>新增</el-button
>
<el-table :data="formData" style="width: 100%">
<el-table-column prop="color" label="颜色" align="center">
<template slot-scope="scope">
<span class="color-box" :style="{ background: scope.row.color }" />
</template>
</el-table-column>
<el-table-column label="位置" align="center">
<template slot-scope="scope">
<span
class="editor"
@click="handleEditorClick(scope.$index, scope.row)"
>
<i class="el-icon-edit" /> 编辑
</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<span
class="editor"
@click="handleDeleteClick(scope.$index, scope.row)"
>
<i class="el-icon-delete" /> 删除
</span>
</template>
</el-table-column>
</el-table>
<el-dialog
title="新增"
:visible.sync="dialogVisible"
width="30%"
:before-close="handleClose"
>
<el-form>
<el-form-item label="颜色">
<el-input
v-model="colorValue"
style="width: 200px"
placeholder="请输入颜色"
size="mini"
>
<template slot="append">
<el-color-picker
v-model="colorValue"
:predefine="predefineColors"
size="mini"
/>
</template>
</el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button size="mini" @click="dialogVisible = false"> </el-button>
<el-button size="mini" type="primary" @click="handleSaveClick"
> </el-button
>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name: "CustomColorComponents",
model: {
prop: "formData",
event: "input"
},
props: {
formData: Array
},
data() {
return {
predefineColors: [
"#ff4500",
"#ff8c00",
"#ffd700",
"#90ee90",
"#00ced1",
"#1e90ff",
"#c71585"
],
colorValue: "",
dialogVisible: false,
flag: true, // true false
indexEditor: -1 //
};
},
mounted() {},
methods: {
//
handleClose() {
this.dialogVisible = false;
this.colorValue = "";
},
//
handleAddClick() {
this.colorValue = "";
this.flag = true;
this.dialogVisible = true;
},
//
handleSaveClick() {
if (this.flag) {
//
const obj = {
color: this.colorValue
};
this.formData.push(obj);
this.dialogVisible = false;
} else {
//
this.formData[this.indexEditor].color = this.colorValue;
this.dialogVisible = false;
}
this.$emit("input", this.formData);
this.$emit("change", this.formData);
},
//
handleEditorClick(index, row) {
this.flag = false;
this.colorValue = row.color;
this.dialogVisible = true;
this.indexEditor = index;
},
//
handleDeleteClick(index) {
this.formData.splice(index, 1);
this.$emit("input", this.formData);
this.$emit("change", this.formData);
}
}
};
</script>
<style lang="scss" scoped>
.color-box {
.title {
display: flex;
flex-direction: row;
}
}
/deep/.el-table,
/deep/.el-table__expanded-cell,
/deep/.el-table th,
/deep/.el-table tr {
background-color: transparent !important;
color: #859094 !important;
}
/deep/.el-table td,
/deep/.el-table th.is-leaf {
border-bottom: none;
line-height: 26px;
}
/deep/.el-table tbody tr:hover > td {
background-color: #263445 !important;
}
/deep/.el-table::before {
height: 0;
}
/deep/.el-color-picker--mini,
/deep/.el-color-picker--mini .el-color-picker__trigger {
width: 23px;
height: 23px;
}
/deep/.el-dialog {
background: #1b1e25;
.el-dialog__title {
color: #fff;
}
}
.color-box {
display: inline-block;
width: 20px;
height: 20px;
border-radius: 5px;
}
.editor {
color: #409eff;
cursor: pointer;
}
</style>

@ -0,0 +1,101 @@
<template>
<div>
<el-input
clearable
v-model.trim="uploadImgUrl"
size="mini"
@change="changeInput"
>
<template slot="append">
<i class="iconfont iconfolder-o"></i>
<input type="file" class="file" ref="files" @change="getImages" />
</template>
</el-input>
</div>
</template>
<script>
import axios from "axios";
import { getToken } from "@/utils/auth";
export default {
model: {
prop: "value",
event: "input"
},
props: {
value: {
type: "",
default: ""
}
},
data() {
return {
requestUrl: process.env.BASE_API + "/file/upload",
headers: {
Authorization: getToken()
},
fileList: [],
uploadImgUrl: ""
};
},
created() {
this.uploadImgUrl = this.value;
},
methods: {
getImages(el) {
let file = el.target.files[0];
let type = file.type.split("/")[0];
if (type === "image") {
this.upload(file);
} else {
this.$message.warn("只能上传图片格式");
}
},
upload(imgUrl) {
let that = this;
console.log(that.headers);
let formdata = new FormData();
formdata.append("file", imgUrl);
axios
.post(this.requestUrl, formdata, {
headers: that.headers
})
.then(response => {
let res = response.data;
if (res.code == "200") {
that.uploadImgUrl = res.data.urlPath;
that.$emit("input", that.uploadImgUrl);
that.$emit("change", that.uploadImgUrl);
}
});
},
changeInput(e) {
if (e) {
this.uploadImgUrl = e;
} else {
this.$refs.files.value = "";
this.uploadImgUrl = "";
}
this.$emit("input", this.uploadImgUrl);
this.$emit("change", this.uploadImgUrl);
}
}
};
</script>
<style lang="scss" scoped>
.file {
position: absolute;
width: 100%;
padding: 100%;
right: 0;
top: 0;
opacity: 0;
}
/deep/.el-input-group__append,
/deep/.el-input-group__prepend {
padding: 0 10px !important;
overflow: hidden;
}
.iconfont {
font-size: 12px;
}
</style>

@ -0,0 +1,178 @@
<template>
<div>
<el-button
type="primary"
size="small"
icon="el-icon-plus"
plain
@click="handleAddClick"
>新增</el-button
>
<el-table :data="formData" style="width: 100%">
<el-table-column prop="name" label="名称" width="60" />
<el-table-column prop="key" label="key值" width="70" />
<el-table-column prop="width" label="宽度" width="50" />
<el-table-column label="操作" width="100">
<template slot-scope="scope">
<div class="button-group">
<el-button
@click="handleEditorClick(scope.$index, scope.row)"
type="text"
size="small"
>编辑</el-button
>
<el-button
type="text"
size="small"
@click="handleDeleteClick(scope.$index, scope.row)"
>删除</el-button
>
</div>
</template>
</el-table-column>
</el-table>
<el-dialog
title="新增"
:visible.sync="dialogVisible"
width="30%"
:before-close="handleClose"
>
<el-form :model="rowFormData" label-width="50px">
<el-form-item label="名称:">
<el-input
v-model.trim="rowFormData['name']"
placeholder="请输入名称"
size="mini"
>
</el-input>
</el-form-item>
<el-form-item label="key值:">
<el-input
v-model.trim="rowFormData['key']"
placeholder="请输入key值"
size="mini"
>
</el-input>
</el-form-item>
<el-form-item label="宽度:">
<el-input
v-model.trim="rowFormData['width']"
placeholder="请输入宽度"
size="mini"
>
</el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button size="mini" @click="dialogVisible = false"> </el-button>
<el-button size="mini" type="primary" @click="handleSaveClick"
> </el-button
>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
model: {
prop: "formData",
event: "input"
},
props: {
formData: Array
},
data() {
return {
dialogVisible: false,
rowFormData: {
name: "",
key: "",
width: ""
},
flag: true, // true false
indexEditor: -1, //
tableData: []
};
},
methods: {
//
handleAddClick() {
this.rowFormData = {};
this.flag = true;
this.dialogVisible = true;
},
//
handleEditorClick(index, row) {
this.flag = false;
this.rowFormData = this.deepClone(row);
this.indexEditor = index;
this.dialogVisible = true;
},
//
handleClose() {
this.dialogVisible = false;
},
//
handleSaveClick() {
if (this.flag) {
//
this.formData.push(this.rowFormData);
this.dialogVisible = false;
} else {
//
this.formData[this.indexEditor] = this.rowFormData;
this.$set(this.formData, this.indexEditor, this.rowFormData);
this.dialogVisible = false;
}
this.$emit("input", this.formData);
this.$emit("change", this.formData);
},
//
handleDeleteClick(index) {
this.formData.splice(index, 1);
this.$emit("input", this.formData);
this.$emit("change", this.formData);
}
}
};
</script>
<style lang="scss" scoped>
/deep/::-webkit-scrollbar-track-piece {
background-color: transparent;
}
/deep/ .el-table__body-wrapper::-webkit-scrollbar {
width: 0; //
height: 8px; //
}
//
/deep/ .el-table__body-wrapper::-webkit-scrollbar-thumb {
border-radius: 5px;
background-color: rgba(144, 146, 152, 0.3);
}
/deep/.el-table,
/deep/.el-table__expanded-cell,
/deep/.el-table th,
/deep/.el-table tr {
background-color: transparent !important;
color: #859094 !important;
font-size: 12px !important;
}
/deep/.el-table td,
/deep/.el-table th.is-leaf {
border-bottom: none;
line-height: 26px;
}
/deep/.el-table tbody tr:hover {
background-color: #263445 !important;
}
/deep/.el-table tbody tr:hover > td {
background-color: #263445 !important;
}
/deep/.el-table::before {
height: 0;
}
.button-group .el-button {
padding: 0;
}
</style>

@ -0,0 +1,161 @@
<template>
<div>
<el-form label-width="100px" label-position="left">
<el-form-item label="数据集">
<el-select
size="mini"
v-model="dataSetValue"
filterable
placeholder="请选择"
@change="selectDataSet"
>
<el-option
v-for="item in dataSet"
:key="item.code"
:label="item.setName"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item
v-for="(item, index) in userNameList"
:key="index"
:label="item.paramName"
>
<el-input v-model.trim="item.sampleItem" size="mini" />
</el-form-item>
<el-form-item v-for="item in setParamList" :key="item" :label="item">
<Dictionary
v-model="params[item]"
:dict-key="getDictKey()"
@input="selectParams($event, item)"
/>
</el-form-item>
<el-button
style="width: 100%"
type="primary"
plain
size="mini"
@click="saveDataBtn"
>刷新</el-button
>
</el-form>
</div>
</template>
<script>
import { queryAllDataSet, detailBysetId } from "@/api/bigscreen";
import Dictionary from "@/components/Dictionary/index";
export default {
name: "DynamicComponents",
components: {
Dictionary
},
model: {
prop: "formData",
event: "input"
},
props: {
chartType: String,
dictKey: String,
formData: Object
},
data() {
return {
dataSetValue: "",
dataSet: [], //
userNameList: [], //
setParamList: [], //
params: {},
chartProperties: {}
};
},
watch: {
formData: {
handler(val) {
this.echoDataSet(val);
},
deep: true
}
},
computed: {
setCode() {
let code = "";
this.dataSet.forEach(el => {
if (el.id == this.dataSetValue) {
code = el.setCode;
}
});
return code;
}
},
mounted() {
this.loadDataSet();
this.echoDataSet(this.formData);
},
methods: {
async loadDataSet() {
const { code, data } = await queryAllDataSet();
this.dataSet = data;
if (code != "200") return;
},
async selectDataSet() {
const { code, data } = await detailBysetId(this.dataSetValue);
this.userNameList = data.dataSetParamDtoList;
this.setParamList = data.setParamList;
if (code != "200") return;
},
async saveDataBtn() {
const contextData = {};
for (let i = 0; i < this.userNameList.length; i++) {
contextData[this.userNameList[i].paramName] = this.userNameList[
i
].sampleItem;
}
const params = {
chartType: this.chartType,
setCode: this.setCode,
chartProperties: this.chartProperties,
contextData
};
this.$emit("input", params);
this.$emit("change", params);
},
selectParams(val, key) {
this.chartProperties[key] = val;
},
getDictKey() {
return this.dictKey == null ? "CHART_PROPERTIES" : this.dictKey;
},
//
async echoDataSet(val) {
if (!val) return;
const setCode = val.setCode;
await this.loadDataSet();
this.dataSetValue = this.dataSet.filter(
el => setCode == el.setCode
)[0].id;
await this.selectDataSet();
this.echoDynamicData(val);
},
echoDynamicData(val) {
const chartProperties = this.deepClone(val.chartProperties);
this.chartProperties = chartProperties;
if (this.userNameList.length > 0) {
}
if (this.setParamList.length > 0) {
for (let i = 0; i < this.setParamList.length; i++) {
const item = this.setParamList[i];
if (chartProperties.hasOwnProperty(item)) {
this.params[item] = chartProperties[item];
}
}
}
}
}
};
</script>
<style lang="sass" scoped></style>

@ -0,0 +1,442 @@
<template>
<div class="collapse-input-style">
<el-form label-width="100px" label-position="left">
<template v-for="(item, index) in options">
<div v-if="isShowForm(item, '[object Object]')" :key="index">
<el-form-item
v-if="
inputShow[item.name] &&
item.type != 'dycustComponents' &&
item.type != 'dynamic-add-table'
"
:label="item.label"
:prop="item.name"
:required="item.required"
>
<el-input-number
v-if="item.type == 'el-input-number'"
size="mini"
style="width:100%"
v-model.trim="formData[item.name]"
controls-position="right"
@change="changed($event, item.name)"
/>
<el-input
v-if="item.type == 'el-input-text'"
v-model.trim="formData[item.name]"
type="text"
size="mini"
placeholder="请输入内容"
clearable
@change="changed($event, item.name)"
/>
<el-input
v-if="item.type == 'el-input-textarea'"
v-model.trim="formData[item.name]"
type="textarea"
size="mini"
rows="2"
placeholder="请输入内容"
@change="changed($event, item.name)"
/>
<el-switch
v-if="item.type == 'el-switch'"
v-model="formData[item.name]"
size="mini"
placeholder="请输入内容"
@change="changed($event, item.name)"
/>
<ColorPicker
v-if="item.type == 'vue-color'"
v-model="formData[item.name]"
@change="val => changed(val, item.name)"
/>
<customUpload
v-if="item.type == 'custom-upload'"
v-model="formData[item.name]"
@change="changed($event, item.name)"
/>
<el-radio-group
v-if="item.type == 'el-radio-group'"
v-model="formData[item.name]"
@change="val => changed(val, item.name)"
>
<el-radio
v-for="itemChild in item.selectOptions"
:key="itemChild.code"
:label="itemChild.code"
>{{ itemChild.name }}</el-radio
>
</el-radio-group>
<el-select
v-if="item.type == 'el-select'"
size="mini"
v-model="formData[item.name]"
clearable
placeholder="请选择"
@change="val => changed(val, item.name)"
>
<el-option
v-for="itemChild in item.selectOptions"
:key="itemChild.code"
:label="itemChild.name"
:value="itemChild.code"
/>
</el-select>
<el-slider
v-if="item.type == 'el-slider'"
v-model="formData[item.name]"
@change="val => changed(val, item.name)"
/>
<el-button
v-if="item.type == 'el-button'"
type="primary"
size="mini"
plain
@click="addStaticData"
>编辑</el-button
>
<!-- 弹窗 -->
<el-dialog
title="代码编辑"
:visible.sync="dialogVisibleStaticData"
width="50%"
:before-close="handleClose"
>
<vue-json-editor
v-model="formData[item.name]"
:show-btns="false"
:mode="'code'"
lang="zh"
class="my-editor"
/>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisibleStaticData = false"
> </el-button
>
<el-button type="primary" @click="saveData"> </el-button>
</span>
</el-dialog>
</el-form-item>
<dynamicComponents
v-if="item.type == 'dycustComponents' && inputShow[item.name]"
v-model="formData[item.name]"
:chart-type="item.chartType"
:dict-key="item.dictKey"
@change="changed($event, item.name)"
/>
<dynamic-add-table
v-if="item.type == 'dynamic-add-table' && inputShow[item.name]"
v-model="formData[item.name]"
:chart-type="item.chartType"
@change="changed($event, item.name)"
/>
</div>
<div v-else-if="isShowForm(item, '[object Array]')" :key="'a-' + index">
<el-collapse accordion>
<el-collapse-item
v-for="(itemChild, indexChild) in item"
:key="indexChild"
:title="itemChild.name"
:name="indexChild"
>
<template v-for="(itemChildList, idx) in itemChild.list">
<el-form-item
:key="idx"
:label="itemChildList.label"
:prop="itemChildList.name"
:required="itemChildList.required"
>
<el-input-number
v-if="itemChildList.type == 'el-input-number'"
size="mini"
style="width:100%"
v-model="formData[itemChildList.name]"
controls-position="right"
:placeholder="itemChildList.placeholder"
@change="changed($event, itemChildList.name)"
/>
<el-input
v-if="itemChildList.type == 'el-input-text'"
v-model.trim="formData[itemChildList.name]"
type="text"
size="mini"
placeholder="请输入内容"
clearable
@change="changed($event, itemChildList.name)"
/>
<el-input
v-if="itemChildList.type == 'el-input-textarea'"
v-model.trim="formData[itemChildList.name]"
size="mini"
type="textarea"
rows="2"
placeholder="请输入内容"
@change="changed($event, itemChildList.name)"
/>
<el-switch
v-if="itemChildList.type == 'el-switch'"
v-model="formData[itemChildList.name]"
placeholder="请输入内容"
size="mini"
@change="changed($event, itemChildList.name)"
/>
<ColorPicker
v-if="itemChildList.type == 'vue-color'"
v-model="formData[itemChildList.name]"
@change="val => changed(val, itemChildList.name)"
/>
<el-upload
v-if="itemChildList.type == 'el-upload-picture'"
size="mini"
action="https://jsonplaceholder.typicode.com/posts/"
list-type="picture-card"
/>
<el-radio-group
v-if="itemChildList.type == 'el-radio-group'"
v-model="formData[itemChildList.name]"
@change="val => changed(val, itemChildList.name)"
>
<el-radio
v-for="it in itemChildList.selectOptions"
:key="it.code"
:label="it.code"
>{{ it.name }}</el-radio
>
</el-radio-group>
<el-select
v-if="itemChildList.type == 'el-select'"
size="mini"
v-model="formData[itemChildList.name]"
clearable
placeholder="请选择"
@change="val => changed(val, itemChildList.name)"
>
<el-option
v-for="it in itemChildList.selectOptions"
:key="it.code"
:label="it.name"
:value="it.code"
/>
</el-select>
<el-slider
v-if="itemChildList.type == 'el-slider'"
v-model="formData[itemChildList.name]"
@change="val => changed(val, itemChildList.name)"
/>
</el-form-item>
<customColorComponents
v-if="itemChildList.type == 'customColor'"
:key="'b-' + idx"
v-model="formData[itemChildList.name]"
@change="changed($event, itemChildList.name)"
/>
</template>
</el-collapse-item>
</el-collapse>
</div>
</template>
</el-form>
</div>
</template>
<script>
import ColorPicker from "./colorPicker.vue";
import vueJsonEditor from "vue-json-editor";
import "codemirror/lib/codemirror.css"; //
import "codemirror/theme/cobalt.css"; // options
// language
import "codemirror/mode/vue/vue.js";
import "codemirror/mode/javascript/javascript.js";
import "codemirror/mode/sql/sql.js";
import "codemirror/mode/shell/shell.js";
import dynamicComponents from "./dynamicComponents.vue";
import customColorComponents from "./customColorComponents";
import dynamicAddTable from "./dynamicAddTable.vue";
import customUpload from "./customUpload.vue";
export default {
name: "DynamicForm",
components: {
ColorPicker,
vueJsonEditor,
dynamicComponents,
customColorComponents,
dynamicAddTable,
customUpload
},
model: {
prop: "value",
event: "input"
},
props: {
options: Array,
value: {
type: [Object],
default: () => {}
}
},
data() {
return {
formData: {},
inputShow: {}, //
dialogVisibleStaticData: false,
validationRules: "",
optionsJavascript: {
mode: "text/javascript",
tabSize: 2, //
lineNumbers: true, //
line: true,
styleActiveLine: true, //
hintOptions: {
completeSingle: true //
}
}
};
},
watch: {
value(newValue, oldValue) {
this.formData = newValue || {};
},
options(val) {
this.setDefaultValue();
this.isShowData();
}
},
created() {
this.isShowData();
this.setDefaultValue();
},
mounted() {},
methods: {
onJsonChange(val) {
console.log(val);
},
onJsonSave(val) {
console.log(val);
},
//
changed(val, key) {
if (val.extend) {
this.$set(this.formData, key, val.value);
} else {
this.$set(this.formData, key, val);
}
this.$emit("onChanged", this.formData);
// key
for (let i = 0; i < this.options.length; i++) {
let item = this.options[i];
if (item.relactiveDom == key) {
this.inputShow[item.name] = val == item.relactiveDomValue;
this.inputShow = Object.assign({}, this.inputShow);
}
}
},
saveData() {
this.$emit("onChanged", this.formData);
this.dialogVisibleStaticData = false;
},
//
addStaticData() {
this.dialogVisibleStaticData = true;
},
handleClose() {
this.dialogVisibleStaticData = false;
},
//
isShowData() {
let currentData = {};
const data = [];
for (let i = 0; i < this.options.length; i++) {
// inputShow
this.inputShow[this.options[i].name] = true;
if (this.options[i].selectValue) {
currentData = this.options[i];
} else {
data.push(this.options[i]);
}
}
data.forEach(el => {
if (el.relactiveDomValue != currentData.value) {
this.inputShow[el.name] = false;
}
});
},
//
setDefaultValue() {
if (this.options && this.options.length > 0) {
for (let i = 0; i < this.options.length; i++) {
const obj = this.options[i];
if (Object.prototype.toString.call(obj) == "[object Object]") {
this.formData[this.options[i].name] = this.deepClone(
this.options[i].value
);
} else if (Object.prototype.toString.call(obj) == "[object Array]") {
for (let j = 0; j < obj.length; j++) {
const list = obj[j].list;
list.forEach(el => {
this.formData[el.name] = el.value;
});
}
}
}
this.formData = Object.assign({}, this.formData);
}
},
//
isShowForm(val, type) {
return Object.prototype.toString.call(val) == type;
}
}
};
</script>
<style scoped lang="scss">
/deep/ .el-form-item {
margin-bottom: 5px;
}
/deep/ .el-form-item__label {
font-size: 12px;
color: #fff;
}
.code-mirror {
width: 100%;
height: 100% !important;
}
.el-collapse {
border-top: none;
border-bottom: none;
}
/deep/.el-collapse-item__header {
height: 40px;
line-height: 40px;
background: transparent;
color: #bcc9d4;
font-weight: 300;
font-size: 12px;
border-color: #282e3a;
}
/deep/.el-collapse-item__wrap {
background: transparent;
border: none;
}
/deep/.el-collapse-item__content {
padding-bottom: 0;
}
</style>

@ -0,0 +1,678 @@
/*
* @Descripttion: 柱状图json
* @version:
* @Author: qianlishi
* @Date: 2021-08-29 07:21:45
* @LastEditors: qianlishi
* @LastEditTime: 2022-03-11 11:40:29
*/
export const widgetBarchart = {
code: 'widget-barchart',
type: 'barChart',
tabName: '柱状图',
label: '柱状图',
icon: 'iconzhuzhuangtu',
options: {
// 配置
setup: [
{
type: 'el-input-text',
label: '图层名称',
name: 'layerName',
required: false,
placeholder: '',
value: '柱状图',
},
{
type: 'el-switch',
label: '竖展示',
name: 'verticalShow',
required: false,
placeholder: '',
value: false,
},
{
type: 'vue-color',
label: '背景颜色',
name: 'background',
required: false,
placeholder: '',
value: ''
},
[
{
name: '柱体设置',
list: [
{
type: 'el-slider',
label: '最大宽度',
name: 'maxWidth',
required: false,
placeholder: '',
value: 10,
},
{
type: 'el-slider',
label: '圆角',
name: 'radius',
require: false,
placeholder: '',
value: 5,
},
{
type: 'el-slider',
label: '最小高度',
name: 'minHeight',
require: false,
placeholder: '',
value: 0,
},
],
},
{
name: '标题设置',
list: [
{
type: 'el-switch',
label: '标题',
name: 'isNoTitle',
required: false,
placeholder: '',
value: true,
},
{
type: 'el-input-text',
label: '标题',
name: 'titleText',
required: false,
placeholder: '',
value: '',
},
{
type: 'vue-color',
label: '字体颜色',
name: 'textColor',
required: false,
placeholder: '',
value: '#FFD700'
},
{
type: 'el-select',
label: '字体粗细',
name: 'textFontWeight',
required: false,
placeholder: '',
selectOptions: [
{code: 'normal', name: '正常'},
{code: 'bold', name: '粗体'},
{code: 'bolder', name: '特粗体'},
{code: 'lighter', name: '细体'}
],
value: 'normal'
},
{
type: 'el-input-number',
label: '字体字号',
name: 'textFontSize',
required: false,
placeholder: '',
value: 20
},
{
type: 'el-select',
label: '字体位置',
name: 'textAlign',
required: false,
placeholder: '',
selectOptions: [
{code: 'center', name: '居中'},
{code: 'left', name: '左对齐'},
{code: 'right', name: '右对齐'},
],
value: 'center'
},
{
type: 'el-input-text',
label: '副标题',
name: 'subText',
required: false,
placeholder: '',
value: ''
},
{
type: 'vue-color',
label: '字体颜色',
name: 'subTextColor',
required: false,
placeholder: '',
value: 'rgba(30, 144, 255, 1)'
},
{
type: 'el-select',
label: '字体粗细',
name: 'subTextFontWeight',
required: false,
placeholder: '',
selectOptions: [
{code: 'normal', name: '正常'},
{code: 'bold', name: '粗体'},
{code: 'bolder', name: '特粗体'},
{code: 'lighter', name: '细体'}
],
value: 'normal'
},
{
type: 'el-input-number',
label: '字体字号',
name: 'subTextFontSize',
required: false,
placeholder: '',
value: 20
},
],
},
{
name: '图例操作',
list: [
{
type: 'el-switch',
label: '图例显示',
name: 'isShowLegend',
required: false,
placeholder: '',
value: true,
},
{
type: 'el-input-text',
label: '图例名称',
name: 'legendName',
required: false,
placeholder: '',
value: ''
},
{
type: 'vue-color',
label: '字体颜色',
name: 'lengedColor',
required: false,
placeholder: '',
value: '#fff',
},
{
type: 'el-input-number',
label: '字体字号',
name: 'lengedFontSize',
required: false,
placeholder: '',
value: 12,
},
{
type: 'el-input-number',
label: '图例宽度',
name: 'lengedWidth',
required: false,
placeholder: '',
value: 12,
},
{
type: 'el-select',
label: '横向位置',
name: 'lateralPosition',
required: false,
placeholder: '',
selectOptions: [
{code: 'center', name: '居中'},
{code: 'left', name: '左对齐'},
{code: 'right', name: '右对齐'},
],
value: 'center'
},
{
type: 'el-select',
label: '纵向位置',
name: 'longitudinalPosition',
required: false,
placeholder: '',
selectOptions: [
{code: 'top', name: '顶部'},
{code: 'bottom', name: '底部'},
],
value: 'top'
},
{
type: 'el-select',
label: '布局前置',
name: 'layoutFront',
required: false,
placeholder: '',
selectOptions: [
{code: 'vertical', name: '竖排'},
{code: 'horizontal', name: '横排'},
],
value: 'horizontal'
},
],
},
{
name: 'X轴设置',
list: [
{
type: 'el-switch',
label: '显示',
name: 'hideX',
required: false,
placeholder: '',
value: true,
},
{
type: 'el-input-text',
label: '坐标名',
name: 'xName',
required: false,
placeholder: '',
value: ''
},
{
type: 'vue-color',
label: '坐标名颜色',
name: 'nameColorX',
required: false,
placeholder: '',
value: '#fff'
},
{
type: 'el-input-number',
label: '坐标字号',
name: 'nameFontSizeX',
required: false,
placeholder: '',
value: 14
},
{
type: 'vue-color',
label: '数值颜色',
name: 'Xcolor',
required: false,
placeholder: '',
value: '#fff',
},
{
type: 'el-input-number',
label: '数值字号',
name: 'fontSizeX',
required: false,
placeholder: '',
value: 14,
},
{
type: 'el-slider',
label: '数值角度',
name: 'textAngle',
required: false,
placeholder: '',
value: 0
},
{
type: 'el-input-number',
label: '数值间隔',
name: 'textInterval',
required: false,
placeholder: '',
value: ''
},
{
type: 'el-switch',
label: '轴反转',
name: 'reversalX',
required: false,
placeholder: '',
value: false
},
{
type: 'vue-color',
label: '轴颜色',
name: 'lineColorX',
required: false,
placeholder: '',
value: '#fff',
},
{
type: 'el-switch',
label: '分割线显示',
name: 'isShowSplitLineX',
require: false,
placeholder: '',
value: false,
},
{
type: 'vue-color',
label: '分割线颜色',
name: 'splitLineColorX',
required: false,
placeholder: '',
value: '#fff',
}
],
},
{
name: 'Y轴设置',
list: [
{
type: 'el-switch',
label: '显示',
name: 'isShowY',
require: false,
placeholder: '',
value: true,
},
{
type: 'el-input-text',
label: '坐标名',
name: 'textNameY',
require: false,
placeholder: '',
value: ''
},
{
type: 'vue-color',
label: '坐标名颜色',
name: 'nameColorY',
required: false,
placeholder: '',
value: '#fff',
},
{
type: 'el-input-number',
label: '坐标字号',
name: 'nameFontSizeY',
required: false,
placeholder: '',
value: 14,
},
{
type: 'vue-color',
label: '数值颜色',
name: 'colorY',
required: false,
placeholder: '',
value: '#fff',
},
{
type: 'el-input-number',
label: '数值字号',
name: 'fontSizeY',
required: false,
placeholder: '',
value: 14,
},
{
type: 'el-slider',
label: '数值角度',
name: 'ytextAngle',
required: false,
placeholder: '',
value: 0
},
{
type: 'el-switch',
label: '缩放',
name: 'scale',
require: false,
placeholder: '',
value: false,
},
{
type: 'el-input-number',
label: '均分',
name: 'splitNumber',
required: false,
placeholder: '',
value: ''
},
{
type: 'el-switch',
label: '轴反转',
name: 'reversalY',
required: false,
placeholder: '',
value: false
},
{
type: 'vue-color',
label: '轴颜色',
name: 'lineColorY',
required: false,
placeholder: '',
value: '#fff',
}, {
type: 'el-switch',
label: '分割线显示',
name: 'isShowSplitLineY',
require: false,
placeholder: '',
value: false,
}, {
type: 'vue-color',
label: '分割线颜色',
name: 'splitLineColorY',
required: false,
placeholder: '',
value: '#fff',
}
],
},
{
name: '数值设定',
list: [
{
type: 'el-switch',
label: '显示',
name: 'isShow',
required: false,
placeholder: '',
value: true
},
{
type: 'el-input-number',
label: '距离',
name: 'distance',
required: false,
placeholder: '',
value: 5
},
{
type: 'el-input-number',
label: '字体字号',
name: 'fontSize',
required: false,
placeholder: '',
value: 14
},
{
type: 'vue-color',
label: '字体颜色',
name: 'subTextColor',
required: false,
placeholder: '',
value: '#fff'
},
{
type: 'el-select',
label: '字体粗细',
name: 'fontWeight',
required: false,
placeholder: '',
selectOptions: [
{code: 'normal', name: '正常'},
{code: 'bold', name: '粗体'},
{code: 'bolder', name: '特粗体'},
{code: 'lighter', name: '细体'}
],
value: 'normal'
},
],
},
{
name: '提示语设置',
list: [
{
type: 'el-input-number',
label: '字体字号',
name: 'tipFontSize',
required: false,
placeholder: '',
},
{
type: 'vue-color',
label: '字体颜色',
name: 'lineColor',
required: false,
placeholder: '',
},
],
},
{
name: '坐标轴边距设置',
list: [
{
type: 'el-slider',
label: '左边距(像素)',
name: 'marginLeft',
required: false,
placeholder: '',
value: 10,
}, {
type: 'el-slider',
label: '顶边距(像素)',
name: 'marginTop',
required: false,
placeholder: '',
value: 50,
}, {
type: 'el-slider',
label: '右边距(像素)',
name: 'marginRight',
required: false,
placeholder: '',
value: 40,
}, {
type: 'el-slider',
label: '底边距(像素)',
name: 'marginBottom',
required: false,
placeholder: '',
value: 10,
},
],
},
{
name: '自定义配色',
list: [
{
type: 'customColor',
label: '',
name: 'customColor',
required: false,
value: [{color: '#ff7f50'}, {color: '#87cefa'}, {color: '#da70d6'}, {color: '#32cd32'}, {color: '#6495ed'}],
},
],
},
],
],
// 数据
data: [
{
type: 'el-radio-group',
label: '数据类型',
name: 'dataType',
require: false,
placeholder: '',
selectValue: true,
selectOptions: [
{
code: 'staticData',
name: '静态数据',
},
{
code: 'dynamicData',
name: '动态数据',
},
],
value: 'staticData',
},
{
type: 'el-input-number',
label: '刷新时间(毫秒)',
name: 'refreshTime',
relactiveDom: 'dataType',
relactiveDomValue: 'dynamicData',
value: 5000
},
{
type: 'el-button',
label: '静态数据',
name: 'staticData',
required: false,
placeholder: '',
relactiveDom: 'dataType',
relactiveDomValue: 'staticData',
value: [
{"axis": "苹果", "data": 1000},
{"axis": "三星", "data": 2229},
{"axis": "小米", "data": 3879},
{"axis": "oppo", "data": 2379},
{"axis": "vivo", "data": 4079},
],
},
{
type: 'dycustComponents',
label: '',
name: 'dynamicData',
required: false,
placeholder: '',
relactiveDom: 'dataType',
relactiveDomValue: 'dynamicData',
chartType: 'widget-barchart',
dictKey: 'BAR_PROPERTIES',
value: '',
},
],
// 坐标
position: [
{
type: 'el-input-number',
label: '左边距',
name: 'left',
required: false,
placeholder: '',
value: 0,
},
{
type: 'el-input-number',
label: '上边距',
name: 'top',
required: false,
placeholder: '',
value: 0,
},
{
type: 'el-input-number',
label: '宽度',
name: 'width',
required: false,
placeholder: '该容器在1920px大屏中的宽度',
value: 400,
},
{
type: 'el-input-number',
label: '高度',
name: 'height',
required: false,
placeholder: '该容器在1080px大屏中的高度',
value: 200,
},
],
}
}

@ -0,0 +1,30 @@
/**
* 文本栏{type: 'text',tabName: '文本栏'}
* 柱状图{type: 'barChart',tabName: '柱状图'}
* **/
import {widgetHref} from "./texts/widget-href"
import {widgetIframe} from "./texts/widget-iframe"
import {widgetImage} from "./texts/widget-image"
import {widgetMarquee} from "./texts/widget-marquee"
import {widgetSliders} from "./texts/widget-slider"
import {widgetTable} from "./texts/widget-table"
import {widgetText} from "./texts/widget-text"
import { widgetTime } from "./texts/widget-time"
import {widgetVideo} from "./texts/widget-video"
import {widgetBarchart} from './barCharts/widget-barchart'
export const widgetTool = [
widgetHref,
widgetIframe,
widgetImage,
widgetMarquee,
// widgetSliders,
widgetTable,
widgetText,
widgetTime,
widgetVideo,
widgetBarchart
]

@ -0,0 +1,10 @@
import {converArr} from '../util/common'
import { widgetTool } from "./configs"
export const widgetTools = converArr([...widgetTool])
export const getToolByCode = (code) => {
return [...widgetTool].find((item) => {
return item.code = code
})
}

@ -0,0 +1,67 @@
/*
* @Descripttion: 大屏配置
* @version:
* @Author: qianlishi
* @Date: 2022-03-09 19:45:37
* @LastEditors: qianlishi
* @LastEditTime: 2022-03-09 19:59:18
*/
export const screenConfig = {
code: 'screen',
type: 'screen',
label: '大屏设置',
icon: '',
options: {
setup: [
{
type: 'el-input-number',
label: '大屏宽度',
name: 'width',
required: false,
placeholder: 'px',
value: '1920',
},
{
type: 'el-input-number',
label: '大屏高度',
name: 'height',
required: false,
placeholder: 'px',
value: '1080',
},
{
type: 'el-input-text',
label: '标题',
name: 'title',
require: false,
placeholder: '',
value: '大屏',
},
{
type: 'el-input-textarea',
label: '大屏简介',
name: 'description',
required: false,
placeholder: '',
},
{
type: 'vue-color',
label: '背景颜色',
name: 'backgroundColor',
required: false,
placeholder: '',
value: '#000',
},
{
type: 'custom-upload',
label: '图片地址',
name: 'backgroundImage',
required: false,
placeholder: '',
value: 'https://report.anji-plus.com/file/download/bf566e48-ccad-40e1-8ee9-228427e5466b',
},
],
data: [],
position: [],
}
}

@ -0,0 +1,158 @@
/*
* @Descripttion: 超链接文本
* @version:
* @Author: qianlishi
* @Date: 2021-08-29 07:03:58
* @LastEditors: qianlishi
* @LastEditTime: 2022-03-11 10:37:53
*/
export const widgetHref = {
code: 'widget-href',
type: 'text',
tabName: '文本栏',
label: '超链接',
icon: 'iconchaolianjie',
options: {
// 配置
setup: [
{
type: 'el-input-text',
label: '图层名称',
name: 'layerName',
required: false,
placeholder: '',
value: '超链接',
},
{
type: 'el-input-text',
label: '文本内容',
name: 'text',
required: false,
placeholder: '',
value: '超链接',
},
{
type: 'el-input-number',
label: '字体大小',
name: 'fontSize',
required: false,
placeholder: '',
value: '26',
},
{
type: 'vue-color',
label: '字体颜色',
name: 'color',
required: false,
placeholder: '',
value: '#FAD400',
},
{
type: 'el-input-number',
label: '字体间距',
name: 'letterSpacing',
required: false,
placeholder: '',
value: '0',
},
{
type: 'vue-color',
label: '字体背景',
name: 'background',
required: false,
placeholder: '',
value: 'rgba(115,170,229,.5)',
},
{
type: 'el-select',
label: '文字粗细',
name: 'fontWeight',
required: false,
placeholder: '',
selectOptions: [
{code: 'normal', name: '正常'},
{code: 'bold', name: '粗体'},
{code: 'bolder', name: '特粗体'},
{code: 'lighter', name: '细体'}
],
value: 'normal'
},
{
type: 'el-select',
label: '对齐方式',
name: 'textAlign',
required: false,
placeholder: '',
selectOptions: [
{code: 'center', name: '居中'},
{code: 'left', name: '左对齐'},
{code: 'right', name: '右对齐'},
],
value: 'center'
},
{
type: 'el-radio-group',
label: '跳转方式',
name: 'jumpMode',
required: false,
placeholder: '',
selectOptions: [
{
code: 'self',
name: '本窗口',
},
{
code: 'other',
name: '新窗口',
},
],
value: 'self',
},
{
type: 'el-input-text',
label: '超链地址',
name: 'linkAdress',
required: false,
placeholder: '',
value: 'http://www.baidu.com',
},
],
// 数据
data: [],
// 坐标
position: [
{
type: 'el-input-number',
label: '左边距',
name: 'left',
required: false,
placeholder: '',
value: 0,
},
{
type: 'el-input-number',
label: '上边距',
name: 'top',
required: false,
placeholder: '',
value: 0,
},
{
type: 'el-input-number',
label: '宽度',
name: 'width',
required: false,
placeholder: '该容器在1920px大屏中的宽度',
value: 100,
},
{
type: 'el-input-number',
label: '高度',
name: 'height',
required: false,
placeholder: '该容器在1080px大屏中的高度',
value: 40,
},
],
}
}

@ -0,0 +1,73 @@
/*
* @Descripttion: iframe json
* @version:
* @Author: qianlishi
* @Date: 2021-08-29 07:17:55
* @LastEditors: qianlishi
* @LastEditTime: 2022-03-11 10:37:58
*/
export const widgetIframe = {
code: 'widget-iframe',
type: 'text',
tabName: '文本栏',
label: '内联框架',
icon: 'iconkuangjia',
options: {
// 配置
setup: [
{
type: 'el-input-text',
label: '图层名称',
name: 'layerName',
required: false,
placeholder: '',
value: 'iframe',
},
{
type: 'el-input-text',
label: '地址',
name: 'iframeAdress',
required: false,
placeholder: '',
value: 'https://report.anji-plus.com/index.html',
},
],
// 数据
data: [],
// 坐标
position: [
{
type: 'el-input-number',
label: '左边距',
name: 'left',
required: false,
placeholder: '',
value: 0,
},
{
type: 'el-input-number',
label: '上边距',
name: 'top',
required: false,
placeholder: '',
value: 0,
},
{
type: 'el-input-number',
label: '宽度',
name: 'width',
required: false,
placeholder: '该容器在1920px大屏中的宽度',
value: 300,
},
{
type: 'el-input-number',
label: '高度',
name: 'height',
required: false,
placeholder: '该容器在1080px大屏中的高度',
value: 200,
},
],
}
}

@ -0,0 +1,112 @@
/*
* @Descripttion: 图片json
* @version:
* @Author: qianlishi
* @Date: 2021-08-29 07:07:23
* @LastEditors: qianlishi
* @LastEditTime: 2022-03-11 10:38:01
*/
export const widgetImage = {
code: 'widget-image',
type: 'text',
tabName: '文本栏',
label: '图片',
icon: 'icontupian',
options: {
// 配置
setup: [
{
type: 'el-input-text',
label: '图层名称',
name: 'layerName',
required: false,
placeholder: '',
value: '图片',
},
{
type: 'el-switch',
label: '开启旋转',
name: 'startRotate',
required: false,
placeholder: '',
value: false,
},
{
type: 'el-slider',
label: '旋转速度',
name: 'rotationSpeed',
required: false,
placeholder: '',
value: 70
},
{
type: 'el-slider',
label: '透明度',
name: 'transparency',
required: false,
placeholder: '',
value: 100
},
{
type: 'el-input-number',
label: '圆角',
name: 'borderRadius',
required: false,
placeholder: '',
value: '0'
},
{
type: 'custom-upload',
label: '图片地址',
name: 'imageAdress',
required: false,
placeholder: '',
value: 'http://10.108.26.197:9095/file/download/fd20d563-00aa-45e2-b5db-aff951f814ec',
},
{
type: 'vue-color',
label: '背景颜色',
name: 'background',
required: false,
placeholder: '',
},
],
// 数据
data: [],
// 坐标
position: [
{
type: 'el-input-number',
label: '左边距',
name: 'left',
required: false,
placeholder: '',
value: 0,
},
{
type: 'el-input-number',
label: '上边距',
name: 'top',
required: false,
placeholder: '',
value: 0,
},
{
type: 'el-input-number',
label: '宽度',
name: 'width',
required: false,
placeholder: '该容器在1920px大屏中的宽度',
value: 300,
},
{
type: 'el-input-number',
label: '高度',
name: 'height',
required: false,
placeholder: '该容器在1080px大屏中的高度',
value: 200,
},
],
}
}

@ -0,0 +1,177 @@
/*
* @Descripttion: 滚动文件json
* @version:
* @Author: qianlishi
* @Date: 2021-08-29 07:00:00
* @LastEditors: qianlishi
* @LastEditTime: 2022-03-11 10:38:04
*/
export const widgetMarquee = {
code: 'widget-marquee',
type: 'text',
tabName: '文本栏',
label: '滚动文本',
icon: 'iconhengxiangwenzi',
options: {
// 配置
setup: [
{
type: 'el-input-text',
label: '图层名称',
name: 'layerName',
required: false,
placeholder: '',
value: '跑马灯',
},
{
type: 'el-input-text',
label: '文本内容',
name: 'text',
required: false,
placeholder: '',
value: '滚动文本',
},
{
type: 'el-input-number',
label: '字体大小',
name: 'fontSize',
required: false,
placeholder: '',
value: '26',
},
{
type: 'vue-color',
label: '字体颜色',
name: 'color',
required: false,
placeholder: '',
value: '#FAD400',
},
{
type: 'el-input-number',
label: '字体间距',
name: 'letterSpacing',
required: false,
placeholder: '',
value: '0',
},
{
type: 'vue-color',
label: '字体背景',
name: 'background',
required: false,
placeholder: '',
value: 'rgba(115,170,229,.5)',
},
{
type: 'el-select',
label: '文字粗细',
name: 'fontWeight',
required: false,
placeholder: '',
selectOptions: [
{code: 'normal', name: '正常'},
{code: 'bold', name: '粗体'},
{code: 'bolder', name: '特粗体'},
{code: 'lighter', name: '细体'}
],
value: 'normal'
},
/* {
type: 'el-input-number',
label: '滚动速度',
name: 'jScrollPane',
//required: false,
placeholder: '',
value: '50',
}*/
],
// 数据
data: [
{
type: 'el-radio-group',
label: '数据类型',
name: 'dataType',
require: false,
placeholder: '',
selectValue: true,
selectOptions: [
{
code: 'staticData',
name: '静态数据',
},
{
code: 'dynamicData',
name: '动态数据',
},
],
value: 'staticData',
},
{
type: 'el-input-number',
label: '刷新时间(毫秒)',
name: 'refreshTime',
relactiveDom: 'dataType',
relactiveDomValue: 'dynamicData',
value: 5000
},
{
type: 'el-button',
label: '静态数据',
name: 'staticData',
required: false,
placeholder: '',
relactiveDom: 'dataType',
relactiveDomValue: 'staticData',
value: '文本框',
},
{
type: 'dycustComponents',
label: '',
name: 'dynamicData',
required: false,
placeholder: '',
relactiveDom: 'dataType',
relactiveDomValue: 'dynamicData',
chartType: 'widget-text',
dictKey: 'TEXT_PROPERTIES',
value: '',
}
],
// 坐标
position: [
{
type: 'el-input-number',
label: '左边距',
name: 'left',
required: false,
placeholder: '',
value: 0,
},
{
type: 'el-input-number',
label: '上边距',
name: 'top',
required: false,
placeholder: '',
value: 0,
},
{
type: 'el-input-number',
label: '宽度',
name: 'width',
required: false,
placeholder: '该容器在1920px大屏中的宽度',
value: 100,
},
{
type: 'el-input-number',
label: '高度',
name: 'height',
required: false,
placeholder: '该容器在1080px大屏中的高度',
value: 40,
},
],
}
}

@ -0,0 +1,88 @@
/*
* @Descripttion: 轮播图
* @version:
* @Author: qianlishi
* @Date: 2021-08-29 07:08:53
* @LastEditors: qianlishi
* @LastEditTime: 2022-03-11 10:38:08
*/
export const widgetSliders = {
code: 'widget-slider',
type: 'text',
tabName: '文本栏',
label: '轮播图片',
icon: 'slider',
options: {
// 配置
setup: [
{
type: 'el-input-text',
label: '图层名称',
name: 'layerName',
required: false,
placeholder: '',
},
{
type: 'el-switch',
label: '隐藏图层',
name: 'hideLayer',
required: false,
placeholder: '',
},
{
type: 'el-select',
label: '轮播方向',
name: 'tabDirection',
required: false,
placeholder: '',
},
{
type: 'el-select',
label: '选择器',
name: 'tabSelector',
required: false,
placeholder: '',
},
{
type: 'el-input-number',
label: '轮播时间',
name: 'tabTime',
required: false,
placeholder: '',
},
],
// 数据
data: [],
// 坐标
position: [
{
type: 'el-input-number',
label: '左边距',
name: 'left',
required: true,
placeholder: '',
},
{
type: 'el-input-number',
label: '上边距',
name: 'top',
required: true,
placeholder: '',
},
{
type: 'el-input-number',
label: '宽度',
name: 'width',
required: true,
placeholder: '该容器在1920px大屏中的宽度',
},
{
type: 'el-input-number',
label: '高度',
name: 'height',
required: true,
placeholder: '该容器在1080px大屏中的高度',
},
],
}
}

@ -0,0 +1,305 @@
/*
* @Descripttion: 表格json
* @version:
* @Author: qianlishi
* @Date: 2021-08-29 07:16:10
* @LastEditors: qianlishi
* @LastEditTime: 2022-03-11 10:38:11
*/
export const widgetTable = {
code: 'widget-table',
type: 'text',
tabName: '文本栏',
label: '表格',
icon: 'iconbiaoge',
options: {
setup: [
{
type: 'el-input-text',
label: '图层名称',
name: 'layerName',
required: false,
placeholder: '',
value: '表格',
},
{
type: 'el-select',
label: '字体位置',
name: 'textAlign',
required: false,
placeholder: '',
selectOptions: [
{code: 'center', name: '居中'},
{code: 'left', name: '左对齐'},
{code: 'right', name: '右对齐'},
],
value: 'center'
},
{
type: 'el-input-number',
label: '字体大小',
name: 'fontSize',
required: false,
placeholder: '',
value: '16'
},
{
type: 'el-input-number',
label: '显示行数',
name: 'vis',
required: false,
placeholder: '',
value: '5'
},
{
type: 'el-input-number',
label: '行高',
name: 'rowHeight',
required: false,
placeholder: '',
value: '50'
},
{
type: 'el-switch',
label: '开启滚动',
name: 'isRoll',
required: false,
placeholder: '',
value: true
},
{
type: 'el-select',
label: '动画效果',
name: 'effect',
required: false,
placeholder: '',
selectOptions: [
{code: 'top', name: '上滚动'},
{code: 'topLoop', name: '上循环滚动'},
],
value: 'topLoop'
},
{
type: 'el-input-number',
label: '滚动间隔(毫秒)',
name: 'interTime',
required: false,
placeholder: '',
value: 2500
},
{
type: 'el-input-number',
label: '动效时间(毫秒)',
name: 'delayTime',
required: false,
placeholder: '',
value: 500
},
{
type: 'el-input-number',
label: '滚动个数',
name: 'scroll',
required: false,
placeholder: '',
value: 1
},
{
type: 'el-switch',
label: '边框线',
name: 'isLine',
required: false,
placeholder: '',
value: false
},
{
type: 'el-input-number',
label: '边框宽度',
name: 'borderWidth',
required: false,
placeholder: '',
value: 1
},
{
type: 'vue-color',
label: '边框颜色',
name: 'borderColor',
required: false,
placeholder: '',
value: '#fff'
},
[
{
name: '表头设置',
list: [
{
type: 'el-switch',
label: '表头显隐',
name: 'isHeader',
required: false,
placeholder: '',
value: true,
},
{
type: 'vue-color',
label: '表头颜色',
name: 'headColor',
require: false,
placeholder: '',
value: '#fff',
},
{
type: 'vue-color',
label: '表头背景',
name: 'headBackColor',
require: false,
placeholder: '',
value: '#0a73ff',
},
],
},
{
name: '表体设置',
list: [
{
type: 'vue-color',
label: '文字颜色',
name: 'bodyColor',
required: false,
placeholder: '',
value: '#fff',
},
{
type: 'vue-color',
label: '表格背景色',
name: 'tableBgColor',
require: false,
placeholder: '',
value: '',
},
{
type: 'vue-color',
label: '奇行颜色',
name: 'oldColor',
require: false,
placeholder: '',
value: '#0a2732',
},
{
type: 'vue-color',
label: '偶行颜色',
name: 'eventColor',
required: false,
placeholder: '',
value: '#003b51'
}
],
},
],
{
type: 'dynamic-add-table',
label: '',
name: 'dynamicAddTable',
required: false,
placeholder: '',
value: [
{name: '日期', key: 'date', width: '50%'},
{name: '姓名', key: 'name', width: '50%'},
{name: '地址', key: 'address', width: '200%',
}]
}
],
data: [
{
type: 'el-radio-group',
label: '数据类型',
name: 'dataType',
require: false,
placeholder: '',
selectValue: true,
selectOptions: [
{
code: 'staticData',
name: '静态数据',
},
{
code: 'dynamicData',
name: '动态数据',
},
],
value: 'staticData',
},
{
type: 'el-input-number',
label: '刷新时间(毫秒)',
name: 'refreshTime',
relactiveDom: 'dataType',
relactiveDomValue: 'dynamicData',
value: 30000
},
{
type: 'el-button',
label: '静态数据',
name: 'staticData',
required: false,
placeholder: '',
relactiveDom: 'dataType',
relactiveDomValue: 'staticData',
value: [
{date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄0001'},
{date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄0002'},
{date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄0003'},
{date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄0004'},
{date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄0005'},
{date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄0006'},
{date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄0007'},
],
},
{
type: 'dycustComponents',
label: '',
name: 'dynamicData',
required: false,
placeholder: '',
relactiveDom: 'dataType',
relactiveDomValue: 'dynamicData',
chartType: 'widget-table',
dictKey: 'TEXT_PROPERTIES', //表格的暂不起作用
value: '',
},
],
position: [
{
type: 'el-input-number',
label: '左边距',
name: 'left',
required: false,
placeholder: '',
value: 0,
},
{
type: 'el-input-number',
label: '上边距',
name: 'top',
required: false,
placeholder: '',
value: 0,
},
{
type: 'el-input-number',
label: '宽度',
name: 'width',
required: false,
placeholder: '该容器在1920px大屏中的宽度',
value: 600,
},
{
type: 'el-input-number',
label: '高度',
name: 'height',
required: false,
placeholder: '该容器在1080px大屏中的高度',
value: 300,
},
]
}
}

@ -0,0 +1,183 @@
/*
* @Descripttion: 文本json文件
* @version:
* @Author: qianlishi
* @Date: 2021-08-29 06:52:13
* @LastEditors: qianlishi
* @LastEditTime: 2022-03-11 10:38:13
*/
export const widgetText = {
code: 'widget-text',
type: 'text',
tabName: '文本栏',
label: '文本',
icon: 'iconziyuan',
options: {
// 配置
setup: [
{
type: 'el-input-text',
label: '图层名称',
name: 'layerName',
required: false,
placeholder: '',
value: '文本框',
},
{
type: 'el-input-text',
label: '文本内容',
name: 'text',
required: false,
placeholder: '',
value: '文本框',
},
{
type: 'el-input-number',
label: '字体大小',
name: 'fontSize',
required: false,
placeholder: '',
value: '26',
},
{
type: 'vue-color',
label: '字体颜色',
name: 'color',
required: false,
placeholder: '',
value: '#FAD400',
},
{
type: 'el-input-number',
label: '字体间距',
name: 'letterSpacing',
required: false,
placeholder: '',
value: '0',
},
{
type: 'vue-color',
label: '字体背景',
name: 'background',
required: false,
placeholder: '',
value: 'rgba(115,170,229,.0)',
},
{
type: 'el-select',
label: '文字粗细',
name: 'fontWeight',
required: false,
placeholder: '',
selectOptions: [
{code: 'normal', name: '正常'},
{code: 'bold', name: '粗体'},
{code: 'bolder', name: '特粗体'},
{code: 'lighter', name: '细体'}
],
value: 'normal'
},
{
type: 'el-select',
label: '对齐方式',
name: 'textAlign',
required: false,
placeholder: '',
selectOptions: [
{code: 'center', name: '居中'},
{code: 'left', name: '左对齐'},
{code: 'right', name: '右对齐'},
],
value: 'center'
},
],
// 数据
data: [
{
type: 'el-radio-group',
label: '数据类型',
name: 'dataType',
require: false,
placeholder: '',
selectValue: true,
selectOptions: [
{
code: 'staticData',
name: '静态数据',
},
{
code: 'dynamicData',
name: '动态数据',
},
],
value: 'staticData',
},
{
type: 'el-input-number',
label: '刷新时间(毫秒)',
name: 'refreshTime',
relactiveDom: 'dataType',
relactiveDomValue: 'dynamicData',
value: 5000
},
{
type: 'el-button',
label: '静态数据',
name: 'staticData',
required: false,
placeholder: '',
relactiveDom: 'dataType',
relactiveDomValue: 'staticData',
value: '文本框',
},
{
type: 'dycustComponents',
label: '',
name: 'dynamicData',
required: false,
placeholder: '',
relactiveDom: 'dataType',
relactiveDomValue: 'dynamicData',
chartType: 'widget-text',
dictKey: 'TEXT_PROPERTIES',
value: '',
}
],
// 坐标
position: [
{
type: 'el-input-number',
label: '左边距',
name: 'left',
required: false,
placeholder: '',
value: 0,
},
{
type: 'el-input-number',
label: '上边距',
name: 'top',
required: false,
placeholder: '',
value: 0,
},
{
type: 'el-input-number',
label: '宽度',
name: 'width',
required: false,
placeholder: '该容器在1920px大屏中的宽度',
value: 100,
},
{
type: 'el-input-number',
label: '高度',
name: 'height',
required: false,
placeholder: '该容器在1080px大屏中的高度',
value: 40
},
],
}
}

@ -0,0 +1,144 @@
/*
* @Descripttion: 时间控件json
* @version:
* @Author: qianlishi
* @Date: 2021-08-29 07:05:52
* @LastEditors: qianlishi
* @LastEditTime: 2022-03-11 10:38:16
*/
export const widgetTime = {
code: 'widget-time',
type: 'text',
tabName: '文本栏',
label: '当前时间',
icon: 'iconshijian',
options: {
// 配置
setup: [
{
type: 'el-input-text',
label: '图层名称',
name: 'layerName',
required: false,
placeholder: '',
value: '当前时间',
},
{
type: 'el-select',
label: '时间格式',
name: 'timeFormat',
required: false,
placeholder: '',
selectOptions: [
{code: 'yyyy-MM-dd', name: '日期'},
{code: 'yyyy-MM-dd hh:mm', name: '日期+时分'},
{code: 'yyyy-MM-dd hh:mm:ss', name: '日期+时分秒'},
{code: 'MM-dd', name: '日期无年'},
{code: 'hh:mm', name: '时分'},
{code: 'hh:mm:ss', name: '时分秒'},
{code: 'year-week', name: '日期+星期'},
{code: 'year-h-m-week', name: '日期+时分+星期'},
{code: 'year-h-m-s-week', name: '日期+时分秒+星期'},
{code: 'week', name: '星期'}
],
value: 'yyyy-MM-dd hh:mm:ss'
},
{
type: 'el-input-number',
label: '字体间距',
name: 'letterSpacing',
required: false,
placeholder: '',
value: '0'
},
{
type: 'el-input-number',
label: '字体大小',
name: 'fontSize',
required: false,
placeholder: '',
value: '26'
},
{
type: 'vue-color',
label: '字体颜色',
name: 'color',
required: false,
placeholder: '',
value: '#FAD400'
},
{
type: 'vue-color',
label: '字体背景',
name: 'background',
required: false,
placeholder: '',
value: 'rgba(115,170,229,.5)'
},
{
type: 'el-select',
label: '文字粗细',
name: 'fontWeight',
required: false,
placeholder: '',
selectOptions: [
{code: 'normal', name: '正常'},
{code: 'bold', name: '粗体'},
{code: 'bolder', name: '特粗体'},
{code: 'lighter', name: '细体'}
],
value: 'normal'
},
{
type: 'el-select',
label: '对齐方式',
name: 'textAlign',
required: false,
placeholder: '',
selectOptions: [
{code: 'center', name: '居中'},
{code: 'left', name: '左对齐'},
{code: 'right', name: '右对齐'},
],
value: 'left'
},
],
// 数据
data: [],
// 坐标
position: [
{
type: 'el-input-number',
label: '左边距',
name: 'left',
required: false,
placeholder: '',
value: 0,
},
{
type: 'el-input-number',
label: '上边距',
name: 'top',
required: false,
placeholder: '',
value: 0,
},
{
type: 'el-input-number',
label: '宽度',
name: 'width',
required: false,
placeholder: '该容器在1920px大屏中的宽度',
value: 300,
},
{
type: 'el-input-number',
label: '高度',
name: 'height',
required: false,
placeholder: '该容器在1080px大屏中的高度',
value: 100,
},
],
}
}

@ -0,0 +1,73 @@
/*
* @Descripttion: 视频json
* @version:
* @Author: qianlishi
* @Date: 2021-08-29 07:10:22
* @LastEditors: qianlishi
* @LastEditTime: 2022-03-11 10:38:19
*/
export const widgetVideo = {
code: 'widget-video',
type: 'text',
tabName: '文本栏',
label: '视频',
icon: 'iconshipin',
options: {
// 配置
setup: [
{
type: 'el-input-text',
label: '图层名称',
name: 'layerName',
required: false,
placeholder: '',
value: 'video',
},
{
type: 'el-input-text',
label: '地址',
name: 'videoAdress',
required: false,
placeholder: '',
value: 'https://www.w3school.com.cn//i/movie.ogg',
},
],
// 数据
data: [],
// 坐标
position: [
{
type: 'el-input-number',
label: '左边距',
name: 'left',
required: false,
placeholder: '',
value: 0,
},
{
type: 'el-input-number',
label: '上边距',
name: 'top',
required: false,
placeholder: '',
value: 0,
},
{
type: 'el-input-number',
label: '宽度',
name: 'width',
required: false,
placeholder: '该容器在1920px大屏中的宽度',
value: 300,
},
{
type: 'el-input-number',
label: '高度',
name: 'height',
required: false,
placeholder: '该容器在1080px大屏中的高度',
value: 200,
},
],
}
}

@ -0,0 +1,865 @@
<template>
<div class="layout">
<!-- 操作栏 -->
<div class="layout-bar">
<div class="bar-item"><i class="iconfont iconsave"></i>保存</div>
<div class="bar-item"><i class="iconfont iconyulan"></i>预览</div>
<div class="bar-item"><i class="iconfont iconundo"></i>撤销</div>
<div class="bar-item"><i class="iconfont iconhuifubeifen"></i>恢复</div>
<div class="bar-item">
<!-- <el-upload
class="el-upload"
ref="upload"
:action="uploadUrl"
:headers="headers"
accept=".zip"
:on-success="handleUpload"
:on-error="handleError"
:show-file-list="false"
:limit="1"
>
<i class="iconfont icondaoru"></i>
</el-upload> -->
导入
</div>
<div class="bar-item">
<i class="iconfont icondaochu"></i>
<el-dropdown>
<span class="el-dropdown-link">
导出<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>导出(包含数据集)</el-dropdown-item>
<el-dropdown-item>导出(不包含数据集)</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
<div class="layout-container">
<!-- 图表 -->
<el-tabs class="layout-left" type="border-card">
<el-tab-pane>
<span slot="label"><i class="el-icon-date icon"></i>工具栏</span>
<div class="chart-type">
<el-tabs class="type-left" tab-position="left">
<el-tab-pane
v-for="(item, index) in widgetTools"
:key="index"
:label="item.name"
>
<draggable
v-for="(it, idx) in item.list"
:key="idx"
@end="evt => widgetOnDragged(evt, it.code)"
>
<div class="tools-item">
<span class="tools-item-icon">
<i class="iconfont" :class="it.icon"></i>
</span>
<span class="tools-item-text">{{ it.label }}</span>
</div>
</draggable>
</el-tab-pane>
</el-tabs>
</div>
</el-tab-pane>
<el-tab-pane>
<span slot="label" class="icon"
><i class="el-icon-date icon"></i>图层</span
>
<div class="tools-item">
<span class="tools-item-icon">
<i class="iconfont iconkuangjia"></i>
</span>
<span class="tools-item-text">内联框架</span>
</div>
<div class="tools-item">
<span class="tools-item-icon">
<i class="iconfont iconkuangjia"></i>
</span>
<span class="tools-item-text">内联框架</span>
</div>
</el-tab-pane>
</el-tabs>
<!-- 设计器 -->
<div
class="layout-middle"
:style="{ width: middleWidth + 'px', height: middleHeight + 'px' }"
>
<div
class="workbench-container"
:style="{
width: bigscreenWidthInWorkbench + 'px',
height: bigscreenHeightInWorkbench + 'px'
}"
@mousedown="handleMouseDown"
>
<vue-ruler-tool
v-model="dashboard.presetLine"
class="vueRuler"
:step-length="50"
:parent="true"
:position="'relative'"
:is-scale-revise="true"
:visible.sync="dashboard.presetLineVisible"
>
<div
id="workbench"
class="workbench"
:style="{
transform: workbenchTransform,
width: bigscreenWidth + 'px',
height: bigscreenHeight + 'px',
'background-color': dashboard.backgroundColor,
'background-image': 'url(' + dashboard.backgroundImage + ')',
'background-position': '0% 0%',
'background-size': '100% 100%',
'background-repeat': 'initial',
'background-attachment': 'initial',
'background-origin': 'initial',
'background-clip': 'initial'
}"
@click.self="setOptionsOnClickScreen"
>
<div v-if="grade" class="bg-grid"></div>
<widget
ref="widgets"
v-for="(widget, index) in widgets"
:key="index"
v-model="widget.value"
:index="index"
:step="step"
:type="widget.type"
:bigscreen="{ bigscreenWidth, bigscreenHeight }"
@onActivated="setOptionsOnClickWidget"
@contextmenu.prevent.native="rightClick($event, index)"
@mousedown.prevent.native="widgetsClick(index)"
@mouseup.prevent.native="widgetsMouseup"
/>
</div>
</vue-ruler-tool>
</div>
</div>
<!-- 设置 -->
<div class="layout-right">
<el-tabs v-model="activeName" type="border-card" :stretch="true">
<el-tab-pane
v-if="
isNotNull(widgetOptions.setup) ||
isNotNull(widgetOptions.collapse)
"
name="first"
label="配置"
>
<dynamicForm
ref="formData"
:options="widgetOptions.setup"
@onChanged="val => widgetValueChanged('setup', val)"
/>
</el-tab-pane>
<el-tab-pane
v-if="isNotNull(widgetOptions.data)"
name="second"
label="数据"
>
<dynamicForm
ref="formData"
:options="widgetOptions.data"
@onChanged="val => widgetValueChanged('data', val)"
/>
</el-tab-pane>
<el-tab-pane
v-if="isNotNull(widgetOptions.position)"
name="third"
label="坐标"
>
<dynamicForm
ref="formData"
:options="widgetOptions.position"
@onChanged="val => widgetValueChanged('position', val)"
/>
</el-tab-pane>
</el-tabs>
</div>
</div>
<content-menu
:visible.sync="visibleContentMenu"
:style-obj="styleObj"
@deletelayer="deletelayer"
@copylayer="copylayer"
@istopLayer="istopLayer"
@setlowLayer="setlowLayer"
@moveupLayer="moveupLayer"
@movedownLayer="movedownLayer"
/>
</div>
</template>
<script>
import {
insertDashboard,
detailDashboard,
importDashboard,
exportDashboard
} from "@/api/bigscreen";
import { screenConfig } from "./config/texts/screenConfig.js";
import { widgetTools, getToolByCode } from "./config/index.js";
import VueRulerTool from "vue-ruler-tool"; //
import widget from "./widget/index.vue";
import dynamicForm from "./components/dynamicForm.vue";
import draggable from "vuedraggable";
import contentMenu from "./components/contentMenu";
import { getToken } from "@/utils/auth";
import { Revoke } from "@/utils/revoke"; // 2022-02-22
export default {
components: {
VueRulerTool,
widget,
dynamicForm,
draggable,
contentMenu
},
data() {
return {
uploadUrl:
process.env.BASE_API +
"/reportDashboard/import/" +
this.$route.query.reportCode,
grade: false,
layerWidget: [],
widgetTools: widgetTools, // js
widthLeftForTools: 200, //
widthLeftForToolsHideButton: 15, //
widthLeftForOptions: 300, //
widthPaddingTools: 18,
toolIsShow: true, //
bigscreenWidth: 1920, //
bigscreenHeight: 1080,
revoke: null, // 2022-02-22
// gaea_report_dashboard
dashboard: {
id: null,
title: "", //
width: 1920, //
height: 1080, //
backgroundColor: "", //
backgroundImage: "", //
refreshSeconds: null, //
presetLine: [], // 线
presetLineVisible: true // 线
},
//
screenCode: "",
//
widgets: [
{
// typevaluegaea_report_dashboard_widget
type: "widget-text",
value: {
setup: {},
data: {},
position: {
width: 100,
height: 100,
left: 0,
top: 0,
zIndex: 0
}
},
// optionstools
options: []
}
], //
//
widgetIndex: 0,
//
widgetOptions: {
setup: [], //
data: [], //
position: [] //
},
flagWidgetClickStopPropagation: false, // click
styleObj: {
left: 0,
top: 0
},
visibleContentMenu: false,
rightClickIndex: -1,
activeName: "first"
};
},
computed: {
step() {
return Number(100 / (this.bigscreenScaleInWorkbench * 100));
},
headers() {
return {
Authorization: getToken() // token
};
},
//
middleWidth() {
let widthLeftAndRight = 0;
if (this.toolIsShow) {
widthLeftAndRight += this.widthLeftForTools; //
}
widthLeftAndRight += this.widthLeftForToolsHideButton; //
widthLeftAndRight += this.widthLeftForOptions; //
let middleWidth = this.bodyWidth - widthLeftAndRight;
return middleWidth;
},
middleHeight() {
return this.bodyHeight;
},
//
bigscreenScaleInWorkbench() {
let widthScale =
(this.middleWidth - this.widthPaddingTools) / this.bigscreenWidth;
let heightScale =
(this.middleHeight - this.widthPaddingTools) / this.bigscreenHeight;
return Math.min(widthScale, heightScale);
},
workbenchTransform() {
return `scale(${this.bigscreenScaleInWorkbench}, ${
this.bigscreenScaleInWorkbench
})`;
},
//
bigscreenWidthInWorkbench() {
return this.getPXUnderScale(this.bigscreenWidth) + this.widthPaddingTools;
},
bigscreenHeightInWorkbench() {
return (
this.getPXUnderScale(this.bigscreenHeight) + this.widthPaddingTools
);
}
},
watch: {
widgets: {
handler(val) {
this.handlerLayerWidget(val);
//
this.$nextTick(() => {
this.revoke.push(this.widgets);
});
},
deep: true
}
},
created() {
/* 以下是记录历史的 */
this.revoke = new Revoke();
},
mounted() {
this.initScreen();
//
// this.initEchartData();
this.widgets = [];
window.addEventListener("mouseup", () => {
this.grade = false;
});
},
methods: {
//
initScreen() {
this.widgetOptions = screenConfig["options"];
},
/**
* @description: 恢复
* @param {*}
* @return {*}
*/
handleUndo() {
const record = this.revoke.undo();
if (!record) {
return false;
}
this.widgets = record;
},
/**
* @description: 重做
* @param {*}
* @return {*}
*/
handleRedo() {
const record = this.revoke.redo();
if (!record) {
return false;
}
this.widgets = record;
},
handlerLayerWidget(val) {
const layerWidgetArr = [];
for (let i = 0; i < val.length; i++) {
const obj = {};
obj.icon = getToolByCode(val[i].type).icon;
const options = val[i].options["setup"];
options.forEach(el => {
if (el.name == "layerName") {
obj.label = el.value;
}
});
layerWidgetArr.push(obj);
}
this.layerWidget = layerWidgetArr;
},
async initEchartData() {
const reportCode = this.$route.query.reportCode;
const { code, data } = await detailDashboard(reportCode);
if (code != 200) return;
const processData = this.handleInitEchartsData(data);
const screenData = this.handleBigScreen(data.dashboard);
this.widgets = processData;
this.dashboard = screenData;
this.bigscreenWidth = this.dashboard.width;
this.bigscreenHeight = this.dashboard.height;
},
handleBigScreen(data) {
const optionScreen = getToolByCode("screen").options;
const setup = optionScreen.setup;
for (const key in data) {
for (let i = 0; i < setup.length; i++) {
if (key == setup[i].name) {
setup[i].value = data[key];
}
}
}
this.setOptionsOnClickScreen();
return {
backgroundColor: (data && data.backgroundColor) || "",
backgroundImage: (data && data.backgroundImage) || "",
height: (data && data.height) || "1080",
title: (data && data.title) || "",
width: (data && data.width) || "1920"
};
},
handleInitEchartsData(data) {
const widgets = data.dashboard ? data.dashboard.widgets : [];
const widgetsData = [];
for (let i = 0; i < widgets.length; i++) {
let obj = {};
obj.type = widgets[i].type;
obj.value = {
setup: widgets[i].value.setup,
data: widgets[i].value.data,
position: widgets[i].value.position
};
const tool = this.deepClone(getToolByCode(widgets[i].type));
const option = tool.options;
const options = this.handleOptionsData(widgets[i].value, option);
obj.options = options;
widgetsData.push(obj);
}
return widgetsData;
},
handleOptionsData(data, option) {
for (const key in data.setup) {
for (let i = 0; i < option.setup.length; i++) {
let item = option.setup[i];
if (Object.prototype.toString.call(item) == "[object Object]") {
if (key == option.setup[i].name) {
option.setup[i].value = data.setup[key];
}
} else if (Object.prototype.toString.call(item) == "[object Array]") {
for (let j = 0; j < item.length; j++) {
const list = item[j].list;
list.forEach(el => {
if (key == el.name) {
el.value = data.setup[key];
}
});
}
}
}
}
// position
for (const key in data.position) {
for (let i = 0; i < option.position.length; i++) {
if (key == option.position[i].name) {
option.position[i].value = data.position[key];
}
}
}
// data
for (const key in data.data) {
for (let i = 0; i < option.data.length; i++) {
if (key == option.data[i].name) {
option.data[i].value = data.data[key];
}
}
}
return option;
},
//
async saveData() {
if (!this.widgets || this.widgets.length == 0) {
this.$message.error("请添加组件");
return;
}
const screenData = {
reportCode: this.$route.query.reportCode,
dashboard: {
title: this.dashboard.title,
width: this.dashboard.width,
height: this.dashboard.height,
backgroundColor: this.dashboard.backgroundColor,
backgroundImage: this.dashboard.backgroundImage
},
widgets: this.widgets
};
const { code, data } = await insertDashboard(screenData);
if (code == "200") {
this.$message.success("保存成功!");
}
},
//
viewScreen() {
let routeUrl = this.$router.resolve({
path: "/bigscreen/viewer",
query: { reportCode: this.$route.query.reportCode }
});
window.open(routeUrl.href, "_blank");
},
//
async exportDashboard(val) {
const fileName = this.$route.query.reportCode + ".zip";
const param = {
reportCode: this.$route.query.reportCode,
showDataSet: val
};
exportDashboard(param).then(res => {
const that = this;
const type = res.type;
if (type == "application/json") {
let reader = new FileReader();
reader.readAsText(res, "utf-8");
reader.onload = function() {
const data = JSON.parse(reader.result);
that.$message.error(data.message);
};
return;
}
const blob = new Blob([res], { type: "application/octet-stream" });
if (window.navigator.msSaveOrOpenBlob) {
//msSaveOrOpenBlobbool
navigator.msSaveBlob(blob, fileName); //
} else {
const link = document.createElement("a"); //a
link.href = window.URL.createObjectURL(blob);
link.download = fileName;
link.click();
window.URL.revokeObjectURL(link.href);
}
});
},
//
handleUpload(response, file, fileList) {
//el-upload
this.$refs.upload.clearFiles();
//
this.initEchartData();
if (response.code == "200") {
this.$message({
message: "导入成功!",
type: "success"
});
} else {
this.$message({
message: response.message,
type: "error"
});
}
},
handleError(err) {
this.$message({
message: "上传失败!",
type: "error"
});
},
//
getPXUnderScale(px) {
return this.bigscreenScaleInWorkbench * px;
},
//
widgetOnDragged(evt, widgetCode) {
let widgetType = widgetCode;
//
let eventX = evt.originalEvent.clientX; // x
let eventY = evt.originalEvent.clientY; // y
let workbenchPosition = this.getDomTopLeftById("workbench");
let widgetTopInWorkbench = eventY - workbenchPosition.top;
let widgetLeftInWorkbench = eventX - workbenchPosition.left;
// x y
let x = widgetLeftInWorkbench / this.bigscreenScaleInWorkbench;
let y = widgetTopInWorkbench / this.bigscreenScaleInWorkbench;
//
let tool = getToolByCode(widgetType);
let widgetJson = {
type: widgetType,
value: {
setup: {},
data: {},
position: {
width: 0,
height: 0,
left: 0,
top: 0,
zIndex: 0
}
},
options: tool.options
};
//
const widgetJsonValue = this.handleDefaultValue(widgetJson);
//20220222
widgetJsonValue.value.position.left =
x - widgetJsonValue.value.position.width / 2;
widgetJsonValue.value.position.top =
y - widgetJsonValue.value.position.height / 2;
//
this.widgets.push(this.deepClone(widgetJsonValue));
//
this.setOptionsOnClickWidget(this.widgets.length - 1);
},
//
handleDefaultValue(widgetJson) {
for (const key in widgetJson) {
if (key == "options") {
// collapsedatapositionsetup
// setup
for (let i = 0; i < widgetJson.options.setup.length; i++) {
const item = widgetJson.options.setup[i];
if (Object.prototype.toString.call(item) == "[object Object]") {
widgetJson.value.setup[item.name] = item.value;
} else if (
Object.prototype.toString.call(item) == "[object Array]"
) {
for (let j = 0; j < item.length; j++) {
const list = item[j].list;
list.forEach(el => {
widgetJson.value.setup[el.name] = el.value;
});
}
}
}
// position
for (let i = 0; i < widgetJson.options.position.length; i++) {
const item = widgetJson.options.position[i];
if (item.value) {
widgetJson.value.position[item.name] = item.value;
}
}
// data
if (widgetJson.options.data && widgetJson.options.data.length > 0) {
for (let i = 0; i < widgetJson.options.data.length; i++) {
const item = widgetJson.options.data[i];
if (item.value) {
widgetJson.value.data[item.name] = item.value;
}
}
}
}
}
return widgetJson;
},
layerClick(index) {
this.widgetIndex = index;
this.widgetsClick(index);
},
//
setOptionsOnClickScreen() {
this.screenCode = "screen";
//
this.activeName = "first";
this.widgetOptions = getToolByCode("screen")["options"];
},
//
setOptionsOnClickWidget(obj) {
this.screenCode = "";
if (typeof obj == "number") {
this.widgetOptions = this.deepClone(this.widgets[obj]["options"]);
return;
}
if (obj.index < 0 || obj.index >= this.widgets.length) {
return;
}
this.widgetIndex = obj.index;
this.widgets[obj.index].value.position = obj;
this.widgets[obj.index].options.position.forEach(el => {
for (const key in obj) {
if (el.name == key) {
el.value = obj[key];
}
}
});
this.widgetOptions = this.deepClone(this.widgets[obj.index]["options"]);
},
widgetsClick(index) {
const draggableArr = this.$refs.widgets;
for (let i = 0; i < draggableArr.length; i++) {
if (i == index) {
this.$refs.widgets[i].$refs.draggable.setActive(true);
} else {
this.$refs.widgets[i].$refs.draggable.setActive(false);
}
}
this.setOptionsOnClickWidget(index);
this.grade = true;
},
widgetsMouseup(e) {
this.grade = false;
},
handleMouseDown() {
const draggableArr = this.$refs.widgets;
for (let i = 0; i < draggableArr.length; i++) {
this.$refs.widgets[i].$refs.draggable.setActive(false);
}
},
//
widgetValueChanged(key, val) {
if (this.screenCode == "screen") {
let newSetup = new Array();
this.dashboard = this.deepClone(val);
if (this.bigscreenWidth != this.dashboard.width) {
this.bigscreenWidth = this.dashboard.width;
}
if (this.bigscreenHeight != this.dashboard.height) {
this.bigscreenHeight = this.dashboard.height;
}
this.widgetOptions.setup.forEach(el => {
if (el.name == "width") {
el.value = this.bigscreenWidth;
} else if (el.name == "height") {
el.value = this.bigscreenHeight;
}
newSetup.push(el);
});
this.widgetOptions.setup = newSetup;
} else {
for (let i = 0; i < this.widgets.length; i++) {
if (this.widgetIndex == i) {
this.widgets[i].value[key] = this.deepClone(val);
this.setDefaultValue(this.widgets[i].options[key], val);
}
}
}
},
rightClick(event, index) {
this.rightClickIndex = index;
const left = event.clientX;
const top = event.clientY;
if (left || top) {
this.styleObj = {
left: left + "px",
top: top + "px",
display: "block"
};
}
this.visibleContentMenu = true;
return false;
},
setDefaultValue(options, val) {
for (let i = 0; i < options.length; i++) {
if (Object.prototype.toString.call(options[i]) == "[object Object]") {
for (const k in val) {
if (options[i].name == k) {
options[i].value = val[k];
}
}
} else if (
Object.prototype.toString.call(options[i]) == "[object Array]"
) {
for (let j = 0; j < options[i].length; j++) {
const list = options[i][j].list;
for (let z = 0; z < list.length; z++) {
for (const k in val) {
if (list[z].name == k) {
list[z].value = val[k];
}
}
}
}
}
}
},
datadragEnd(evt) {
evt.preventDefault();
this.widgets = this.swapArr(this.widgets, evt.oldIndex, evt.newIndex);
},
//
swapArr(arr, oldIndex, newIndex) {
arr[oldIndex] = arr.splice(newIndex, 1, arr[oldIndex])[0];
return arr;
},
//
deletelayer() {
this.widgets.splice(this.rightClickIndex, 1);
},
//
copylayer() {
const obj = this.deepClone(this.widgets[this.rightClickIndex]);
this.widgets.splice(this.widgets.length, 0, obj);
},
//
istopLayer() {
if (this.rightClickIndex + 1 < this.widgets.length) {
const temp = this.widgets.splice(this.rightClickIndex, 1)[0];
this.widgets.push(temp);
}
},
//
setlowLayer() {
if (this.rightClickIndex != 0) {
this.widgets.unshift(this.widgets.splice(this.rightClickIndex, 1)[0]);
}
},
//
moveupLayer() {
if (this.rightClickIndex != 0) {
this.widgets[this.rightClickIndex] = this.widgets.splice(
this.rightClickIndex - 1,
1,
this.widgets[this.rightClickIndex]
)[0];
} else {
this.widgets.push(this.widgets.shift());
}
},
//
movedownLayer() {
if (this.rightClickIndex != this.widgets.length - 1) {
this.widgets[this.rightClickIndex] = this.widgets.splice(
this.rightClickIndex + 1,
1,
this.widgets[this.rightClickIndex]
)[0];
} else {
this.widgets.unshift(this.widgets.splice(this.rightClickIndex, 1)[0]);
}
}
}
};
</script>
<style scoped lang="scss">
@import "../../assets/styles/screenDesigner.scss";
</style>

@ -0,0 +1,19 @@
### 目录结构
├── screenDesigner
│ ├── components(文件夹) 公共组件目录
│ ├── config(文件夹) 配置 json
│ │ ├── texts(文件夹) (文本、滚动文本、超链接、当前时间、图片、视频、表格、内联框架)
│ │ ├── barCharts(文件夹) (柱状图)
│ │ ├── lineCharts(文件夹) (折线图)
│ │ ├── pieCharts(文件夹) (饼图)
│ │ ├── mapCharts(文件夹) (地图)
│ ├── util(文件夹) 公共 js
│ ├── widget(文件夹) 图表组件
│ │ ├── texts(文件夹) (文本、滚动文本、超链接、当前时间、图片、视频、表格、内联框架)
│ │ ├── barCharts(文件夹) (柱状图)
│ │ ├── lineCharts(文件夹) (折线图)
│ │ ├── pieCharts(文件夹) (饼图)
│ │ ├── mapCharts(文件夹) (地图)
│ ├── index.vue 大屏设计器
│ ├── preview.vue 预览大屏

@ -0,0 +1,23 @@
export const converArr = (data) => {
console.log(data)
let tempArr = [], newArr = []
for (let i = 0; i < data.length; i++) {
const item = data[i]
if (tempArr.indexOf(item.type) === -1) {
newArr.push({
name: item.tabName,
type: item.type,
list: [item]
})
tempArr.push(item.type);
} else {
for (let j = 0; j < newArr.length; j++) {
if (newArr[j].type == item.type) {
newArr[j].list.push(item)
}
}
}
}
return newArr
}

@ -0,0 +1,109 @@
<template>
<avue-draggable
:step="step"
:width="widgetsWidth"
:height="widgetsHeight"
:left="widgetsLeft"
:top="widgetsTop"
ref="draggable"
:index="index"
:z-index="-1"
@blur="handleBlur"
>
<component :is="type" :value="value" />
</avue-draggable>
</template>
<script>
import widgetHref from "./texts/widgetHref.vue";
import WidgetIframe from "./texts/widgetIframe.vue";
import widgetImage from "./texts/widgetImage.vue";
import WidgetMarquee from "./texts/widgetMarquee.vue";
import widgetSlider from "./texts/widgetSlider.vue";
import widgetTable from "./texts/widgetTable.vue";
import widgetText from "./texts/widgetText.vue";
import widgetTime from "./texts/widgetTime.vue";
import widgetVideo from "./texts/widgetVideo.vue";
export default {
name: "Widget",
components: {
widgetHref,
WidgetIframe,
widgetImage,
WidgetMarquee,
widgetSlider,
widgetTable,
widgetText,
widgetTime,
widgetVideo
},
model: {
prop: "value",
event: "input"
},
props: {
/*
widget-text widget-marquee widget-href widget-time widget-image widget-slider widget-video widget-table widget-iframe widget-universal
widget-linechart widget-barlinechart widget-piechart widget-hollow-piechart widget-funnel widget-gauge widget-china-map
*/
index: Number, // widgetInWorkbench
type: String,
bigscreen: Object,
value: {
type: [Object],
default: () => {}
},
step: Number
},
data() {
return {
data: {
setup: {},
data: {},
position: {}
}
};
},
computed: {
widgetsWidth() {
return this.value.position.width;
},
widgetsHeight() {
return this.value.position.height;
},
widgetsLeft() {
return this.value.position.left;
},
widgetsTop() {
return this.value.position.top;
},
widgetsZIndex() {
return this.value.position.zIndex || 1;
}
},
mounted() {},
methods: {
handleBlur({ index, left, top, width, height }) {
this.$emit("onActivated", { index, left, top, width, height });
this.$refs.draggable.setActive(true);
}
}
};
</script>
<style scoped lang="scss">
.vue-draggalbe {
position: absolute;
}
.widget-active {
cursor: move;
border: 1px dashed #09f;
background-color: rgba(115, 170, 229, 0.5);
}
.avue-draggable {
padding: 0 !important;
}
</style>

@ -0,0 +1,80 @@
<!--
* @Author: lide1202@hotmail.com
* @Date: 2021-3-13 11:04:24
* @Last Modified by: lide1202@hotmail.com
* @Last Modified time: 2021-3-13 11:04:24
!-->
<template>
<a
:href="styleColor.linkAdress"
:style="styleColor"
:target="styleColor.jumpMode"
>{{ styleColor.text }}</a
>
</template>
<script>
export default {
name: "WidgetHref",
components: {},
props: {
value: Object,
ispreview: Boolean
},
data() {
return {
options: {}
};
},
computed: {
transStyle() {
return this.objToOne(this.options);
},
styleColor() {
return {
position: this.ispreview ? "absolute" : "static",
color: this.transStyle.color || "#fff",
"font-weight": this.transStyle.fontWeight || "600",
text: this.transStyle.text || "超链接",
"font-size": this.transStyle.fontSize + "px" || "12px",
"letter-spacing": this.transStyle.letterSpacing + "em",
background: this.transStyle.background,
"text-align": this.transStyle.textAlign,
display:
this.transStyle.hideLayer == undefined
? "block"
: this.transStyle.hideLayer
? "none"
: "block",
width: this.transStyle.width + "px",
height: this.transStyle.height + "px",
left: this.transStyle.left + "px",
top: this.transStyle.top + "px",
right: this.transStyle.right + "px",
linkAdress: this.transStyle.linkAdress,
jumpMode: this.transStyle.jumpMode == "other" ? "_blank" : "_self"
};
}
},
watch: {
value: {
handler(val) {
this.options = val;
},
deep: true
}
},
mounted() {
this.options = this.value;
},
methods: {}
};
</script>
<style scoped lang="scss">
a {
width: 100%;
height: 100%;
overflow: hidden;
}
</style>

@ -0,0 +1,60 @@
<template>
<iframe
:style="styleColor"
:src="styleColor.iframeAdress"
width="100%"
height="100%"
/>
</template>
<script>
export default {
name: "WidgetIframe",
components: {},
props: {
value: Object,
ispreview: Boolean
},
data() {
return {
options: {}
};
},
computed: {
transStyle() {
return this.objToOne(this.options);
},
styleColor() {
return {
position: this.ispreview ? "absolute" : "static",
width: this.transStyle.width + "px",
height: this.transStyle.height + "px",
left: this.transStyle.left + "px",
top: this.transStyle.top + "px",
right: this.transStyle.right + "px",
iframeAdress: this.transStyle.iframeAdress
};
}
},
watch: {
value: {
handler(val) {
this.options = val;
},
deep: true
}
},
mounted() {
this.options = this.value;
},
methods: {}
};
</script>
<style scoped lang="scss">
iframe {
width: 100%;
height: 100%;
border: none;
}
</style>

@ -0,0 +1,79 @@
<template>
<div class="imagebox" :style="styleColor">
<img
:class="transStyle.startRotate ? 'startImg' : ''"
:style="imgStyle"
:src="imgStyle.imageAdress"
alt=""
/>
</div>
</template>
<script>
export default {
name: "WidgetImage",
components: {},
props: {
value: Object,
ispreview: Boolean
},
data() {
return {
options: {}
};
},
computed: {
transStyle() {
return this.objToOne(this.options);
},
styleColor() {
return {
position: this.ispreview ? "absolute" : "static",
background: this.transStyle.background,
"text-align": this.transStyle.textAlign,
width: this.transStyle.width + "px",
height: this.transStyle.height + "px",
left: this.transStyle.left + "px",
top: this.transStyle.top + "px",
right: this.transStyle.right + "px"
};
},
imgStyle() {
return {
imageAdress: this.transStyle.imageAdress,
"border-radius": this.transStyle.borderRadius + "px",
opacity: this.transStyle.transparency / 100,
animation: this.transStyle.startRotate? "turn "+(101-this.transStyle.rotationSpeed)/10+"s linear infinite":"none"
};
}
},
watch: {
value: {
handler(val) {
this.options = val;
},
deep: true
}
},
created() {
this.options = this.value;
},
mounted() {},
methods: {}
};
</script>
<style scoped lang="scss">
.imagebox {
width: 100%;
height: 100%;
overflow: hidden;
}
.imagebox img {
width: 100%;
height: 100%;
}
.startImg {
animation: turn 1s linear infinite;
}
</style>

@ -0,0 +1,100 @@
<template>
<div class="text" :style="styleColor">
<marquee behavior="" :direction="styleColor.direction">{{
styleColor.text
}}</marquee>
</div>
</template>
<script>
export default {
name: "WidgetMarquee",
components: {},
props: {
value: Object,
ispreview: Boolean
},
data() {
return {
options: {}
};
},
computed: {
transStyle() {
return this.objToOne(this.options);
},
styleColor() {
return {
position: this.ispreview ? "absolute" : "static",
color: this.transStyle.color,
"font-weight": this.transStyle.fontWeight,
text: this.transStyle.text,
"font-size": this.transStyle.fontSize + "px",
"letter-spacing": this.transStyle.letterSpacing + "em",
background: this.transStyle.background,
"text-align": this.transStyle.textAlign,
width: this.transStyle.width + "px",
height: this.transStyle.height + "px",
left: this.transStyle.left + "px",
top: this.transStyle.top + "px",
right: this.transStyle.right + "px",
marqueeSet: this.transStyle.marqueeSet,
styleColor: this.transStyle.marqueeQuit
};
},
isBehavior() {
return this.styleColor.marqueeSet ? "start()" : "stop()";
}
},
watch: {
value: {
handler(val) {
this.options = val;
this.optionsData = val.data;
this.setOptionsData();
},
deep: true
}
},
mounted() {
this.options = this.value;
this.optionsData = this.value.data;
this.setOptionsData();
},
methods: {
//
setOptionsData() {
const optionsData = this.optionsData; // or
if (optionsData.dataType == "dynamicData") {
this.dynamicDataFn(optionsData.dynamicData, optionsData.refreshTime);
} else {};
},
dynamicDataFn(val, refreshTime) {
if (!val) return;
if (this.ispreview) {
this.getEchartData(val);
this.flagInter = setInterval(() => {
this.getEchartData(val);
}, refreshTime);
} else {
this.getEchartData(val);
}
},
getEchartData(val) {
const data = this.queryEchartsData(val);
data.then(res => {
this.styleColor.text = res[0].value;
this.$forceUpdate();
});
}
}
};
</script>
<style scoped lang="scss">
.text {
width: 100%;
height: 100%;
overflow: hidden;
}
</style>

@ -0,0 +1,128 @@
<template>
<superslide :options="options" class="slideBox">
<!-- slides -->
<div class="bd">
<ul>
<li>
<img src="https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=717294809,2494697366&fm=26&gp=0.jpg" alt="">
</li>
<li>
<img src="https://dss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2090090414,3038344648&fm=26&gp=0.jpg" alt="">
</li>
</ul>
</div>
<!-- Optional controls slots -->
<!-- slot="titCell" -->
<div slot="titCell" class="hd">
<ul>
<li class="on">1</li>
<li class="">2</li>
<li class="">3</li>
</ul>
</div>
<!-- slot="prev" -->
<a slot="prev" class="prev" href="javascript:void(0)" />
<!-- slot="next" -->
<a slot="next" class="next" href="javascript:void(0)" />
<!-- slot="pageStateCell" -->
<span slot="pageStateCell" class="pageState" />
</superslide>
</template>
<script>
export default {
name: 'WidgetSlider',
components: {},
data() {
return {
options: {
mainCell: '.bd ul',
autoPlay: true,
effect: 'leftLoop',
},
}
},
mounted() {},
methods: {},
}
</script>
<style scoped lang="scss">
.slideBox {
width: 450px;
height: 230px;
overflow: hidden;
position: relative;
}
.slideBox .hd {
height: 15px;
overflow: hidden;
position: absolute;
right: 5px;
bottom: 5px;
z-index: 1;
}
.slideBox .hd ul {
overflow: hidden;
zoom: 1;
float: left;
}
.slideBox .hd ul li {
float: left;
margin-right: 2px;
width: 15px;
height: 15px;
line-height: 14px;
text-align: center;
background: #fff;
cursor: pointer;
}
.slideBox .hd ul li.on {
background: #f00;
color: #fff;
}
.slideBox .bd {
position: relative;
height: 100%;
z-index: 0;
}
.slideBox .bd li {
zoom: 1;
vertical-align: middle;
}
.slideBox .bd img {
width: 450px;
height: 230px;
display: block;
}
/* 下面是前/后按钮代码,如果不需要删除即可 */
.slideBox .prev,
.slideBox .next {
position: absolute;
left: 3%;
top: 50%;
margin-top: -25px;
display: block;
width: 32px;
height: 40px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOsAAAAgCAMAAADE+3+QAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MkYyNjE4RUVDRjgxMTFFMjk1ODhDQkIzNDg3MjdGNUEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MkYyNjE4RUZDRjgxMTFFMjk1ODhDQkIzNDg3MjdGNUEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDoyRjI2MThFQ0NGODExMUUyOTU4OENCQjM0ODcyN0Y1QSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDoyRjI2MThFRENGODExMUUyOTU4OENCQjM0ODcyN0Y1QSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PmLDzTcAAAAJUExURcHBwf///////wCiYf4AAAADdFJOU///ANfKDUEAAACjSURBVHja5JnRDUQhDMNM9h/6STfCgeKPsIBjhGgpnHPy7wLyYLUicC5IPJGtJfi5ngsSL1Q7AYgsW8QTV7YJJ6psFU1M2S6YiLJlLPFk21CiydaRaOT+7mKxhYOERDcuCBy+cheiJHBqHEYGqZzPug6d4aG7aajmDPUSQz3iUO8/9KYbeqsPzWCGZmtDM9OhWfjSH8fY31UuSMkT2UqET4ABAHo9NyVXKF5RAAAAAElFTkSuQmCC) -110px
5px no-repeat;
filter: alpha(opacity=50);
opacity: 0.5;
}
.slideBox .next {
left: auto;
right: 3%;
background-position: 8px 5px;
}
.slideBox .prev:hover,
.slideBox .next:hover {
filter: alpha(opacity=100);
opacity: 1;
}
.slideBox .prevStop {
display: none;
}
.slideBox .nextStop {
display: none;
}
</style>

@ -0,0 +1,257 @@
<template>
<div :style="styleObj">
<superslide v-if="hackReset" :options="options" class="txtScroll-top">
<!--表头-->
<div class="title">
<div
v-for="(item, index) in header"
:style="[headerTableStlye, tableFiledWidth(index), tableRowHeight()]"
:key="index"
>
{{ item.name }}
</div>
</div>
<!--数据-->
<div class="bd">
<ul class="infoList">
<li
v-for="(item, index) in list"
:key="index"
:style="tableRowHeight()"
>
<div
v-for="(itemChild, idx) in header"
:key="idx"
:style="[
bodyTableStyle,
bodyTable(index),
tableFiledWidth(idx),
tableRowHeight()
]"
>
{{ item[itemChild.key] }}
</div>
</li>
</ul>
</div>
</superslide>
</div>
</template>
<script>
import vue from "vue";
import VueSuperSlide from "vue-superslide";
vue.use(VueSuperSlide);
export default {
props: {
value: Object,
ispreview: Boolean
},
data() {
return {
hackReset: true,
options: {
titCell: ".hd ul",
mainCell: ".bd ul",
effect: "topLoop",
autoPage: true,
//effect: "top",
autoPlay: true,
vis: 5,
rowHeight: "50px"
},
header: [],
list: [],
optionsSetUp: {},
optionsPosition: {},
optionsData: {}
};
},
computed: {
styleObj() {
console.log(this.optionsSetUp);
const allStyle = this.optionsPosition;
return {
position: this.ispreview ? "absolute" : "static",
width: allStyle.width + "px",
height: allStyle.height + "px",
left: allStyle.left + "px",
top: allStyle.top + "px",
background: this.optionsSetUp.tableBgColor
};
},
headerTableStlye() {
const headStyle = this.optionsSetUp;
return {
"text-align": headStyle.textAlign,
"font-size": headStyle.fontSize + "px",
"border-style": headStyle.isLine ? "solid" : "none",
"border-width": headStyle.borderWidth + "px",
"border-color": headStyle.borderColor,
display: headStyle.isHeader ? "block" : "none",
color: headStyle.headColor,
"background-color": headStyle.headBackColor
};
},
bodyTableStyle() {
const bodyStyle = this.optionsSetUp;
return {
"text-align": bodyStyle.textAlign,
"font-size": bodyStyle.fontSize + "px",
"border-style": bodyStyle.isLine ? "solid" : "none",
"border-width": bodyStyle.borderWidth + "px",
"border-color": bodyStyle.borderColor,
color: bodyStyle.bodyColor,
"background-color": bodyStyle.tableBgColor
};
}
},
watch: {
value: {
handler(val) {
this.optionsSetUp = val.setup;
this.optionsPosition = val.position;
this.optionsData = val.data;
this.initData();
},
deep: true
}
},
mounted() {
this.optionsSetUp = this.value.setup;
this.optionsPosition = this.value.position;
this.optionsData = this.value.data;
this.initData();
},
methods: {
initData() {
this.handlerRollFn();
this.handlerHead();
this.handlerData();
this.visConfig();
},
visConfig() {
this.options.vis = this.optionsSetUp.vis;
},
handlerRollFn() {
const options = this.options;
const rollSet = this.optionsSetUp;
options.autoPlay = rollSet.isRoll;
options.effect = rollSet.effect;
options.interTime = rollSet.interTime;
options.delayTime = rollSet.delayTime;
options.scroll = rollSet.scroll;
this.options = options;
this.hackResetFun();
},
handlerHead() {
const head = this.optionsSetUp.dynamicAddTable;
this.header = head;
},
handlerData() {
const tableData = this.optionsData;
tableData.dataType == "staticData"
? this.handlerStaticData(tableData.staticData)
: this.handlerDynamicData(tableData.dynamicData, tableData.refreshTime);
},
handlerStaticData(data) {
this.list = data;
},
handlerDynamicData(data, refreshTime) {
if (!data) return;
if (this.ispreview) {
this.getEchartData(data);
this.flagInter = setInterval(() => {
this.getEchartData(data);
}, refreshTime);
} else {
this.getEchartData(data);
}
},
getEchartData(val) {
const data = this.queryEchartsData(val);
data.then(res => {
this.list = res;
this.hackResetFun();
});
},
// vue hack
hackResetFun() {
this.hackReset = false;
this.$nextTick(() => {
this.hackReset = true;
});
},
//
bodyTable(index) {
let styleJson = {};
if (index % 2) {
styleJson["background-color"] = this.optionsSetUp.eventColor;
} else {
styleJson["background-color"] = this.optionsSetUp.oldColor;
}
return styleJson;
},
tableRowHeight() {
let styleJson = {};
if (this.optionsSetUp.rowHeight) {
styleJson["height"] = this.optionsSetUp.rowHeight + "px";
styleJson["line-height"] = this.optionsSetUp.rowHeight + "px";
} else {
styleJson["height"] = this.options.rowHeight;
styleJson["line-height"] = this.optionsSetUp.rowHeight + "px";
}
return styleJson;
},
tableFiledWidth(index) {
let styleJson = {};
if (this.optionsSetUp.dynamicAddTable[index].width) {
styleJson["width"] = this.optionsSetUp.dynamicAddTable[index].width;
}
return styleJson;
}
}
};
</script>
<style lang="scss" scoped>
/* 本例子css */
.txtScroll-top {
overflow: hidden;
position: relative;
}
.title {
display: flex;
flex-direction: row;
width: 100%;
}
.title > div {
height: 50px;
line-height: 50px;
width: 100%;
}
.txtScroll-top .bd {
width: 100%;
}
.txtScroll-top .infoList li {
height: 50px;
line-height: 50px;
display: flex;
flex-direction: row;
}
.txtScroll-top .infoList li > div {
width: 100%;
}
/*.txtScroll-top .infoList li:nth-child(n) {
background: rgb(0, 59, 81);
}
.txtScroll-top .infoList li:nth-child(2n) {
background: rgb(10, 39, 50);
}*/
</style>

@ -0,0 +1,98 @@
<!--
* @Author: lide1202@hotmail.com
* @Date: 2021-3-13 11:04:24
* @Last Modified by: lide1202@hotmail.com
* @Last Modified time: 2021-3-13 11:04:24
!-->
<template>
<div class="text" :style="styleColor">{{ styleColor.text }}</div>
</template>
<script>
export default {
name: "WidgetText",
components: {},
props: {
value: Object,
ispreview: Boolean
},
data() {
return {
options: {},
optionsData: {}
};
},
computed: {
transStyle() {
return this.objToOne(this.options);
},
styleColor() {
return {
position: this.ispreview ? "absolute" : "static",
color: this.transStyle.color,
"font-weight": this.transStyle.fontWeight,
text: this.transStyle.text,
"font-size": this.transStyle.fontSize + "px",
"letter-spacing": this.transStyle.letterSpacing + "em",
background: this.transStyle.background,
"text-align": this.transStyle.textAlign,
width: this.transStyle.width + "px",
height: this.transStyle.height + "px",
left: this.transStyle.left + "px",
top: this.transStyle.top + "px",
right: this.transStyle.right + "px"
};
}
},
watch: {
value: {
handler(val) {
this.options = val;
this.optionsData = val.data;
this.setOptionsData();
},
deep: true
}
},
mounted() {
this.options = this.value;
this.optionsData = this.value.data;
this.setOptionsData();
},
methods: {
//
setOptionsData() {
const optionsData = this.optionsData; // or
if (optionsData.dataType == "dynamicData") {
this.dynamicDataFn(optionsData.dynamicData, optionsData.refreshTime);
} else {};
},
dynamicDataFn(val, refreshTime) {
if (!val) return;
if (this.ispreview) {
this.getEchartData(val);
this.flagInter = setInterval(() => {
this.getEchartData(val);
}, refreshTime);
} else {
this.getEchartData(val);
}
},
getEchartData(val) {
const data = this.queryEchartsData(val);
data.then(res => {
this.styleColor.text = res[0].value;
this.$forceUpdate();
});
}
}
};
</script>
<style scoped lang="scss">
.text {
width: 100%;
height: 100%;
overflow: hidden;
}
</style>

@ -0,0 +1,163 @@
<template>
<div class="text" :style="styleColor">{{ timestr }}</div>
</template>
<script>
export default {
name: "WidgetTime",
components: {},
props: {
value: Object,
ispreview: Boolean
},
data() {
return {
timestr: "",
options: {}
};
},
computed: {
transStyle() {
console.log(this.objToOne(this.options));
return this.objToOne(this.options);
},
styleColor() {
return {
position: this.ispreview ? "absolute" : "static",
color: this.transStyle.color || "#fff",
text: this.transStyle.text || "文本框",
"font-size": this.transStyle.fontSize + "px" || "30px",
"letter-spacing": this.transStyle.letterSpacing + "em",
background: this.transStyle.background,
"font-weight": this.transStyle.fontWeight,
"text-align": this.transStyle.textAlign,
display:
this.transStyle.hideLayer == undefined
? "block"
: this.transStyle.hideLayer
? "none"
: "block",
width: this.transStyle.width + "px",
height: this.transStyle.height + "px",
left: this.transStyle.left + "px",
top: this.transStyle.top + "px",
right: this.transStyle.right + "px"
};
}
},
watch: {
value: {
handler(val) {
this.options = val;
},
deep: true
}
},
mounted() {
this.options = this.value;
this.getTime();
},
methods: {
formatFunction(date, fmt) {
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(
RegExp.$1,
(date.getFullYear() + "").substr(4 - RegExp.$1.length)
);
}
const o = {
"M+": date.getMonth() + 1, //
"d+": date.getDate(), //
"h+": date.getHours(), //
"m+": date.getMinutes(), //
"s+": date.getSeconds(), //
"q+": Math.floor((date.getMonth() + 3) / 3), //
S: date.getMilliseconds() //
};
for (let k in o) {
if (new RegExp("(" + k + ")").test(fmt)) {
fmt = fmt.replace(
RegExp.$1,
RegExp.$1.length == 1
? o[k]
: ("00" + o[k]).substr(("" + o[k]).length)
);
}
}
return fmt;
},
check(val) {
if (val < 10) {
return "0" + val;
} else {
return val;
}
},
formatWeek(date, fmt) {
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
const hours = date.getHours();
const minutes = date.getMinutes();
const seconds = date.getSeconds();
let dayCycle = date.getDay();
const dayCycleArray = ["日", "一", "二", "三", "四", "五", "六"];
for (let i = 0; i < 7; i++) {
if (dayCycle == i) {
dayCycle = " 星期" + dayCycleArray[i];
}
}
if (fmt == "year-week") {
return year + "-" + month + "-" + day + dayCycle;
} else if (fmt == "year-h-m-week") {
return (
year +
"-" +
month +
"-" +
day +
" " +
hours +
":" +
minutes +
dayCycle
);
} else if (fmt == "year-h-m-s-week") {
return (
year +
"-" +
month +
"-" +
day +
" " +
hours +
":" +
minutes +
":" +
seconds +
dayCycle
);
} else if (fmt == "week") {
return dayCycle;
}
},
displayTime() {
this.timestr =
this.transStyle.timeFormat.indexOf("week") > -1
? this.formatWeek(new Date(), this.transStyle.timeFormat)
: this.formatFunction(new Date(), this.transStyle.timeFormat);
},
getTime() {
setInterval(() => {
this.displayTime();
}, 1000);
}
}
};
</script>
<style lang="scss" scoped>
.text {
width: 100%;
height: 100%;
overflow: hidden;
}
</style>

@ -0,0 +1,61 @@
<template>
<video :style="styleColor" :src="styleColor.videoAdress" controls="controls">
您的浏览器不支持 video 标签
</video>
</template>
<script>
export default {
name: "WidgetVideo",
components: {},
props: {
value: Object,
ispreview: Boolean
},
data() {
return {
options: {}
};
},
computed: {
transStyle() {
return this.objToOne(this.options);
},
styleColor() {
return {
position: this.ispreview ? "absolute" : "static",
width: this.transStyle.width + "px",
height: this.transStyle.height + "px",
left: this.transStyle.left + "px",
top: this.transStyle.top + "px",
right: this.transStyle.right + "px",
videoAdress: this.transStyle.videoAdress
};
}
},
watch: {
value: {
handler(val) {
this.options = val;
},
deep: true
}
},
mounted() {
this.options = this.value;
},
methods: {}
};
</script>
<style scoped lang="scss">
.container {
width: 100%;
height: 100%;
}
video {
width: 100%;
height: 100%;
display: block;
}
</style>
Loading…
Cancel
Save