Merge branch 'projects/mesxc-test' of git.picaiba.com:mt-fe-group/yudao-dev into projects/mesxc-test

This commit is contained in:
gtz 2024-03-28 18:04:33 +08:00
commit e75d2f1810
123 changed files with 1437 additions and 15074 deletions

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="22px" height="22px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<svg width="32px" height="32px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 54</title>
<g id="驾驶舱" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="运营总览_生产线监控驾驶舱" transform="translate(-1866.000000, -36.000000)">
<g id="编组-54" transform="translate(1866.000000, 36.000000)">
<rect id="矩形" stroke="#979797" fill="#D8D8D8" opacity="0" x="0.5" y="0.5" width="21" height="21"></rect>
<rect id="矩形" stroke="#979797" fill="#D8D8D8" opacity="0" x="0.5" y="0.5" width="32" height="32"></rect>
<path d="M18.4001211,1 L18.574731,1.00571398 C18.8641421,1.02474925 19.1451559,1.09128771 19.4122178,1.20447947 C19.7221027,1.33395436 19.9991094,1.52058631 20.2392616,1.76073844 C20.4776764,1.99915325 20.6652172,2.27804627 20.7953442,2.58736464 C20.9313506,2.90825642 21,3.24882158 21,3.59987893 L21,3.59987893 L21,18.4001211 L20.994286,18.574731 C20.9752507,18.8641421 20.9087123,19.1451559 20.7955205,19.4122178 C20.6660456,19.7221027 20.4794137,19.9991094 20.2392616,20.2392616 C20.0008468,20.4776764 19.7219537,20.6652172 19.4126354,20.7953442 C19.0917436,20.9313506 18.7511784,21 18.4001211,21 L18.4001211,21 L3.59987893,21 L3.42526905,20.994286 C3.13585794,20.9752507 2.85484405,20.9087123 2.58778224,20.7955205 C2.2778973,20.6660456 2.00089057,20.4794137 1.76073844,20.2392616 C1.52232363,20.0008468 1.33478285,19.7219537 1.20465581,19.4126354 C1.06864936,19.0917436 1,18.7511784 1,18.4001211 L1,18.4001211 L1,3.59987893 L1.00571398,3.42526905 C1.02474925,3.13585794 1.09128771,2.85484405 1.20447947,2.58778224 C1.33395436,2.2778973 1.52058631,2.00089057 1.76073844,1.76073844 C1.99915325,1.52232363 2.27804627,1.33478285 2.58736464,1.20465581 C2.90825642,1.06864936 3.24882158,1 3.59987893,1 L3.59987893,1 L18.4001211,1 Z M18.4001211,2.29539952 L3.59987893,2.29539952 L3.49797651,2.2993263 C2.82542992,2.35136056 2.29539952,2.9140495 2.29539952,3.59987893 L2.29539952,3.59987893 L2.29539952,18.4001211 L2.2993263,18.5020235 C2.35136056,19.1745701 2.9140495,19.7046005 3.59987893,19.7046005 L3.59987893,19.7046005 L18.4001211,19.7046005 L18.5020235,19.7006737 C19.1745701,19.6486394 19.7046005,19.0859505 19.7046005,18.4001211 L19.7046005,18.4001211 L19.7046005,3.59987893 L19.7006737,3.49797651 C19.6486394,2.82542992 19.0859505,2.29539952 18.4001211,2.29539952 L18.4001211,2.29539952 Z M4.56580299,11.8731508 L4.63987359,11.8789244 C4.95620444,11.9219442 5.20096852,12.1943435 5.20096852,12.5208838 L5.20096852,12.5208838 L5.20096852,15.8606113 L8.39814764,12.6634321 L8.45892035,12.6098356 C8.71226443,12.4133149 9.08161636,12.4311804 9.3138681,12.6634321 C9.56547415,12.9150382 9.56547415,13.3275466 9.3138681,13.5791526 L9.3138681,13.5791526 L6.09149511,16.7990315 L9.4155569,16.7990315 L9.49368756,16.8035151 C9.82695229,16.8420028 10.0864105,17.123441 10.081435,17.4601165 C10.0742517,17.8119637 9.78624591,18.094431 9.43371671,18.094431 L9.43371671,18.094431 L4.5691586,18.094431 L4.49163938,18.0899766 C4.16113157,18.051728 3.90556901,17.7718105 3.90556901,17.4308414 L3.90556901,17.4308414 L3.90556901,12.5367736 L3.91007171,12.4587841 C3.94871707,12.1260764 4.23118526,11.8665247 4.56580299,11.8731508 L4.56580299,11.8731508 Z M17.4353814,3.90556901 L17.512257,3.91000958 C17.8400885,3.94813523 18.094431,4.22707005 18.094431,4.56461864 L18.094431,4.56461864 L18.094431,9.46095642 L18.0899283,9.53894589 C18.0512829,9.87165361 17.7688147,10.1312053 17.434197,10.1245792 C17.0828999,10.1173731 16.7990315,9.82850504 16.7990315,9.47684625 L16.7990315,9.47684625 L16.7990315,6.13938874 L13.6018524,9.33656786 L13.5410796,9.39016441 C13.2877356,9.58668512 12.9183836,9.5688196 12.6861319,9.33656786 C12.4345258,9.08496181 12.4345258,8.67245345 12.6861319,8.4208474 L12.6861319,8.4208474 L15.9060108,5.20096852 L12.5821731,5.20096852 L12.5040246,5.19648608 C12.170734,5.1580095 11.9119308,4.876675 11.9185506,4.54071802 C11.9257483,4.18803625 12.2137541,3.90556901 12.5662833,3.90556901 L12.5662833,3.90556901 L17.4353814,3.90556901 Z" id="形状结合" fill="#52FFF1" fill-rule="nonzero" opacity="0.79078311"></path>
</g>
</g>

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
src/assets/img/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

BIN
src/assets/img/large.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -21,9 +21,11 @@ body {
.searchBarBox .el-form-item--medium .el-form-item__label {
line-height: 40px;
}
.searchBarBox .el-form-item--medium .el-form-item__content {
line-height: 40px;
}
.searchBarBox .el-range-editor--small.el-input__inner {
height: 34px;
}
@ -153,13 +155,11 @@ aside {
text-align: right;
padding-right: 20px;
transition: 600ms ease position;
background: linear-gradient(
90deg,
background: linear-gradient(90deg,
rgba(32, 182, 249, 1) 0%,
rgba(32, 182, 249, 1) 0%,
rgba(33, 120, 241, 1) 100%,
rgba(33, 120, 241, 1) 100%
);
rgba(33, 120, 241, 1) 100%);
.subtitle {
font-size: 20px;
@ -204,10 +204,85 @@ aside {
z-index: 1000 !important;
}
// 滚动条
::-webkit-scrollbar {
width: 8px;
height: 8px;
background-color: transparent;
}
::-webkit-scrollbar-track-piece {
background-color: rgba(144, 147, 153, 0);
}
::-webkit-scrollbar-corner {
background-color: rgba(144, 147, 153, 0);
}
::-webkit-scrollbar-track {
width: 6px;
background: rgba(144, 147, 153, 0);
-webkit-border-radius: 2em;
-moz-border-radius: 2em;
border-radius: 2em;
}
::-webkit-scrollbar-thumb {
background-color: #EDEDED;
background-clip: padding-box;
min-height: 28px;
-webkit-border-radius: 2em;
-moz-border-radius: 2em;
border-radius: 2em;
transition: background-color .3s;
cursor: pointer;
}
::-webkit-scrollbar-thumb:hover {
background-color: #D9D9D9;
}
// 抽屉head区域---start
.el-drawer__header {
padding-bottom: 20px;
padding-left: 30px;
margin-bottom: 23px;
font-size: 20px;
font-weight: 500;
color: rgba(0, 0, 0, 0.85);
border-bottom: 1px solid rgba(233, 233, 233, 1);
}
.el-drawer__header> :first-child::before {
content: '';
display: inline-block;
width: 4px;
height: 24px;
background-color: #0b58ff;
margin-right: 8px;
vertical-align: middle;
}
// 抽屉head区域---end
// 弹出框上下分布去掉label的padding-bottom
.el-form--label-top .el-form-item__label {
padding: 0;
}
// 大屏滚动表格
.dv-scroll-board .rows .ceil,
.dv-scroll-board .header .header-item {
border-right: 1px solid rgba(13, 23, 40, 1);
}
.dv-scroll-board .rows .ceil:last-child,
.dv-scroll-board .header .header-item:last-child {
border-right: none;
}
.no-data-bg {
height: 240px;
background: url(../images/no-data-bg.png) 50% 100% / contain
no-repeat;
background: url(../images/no-data-bg.png) 50% 100% / contain no-repeat;
position: relative;
&::after {

View File

@ -2,7 +2,8 @@
<el-breadcrumb class="app-breadcrumb" separator="/">
<transition-group name="breadcrumb">
<el-breadcrumb-item v-for="(item, index) in levelList" :key="item.path">
<span v-if="item.redirect==='noRedirect'||index===levelList.length-1" class="no-redirect">{{ item.meta.title }}</span>
<span v-if="item.redirect === 'noRedirect' || index === levelList.length - 1" class="no-redirect">{{ item.meta.title
}}</span>
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
</el-breadcrumb-item>
</transition-group>
@ -64,7 +65,7 @@ export default {
.app-breadcrumb.el-breadcrumb {
display: inline-block;
font-size: 14px;
line-height: 56px;
line-height: 48px;
margin-left: 8px;
.no-redirect {
@ -73,7 +74,8 @@ export default {
}
}
.app-breadcrumb .el-breadcrumb__inner a, .el-breadcrumb__inner.is-link {
.app-breadcrumb .el-breadcrumb__inner a,
.el-breadcrumb__inner.is-link {
color: rgba(0, 0, 0, 0.45);
}
</style>

View File

@ -1,160 +0,0 @@
<template>
<el-form size="small">
<el-form-item>
<el-radio v-model='radioValue' :label="1">
允许的通配符[, - * ? / L W]
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="2">
不指定
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="3">
周期从
<el-input-number v-model='cycle01' :min="1" :max="30" /> -
<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 2" :max="31" />
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="4">
<el-input-number v-model='average01' :min="1" :max="30" /> 号开始
<el-input-number v-model='average02' :min="1" :max="31 - average01 || 1" /> 日执行一次
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="5">
每月
<el-input-number v-model='workday' :min="1" :max="31" /> 号最近的那个工作日
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="6">
本月最后一天
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="7">
指定
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
<el-option v-for="item in 31" :key="item" :value="item">{{item}}</el-option>
</el-select>
</el-radio>
</el-form-item>
</el-form>
</template>
<script>
export default {
data() {
return {
radioValue: 1,
workday: 1,
cycle01: 1,
cycle02: 2,
average01: 1,
average02: 1,
checkboxList: [],
checkNum: this.$options.propsData.check
}
},
name: 'crontab-day',
props: ['check', 'cron'],
methods: {
//
radioChange() {
('day rachange');
if (this.radioValue !== 2 && this.cron.week !== '?') {
this.$emit('update', 'week', '?', 'day')
}
switch (this.radioValue) {
case 1:
this.$emit('update', 'day', '*');
break;
case 2:
this.$emit('update', 'day', '?');
break;
case 3:
this.$emit('update', 'day', this.cycleTotal);
break;
case 4:
this.$emit('update', 'day', this.averageTotal);
break;
case 5:
this.$emit('update', 'day', this.workday + 'W');
break;
case 6:
this.$emit('update', 'day', 'L');
break;
case 7:
this.$emit('update', 'day', this.checkboxString);
break;
}
('day rachange end');
},
//
cycleChange() {
if (this.radioValue === '3') {
this.$emit('update', 'day', this.cycleTotal);
}
},
//
averageChange() {
if (this.radioValue === '4') {
this.$emit('update', 'day', this.averageTotal);
}
},
//
workdayChange() {
if (this.radioValue === '5') {
this.$emit('update', 'day', this.workdayCheck + 'W');
}
},
// checkbox
checkboxChange() {
if (this.radioValue === '7') {
this.$emit('update', 'day', this.checkboxString);
}
}
},
watch: {
'radioValue': 'radioChange',
'cycleTotal': 'cycleChange',
'averageTotal': 'averageChange',
'workdayCheck': 'workdayChange',
'checkboxString': 'checkboxChange',
},
computed: {
//
cycleTotal: function () {
const cycle01 = this.checkNum(this.cycle01, 1, 30)
const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 2, 31, 31)
return cycle01 + '-' + cycle02;
},
//
averageTotal: function () {
const average01 = this.checkNum(this.average01, 1, 30)
const average02 = this.checkNum(this.average02, 1, 31 - average01 || 0)
return average01 + '/' + average02;
},
//
workdayCheck: function () {
return this.checkNum(this.workday, 1, 31);
},
// checkbox
checkboxString: function () {
let str = this.checkboxList.join();
return str === '' ? '*' : str;
}
}
}
</script>

View File

@ -1,114 +0,0 @@
<template>
<el-form size="small">
<el-form-item>
<el-radio v-model='radioValue' :label="1">
小时允许的通配符[, - * /]
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="2">
周期从
<el-input-number v-model='cycle01' :min="0" :max="22" /> -
<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 1" :max="23" /> 小时
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="3">
<el-input-number v-model='average01' :min="0" :max="22" /> 小时开始
<el-input-number v-model='average02' :min="1" :max="23 - average01 || 0" /> 小时执行一次
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="4">
指定
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
<el-option v-for="item in 24" :key="item" :value="item-1">{{item-1}}</el-option>
</el-select>
</el-radio>
</el-form-item>
</el-form>
</template>
<script>
export default {
data() {
return {
radioValue: 1,
cycle01: 0,
cycle02: 1,
average01: 0,
average02: 1,
checkboxList: [],
checkNum: this.$options.propsData.check
}
},
name: 'crontab-hour',
props: ['check', 'cron'],
methods: {
//
radioChange() {
switch (this.radioValue) {
case 1:
this.$emit('update', 'hour', '*')
break;
case 2:
this.$emit('update', 'hour', this.cycleTotal);
break;
case 3:
this.$emit('update', 'hour', this.averageTotal);
break;
case 4:
this.$emit('update', 'hour', this.checkboxString);
break;
}
},
//
cycleChange() {
if (this.radioValue === '2') {
this.$emit('update', 'hour', this.cycleTotal);
}
},
//
averageChange() {
if (this.radioValue === '3') {
this.$emit('update', 'hour', this.averageTotal);
}
},
// checkbox
checkboxChange() {
if (this.radioValue === '4') {
this.$emit('update', 'hour', this.checkboxString);
}
}
},
watch: {
'radioValue': 'radioChange',
'cycleTotal': 'cycleChange',
'averageTotal': 'averageChange',
'checkboxString': 'checkboxChange'
},
computed: {
//
cycleTotal: function () {
const cycle01 = this.checkNum(this.cycle01, 0, 22)
const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 23)
return cycle01 + '-' + cycle02;
},
//
averageTotal: function () {
const average01 = this.checkNum(this.average01, 0, 22)
const average02 = this.checkNum(this.average02, 1, 23 - average01 || 0)
return average01 + '/' + average02;
},
// checkbox
checkboxString: function () {
let str = this.checkboxList.join();
return str === '' ? '*' : str;
}
}
}
</script>

View File

@ -1,430 +0,0 @@
<template>
<div>
<el-tabs type="border-card">
<el-tab-pane label="秒" v-if="shouldHide('second')">
<CrontabSecond
@update="updateCrontabValue"
:check="checkNumber"
:cron="crontabValueObj"
ref="cronsecond"
/>
</el-tab-pane>
<el-tab-pane label="分钟" v-if="shouldHide('min')">
<CrontabMin
@update="updateCrontabValue"
:check="checkNumber"
:cron="crontabValueObj"
ref="cronmin"
/>
</el-tab-pane>
<el-tab-pane label="小时" v-if="shouldHide('hour')">
<CrontabHour
@update="updateCrontabValue"
:check="checkNumber"
:cron="crontabValueObj"
ref="cronhour"
/>
</el-tab-pane>
<el-tab-pane label="日" v-if="shouldHide('day')">
<CrontabDay
@update="updateCrontabValue"
:check="checkNumber"
:cron="crontabValueObj"
ref="cronday"
/>
</el-tab-pane>
<el-tab-pane label="月" v-if="shouldHide('month')">
<CrontabMonth
@update="updateCrontabValue"
:check="checkNumber"
:cron="crontabValueObj"
ref="cronmonth"
/>
</el-tab-pane>
<el-tab-pane label="周" v-if="shouldHide('week')">
<CrontabWeek
@update="updateCrontabValue"
:check="checkNumber"
:cron="crontabValueObj"
ref="cronweek"
/>
</el-tab-pane>
<el-tab-pane label="年" v-if="shouldHide('year')">
<CrontabYear
@update="updateCrontabValue"
:check="checkNumber"
:cron="crontabValueObj"
ref="cronyear"
/>
</el-tab-pane>
</el-tabs>
<div class="popup-main">
<div class="popup-result">
<p class="title">时间表达式</p>
<table>
<thead>
<th v-for="item of tabTitles" width="40" :key="item">{{item}}</th>
<th>Cron 表达式</th>
</thead>
<tbody>
<td>
<span>{{crontabValueObj.second}}</span>
</td>
<td>
<span>{{crontabValueObj.min}}</span>
</td>
<td>
<span>{{crontabValueObj.hour}}</span>
</td>
<td>
<span>{{crontabValueObj.day}}</span>
</td>
<td>
<span>{{crontabValueObj.month}}</span>
</td>
<td>
<span>{{crontabValueObj.week}}</span>
</td>
<td>
<span>{{crontabValueObj.year}}</span>
</td>
<td>
<span>{{crontabValueString}}</span>
</td>
</tbody>
</table>
</div>
<CrontabResult :ex="crontabValueString"></CrontabResult>
<div class="pop_btn">
<el-button size="small" type="primary" @click="submitFill">确定</el-button>
<el-button size="small" type="warning" @click="clearCron">重置</el-button>
<el-button size="small" @click="hidePopup">取消</el-button>
</div>
</div>
</div>
</template>
<script>
import CrontabSecond from "./second.vue";
import CrontabMin from "./min.vue";
import CrontabHour from "./hour.vue";
import CrontabDay from "./day.vue";
import CrontabMonth from "./month.vue";
import CrontabWeek from "./week.vue";
import CrontabYear from "./year.vue";
import CrontabResult from "./result.vue";
export default {
data() {
return {
tabTitles: ["秒", "分钟", "小时", "日", "月", "周", "年"],
tabActive: 0,
myindex: 0,
crontabValueObj: {
second: "*",
min: "*",
hour: "*",
day: "*",
month: "*",
week: "?",
year: "",
},
};
},
name: "vcrontab",
props: ["expression", "hideComponent"],
methods: {
shouldHide(key) {
return !(this.hideComponent && this.hideComponent.includes(key));
},
resolveExp() {
//
if (this.expression) {
let arr = this.expression.split(" ");
if (arr.length >= 6) {
//6
let obj = {
second: arr[0],
min: arr[1],
hour: arr[2],
day: arr[3],
month: arr[4],
week: arr[5],
year: arr[6] ? arr[6] : "",
};
this.crontabValueObj = {
...obj,
};
for (let i in obj) {
if (obj[i]) this.changeRadio(i, obj[i]);
}
}
} else {
//
this.clearCron();
}
},
// tab
tabCheck(index) {
this.tabActive = index;
},
//
updateCrontabValue(name, value, from) {
"updateCrontabValue", name, value, from;
this.crontabValueObj[name] = value;
if (from && from !== name) {
console.log(`来自组件 ${from} 改变了 ${name} ${value}`);
this.changeRadio(name, value);
}
},
//
changeRadio(name, value) {
let arr = ["second", "min", "hour", "month"],
refName = "cron" + name,
insValue;
if (!this.$refs[refName]) return;
if (arr.includes(name)) {
if (value === "*") {
insValue = 1;
} else if (value.indexOf("-") > -1) {
let indexArr = value.split("-");
isNaN(indexArr[0])
? (this.$refs[refName].cycle01 = 0)
: (this.$refs[refName].cycle01 = indexArr[0]);
this.$refs[refName].cycle02 = indexArr[1];
insValue = 2;
} else if (value.indexOf("/") > -1) {
let indexArr = value.split("/");
isNaN(indexArr[0])
? (this.$refs[refName].average01 = 0)
: (this.$refs[refName].average01 = indexArr[0]);
this.$refs[refName].average02 = indexArr[1];
insValue = 3;
} else {
insValue = 4;
this.$refs[refName].checkboxList = value.split(",");
}
} else if (name === "day") {
if (value === "*") {
insValue = 1;
} else if (value === "?") {
insValue = 2;
} else if (value.indexOf("-") > -1) {
let indexArr = value.split("-");
isNaN(indexArr[0])
? (this.$refs[refName].cycle01 = 0)
: (this.$refs[refName].cycle01 = indexArr[0]);
this.$refs[refName].cycle02 = indexArr[1];
insValue = 3;
} else if (value.indexOf("/") > -1) {
let indexArr = value.split("/");
isNaN(indexArr[0])
? (this.$refs[refName].average01 = 0)
: (this.$refs[refName].average01 = indexArr[0]);
this.$refs[refName].average02 = indexArr[1];
insValue = 4;
} else if (value.indexOf("W") > -1) {
let indexArr = value.split("W");
isNaN(indexArr[0])
? (this.$refs[refName].workday = 0)
: (this.$refs[refName].workday = indexArr[0]);
insValue = 5;
} else if (value === "L") {
insValue = 6;
} else {
this.$refs[refName].checkboxList = value.split(",");
insValue = 7;
}
} else if (name === "week") {
if (value === "*") {
insValue = 1;
} else if (value === "?") {
insValue = 2;
} else if (value.indexOf("-") > -1) {
let indexArr = value.split("-");
isNaN(indexArr[0])
? (this.$refs[refName].cycle01 = 0)
: (this.$refs[refName].cycle01 = indexArr[0]);
this.$refs[refName].cycle02 = indexArr[1];
insValue = 3;
} else if (value.indexOf("#") > -1) {
let indexArr = value.split("#");
isNaN(indexArr[0])
? (this.$refs[refName].average01 = 1)
: (this.$refs[refName].average01 = indexArr[0]);
this.$refs[refName].average02 = indexArr[1];
insValue = 4;
} else if (value.indexOf("L") > -1) {
let indexArr = value.split("L");
isNaN(indexArr[0])
? (this.$refs[refName].weekday = 1)
: (this.$refs[refName].weekday = indexArr[0]);
insValue = 5;
} else {
this.$refs[refName].checkboxList = value.split(",");
insValue = 6;
}
} else if (name === "year") {
if (value === "") {
insValue = 1;
} else if (value === "*") {
insValue = 2;
} else if (value.indexOf("-") > -1) {
insValue = 3;
} else if (value.indexOf("/") > -1) {
insValue = 4;
} else {
this.$refs[refName].checkboxList = value.split(",");
insValue = 5;
}
}
this.$refs[refName].radioValue = insValue;
},
// -props
checkNumber(value, minLimit, maxLimit) {
//
value = Math.floor(value);
if (value < minLimit) {
value = minLimit;
} else if (value > maxLimit) {
value = maxLimit;
}
return value;
},
//
hidePopup() {
this.$emit("hide");
},
//
submitFill() {
this.$emit("fill", this.crontabValueString);
this.hidePopup();
},
clearCron() {
//
("准备还原");
this.crontabValueObj = {
second: "*",
min: "*",
hour: "*",
day: "*",
month: "*",
week: "?",
year: "",
};
for (let j in this.crontabValueObj) {
this.changeRadio(j, this.crontabValueObj[j]);
}
},
},
computed: {
crontabValueString: function() {
let obj = this.crontabValueObj;
let str =
obj.second +
" " +
obj.min +
" " +
obj.hour +
" " +
obj.day +
" " +
obj.month +
" " +
obj.week +
(obj.year === "" ? "" : " " + obj.year);
return str;
},
},
components: {
CrontabSecond,
CrontabMin,
CrontabHour,
CrontabDay,
CrontabMonth,
CrontabWeek,
CrontabYear,
CrontabResult,
},
watch: {
expression: "resolveExp",
hideComponent(value) {
//
},
},
mounted: function() {
this.resolveExp();
},
};
</script>
<style scoped>
.pop_btn {
text-align: center;
margin-top: 20px;
}
.popup-main {
position: relative;
margin: 10px auto;
background: #fff;
border-radius: 5px;
font-size: 12px;
overflow: hidden;
}
.popup-title {
overflow: hidden;
line-height: 34px;
padding-top: 6px;
background: #f2f2f2;
}
.popup-result {
box-sizing: border-box;
line-height: 24px;
margin: 25px auto;
padding: 15px 10px 10px;
border: 1px solid #ccc;
position: relative;
}
.popup-result .title {
position: absolute;
top: -28px;
left: 50%;
width: 140px;
font-size: 14px;
margin-left: -70px;
text-align: center;
line-height: 30px;
background: #fff;
}
.popup-result table {
text-align: center;
width: 100%;
margin: 0 auto;
}
.popup-result table span {
display: block;
width: 100%;
font-family: arial;
line-height: 30px;
height: 30px;
white-space: nowrap;
overflow: hidden;
border: 1px solid #e8e8e8;
}
.popup-result-scroll {
font-size: 12px;
line-height: 24px;
height: 10em;
overflow-y: auto;
}
</style>

View File

@ -1,116 +0,0 @@
<template>
<el-form size="small">
<el-form-item>
<el-radio v-model='radioValue' :label="1">
分钟允许的通配符[, - * /]
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="2">
周期从
<el-input-number v-model='cycle01' :min="0" :max="58" /> -
<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 1" :max="59" /> 分钟
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="3">
<el-input-number v-model='average01' :min="0" :max="58" /> 分钟开始
<el-input-number v-model='average02' :min="1" :max="59 - average01 || 0" /> 分钟执行一次
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="4">
指定
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
<el-option v-for="item in 60" :key="item" :value="item-1">{{item-1}}</el-option>
</el-select>
</el-radio>
</el-form-item>
</el-form>
</template>
<script>
export default {
data() {
return {
radioValue: 1,
cycle01: 1,
cycle02: 2,
average01: 0,
average02: 1,
checkboxList: [],
checkNum: this.$options.propsData.check
}
},
name: 'crontab-min',
props: ['check', 'cron'],
methods: {
//
radioChange() {
switch (this.radioValue) {
case 1:
this.$emit('update', 'min', '*', 'min');
break;
case 2:
this.$emit('update', 'min', this.cycleTotal, 'min');
break;
case 3:
this.$emit('update', 'min', this.averageTotal, 'min');
break;
case 4:
this.$emit('update', 'min', this.checkboxString, 'min');
break;
}
},
//
cycleChange() {
if (this.radioValue === '2') {
this.$emit('update', 'min', this.cycleTotal, 'min');
}
},
//
averageChange() {
if (this.radioValue === '3') {
this.$emit('update', 'min', this.averageTotal, 'min');
}
},
// checkbox
checkboxChange() {
if (this.radioValue === '4') {
this.$emit('update', 'min', this.checkboxString, 'min');
}
},
},
watch: {
'radioValue': 'radioChange',
'cycleTotal': 'cycleChange',
'averageTotal': 'averageChange',
'checkboxString': 'checkboxChange',
},
computed: {
//
cycleTotal: function () {
const cycle01 = this.checkNum(this.cycle01, 0, 58)
const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 59)
return cycle01 + '-' + cycle02;
},
//
averageTotal: function () {
const average01 = this.checkNum(this.average01, 0, 58)
const average02 = this.checkNum(this.average02, 1, 59 - average01 || 0)
return average01 + '/' + average02;
},
// checkbox
checkboxString: function () {
let str = this.checkboxList.join();
return str === '' ? '*' : str;
}
}
}
</script>

View File

@ -1,114 +0,0 @@
<template>
<el-form size='small'>
<el-form-item>
<el-radio v-model='radioValue' :label="1">
允许的通配符[, - * /]
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="2">
周期从
<el-input-number v-model='cycle01' :min="1" :max="11" /> -
<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 2" :max="12" />
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="3">
<el-input-number v-model='average01' :min="1" :max="11" /> 月开始
<el-input-number v-model='average02' :min="1" :max="12 - average01 || 0" /> 月月执行一次
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="4">
指定
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
<el-option v-for="item in 12" :key="item" :value="item">{{item}}</el-option>
</el-select>
</el-radio>
</el-form-item>
</el-form>
</template>
<script>
export default {
data() {
return {
radioValue: 1,
cycle01: 1,
cycle02: 2,
average01: 1,
average02: 1,
checkboxList: [],
checkNum: this.check
}
},
name: 'crontab-month',
props: ['check', 'cron'],
methods: {
//
radioChange() {
switch (this.radioValue) {
case 1:
this.$emit('update', 'month', '*');
break;
case 2:
this.$emit('update', 'month', this.cycleTotal);
break;
case 3:
this.$emit('update', 'month', this.averageTotal);
break;
case 4:
this.$emit('update', 'month', this.checkboxString);
break;
}
},
//
cycleChange() {
if (this.radioValue === '2') {
this.$emit('update', 'month', this.cycleTotal);
}
},
//
averageChange() {
if (this.radioValue === '3') {
this.$emit('update', 'month', this.averageTotal);
}
},
// checkbox
checkboxChange() {
if (this.radioValue === '4') {
this.$emit('update', 'month', this.checkboxString);
}
}
},
watch: {
'radioValue': 'radioChange',
'cycleTotal': 'cycleChange',
'averageTotal': 'averageChange',
'checkboxString': 'checkboxChange'
},
computed: {
//
cycleTotal: function () {
const cycle01 = this.checkNum(this.cycle01, 1, 11)
const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 2, 12)
return cycle01 + '-' + cycle02;
},
//
averageTotal: function () {
const average01 = this.checkNum(this.average01, 1, 11)
const average02 = this.checkNum(this.average02, 1, 12 - average01 || 0)
return average01 + '/' + average02;
},
// checkbox
checkboxString: function () {
let str = this.checkboxList.join();
return str === '' ? '*' : str;
}
}
}
</script>

View File

@ -1,559 +0,0 @@
<template>
<div class="popup-result">
<p class="title">最近5次运行时间</p>
<ul class="popup-result-scroll">
<template v-if='isShow'>
<li v-for='item in resultList' :key="item">{{item}}</li>
</template>
<li v-else>计算结果中...</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
dayRule: '',
dayRuleSup: '',
dateArr: [],
resultList: [],
isShow: false
}
},
name: 'crontab-result',
methods: {
//
expressionChange() {
// -
this.isShow = false;
// [0123456]
let ruleArr = this.$options.propsData.ex.split(' ');
//
let nums = 0;
//
let resultArr = [];
// []
let nTime = new Date();
let nYear = nTime.getFullYear();
let nMonth = nTime.getMonth() + 1;
let nDay = nTime.getDate();
let nHour = nTime.getHours();
let nMin = nTime.getMinutes();
let nSecond = nTime.getSeconds();
// 100
this.getSecondArr(ruleArr[0]);
this.getMinArr(ruleArr[1]);
this.getHourArr(ruleArr[2]);
this.getDayArr(ruleArr[3]);
this.getMonthArr(ruleArr[4]);
this.getWeekArr(ruleArr[5]);
this.getYearArr(ruleArr[6], nYear);
// -便使
let sDate = this.dateArr[0];
let mDate = this.dateArr[1];
let hDate = this.dateArr[2];
let DDate = this.dateArr[3];
let MDate = this.dateArr[4];
let YDate = this.dateArr[5];
//
let sIdx = this.getIndex(sDate, nSecond);
let mIdx = this.getIndex(mDate, nMin);
let hIdx = this.getIndex(hDate, nHour);
let DIdx = this.getIndex(DDate, nDay);
let MIdx = this.getIndex(MDate, nMonth);
let YIdx = this.getIndex(YDate, nYear);
// ()
const resetSecond = function () {
sIdx = 0;
nSecond = sDate[sIdx]
}
const resetMin = function () {
mIdx = 0;
nMin = mDate[mIdx]
resetSecond();
}
const resetHour = function () {
hIdx = 0;
nHour = hDate[hIdx]
resetMin();
}
const resetDay = function () {
DIdx = 0;
nDay = DDate[DIdx]
resetHour();
}
const resetMonth = function () {
MIdx = 0;
nMonth = MDate[MIdx]
resetDay();
}
//
if (nYear !== YDate[YIdx]) {
resetMonth();
}
//
if (nMonth !== MDate[MIdx]) {
resetDay();
}
//
if (nDay !== DDate[DIdx]) {
resetHour();
}
//
if (nHour !== hDate[hIdx]) {
resetMin();
}
//
if (nMin !== mDate[mIdx]) {
resetSecond();
}
//
goYear: for (let Yi = YIdx; Yi < YDate.length; Yi++) {
let YY = YDate[Yi];
//
if (nMonth > MDate[MDate.length - 1]) {
resetMonth();
continue;
}
//
goMonth: for (let Mi = MIdx; Mi < MDate.length; Mi++) {
// 便
let MM = MDate[Mi];
MM = MM < 10 ? '0' + MM : MM;
//
if (nDay > DDate[DDate.length - 1]) {
resetDay();
if (Mi === MDate.length - 1) {
resetMonth();
continue goYear;
}
continue;
}
//
goDay: for (let Di = DIdx; Di < DDate.length; Di++) {
// 便
let DD = DDate[Di];
let thisDD = DD < 10 ? '0' + DD : DD;
//
if (nHour > hDate[hDate.length - 1]) {
resetHour();
if (Di === DDate.length - 1) {
resetDay();
if (Mi === MDate.length - 1) {
resetMonth();
continue goYear;
}
continue goMonth;
}
continue;
}
//
if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true && this.dayRule !== 'workDay' && this.dayRule !== 'lastWeek' && this.dayRule !== 'lastDay') {
resetDay();
continue goMonth;
}
//
if (this.dayRule === 'lastDay') {
//
if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
while (DD > 0 && this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
DD--;
thisDD = DD < 10 ? '0' + DD : DD;
}
}
} else if (this.dayRule === 'workDay') {
// 230
if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
while (DD > 0 && this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
DD--;
thisDD = DD < 10 ? '0' + DD : DD;
}
}
// X
let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + thisDD + ' 00:00:00'), 'week');
//
if (thisWeek === 1) {
//
DD++;
thisDD = DD < 10 ? '0' + DD : DD;
//
if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
DD -= 3;
}
} else if (thisWeek === 7) {
// 61
if (this.dayRuleSup !== 1) {
DD--;
} else {
DD += 2;
}
}
} else if (this.dayRule === 'weekDay') {
//
//
let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + DD + ' 00:00:00'), 'week');
// dayRuleSup
if (this.dayRuleSup.indexOf(thisWeek) < 0) {
//
if (Di === DDate.length - 1) {
resetDay();
if (Mi === MDate.length - 1) {
resetMonth();
continue goYear;
}
continue goMonth;
}
continue;
}
} else if (this.dayRule === 'assWeek') {
//
// 1
let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + DD + ' 00:00:00'), 'week');
if (this.dayRuleSup[1] >= thisWeek) {
DD = (this.dayRuleSup[0] - 1) * 7 + this.dayRuleSup[1] - thisWeek + 1;
} else {
DD = this.dayRuleSup[0] * 7 + this.dayRuleSup[1] - thisWeek + 1;
}
} else if (this.dayRule === 'lastWeek') {
//
// 230
if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
while (DD > 0 && this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
DD--;
thisDD = DD < 10 ? '0' + DD : DD;
}
}
//
let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + thisDD + ' 00:00:00'), 'week');
//
if (this.dayRuleSup < thisWeek) {
DD -= thisWeek - this.dayRuleSup;
} else if (this.dayRuleSup > thisWeek) {
DD -= 7 - (this.dayRuleSup - thisWeek)
}
}
// 1005
DD = DD < 10 ? '0' + DD : DD;
//
goHour: for (let hi = hIdx; hi < hDate.length; hi++) {
let hh = hDate[hi] < 10 ? '0' + hDate[hi] : hDate[hi]
//
if (nMin > mDate[mDate.length - 1]) {
resetMin();
if (hi === hDate.length - 1) {
resetHour();
if (Di === DDate.length - 1) {
resetDay();
if (Mi === MDate.length - 1) {
resetMonth();
continue goYear;
}
continue goMonth;
}
continue goDay;
}
continue;
}
// ""
goMin: for (let mi = mIdx; mi < mDate.length; mi++) {
let mm = mDate[mi] < 10 ? '0' + mDate[mi] : mDate[mi];
//
if (nSecond > sDate[sDate.length - 1]) {
resetSecond();
if (mi === mDate.length - 1) {
resetMin();
if (hi === hDate.length - 1) {
resetHour();
if (Di === DDate.length - 1) {
resetDay();
if (Mi === MDate.length - 1) {
resetMonth();
continue goYear;
}
continue goMonth;
}
continue goDay;
}
continue goHour;
}
continue;
}
// ""
goSecond: for (let si = sIdx; si <= sDate.length - 1; si++) {
let ss = sDate[si] < 10 ? '0' + sDate[si] : sDate[si];
//
if (MM !== '00' && DD !== '00') {
resultArr.push(YY + '-' + MM + '-' + DD + ' ' + hh + ':' + mm + ':' + ss)
nums++;
}
// 退
if (nums === 5) break goYear;
//
if (si === sDate.length - 1) {
resetSecond();
if (mi === mDate.length - 1) {
resetMin();
if (hi === hDate.length - 1) {
resetHour();
if (Di === DDate.length - 1) {
resetDay();
if (Mi === MDate.length - 1) {
resetMonth();
continue goYear;
}
continue goMonth;
}
continue goDay;
}
continue goHour;
}
continue goMin;
}
} //goSecond
} //goMin
}//goHour
}//goDay
}//goMonth
}
// 100
if (resultArr.length === 0) {
this.resultList = ['没有达到条件的结果!'];
} else {
this.resultList = resultArr;
if (resultArr.length !== 5) {
this.resultList.push('最近100年内只有上面' + resultArr.length + '条结果!')
}
}
// -
this.isShow = true;
},
//
getIndex(arr, value) {
if (value <= arr[0] || value > arr[arr.length - 1]) {
return 0;
} else {
for (let i = 0; i < arr.length - 1; i++) {
if (value > arr[i] && value <= arr[i + 1]) {
return i + 1;
}
}
}
},
// ""
getYearArr(rule, year) {
this.dateArr[5] = this.getOrderArr(year, year + 100);
if (rule !== undefined) {
if (rule.indexOf('-') >= 0) {
this.dateArr[5] = this.getCycleArr(rule, year + 100, false)
} else if (rule.indexOf('/') >= 0) {
this.dateArr[5] = this.getAverageArr(rule, year + 100)
} else if (rule !== '*') {
this.dateArr[5] = this.getAssignArr(rule)
}
}
},
// ""
getMonthArr(rule) {
this.dateArr[4] = this.getOrderArr(1, 12);
if (rule.indexOf('-') >= 0) {
this.dateArr[4] = this.getCycleArr(rule, 12, false)
} else if (rule.indexOf('/') >= 0) {
this.dateArr[4] = this.getAverageArr(rule, 12)
} else if (rule !== '*') {
this.dateArr[4] = this.getAssignArr(rule)
}
},
// ""-
getWeekArr(rule) {
//
if (this.dayRule === '' && this.dayRuleSup === '') {
if (rule.indexOf('-') >= 0) {
this.dayRule = 'weekDay';
this.dayRuleSup = this.getCycleArr(rule, 7, false)
} else if (rule.indexOf('#') >= 0) {
this.dayRule = 'assWeek';
let matchRule = rule.match(/[0-9]/g);
this.dayRuleSup = [Number(matchRule[1]), Number(matchRule[0])];
this.dateArr[3] = [1];
if (this.dayRuleSup[1] === 7) {
this.dayRuleSup[1] = 0;
}
} else if (rule.indexOf('L') >= 0) {
this.dayRule = 'lastWeek';
this.dayRuleSup = Number(rule.match(/[0-9]{1,2}/g)[0]);
this.dateArr[3] = [31];
if (this.dayRuleSup === 7) {
this.dayRuleSup = 0;
}
} else if (rule !== '*' && rule !== '?') {
this.dayRule = 'weekDay';
this.dayRuleSup = this.getAssignArr(rule)
}
}
},
// ""-
getDayArr(rule) {
this.dateArr[3] = this.getOrderArr(1, 31);
this.dayRule = '';
this.dayRuleSup = '';
if (rule.indexOf('-') >= 0) {
this.dateArr[3] = this.getCycleArr(rule, 31, false)
this.dayRuleSup = 'null';
} else if (rule.indexOf('/') >= 0) {
this.dateArr[3] = this.getAverageArr(rule, 31)
this.dayRuleSup = 'null';
} else if (rule.indexOf('W') >= 0) {
this.dayRule = 'workDay';
this.dayRuleSup = Number(rule.match(/[0-9]{1,2}/g)[0]);
this.dateArr[3] = [this.dayRuleSup];
} else if (rule.indexOf('L') >= 0) {
this.dayRule = 'lastDay';
this.dayRuleSup = 'null';
this.dateArr[3] = [31];
} else if (rule !== '*' && rule !== '?') {
this.dateArr[3] = this.getAssignArr(rule)
this.dayRuleSup = 'null';
} else if (rule === '*') {
this.dayRuleSup = 'null';
}
},
// ""
getHourArr(rule) {
this.dateArr[2] = this.getOrderArr(0, 23);
if (rule.indexOf('-') >= 0) {
this.dateArr[2] = this.getCycleArr(rule, 24, true)
} else if (rule.indexOf('/') >= 0) {
this.dateArr[2] = this.getAverageArr(rule, 23)
} else if (rule !== '*') {
this.dateArr[2] = this.getAssignArr(rule)
}
},
// ""
getMinArr(rule) {
this.dateArr[1] = this.getOrderArr(0, 59);
if (rule.indexOf('-') >= 0) {
this.dateArr[1] = this.getCycleArr(rule, 60, true)
} else if (rule.indexOf('/') >= 0) {
this.dateArr[1] = this.getAverageArr(rule, 59)
} else if (rule !== '*') {
this.dateArr[1] = this.getAssignArr(rule)
}
},
// ""
getSecondArr(rule) {
this.dateArr[0] = this.getOrderArr(0, 59);
if (rule.indexOf('-') >= 0) {
this.dateArr[0] = this.getCycleArr(rule, 60, true)
} else if (rule.indexOf('/') >= 0) {
this.dateArr[0] = this.getAverageArr(rule, 59)
} else if (rule !== '*') {
this.dateArr[0] = this.getAssignArr(rule)
}
},
// min-max
getOrderArr(min, max) {
let arr = [];
for (let i = min; i <= max; i++) {
arr.push(i);
}
return arr;
},
//
getAssignArr(rule) {
let arr = [];
let assiginArr = rule.split(',');
for (let i = 0; i < assiginArr.length; i++) {
arr[i] = Number(assiginArr[i])
}
arr.sort(this.compare)
return arr;
},
//
getAverageArr(rule, limit) {
let arr = [];
let agArr = rule.split('/');
let min = Number(agArr[0]);
let step = Number(agArr[1]);
while (min <= limit) {
arr.push(min);
min += step;
}
return arr;
},
//
getCycleArr(rule, limit, status) {
// status--01
let arr = [];
let cycleArr = rule.split('-');
let min = Number(cycleArr[0]);
let max = Number(cycleArr[1]);
if (min > max) {
max += limit;
}
for (let i = min; i <= max; i++) {
let add = 0;
if (status === false && i % limit === 0) {
add = limit;
}
arr.push(Math.round(i % limit + add))
}
arr.sort(this.compare)
return arr;
},
// Array.sort
compare(value1, value2) {
if (value2 - value1 > 0) {
return -1;
} else {
return 1;
}
},
// 2017-9-19 18:04:33
formatDate(value, type) {
//
let time = typeof value == 'number' ? new Date(value) : value;
let Y = time.getFullYear();
let M = time.getMonth() + 1;
let D = time.getDate();
let h = time.getHours();
let m = time.getMinutes();
let s = time.getSeconds();
let week = time.getDay();
// type
if (type === undefined) {
return Y + '-' + (M < 10 ? '0' + M : M) + '-' + (D < 10 ? '0' + D : D) + ' ' + (h < 10 ? '0' + h : h) + ':' + (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
} else if (type === 'week') {
// quartz 1
return week + 1;
}
},
//
checkDate(value) {
let time = new Date(value);
let format = this.formatDate(time)
return value === format;
}
},
watch: {
'ex': 'expressionChange'
},
props: ['ex'],
mounted: function () {
//
this.expressionChange();
}
}
</script>

View File

@ -1,117 +0,0 @@
<template>
<el-form size="small">
<el-form-item>
<el-radio v-model='radioValue' :label="1">
允许的通配符[, - * /]
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="2">
周期从
<el-input-number v-model='cycle01' :min="0" :max="58" /> -
<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 1" :max="59" />
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="3">
<el-input-number v-model='average01' :min="0" :max="58" /> 秒开始
<el-input-number v-model='average02' :min="1" :max="59 - average01 || 0" /> 秒执行一次
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="4">
指定
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
<el-option v-for="item in 60" :key="item" :value="item-1">{{item-1}}</el-option>
</el-select>
</el-radio>
</el-form-item>
</el-form>
</template>
<script>
export default {
data() {
return {
radioValue: 1,
cycle01: 1,
cycle02: 2,
average01: 0,
average02: 1,
checkboxList: [],
checkNum: this.$options.propsData.check
}
},
name: 'crontab-second',
props: ['check', 'radioParent'],
methods: {
//
radioChange() {
switch (this.radioValue) {
case 1:
this.$emit('update', 'second', '*', 'second');
break;
case 2:
this.$emit('update', 'second', this.cycleTotal);
break;
case 3:
this.$emit('update', 'second', this.averageTotal);
break;
case 4:
this.$emit('update', 'second', this.checkboxString);
break;
}
},
//
cycleChange() {
if (this.radioValue === '2') {
this.$emit('update', 'second', this.cycleTotal);
}
},
//
averageChange() {
if (this.radioValue === '3') {
this.$emit('update', 'second', this.averageTotal);
}
},
// checkbox
checkboxChange() {
if (this.radioValue === '4') {
this.$emit('update', 'second', this.checkboxString);
}
}
},
watch: {
'radioValue': 'radioChange',
'cycleTotal': 'cycleChange',
'averageTotal': 'averageChange',
'checkboxString': 'checkboxChange',
radioParent() {
this.radioValue = this.radioParent
}
},
computed: {
//
cycleTotal: function () {
const cycle01 = this.checkNum(this.cycle01, 0, 58)
const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 59)
return cycle01 + '-' + cycle02;
},
//
averageTotal: function () {
const average01 = this.checkNum(this.average01, 0, 58)
const average02 = this.checkNum(this.average02, 1, 59 - average01 || 0)
return average01 + '/' + average02;
},
// checkbox
checkboxString: function () {
let str = this.checkboxList.join();
return str === '' ? '*' : str;
}
}
}
</script>

View File

@ -1,202 +0,0 @@
<template>
<el-form size='small'>
<el-form-item>
<el-radio v-model='radioValue' :label="1">
允许的通配符[, - * ? / L #]
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="2">
不指定
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="3">
周期从星期
<el-select clearable v-model="cycle01">
<el-option
v-for="(item,index) of weekList"
:key="index"
:label="item.value"
:value="item.key"
:disabled="item.key === 1"
>{{item.value}}</el-option>
</el-select>
-
<el-select clearable v-model="cycle02">
<el-option
v-for="(item,index) of weekList"
:key="index"
:label="item.value"
:value="item.key"
:disabled="item.key < cycle01 && item.key !== 1"
>{{item.value}}</el-option>
</el-select>
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="4">
<el-input-number v-model='average01' :min="1" :max="4" /> 周的星期
<el-select clearable v-model="average02">
<el-option v-for="(item,index) of weekList" :key="index" :label="item.value" :value="item.key">{{item.value}}</el-option>
</el-select>
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="5">
本月最后一个星期
<el-select clearable v-model="weekday">
<el-option v-for="(item,index) of weekList" :key="index" :label="item.value" :value="item.key">{{item.value}}</el-option>
</el-select>
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :label="6">
指定
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
<el-option v-for="(item,index) of weekList" :key="index" :label="item.value" :value="String(item.key)">{{item.value}}</el-option>
</el-select>
</el-radio>
</el-form-item>
</el-form>
</template>
<script>
export default {
data() {
return {
radioValue: 2,
weekday: 2,
cycle01: 2,
cycle02: 3,
average01: 1,
average02: 2,
checkboxList: [],
weekList: [
{
key: 2,
value: '星期一'
},
{
key: 3,
value: '星期二'
},
{
key: 4,
value: '星期三'
},
{
key: 5,
value: '星期四'
},
{
key: 6,
value: '星期五'
},
{
key: 7,
value: '星期六'
},
{
key: 1,
value: '星期日'
}
],
checkNum: this.$options.propsData.check
}
},
name: 'crontab-week',
props: ['check', 'cron'],
methods: {
//
radioChange() {
if (this.radioValue !== 2 && this.cron.day !== '?') {
this.$emit('update', 'day', '?', 'week');
}
switch (this.radioValue) {
case 1:
this.$emit('update', 'week', '*');
break;
case 2:
this.$emit('update', 'week', '?');
break;
case 3:
this.$emit('update', 'week', this.cycleTotal);
break;
case 4:
this.$emit('update', 'week', this.averageTotal);
break;
case 5:
this.$emit('update', 'week', this.weekdayCheck + 'L');
break;
case 6:
this.$emit('update', 'week', this.checkboxString);
break;
}
},
//
cycleChange() {
if (this.radioValue === '3') {
this.$emit('update', 'week', this.cycleTotal);
}
},
//
averageChange() {
if (this.radioValue === '4') {
this.$emit('update', 'week', this.averageTotal);
}
},
//
weekdayChange() {
if (this.radioValue === '5') {
this.$emit('update', 'week', this.weekday + 'L');
}
},
// checkbox
checkboxChange() {
if (this.radioValue === '6') {
this.$emit('update', 'week', this.checkboxString);
}
},
},
watch: {
'radioValue': 'radioChange',
'cycleTotal': 'cycleChange',
'averageTotal': 'averageChange',
'weekdayCheck': 'weekdayChange',
'checkboxString': 'checkboxChange',
},
computed: {
//
cycleTotal: function () {
this.cycle01 = this.checkNum(this.cycle01, 1, 7)
this.cycle02 = this.checkNum(this.cycle02, 1, 7)
return this.cycle01 + '-' + this.cycle02;
},
//
averageTotal: function () {
this.average01 = this.checkNum(this.average01, 1, 4)
this.average02 = this.checkNum(this.average02, 1, 7)
return this.average02 + '#' + this.average01;
},
//
weekdayCheck: function () {
this.weekday = this.checkNum(this.weekday, 1, 7)
return this.weekday;
},
// checkbox
checkboxString: function () {
let str = this.checkboxList.join();
return str === '' ? '*' : str;
}
}
}
</script>

View File

@ -1,131 +0,0 @@
<template>
<el-form size="small">
<el-form-item>
<el-radio :label="1" v-model='radioValue'>
不填允许的通配符[, - * /]
</el-radio>
</el-form-item>
<el-form-item>
<el-radio :label="2" v-model='radioValue'>
每年
</el-radio>
</el-form-item>
<el-form-item>
<el-radio :label="3" v-model='radioValue'>
周期从
<el-input-number v-model='cycle01' :min='fullYear' :max="2098" /> -
<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : fullYear + 1" :max="2099" />
</el-radio>
</el-form-item>
<el-form-item>
<el-radio :label="4" v-model='radioValue'>
<el-input-number v-model='average01' :min='fullYear' :max="2098"/> 年开始
<el-input-number v-model='average02' :min="1" :max="2099 - average01 || fullYear" /> 年执行一次
</el-radio>
</el-form-item>
<el-form-item>
<el-radio :label="5" v-model='radioValue'>
指定
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple>
<el-option v-for="item in 9" :key="item" :value="item - 1 + fullYear" :label="item -1 + fullYear" />
</el-select>
</el-radio>
</el-form-item>
</el-form>
</template>
<script>
export default {
data() {
return {
fullYear: 0,
radioValue: 1,
cycle01: 0,
cycle02: 0,
average01: 0,
average02: 1,
checkboxList: [],
checkNum: this.$options.propsData.check
}
},
name: 'crontab-year',
props: ['check', 'month', 'cron'],
methods: {
//
radioChange() {
switch (this.radioValue) {
case 1:
this.$emit('update', 'year', '');
break;
case 2:
this.$emit('update', 'year', '*');
break;
case 3:
this.$emit('update', 'year', this.cycleTotal);
break;
case 4:
this.$emit('update', 'year', this.averageTotal);
break;
case 5:
this.$emit('update', 'year', this.checkboxString);
break;
}
},
//
cycleChange() {
if (this.radioValue === '3') {
this.$emit('update', 'year', this.cycleTotal);
}
},
//
averageChange() {
if (this.radioValue === '4') {
this.$emit('update', 'year', this.averageTotal);
}
},
// checkbox
checkboxChange() {
if (this.radioValue === '5') {
this.$emit('update', 'year', this.checkboxString);
}
}
},
watch: {
'radioValue': 'radioChange',
'cycleTotal': 'cycleChange',
'averageTotal': 'averageChange',
'checkboxString': 'checkboxChange'
},
computed: {
//
cycleTotal: function () {
const cycle01 = this.checkNum(this.cycle01, this.fullYear, 2098)
const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : this.fullYear + 1, 2099)
return cycle01 + '-' + cycle02;
},
//
averageTotal: function () {
const average01 = this.checkNum(this.average01, this.fullYear, 2098)
const average02 = this.checkNum(this.average02, 1, 2099 - average01 || this.fullYear)
return average01 + '/' + average02;
},
// checkbox
checkboxString: function () {
let str = this.checkboxList.join();
return str;
}
},
mounted: function () {
//
this.fullYear = Number(new Date().getFullYear());
this.cycle01 = this.fullYear
this.average01 = this.fullYear
}
}
</script>

View File

@ -1,33 +0,0 @@
<template>
<el-alert v-if="enable()" type="success" show-icon>
<template slot="title">
<div @click="goToUrl">{{ '' + title + '文档地址' + url }}</div>
</template>
</el-alert>
</template>
<script>
import {getDocEnable} from "@/utils/ruoyi";
export default {
name: "DocAlert",
props: {
title: String,
url: String,
},
methods: {
enable: function () {
return getDocEnable();
},
goToUrl: function() {
window.open(this.url);
}
}
};
</script>
<style scoped>
.el-alert--success.is-light {
margin-bottom: 10px;
cursor: pointer;
}
</style>

View File

@ -1,141 +0,0 @@
<template>
<div :style="{zIndex:zIndex,height:height,width:width}" class="pan-item">
<div class="pan-info">
<div class="pan-info-roles-container">
<slot />
</div>
</div>
<!-- eslint-disable-next-line -->
<div :style="{backgroundImage: `url(${image})`}" class="pan-thumb"></div>
</div>
</template>
<script>
export default {
name: 'PanThumb',
props: {
image: {
type: String,
required: true
},
zIndex: {
type: Number,
default: 1
},
width: {
type: String,
default: '150px'
},
height: {
type: String,
default: '150px'
}
}
}
</script>
<style scoped>
.pan-item {
width: 200px;
height: 200px;
border-radius: 50%;
display: inline-block;
position: relative;
cursor: default;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}
.pan-info-roles-container {
padding: 20px;
text-align: center;
}
.pan-thumb {
width: 100%;
height: 100%;
background-position: center center;
background-size: cover;
border-radius: 50%;
overflow: hidden;
position: absolute;
transform-origin: 95% 40%;
transition: all 0.3s ease-in-out;
}
/* .pan-thumb:after {
content: '';
width: 8px;
height: 8px;
position: absolute;
border-radius: 50%;
top: 40%;
left: 95%;
margin: -4px 0 0 -4px;
background: radial-gradient(ellipse at center, rgba(14, 14, 14, 1) 0%, rgba(125, 126, 125, 1) 100%);
box-shadow: 0 0 1px rgba(255, 255, 255, 0.9);
} */
.pan-info {
position: absolute;
width: inherit;
height: inherit;
border-radius: 50%;
overflow: hidden;
box-shadow: inset 0 0 0 5px rgba(0, 0, 0, 0.05);
}
.pan-info h3 {
color: #fff;
text-transform: uppercase;
position: relative;
letter-spacing: 2px;
font-size: 18px;
margin: 0 60px;
padding: 22px 0 0 0;
height: 85px;
font-family: 'Open Sans', Arial, sans-serif;
text-shadow: 0 0 1px #fff, 0 1px 2px rgba(0, 0, 0, 0.3);
}
.pan-info p {
color: #fff;
padding: 10px 5px;
font-style: italic;
margin: 0 30px;
font-size: 12px;
border-top: 1px solid rgba(255, 255, 255, 0.5);
}
.pan-info p a {
display: block;
width: 80px;
height: 80px;
background: rgba(255, 255, 255, 0.3);
border-radius: 50%;
color: #fff;
font-style: normal;
font-weight: 700;
text-transform: uppercase;
font-size: 9px;
letter-spacing: 1px;
padding-top: 24px;
margin: 7px auto 0;
font-family: 'Open Sans', Arial, sans-serif;
opacity: 0;
transition: transform 0.3s ease-in-out 0.2s, opacity 0.3s ease-in-out 0.2s, background 0.2s linear 0s;
transform: translateX(60px) rotate(90deg);
}
.pan-info p a:hover {
background: rgba(255, 255, 255, 0.5);
}
.pan-item:hover .pan-thumb {
transform: rotate(-110deg);
}
.pan-item:hover .pan-info p a {
opacity: 1;
transform: translateX(0px) rotate(0deg);
}
</style>

View File

@ -1,21 +0,0 @@
## form-generator
github 地址https://github.com/JakHuang/form-generator
* generator
* parser
* render
* tinymce
## bpmn-process-designer
github 地址https://github.com/miyuesc/bpmn-process-designer
* bpmnProcessDesigner
TODO 目前存在的问题,如果选择 activiti 类型时,因为不支持内置表单的设计,所以会报 Error: unknown type activiti:FormData 错误。具体可见 https://github.com/miyuesc/bpmn-process-designer/issues/16 。
另外几个流程设计器的选型:
* https://gitee.com/jimlow/vue-bpmn 相比差一些,已经停止维护,不算推荐。
* https://github.com/GoldSubmarine/workflow-bpmn-modeler 仅支持 flowable 流程引擎。如果只考虑 flowable 的话,也是非常不错的选择。

View File

@ -1,21 +0,0 @@
<template>
<div>
<svg-icon icon-class="question" @click="goto"/>
</div>
</template>
<script>
export default {
name: 'YudaoDoc',
data() {
return {
url: 'https://doc.iocoder.cn/'
}
},
methods: {
goto() {
window.open(this.url)
}
}
}
</script>

View File

@ -1,21 +0,0 @@
<template>
<div>
<svg-icon icon-class="github" @click="goto"/>
</div>
</template>
<script>
export default {
name: 'YudaoGit',
data() {
return {
url: 'https://github.com/YunaiV/ruoyi-vue-pro'
}
},
methods: {
goto() {
window.open(this.url)
}
}
}
</script>

View File

@ -1,211 +0,0 @@
<template>
<div class="editPage__video">
<el-upload
class="uploader"
list-type="picture-card"
:action="uploadUrl"
:on-success="handleSuccess"
:before-upload="beforeUpload"
:headers="headers"
:on-error="handleError"
:show-file-list="false"
>
<div v-if="uploadFlag" @mouseenter="mouseover" @mouseleave="mouseout">
<i class="el-icon-success success-icon"></i>
<div :class="{'hide': activeHover, 'success': !activeHover}">
<span class="item-actions">
<span
class="item-preview"
@click.stop="handlePreview()"
>
<i class="el-icon-zoom-in"></i>
</span>
<span
class="item-delete"
@click.stop="handleRemove()"
>
<i class="el-icon-delete"></i>
</span>
</span>
</div>
</div>
<i v-else-if="uploadFlag === null" class="el-icon-plus uploader-icon"></i>
<i v-else-if="!uploadFlag" class="el-icon-circle-close uploader-icon" style="color: red"></i>
</el-upload>
<!-- 上传提示 -->
<div class="el-upload__tip" slot="tip" v-if="showTip">
请上传
<template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
<template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
的文件
</div>
<el-dialog :visible.sync="dialogVisible" append-to-body width="800" title="预览">
<video width="100%" v-if="videoUrl" controls="controls" :key="menuKey">
<source :src="videoUrl" type="video/mp4" />
</video>
</el-dialog>
</div>
</template>
<script>
import { getAccessToken } from "@/utils/auth";
export default {
props: {
value: [String, Object],
// (MB)
fileSize: {
type: Number,
default: 300,
},
// , "video/mp4"
fileType: {
type: [String, Array],
default: () =>["video/mp4"],
},
//
isShowTip: {
type: Boolean,
default: true
}
},
data() {
return {
uploadFlag: null,
activeHover: true,
dialogVisible: false,
videoUrl: null,
//
uploadUrl: process.env.VUE_APP_BASE_API + "/admin-api/infra/file/upload", //
headers: { Authorization: "Bearer " + getAccessToken() }, //
// key
menuKey: 1, // ,
}
},
watch: {
value: {
handler(val) {
if (val) {
this.videoUrl = val;
this.uploadFlag = true;
}
},
deep: true,
immediate: true
}
},
computed: {
//
showTip() {
return this.isShowTip && (this.fileType || this.fileSize);
},
},
methods: {
//
handleSuccess(res) {
++this.menuKey;
if(res.code === 0){
this.uploadFlag = true;
this.videoUrl = res.data;
this.$emit("input", this.videoUrl);
}else{
this.uploadFlag = false;
this.$message.error("错误!"+ res.msg);
}
},
handleError(){
this.uploadFlag = false;
},
beforeUpload(file) {
const isMp4 = this.fileType.includes(file.type);
const isLt300MB = file.size / 1024 / 1024 < 300;
if (!isMp4) {
this.$message.error("视频只能是"+ this.fileType.join("/") +"格式!");
}
if (!isLt300MB) {
this.$message.error("上传视频大小不能超过 300MB!");
}
return isMp4 && isLt300MB;
},
//
handlePreview() {
this.dialogVisible = true;
},
//
handleRemove() {
this.videoUrl = null;
this.uploadFlag = null;
this.$emit("input", null);
},
mouseover(){
this.activeHover = false;
},
mouseout(){
this.activeHover = true;
}
}
}
</script>
<style lang="scss">
.editPage__video {
.hide{
visibility:hidden;
}
.success{
position: relative;
width: 78px;
height: 78px;
line-height: 78px;
background-color: rgba(0,0,0,.5);
transition: opacity .3s;
cursor: default;
.item-preview .el-icon-zoom-in{
width: 30px;
font-size: 20px;
color: #f2f2f2;
cursor: pointer;
}
.item-delete .el-icon-delete{
width: 30px;
font-size: 20px;
color: #f2f2f2;
cursor: pointer;
}
}
.uploader-icon {
font-size: 28px;
color: #8c939d;
width: 80px;
height: 80px;
line-height: 80px;
text-align: center;
position: absolute;
left: 0;
}
.success-icon {
font-size: 28px;
color: green;
width: 80px;
height: 80px;
line-height: 80px;
text-align: center;
position: absolute;
left: 0;
}
.el-upload{
width: 80px;
height: 80px;
}
}
</style>

View File

@ -1,476 +0,0 @@
<template>
<div class="my-process-designer">
<div class="my-process-designer__header">
<slot name="control-header"></slot>
<template v-if="!$slots['control-header']">
<el-button-group key="file-control">
<el-button :size="headerButtonSize" icon="el-icon-folder-opened" @click="$refs.refFile.click()">打开文件</el-button>
<el-tooltip effect="light">
<div slot="content">
<el-button :size="headerButtonSize" type="text" @click="downloadProcessAsXml()">下载为XML文件</el-button>
<br />
<el-button :size="headerButtonSize" type="text" @click="downloadProcessAsSvg()">下载为SVG文件</el-button>
<br />
<el-button :size="headerButtonSize" type="text" @click="downloadProcessAsBpmn()">下载为BPMN文件</el-button>
</div>
<el-button :size="headerButtonSize" icon="el-icon-download">下载文件</el-button>
</el-tooltip>
<el-tooltip effect="light">
<div slot="content">
<el-button :size="headerButtonSize" type="text" @click="previewProcessXML">预览XML</el-button>
<br />
<el-button :size="headerButtonSize" type="text" @click="previewProcessJson">预览JSON</el-button>
</div>
<el-button :size="headerButtonSize" icon="el-icon-view">预览</el-button>
</el-tooltip>
<el-tooltip v-if="simulation" effect="light" :content="this.simulationStatus ? '退出模拟' : '开启模拟'">
<el-button :size="headerButtonSize" icon="el-icon-cpu" @click="processSimulation">
模拟
</el-button>
</el-tooltip>
</el-button-group>
<el-button-group key="align-control">
<el-tooltip effect="light" content="向左对齐">
<el-button :size="headerButtonSize" class="align align-left" icon="el-icon-s-data" @click="elementsAlign('left')" />
</el-tooltip>
<el-tooltip effect="light" content="向右对齐">
<el-button :size="headerButtonSize" class="align align-right" icon="el-icon-s-data" @click="elementsAlign('right')" />
</el-tooltip>
<el-tooltip effect="light" content="向上对齐">
<el-button :size="headerButtonSize" class="align align-top" icon="el-icon-s-data" @click="elementsAlign('top')" />
</el-tooltip>
<el-tooltip effect="light" content="向下对齐">
<el-button :size="headerButtonSize" class="align align-bottom" icon="el-icon-s-data" @click="elementsAlign('bottom')" />
</el-tooltip>
<el-tooltip effect="light" content="水平居中">
<el-button :size="headerButtonSize" class="align align-center" icon="el-icon-s-data" @click="elementsAlign('center')" />
</el-tooltip>
<el-tooltip effect="light" content="垂直居中">
<el-button :size="headerButtonSize" class="align align-middle" icon="el-icon-s-data" @click="elementsAlign('middle')" />
</el-tooltip>
</el-button-group>
<el-button-group key="scale-control">
<el-tooltip effect="light" content="缩小视图">
<el-button :size="headerButtonSize" :disabled="defaultZoom < 0.2" icon="el-icon-zoom-out" @click="processZoomOut()" />
</el-tooltip>
<el-button :size="headerButtonSize">{{ Math.floor(this.defaultZoom * 10 * 10) + "%" }}</el-button>
<el-tooltip effect="light" content="放大视图">
<el-button :size="headerButtonSize" :disabled="defaultZoom > 4" icon="el-icon-zoom-in" @click="processZoomIn()" />
</el-tooltip>
<el-tooltip effect="light" content="重置视图并居中">
<el-button :size="headerButtonSize" icon="el-icon-c-scale-to-original" @click="processReZoom()" />
</el-tooltip>
</el-button-group>
<el-button-group key="stack-control">
<el-tooltip effect="light" content="撤销">
<el-button :size="headerButtonSize" :disabled="!revocable" icon="el-icon-refresh-left" @click="processUndo()" />
</el-tooltip>
<el-tooltip effect="light" content="恢复">
<el-button :size="headerButtonSize" :disabled="!recoverable" icon="el-icon-refresh-right" @click="processRedo()" />
</el-tooltip>
<el-tooltip effect="light" content="重新绘制">
<el-button :size="headerButtonSize" icon="el-icon-refresh" @click="processRestart" />
</el-tooltip>
</el-button-group>
<el-button :size="headerButtonSize" :type="headerButtonType" icon="el-icon-plus" @click="processSave" :disabled = "simulationStatus">保存模型</el-button>
</template>
<!-- 用于打开本地文件-->
<input type="file" id="files" ref="refFile" style="display: none" accept=".xml, .bpmn" @change="importLocalFile" />
</div>
<div class="my-process-designer__container">
<div class="my-process-designer__canvas" ref="bpmn-canvas"></div>
</div>
<el-dialog title="预览" width="80%" :visible.sync="previewModelVisible" append-to-body destroy-on-close>
<pre><code class="hljs" v-html="highlightedCode(previewType, previewResult)"></code></pre>
</el-dialog>
</div>
</template>
<script>
import BpmnModeler from "bpmn-js/lib/Modeler";
import DefaultEmptyXML from "./plugins/defaultEmpty";
//
import customTranslate from "./plugins/translate/customTranslate";
import translationsCN from "./plugins/translate/zh";
//
import tokenSimulation from "bpmn-js-token-simulation";
//
// import bpmnPropertiesProvider from "bpmn-js-properties-panel/lib/provider/bpmn";
// Moddle
import camundaModdleDescriptor from "./plugins/descriptor/camundaDescriptor.json";
import activitiModdleDescriptor from "./plugins/descriptor/activitiDescriptor.json";
import flowableModdleDescriptor from "./plugins/descriptor/flowableDescriptor.json";
// Extension
import camundaModdleExtension from "./plugins/extension-moddle/camunda";
import activitiModdleExtension from "./plugins/extension-moddle/activiti";
import flowableModdleExtension from "./plugins/extension-moddle/flowable";
// json
import convert from "xml-js";
//
import hljs from "highlight.js/lib/highlight";
import "highlight.js/styles/github-gist.css";
hljs.registerLanguage("xml", require("highlight.js/lib/languages/xml"));
hljs.registerLanguage("json", require("highlight.js/lib/languages/json"));
export default {
name: "MyProcessDesigner",
componentName: "MyProcessDesigner",
props: {
value: String, // xml
valueWatch: true, // xml watch
processId: String, // key
processName: String, // name
formId: Number, // form
translations: Object, //
additionalModel: [Object, Array], // model
moddleExtension: Object, // moddle
onlyCustomizeAddi: {
type: Boolean,
default: false
},
onlyCustomizeModdle: {
type: Boolean,
default: false
},
simulation: {
type: Boolean,
default: true
},
keyboard: {
type: Boolean,
default: true
},
prefix: {
type: String,
default: "camunda"
},
events: {
type: Array,
default: () => ["element.click"]
},
headerButtonSize: {
type: String,
default: "small",
validator: value => ["default", "medium", "small", "mini"].indexOf(value) !== -1
},
headerButtonType: {
type: String,
default: "primary",
validator: value => ["default", "primary", "success", "warning", "danger", "info"].indexOf(value) !== -1
}
},
data() {
return {
defaultZoom: 1,
previewModelVisible: false,
simulationStatus: false,
previewResult: "",
previewType: "xml",
recoverable: false,
revocable: false
};
},
computed: {
additionalModules() {
const Modules = [];
//
if (this.onlyCustomizeAddi) {
if (Object.prototype.toString.call(this.additionalModel) === "[object Array]") {
return this.additionalModel || [];
}
return [this.additionalModel];
}
//
if (Object.prototype.toString.call(this.additionalModel) === "[object Array]") {
Modules.push(...this.additionalModel);
} else {
this.additionalModel && Modules.push(this.additionalModel);
}
//
const TranslateModule = {
translate: ["value", customTranslate(this.translations || translationsCN)]
};
Modules.push(TranslateModule);
//
if (this.simulation) {
Modules.push(tokenSimulation);
}
//
// if (this.prefix === "bpmn") {
// Modules.push(bpmnModdleExtension);
// }
if (this.prefix === "camunda") {
Modules.push(camundaModdleExtension);
}
if (this.prefix === "flowable") {
Modules.push(flowableModdleExtension);
}
if (this.prefix === "activiti") {
Modules.push(activitiModdleExtension);
}
return Modules;
},
moddleExtensions() {
const Extensions = {};
// 使
if (this.onlyCustomizeModdle) {
return this.moddleExtension || null;
}
//
if (this.moddleExtension) {
for (let key in this.moddleExtension) {
Extensions[key] = this.moddleExtension[key];
}
}
// ""
if (this.prefix === "activiti") {
Extensions.activiti = activitiModdleDescriptor;
}
if (this.prefix === "flowable") {
Extensions.flowable = flowableModdleDescriptor;
}
if (this.prefix === "camunda") {
Extensions.camunda = camundaModdleDescriptor;
}
return Extensions;
}
},
mounted() {
this.initBpmnModeler();
this.createNewDiagram(this.value);
this.$once("hook:beforeDestroy", () => {
if (this.bpmnModeler) this.bpmnModeler.destroy();
this.$emit("destroy", this.bpmnModeler);
this.bpmnModeler = null;
});
},
methods: {
initBpmnModeler() {
if (this.bpmnModeler) return;
this.bpmnModeler = new BpmnModeler({
container: this.$refs["bpmn-canvas"],
keyboard: this.keyboard ? { bindTo: document } : null,
additionalModules: this.additionalModules,
moddleExtensions: this.moddleExtensions
});
this.$emit("init-finished", this.bpmnModeler);
this.initModelListeners();
},
initModelListeners() {
const EventBus = this.bpmnModeler.get("eventBus");
const that = this;
// , . - ,
this.events.forEach(event => {
EventBus.on(event, function(eventObj) {
let eventName = event.replace(/\./g, "-");
let element = eventObj ? eventObj.element : null;
that.$emit(eventName, element, eventObj);
});
});
// xml
EventBus.on("commandStack.changed", async event => {
try {
this.recoverable = this.bpmnModeler.get("commandStack").canRedo();
this.revocable = this.bpmnModeler.get("commandStack").canUndo();
let { xml } = await this.bpmnModeler.saveXML({ format: true });
this.$emit("commandStack-changed", event);
this.$emit("input", xml);
this.$emit("change", xml);
} catch (e) {
console.error(`[Process Designer Warn]: ${e.message || e}`);
}
});
//
this.bpmnModeler.on("canvas.viewbox.changed", ({ viewbox }) => {
this.$emit("canvas-viewbox-changed", { viewbox });
const { scale } = viewbox;
this.defaultZoom = Math.floor(scale * 100) / 100;
});
},
/* 创建新的流程图 */
async createNewDiagram(xml) {
//
let newId = this.processId || `Process_${new Date().getTime()}`;
let newName = this.processName || `业务流程_${new Date().getTime()}`;
let xmlString = xml || DefaultEmptyXML(newId, newName, this.prefix);
try {
// console.log(this.bpmnModeler.importXML);
let { warnings } = await this.bpmnModeler.importXML(xmlString);
if (warnings && warnings.length) {
warnings.forEach(warn => console.warn(warn));
}
} catch (e) {
console.error(`[Process Designer Warn]: ${e?.message || e}`);
}
},
//
async downloadProcess(type, name) {
try {
const _this = this;
//
if (type === "xml" || type === "bpmn") {
const { err, xml } = await this.bpmnModeler.saveXML();
//
if (err) {
console.error(`[Process Designer Warn ]: ${err.message || err}`);
}
let { href, filename } = _this.setEncoded(type.toUpperCase(), name, xml);
downloadFunc(href, filename);
} else {
const { err, svg } = await this.bpmnModeler.saveSVG();
//
if (err) {
return console.error(err);
}
let { href, filename } = _this.setEncoded("SVG", name, svg);
downloadFunc(href, filename);
}
} catch (e) {
console.error(`[Process Designer Warn ]: ${e.message || e}`);
}
//
function downloadFunc(href, filename) {
if (href && filename) {
let a = document.createElement("a");
a.download = filename; //
a.href = href; // URL
a.click(); //
URL.revokeObjectURL(a.href); // URL
}
}
},
//
setEncoded(type, filename = "diagram", data) {
const encodedData = encodeURIComponent(data);
return {
filename: `${filename}.${type}`,
href: `data:application/${type === "svg" ? "text/xml" : "bpmn20-xml"};charset=UTF-8,${encodedData}`,
data: data
};
},
//
importLocalFile() {
const that = this;
const file = this.$refs.refFile.files[0];
const reader = new FileReader();
reader.readAsText(file);
reader.onload = function() {
let xmlStr = this.result;
that.createNewDiagram(xmlStr);
};
},
/* ------------------------------------------------ refs methods ------------------------------------------------------ */
downloadProcessAsXml() {
this.downloadProcess("xml");
},
downloadProcessAsBpmn() {
this.downloadProcess("bpmn");
},
downloadProcessAsSvg() {
this.downloadProcess("svg");
},
processSimulation() {
this.simulationStatus = !this.simulationStatus;
this.simulation && this.bpmnModeler.get("toggleMode").toggleMode();
},
processRedo() {
this.bpmnModeler.get("commandStack").redo();
},
processUndo() {
this.bpmnModeler.get("commandStack").undo();
},
processZoomIn(zoomStep = 0.1) {
let newZoom = Math.floor(this.defaultZoom * 100 + zoomStep * 100) / 100;
if (newZoom > 4) {
throw new Error("[Process Designer Warn ]: The zoom ratio cannot be greater than 4");
}
this.defaultZoom = newZoom;
this.bpmnModeler.get("canvas").zoom(this.defaultZoom);
},
processZoomOut(zoomStep = 0.1) {
let newZoom = Math.floor(this.defaultZoom * 100 - zoomStep * 100) / 100;
if (newZoom < 0.2) {
throw new Error("[Process Designer Warn ]: The zoom ratio cannot be less than 0.2");
}
this.defaultZoom = newZoom;
this.bpmnModeler.get("canvas").zoom(this.defaultZoom);
},
processZoomTo(newZoom = 1) {
if (newZoom < 0.2) {
throw new Error("[Process Designer Warn ]: The zoom ratio cannot be less than 0.2");
}
if (newZoom > 4) {
throw new Error("[Process Designer Warn ]: The zoom ratio cannot be greater than 4");
}
this.defaultZoom = newZoom;
this.bpmnModeler.get("canvas").zoom(newZoom);
},
processReZoom() {
this.defaultZoom = 1;
this.bpmnModeler.get("canvas").zoom("fit-viewport", "auto");
},
processRestart() {
this.recoverable = false;
this.revocable = false;
this.createNewDiagram(null);
},
elementsAlign(align) {
const Align = this.bpmnModeler.get("alignElements");
const Selection = this.bpmnModeler.get("selection");
const SelectedElements = Selection.get();
if (!SelectedElements || SelectedElements.length <= 1) {
this.$message.warning("请按住 Ctrl 键选择多个元素对齐");
return;
}
this.$confirm("自动对齐可能造成图形变形,是否继续?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => Align.trigger(SelectedElements, align));
},
/*----------------------------- 方法结束 ---------------------------------*/
previewProcessXML() {
this.bpmnModeler.saveXML({ format: true }).then(({ xml }) => {
this.previewResult = xml;
this.previewType = "xml";
this.previewModelVisible = true;
});
},
previewProcessJson() {
this.bpmnModeler.saveXML({ format: true }).then(({ xml }) => {
this.previewResult = convert.xml2json(xml, { spaces: 2 });
this.previewType = "json";
this.previewModelVisible = true;
});
},
/* ------------------------------------------------ 芋道源码 methods ------------------------------------------------------ */
async processSave() {
const { err, xml } = await this.bpmnModeler.saveXML();
//
if (err) {
this.$modal.msgError('保存模型失败,请重试!')
return
}
// save
this.$emit('save', xml)
},
/** 高亮显示 */
highlightedCode(previewType, previewResult) {
const result = hljs.highlight(previewType, previewResult || "", true);
return result.value || '&nbsp;';
},
}
};
</script>

View File

@ -1,487 +0,0 @@
<template>
<div class="my-process-designer">
<div class="my-process-designer__container">
<div class="my-process-designer__canvas" ref="bpmn-canvas"></div>
</div>
</div>
</template>
<script>
import BpmnViewer from "bpmn-js/lib/Viewer";
import DefaultEmptyXML from "./plugins/defaultEmpty";
export default {
name: "MyProcessViewer",
componentName: "MyProcessViewer",
props: {
value: { // BPMN XML
type: String,
},
prefix: { // 使
type: String,
default: "camunda",
},
activityData: { //
type: Array,
default: () => [],
},
processInstanceData: { //
type: Object,
},
taskData: { // UserTask
type: Array,
default: () => [],
}
},
data() {
return {
xml: '',
activityList: [],
processInstance: undefined,
taskList: [],
};
},
mounted() {
this.xml = this.value;
this.activityList = this.activityData;
//
this.initBpmnModeler();
this.createNewDiagram(this.xml);
this.$once("hook:beforeDestroy", () => {
if (this.bpmnModeler) this.bpmnModeler.destroy();
this.$emit("destroy", this.bpmnModeler);
this.bpmnModeler = null;
});
//
this.initModelListeners();
},
watch: {
value: function (newValue) { // xmlString
this.xml = newValue;
this.createNewDiagram(this.xml);
},
activityData: function (newActivityData) {
this.activityList = newActivityData;
this.createNewDiagram(this.xml);
},
processInstanceData: function (newProcessInstanceData) {
this.processInstance = newProcessInstanceData;
this.createNewDiagram(this.xml);
},
taskData: function (newTaskListData) {
this.taskList = newTaskListData;
this.createNewDiagram(this.xml);
}
},
methods: {
initBpmnModeler() {
if (this.bpmnModeler) return;
this.bpmnModeler = new BpmnViewer({
container: this.$refs["bpmn-canvas"],
bpmnRenderer: {
}
})
},
/* 创建新的流程图 */
async createNewDiagram(xml) {
//
let newId = `Process_${new Date().getTime()}`;
let newName = `业务流程_${new Date().getTime()}`;
let xmlString = xml || DefaultEmptyXML(newId, newName, this.prefix);
try {
// console.log(this.bpmnModeler.importXML);
let { warnings } = await this.bpmnModeler.importXML(xmlString);
if (warnings && warnings.length) {
warnings.forEach(warn => console.warn(warn));
}
//
await this.highlightDiagram();
const canvas = this.bpmnModeler.get('canvas');
canvas.zoom("fit-viewport", "auto");
} catch (e) {
console.error(e);
// console.error(`[Process Designer Warn]: ${e?.message || e}`);
}
},
/* 高亮流程图 */
// TODO endActivity https://www.jdon.com/workflow/multi-events.html
async highlightDiagram() {
const activityList = this.activityList;
if (activityList.length === 0) {
return;
}
// https://gitee.com/tony2y/RuoYi-flowable/blob/master/ruoyi-ui/src/components/Process/index.vue#L222
//
let canvas = this.bpmnModeler.get('canvas');
let todoActivity = activityList.find(m => !m.endTime) //
let endActivity = activityList[activityList.length - 1] //
// debugger
// console.log(this.bpmnModeler.getDefinitions().rootElements[0].flowElements);
this.bpmnModeler.getDefinitions().rootElements[0].flowElements?.forEach(n => {
let activity = activityList.find(m => m.key === n.id) //
if (!activity) {
return;
}
if (n.$type === 'bpmn:UserTask') { //
//
const task = this.taskList.find(m => m.id === activity.taskId); // taskId
if (!task) {
return;
}
//
canvas.addMarker(n.id, this.getResultCss(task.result));
// 线
if (task.result !== 2) {
return;
}
// outgoing 线
const outgoing = this.getActivityOutgoing(activity);
outgoing?.forEach(nn => {
// debugger
let targetActivity = activityList.find(m => m.key === nn.targetRef.id)
// bpmn:SequenceFlow线
if (targetActivity) {
canvas.addMarker(nn.id, targetActivity.endTime ? 'highlight' : 'highlight-todo');
} else if (nn.targetRef.$type === 'bpmn:ExclusiveGateway') { // TODO
canvas.addMarker(nn.id, activity.endTime ? 'highlight' : 'highlight-todo');
canvas.addMarker(nn.targetRef.id, activity.endTime ? 'highlight' : 'highlight-todo');
} else if (nn.targetRef.$type === 'bpmn:EndEvent') { // TODO
if (!todoActivity && endActivity.key === n.id) {
canvas.addMarker(nn.id, 'highlight');
canvas.addMarker(nn.targetRef.id, 'highlight');
}
if (!activity.endTime) {
canvas.addMarker(nn.id, 'highlight-todo');
canvas.addMarker(nn.targetRef.id, 'highlight-todo');
}
}
});
} else if (n.$type === 'bpmn:ExclusiveGateway') { //
// bpmn:ExclusiveGateway
canvas.addMarker(n.id, this.getActivityHighlightCss(activity));
// 线
let matchNN = undefined;
let matchActivity = undefined;
n.outgoing?.forEach(nn => {
let targetActivity = activityList.find(m => m.key === nn.targetRef.id);
if (!targetActivity) {
return;
}
// endEvent ExclusiveGateway 2
// 1. UserTask => EndEvent
// 2. EndEvent
// 1 EndEvent 1 2
// matchActivity EndEvent ~~
if (!matchActivity || matchActivity.type === 'endEvent') {
matchNN = nn;
matchActivity = targetActivity;
}
})
if (matchNN && matchActivity) {
canvas.addMarker(matchNN.id, this.getActivityHighlightCss(matchActivity));
}
} else if (n.$type === 'bpmn:ParallelGateway') { //
// bpmn:ParallelGateway
canvas.addMarker(n.id, this.getActivityHighlightCss(activity));
n.outgoing?.forEach(nn => {
// 线
const targetActivity = activityList.find(m => m.key === nn.targetRef.id)
if (targetActivity) {
canvas.addMarker(nn.id, this.getActivityHighlightCss(targetActivity)); // bpmn:SequenceFlow线
// ... ... bpm:UserTask bpm:UserTask
canvas.addMarker(nn.targetRef.id, this.getActivityHighlightCss(targetActivity));
}
})
} else if (n.$type === 'bpmn:StartEvent') { //
n.outgoing?.forEach(nn => { // outgoing bpmn:SequenceFlow线
// 线
let targetActivity = activityList.find(m => m.key === nn.targetRef.id);
if (targetActivity) {
canvas.addMarker(nn.id, 'highlight'); // bpmn:SequenceFlow线
canvas.addMarker(n.id, 'highlight'); // bpmn:StartEvent
}
});
} else if (n.$type === 'bpmn:EndEvent') { //
if (!this.processInstance || this.processInstance.result === 1) {
return;
}
canvas.addMarker(n.id, this.getResultCss(this.processInstance.result));
} else if (n.$type === 'bpmn:ServiceTask'){ //
if(activity.startTime>0 && activity.endTime===0){//
canvas.addMarker(n.id, this.getResultCss(1));
}
if(activity.endTime>0){// , outgoing
canvas.addMarker(n.id, this.getResultCss(2));
const outgoing = this.getActivityOutgoing(activity)
outgoing?.forEach(out=>{
canvas.addMarker(out.id,this.getResultCss(2))
})
}
}
})
},
getActivityHighlightCss(activity) {
return activity.endTime ? 'highlight' : 'highlight-todo';
},
getResultCss(result) {
if (result === 1) { //
return 'highlight-todo';
} else if (result === 2) { //
return 'highlight';
} else if (result === 3) { //
return 'highlight-reject';
} else if (result === 4) { //
return 'highlight-cancel';
}
return '';
},
getActivityOutgoing(activity) {
// outgoing使
if (activity.outgoing && activity.outgoing.length > 0) {
return activity.outgoing;
}
// bpmn:SequenceFlowbpmn-js UserTask outgoing
const flowElements = this.bpmnModeler.getDefinitions().rootElements[0].flowElements;
const outgoing = [];
flowElements.forEach(item => {
if (item.$type !== 'bpmn:SequenceFlow') {
return;
}
if (item.sourceRef.id === activity.key) {
outgoing.push(item);
}
});
return outgoing;
},
initModelListeners() {
const EventBus = this.bpmnModeler.get("eventBus");
const that = this;
//
EventBus.on('element.hover', function(eventObj) {
let element = eventObj ? eventObj.element : null;
that.elementHover(element);
});
EventBus.on('element.out', function(eventObj) {
let element = eventObj ? eventObj.element : null;
that.elementOut(element);
});
},
// hover
elementHover(element) {
this.element = element;
!this.elementOverlayIds && (this.elementOverlayIds = {});
!this.overlays && (this.overlays = this.bpmnModeler.get("overlays"));
//
const activity = this.activityList.find(m => m.key === element.id);
if (!activity) {
return;
}
if (!this.elementOverlayIds[element.id] && element.type !== "bpmn:Process") {
let html = `<div class="element-overlays">
<p>Elemet id: ${element.id}</p>
<p>Elemet type: ${element.type}</p>
</div>`; // 默认值
if (element.type === 'bpmn:StartEvent' && this.processInstance) {
html = `<p>发起人:${this.processInstance.startUser.nickname}</p>
<p>部门${this.processInstance.startUser.deptName}</p>
<p>创建时间${this.parseTime(this.processInstance.createTime)}`;
} else if (element.type === 'bpmn:UserTask') {
// debugger
let task = this.taskList.find(m => m.id === activity.taskId); // taskId
if (!task) {
return;
}
html = `<p>审批人:${task.assigneeUser.nickname}</p>
<p>部门${task.assigneeUser.deptName}</p>
<p>结果${this.getDictDataLabel(this.DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT, task.result)}</p>
<p>创建时间${this.parseTime(task.createTime)}</p>`;
if (task.endTime) {
html += `<p>结束时间:${this.parseTime(task.endTime)}</p>`
}
if (task.reason) {
html += `<p>审批建议:${task.reason}</p>`
}
} else if (element.type === 'bpmn:ServiceTask' && this.processInstance) {
if(activity.startTime>0){
html = `<p>创建时间:${this.parseTime(activity.startTime)}</p>`;
}
if(activity.endTime>0){
html += `<p>结束时间:${this.parseTime(activity.endTime)}</p>`
}
console.log(html)
} else if (element.type === 'bpmn:EndEvent' && this.processInstance) {
html = `<p>结果:${this.getDictDataLabel(this.DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT, this.processInstance.result)}</p>`;
if (this.processInstance.endTime) {
html += `<p>结束时间:${this.parseTime(this.processInstance.endTime)}</p>`
}
}
this.elementOverlayIds[element.id] = this.overlays.add(element, {
position: { left: 0, bottom: 0 },
html: `<div class="element-overlays">${html}</div>`
});
}
},
// out
elementOut(element) {
this.overlays.remove({ element });
this.elementOverlayIds[element.id] = null;
},
}
};
</script>
<style>
/** 处理中 */
.highlight-todo.djs-connection > .djs-visual > path {
stroke: #1890ff !important;
stroke-dasharray: 4px !important;
fill-opacity: 0.2 !important;
}
.highlight-todo.djs-shape .djs-visual > :nth-child(1) {
fill: #1890ff !important;
stroke: #1890ff !important;
stroke-dasharray: 4px !important;
fill-opacity: 0.2 !important;
}
:deep(.highlight-todo.djs-connection > .djs-visual > path) {
stroke: #1890ff !important;
stroke-dasharray: 4px !important;
fill-opacity: 0.2 !important;
marker-end: url(#sequenceflow-end-_E7DFDF-_E7DFDF-803g1kf6zwzmcig1y2ulm5egr);
}
:deep(.highlight-todo.djs-shape .djs-visual > :nth-child(1)) {
fill: #1890ff !important;
stroke: #1890ff !important;
stroke-dasharray: 4px !important;
fill-opacity: 0.2 !important;
}
/** 通过 */
.highlight.djs-shape .djs-visual > :nth-child(1) {
fill: green !important;
stroke: green !important;
fill-opacity: 0.2 !important;
}
.highlight.djs-shape .djs-visual > :nth-child(2) {
fill: green !important;
}
.highlight.djs-shape .djs-visual > path {
fill: green !important;
fill-opacity: 0.2 !important;
stroke: green !important;
}
.highlight.djs-connection > .djs-visual > path {
stroke: green !important;
}
.highlight:not(.djs-connection) .djs-visual > :nth-child(1) {
fill: green !important; /* color elements as green */
}
:deep(.highlight.djs-shape .djs-visual > :nth-child(1)) {
fill: green !important;
stroke: green !important;
fill-opacity: 0.2 !important;
}
:deep(.highlight.djs-shape .djs-visual > :nth-child(2)) {
fill: green !important;
}
:deep(.highlight.djs-shape .djs-visual > path) {
fill: green !important;
fill-opacity: 0.2 !important;
stroke: green !important;
}
:deep(.highlight.djs-connection > .djs-visual > path) {
stroke: green !important;
}
/** 不通过 */
.highlight-reject.djs-shape .djs-visual > :nth-child(1) {
fill: red !important;
stroke: red !important;
fill-opacity: 0.2 !important;
}
.highlight-reject.djs-shape .djs-visual > :nth-child(2) {
fill: red !important;
}
.highlight-reject.djs-shape .djs-visual > path {
fill: red !important;
fill-opacity: 0.2 !important;
stroke: red !important;
}
.highlight-reject.djs-connection > .djs-visual > path {
stroke: red !important;
}
.highlight-reject:not(.djs-connection) .djs-visual > :nth-child(1) {
fill: red !important; /* color elements as green */
}
:deep(.highlight-reject.djs-shape .djs-visual > :nth-child(1)) {
fill: red !important;
stroke: red !important;
fill-opacity: 0.2 !important;
}
:deep(.highlight-reject.djs-shape .djs-visual > :nth-child(2)) {
fill: red !important;
}
:deep(.highlight-reject.djs-shape .djs-visual > path) {
fill: red !important;
fill-opacity: 0.2 !important;
stroke: red !important;
}
:deep(.highlight-reject.djs-connection > .djs-visual > path) {
stroke: red !important;
}
/** 已取消 */
.highlight-cancel.djs-shape .djs-visual > :nth-child(1) {
fill: grey !important;
stroke: grey !important;
fill-opacity: 0.2 !important;
}
.highlight-cancel.djs-shape .djs-visual > :nth-child(2) {
fill: grey !important;
}
.highlight-cancel.djs-shape .djs-visual > path {
fill: grey !important;
fill-opacity: 0.2 !important;
stroke: grey !important;
}
.highlight-cancel.djs-connection > .djs-visual > path {
stroke: grey !important;
}
.highlight-cancel:not(.djs-connection) .djs-visual > :nth-child(1) {
fill: grey !important; /* color elements as green */
}
:deep(.highlight-cancel.djs-shape .djs-visual > :nth-child(1)) {
fill: grey !important;
stroke: grey !important;
fill-opacity: 0.2 !important;
}
:deep(.highlight-cancel.djs-shape .djs-visual > :nth-child(2)) {
fill: grey !important;
}
:deep(.highlight-cancel.djs-shape .djs-visual > path) {
fill: grey !important;
fill-opacity: 0.2 !important;
stroke: grey !important;
}
:deep(.highlight-cancel.djs-connection > .djs-visual > path) {
stroke: grey !important;
}
.element-overlays {
box-sizing: border-box;
padding: 8px;
background: rgba(0, 0, 0, 0.6);
border-radius: 4px;
color: #fafafa;
width: 200px;
}
</style>

View File

@ -1,8 +0,0 @@
import MyProcessDesigner from "./ProcessDesigner.vue";
MyProcessDesigner.install = function(Vue) {
Vue.component(MyProcessDesigner.name, MyProcessDesigner);
};
// 流程图的设计器,可编辑
export default MyProcessDesigner;

View File

@ -1,8 +0,0 @@
import MyProcessViewer from "./ProcessViewer.vue";
MyProcessViewer.install = function(Vue) {
Vue.component(MyProcessViewer.name, MyProcessViewer);
};
// 流程图的查看器,不可编辑
export default MyProcessViewer;

View File

@ -1,390 +0,0 @@
import { assign, forEach, isArray } from "min-dash";
import { is } from "bpmn-js/lib/util/ModelUtil";
import { isExpanded, isEventSubProcess } from "bpmn-js/lib/util/DiUtil";
import { isAny } from "bpmn-js/lib/features/modeling/util/ModelingUtil";
import { getChildLanes } from "bpmn-js/lib/features/modeling/util/LaneUtil";
import { hasPrimaryModifier } from "diagram-js/lib/util/Mouse";
/**
* A provider for BPMN 2.0 elements context pad
*/
export default function ContextPadProvider(
config,
injector,
eventBus,
contextPad,
modeling,
elementFactory,
connect,
create,
popupMenu,
canvas,
rules,
translate,
elementRegistry
) {
config = config || {};
contextPad.registerProvider(this);
this._contextPad = contextPad;
this._modeling = modeling;
this._elementFactory = elementFactory;
this._connect = connect;
this._create = create;
this._popupMenu = popupMenu;
this._canvas = canvas;
this._rules = rules;
this._translate = translate;
if (config.autoPlace !== false) {
this._autoPlace = injector.get("autoPlace", false);
}
eventBus.on("create.end", 250, function(event) {
const context = event.context,
shape = context.shape
if (!hasPrimaryModifier(event) || !contextPad.isOpen(shape)) {
return;
}
const entries = contextPad.getEntries(shape)
if (entries.replace) {
entries.replace.action.click(event, shape);
}
});
}
ContextPadProvider.$inject = [
"config.contextPad",
"injector",
"eventBus",
"contextPad",
"modeling",
"elementFactory",
"connect",
"create",
"popupMenu",
"canvas",
"rules",
"translate",
"elementRegistry"
];
ContextPadProvider.prototype.getContextPadEntries = function(element) {
const contextPad = this._contextPad,
modeling = this._modeling,
elementFactory = this._elementFactory,
connect = this._connect,
create = this._create,
popupMenu = this._popupMenu,
canvas = this._canvas,
rules = this._rules,
autoPlace = this._autoPlace,
translate = this._translate
const actions = {}
if (element.type === "label") {
return actions;
}
const businessObject = element.businessObject
function startConnect(event, element) {
connect.start(event, element);
}
function removeElement() {
modeling.removeElements([element]);
}
function getReplaceMenuPosition(element) {
const Y_OFFSET = 5
const diagramContainer = canvas.getContainer(),
pad = contextPad.getPad(element).html
const diagramRect = diagramContainer.getBoundingClientRect(),
padRect = pad.getBoundingClientRect()
const top = padRect.top - diagramRect.top
const left = padRect.left - diagramRect.left
const pos = {
x: left,
y: top + padRect.height + Y_OFFSET
}
return pos;
}
/**
* Create an append action
*
* @param {string} type
* @param {string} className
* @param {string} [title]
* @param {Object} [options]
*
* @return {Object} descriptor
*/
function appendAction(type, className, title, options) {
if (typeof title !== "string") {
options = title;
title = translate("Append {type}", { type: type.replace(/^bpmn:/, "") });
}
function appendStart(event, element) {
const shape = elementFactory.createShape(assign({ type: type }, options))
create.start(event, shape, {
source: element
});
}
const append = autoPlace
? function(event, element) {
const shape = elementFactory.createShape(assign({ type: type }, options))
autoPlace.append(element, shape)
}
: appendStart
return {
group: "model",
className: className,
title: title,
action: {
dragstart: appendStart,
click: append
}
};
}
function splitLaneHandler(count) {
return function(event, element) {
// actual split
modeling.splitLane(element, count);
// refresh context pad after split to
// get rid of split icons
contextPad.open(element, true);
};
}
if (isAny(businessObject, ["bpmn:Lane", "bpmn:Participant"]) && isExpanded(businessObject)) {
const childLanes = getChildLanes(element)
assign(actions, {
"lane-insert-above": {
group: "lane-insert-above",
className: "bpmn-icon-lane-insert-above",
title: translate("Add Lane above"),
action: {
click: function(event, element) {
modeling.addLane(element, "top");
}
}
}
});
if (childLanes.length < 2) {
if (element.height >= 120) {
assign(actions, {
"lane-divide-two": {
group: "lane-divide",
className: "bpmn-icon-lane-divide-two",
title: translate("Divide into two Lanes"),
action: {
click: splitLaneHandler(2)
}
}
});
}
if (element.height >= 180) {
assign(actions, {
"lane-divide-three": {
group: "lane-divide",
className: "bpmn-icon-lane-divide-three",
title: translate("Divide into three Lanes"),
action: {
click: splitLaneHandler(3)
}
}
});
}
}
assign(actions, {
"lane-insert-below": {
group: "lane-insert-below",
className: "bpmn-icon-lane-insert-below",
title: translate("Add Lane below"),
action: {
click: function(event, element) {
modeling.addLane(element, "bottom");
}
}
}
});
}
if (is(businessObject, "bpmn:FlowNode")) {
if (is(businessObject, "bpmn:EventBasedGateway")) {
assign(actions, {
"append.receive-task": appendAction("bpmn:ReceiveTask", "bpmn-icon-receive-task", translate("Append ReceiveTask")),
"append.message-intermediate-event": appendAction(
"bpmn:IntermediateCatchEvent",
"bpmn-icon-intermediate-event-catch-message",
translate("Append MessageIntermediateCatchEvent"),
{ eventDefinitionType: "bpmn:MessageEventDefinition" }
),
"append.timer-intermediate-event": appendAction(
"bpmn:IntermediateCatchEvent",
"bpmn-icon-intermediate-event-catch-timer",
translate("Append TimerIntermediateCatchEvent"),
{ eventDefinitionType: "bpmn:TimerEventDefinition" }
),
"append.condition-intermediate-event": appendAction(
"bpmn:IntermediateCatchEvent",
"bpmn-icon-intermediate-event-catch-condition",
translate("Append ConditionIntermediateCatchEvent"),
{ eventDefinitionType: "bpmn:ConditionalEventDefinition" }
),
"append.signal-intermediate-event": appendAction(
"bpmn:IntermediateCatchEvent",
"bpmn-icon-intermediate-event-catch-signal",
translate("Append SignalIntermediateCatchEvent"),
{ eventDefinitionType: "bpmn:SignalEventDefinition" }
)
});
} else if (isEventType(businessObject, "bpmn:BoundaryEvent", "bpmn:CompensateEventDefinition")) {
assign(actions, {
"append.compensation-activity": appendAction("bpmn:Task", "bpmn-icon-task", translate("Append compensation activity"), {
isForCompensation: true
})
});
} else if (
!is(businessObject, "bpmn:EndEvent") &&
!businessObject.isForCompensation &&
!isEventType(businessObject, "bpmn:IntermediateThrowEvent", "bpmn:LinkEventDefinition") &&
!isEventSubProcess(businessObject)
) {
assign(actions, {
"append.end-event": appendAction("bpmn:EndEvent", "bpmn-icon-end-event-none", translate("Append EndEvent")),
"append.gateway": appendAction("bpmn:ExclusiveGateway", "bpmn-icon-gateway-none", translate("Append Gateway")),
"append.append-task": appendAction("bpmn:UserTask", "bpmn-icon-user-task", translate("Append Task")),
"append.intermediate-event": appendAction(
"bpmn:IntermediateThrowEvent",
"bpmn-icon-intermediate-event-none",
translate("Append Intermediate/Boundary Event")
)
});
}
}
if (!popupMenu.isEmpty(element, "bpmn-replace")) {
// Replace menu entry
assign(actions, {
replace: {
group: "edit",
className: "bpmn-icon-screw-wrench",
title: translate("Change type"),
action: {
click: function(event, element) {
const position = assign(getReplaceMenuPosition(element), {
cursor: { x: event.x, y: event.y }
})
popupMenu.open(element, "bpmn-replace", position);
}
}
}
});
}
if (isAny(businessObject, ["bpmn:FlowNode", "bpmn:InteractionNode", "bpmn:DataObjectReference", "bpmn:DataStoreReference"])) {
assign(actions, {
"append.text-annotation": appendAction("bpmn:TextAnnotation", "bpmn-icon-text-annotation"),
connect: {
group: "connect",
className: "bpmn-icon-connection-multi",
title: translate("Connect using " + (businessObject.isForCompensation ? "" : "Sequence/MessageFlow or ") + "Association"),
action: {
click: startConnect,
dragstart: startConnect
}
}
});
}
if (isAny(businessObject, ["bpmn:DataObjectReference", "bpmn:DataStoreReference"])) {
assign(actions, {
connect: {
group: "connect",
className: "bpmn-icon-connection-multi",
title: translate("Connect using DataInputAssociation"),
action: {
click: startConnect,
dragstart: startConnect
}
}
});
}
if (is(businessObject, "bpmn:Group")) {
assign(actions, {
"append.text-annotation": appendAction("bpmn:TextAnnotation", "bpmn-icon-text-annotation")
});
}
// delete element entry, only show if allowed by rules
let deleteAllowed = rules.allowed('elements.delete', { elements: [element] })
if (isArray(deleteAllowed)) {
// was the element returned as a deletion candidate?
deleteAllowed = deleteAllowed[0] === element;
}
if (deleteAllowed) {
assign(actions, {
delete: {
group: "edit",
className: "bpmn-icon-trash",
title: translate("Remove"),
action: {
click: removeElement
}
}
});
}
return actions;
};
// helpers /////////
function isEventType(eventBo, type, definition) {
const isType = eventBo.$instanceOf(type)
let isDefinition = false
const definitions = eventBo.eventDefinitions || []
forEach(definitions, function(def) {
if (def.$type === definition) {
isDefinition = true;
}
});
return isType && isDefinition;
}

View File

@ -1,6 +0,0 @@
import CustomContextPadProvider from "./contentPadProvider";
export default {
__init__: ["contextPadProvider"],
contextPadProvider: ["type", CustomContextPadProvider]
};

View File

@ -1,24 +0,0 @@
export default (key, name, type) => {
if (!type) type = "camunda";
const TYPE_TARGET = {
activiti: "http://activiti.org/bpmn",
camunda: "http://bpmn.io/schema/bpmn",
flowable: "http://flowable.org/bpmn"
};
return `<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
id="diagram_${key}"
targetNamespace="${TYPE_TARGET[type]}">
<bpmn2:process id="${key}" name="${name}" isExecutable="true">
</bpmn2:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="${key}">
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>`;
};

View File

@ -1,74 +0,0 @@
"use strict";
const some = require('min-dash').some
const ALLOWED_TYPES = {
FailedJobRetryTimeCycle: ['bpmn:StartEvent', 'bpmn:BoundaryEvent', 'bpmn:IntermediateCatchEvent', 'bpmn:Activity'],
Connector: ['bpmn:EndEvent', 'bpmn:IntermediateThrowEvent'],
Field: ['bpmn:EndEvent', 'bpmn:IntermediateThrowEvent']
}
function is(element, type) {
return element && typeof element.$instanceOf === "function" && element.$instanceOf(type);
}
function exists(element) {
return element && element.length;
}
function includesType(collection, type) {
return (
exists(collection) &&
some(collection, function(element) {
return is(element, type);
})
);
}
function anyType(element, types) {
return some(types, function(type) {
return is(element, type);
});
}
function isAllowed(propName, propDescriptor, newElement) {
const name = propDescriptor.name,
types = ALLOWED_TYPES[name.replace(/activiti:/, '')]
return name === propName && anyType(newElement, types);
}
function ActivitiModdleExtension(eventBus) {
eventBus.on(
"property.clone",
function(context) {
const newElement = context.newElement,
propDescriptor = context.propertyDescriptor
this.canCloneProperty(newElement, propDescriptor);
},
this
);
}
ActivitiModdleExtension.$inject = ["eventBus"];
ActivitiModdleExtension.prototype.canCloneProperty = function(newElement, propDescriptor) {
if (isAllowed("activiti:FailedJobRetryTimeCycle", propDescriptor, newElement)) {
return (
includesType(newElement.eventDefinitions, "bpmn:TimerEventDefinition") ||
includesType(newElement.eventDefinitions, "bpmn:SignalEventDefinition") ||
is(newElement.loopCharacteristics, "bpmn:MultiInstanceLoopCharacteristics")
);
}
if (isAllowed("activiti:Connector", propDescriptor, newElement)) {
return includesType(newElement.eventDefinitions, "bpmn:MessageEventDefinition");
}
if (isAllowed("activiti:Field", propDescriptor, newElement)) {
return includesType(newElement.eventDefinitions, "bpmn:MessageEventDefinition");
}
};
module.exports = ActivitiModdleExtension;

View File

@ -1,9 +0,0 @@
/*
* @author igdianov
* address https://github.com/igdianov/activiti-bpmn-moddle
* */
module.exports = {
__init__: ["ActivitiModdleExtension"],
ActivitiModdleExtension: ["type", require("./activitiExtension")]
};

View File

@ -1,146 +0,0 @@
"use strict";
const isFunction = require('min-dash').isFunction,
isObject = require('min-dash').isObject,
some = require('min-dash').some
const WILDCARD = '*'
function CamundaModdleExtension(eventBus) {
const self = this
eventBus.on("moddleCopy.canCopyProperty", function(context) {
const property = context.property,
parent = context.parent
return self.canCopyProperty(property, parent);
});
}
CamundaModdleExtension.$inject = ["eventBus"];
/**
* Check wether to disallow copying property.
*/
CamundaModdleExtension.prototype.canCopyProperty = function(property, parent) {
// (1) check wether property is allowed in parent
if (isObject(property) && !isAllowedInParent(property, parent)) {
return false;
}
// (2) check more complex scenarios
if (is(property, "camunda:InputOutput") && !this.canHostInputOutput(parent)) {
return false;
}
if (isAny(property, ["camunda:Connector", "camunda:Field"]) && !this.canHostConnector(parent)) {
return false;
}
if (is(property, "camunda:In") && !this.canHostIn(parent)) {
return false;
}
};
CamundaModdleExtension.prototype.canHostInputOutput = function(parent) {
// allowed in camunda:Connector
const connector = getParent(parent, 'camunda:Connector')
if (connector) {
return true;
}
// special rules inside bpmn:FlowNode
const flowNode = getParent(parent, 'bpmn:FlowNode')
if (!flowNode) {
return false;
}
if (isAny(flowNode, ["bpmn:StartEvent", "bpmn:Gateway", "bpmn:BoundaryEvent"])) {
return false;
}
return !(is(flowNode, "bpmn:SubProcess") && flowNode.get("triggeredByEvent"));
};
CamundaModdleExtension.prototype.canHostConnector = function(parent) {
const serviceTaskLike = getParent(parent, 'camunda:ServiceTaskLike')
if (is(serviceTaskLike, "bpmn:MessageEventDefinition")) {
// only allow on throw and end events
return getParent(parent, "bpmn:IntermediateThrowEvent") || getParent(parent, "bpmn:EndEvent");
}
return true;
};
CamundaModdleExtension.prototype.canHostIn = function(parent) {
const callActivity = getParent(parent, 'bpmn:CallActivity')
if (callActivity) {
return true;
}
const signalEventDefinition = getParent(parent, 'bpmn:SignalEventDefinition')
if (signalEventDefinition) {
// only allow on throw and end events
return getParent(parent, "bpmn:IntermediateThrowEvent") || getParent(parent, "bpmn:EndEvent");
}
return true;
};
module.exports = CamundaModdleExtension;
// helpers //////////
function is(element, type) {
return element && isFunction(element.$instanceOf) && element.$instanceOf(type);
}
function isAny(element, types) {
return some(types, function(t) {
return is(element, t);
});
}
function getParent(element, type) {
if (!type) {
return element.$parent;
}
if (is(element, type)) {
return element;
}
if (!element.$parent) {
return;
}
return getParent(element.$parent, type);
}
function isAllowedInParent(property, parent) {
// (1) find property descriptor
const descriptor = property.$type && property.$model.getTypeDescriptor(property.$type)
const allowedIn = descriptor && descriptor.meta && descriptor.meta.allowedIn
if (!allowedIn || isWildcard(allowedIn)) {
return true;
}
// (2) check wether property has parent of allowed type
return some(allowedIn, function(type) {
return getParent(parent, type);
});
}
function isWildcard(allowedIn) {
return allowedIn.indexOf(WILDCARD) !== -1;
}

View File

@ -1,6 +0,0 @@
"use strict";
module.exports = {
__init__: ["camundaModdleExtension"],
camundaModdleExtension: ["type", require("./extension")]
};

View File

@ -1,74 +0,0 @@
"use strict";
const some = require('min-dash').some
const ALLOWED_TYPES = {
FailedJobRetryTimeCycle: ['bpmn:StartEvent', 'bpmn:BoundaryEvent', 'bpmn:IntermediateCatchEvent', 'bpmn:Activity'],
Connector: ['bpmn:EndEvent', 'bpmn:IntermediateThrowEvent'],
Field: ['bpmn:EndEvent', 'bpmn:IntermediateThrowEvent']
}
function is(element, type) {
return element && typeof element.$instanceOf === "function" && element.$instanceOf(type);
}
function exists(element) {
return element && element.length;
}
function includesType(collection, type) {
return (
exists(collection) &&
some(collection, function(element) {
return is(element, type);
})
);
}
function anyType(element, types) {
return some(types, function(type) {
return is(element, type);
});
}
function isAllowed(propName, propDescriptor, newElement) {
const name = propDescriptor.name,
types = ALLOWED_TYPES[name.replace(/flowable:/, '')]
return name === propName && anyType(newElement, types);
}
function FlowableModdleExtension(eventBus) {
eventBus.on(
"property.clone",
function(context) {
const newElement = context.newElement,
propDescriptor = context.propertyDescriptor
this.canCloneProperty(newElement, propDescriptor);
},
this
);
}
FlowableModdleExtension.$inject = ["eventBus"];
FlowableModdleExtension.prototype.canCloneProperty = function(newElement, propDescriptor) {
if (isAllowed("flowable:FailedJobRetryTimeCycle", propDescriptor, newElement)) {
return (
includesType(newElement.eventDefinitions, "bpmn:TimerEventDefinition") ||
includesType(newElement.eventDefinitions, "bpmn:SignalEventDefinition") ||
is(newElement.loopCharacteristics, "bpmn:MultiInstanceLoopCharacteristics")
);
}
if (isAllowed("flowable:Connector", propDescriptor, newElement)) {
return includesType(newElement.eventDefinitions, "bpmn:MessageEventDefinition");
}
if (isAllowed("flowable:Field", propDescriptor, newElement)) {
return includesType(newElement.eventDefinitions, "bpmn:MessageEventDefinition");
}
};
module.exports = FlowableModdleExtension;

View File

@ -1,9 +0,0 @@
/*
* @author igdianov
* address https://github.com/igdianov/activiti-bpmn-moddle
* */
module.exports = {
__init__: ["FlowableModdleExtension"],
FlowableModdleExtension: ["type", require("./flowableExtension")]
};

View File

@ -1,156 +0,0 @@
import PaletteProvider from "bpmn-js/lib/features/palette/PaletteProvider";
import { assign } from "min-dash";
export default function CustomPalette(palette, create, elementFactory, spaceTool, lassoTool, handTool, globalConnect, translate) {
PaletteProvider.call(this, palette, create, elementFactory, spaceTool, lassoTool, handTool, globalConnect, translate, 2000);
}
const F = function() {}; // 核心,利用空对象作为中介;
F.prototype = PaletteProvider.prototype; // 核心将父类的原型赋值给空对象F
// 利用中介函数重写原型链方法
F.prototype.getPaletteEntries = function() {
const actions = {},
create = this._create,
elementFactory = this._elementFactory,
spaceTool = this._spaceTool,
lassoTool = this._lassoTool,
handTool = this._handTool,
globalConnect = this._globalConnect,
translate = this._translate
function createAction(type, group, className, title, options) {
function createListener(event) {
const shape = elementFactory.createShape(assign({ type: type }, options))
if (options) {
shape.businessObject.di.isExpanded = options.isExpanded;
}
create.start(event, shape);
}
const shortType = type.replace(/^bpmn:/, '')
return {
group: group,
className: className,
title: title || translate("Create {type}", { type: shortType }),
action: {
dragstart: createListener,
click: createListener
}
};
}
function createSubprocess(event) {
const subProcess = elementFactory.createShape({
type: 'bpmn:SubProcess',
x: 0,
y: 0,
isExpanded: true
})
const startEvent = elementFactory.createShape({
type: 'bpmn:StartEvent',
x: 40,
y: 82,
parent: subProcess
})
create.start(event, [subProcess, startEvent], {
hints: {
autoSelect: [startEvent]
}
});
}
function createParticipant(event) {
create.start(event, elementFactory.createParticipantShape());
}
assign(actions, {
"hand-tool": {
group: "tools",
className: "bpmn-icon-hand-tool",
title: translate("Activate the hand tool"),
action: {
click: function(event) {
handTool.activateHand(event);
}
}
},
"lasso-tool": {
group: "tools",
className: "bpmn-icon-lasso-tool",
title: translate("Activate the lasso tool"),
action: {
click: function(event) {
lassoTool.activateSelection(event);
}
}
},
"space-tool": {
group: "tools",
className: "bpmn-icon-space-tool",
title: translate("Activate the create/remove space tool"),
action: {
click: function(event) {
spaceTool.activateSelection(event);
}
}
},
"global-connect-tool": {
group: "tools",
className: "bpmn-icon-connection-multi",
title: translate("Activate the global connect tool"),
action: {
click: function(event) {
globalConnect.toggle(event);
}
}
},
"tool-separator": {
group: "tools",
separator: true
},
"create.start-event": createAction("bpmn:StartEvent", "event", "bpmn-icon-start-event-none", translate("Create StartEvent")),
"create.intermediate-event": createAction(
"bpmn:IntermediateThrowEvent",
"event",
"bpmn-icon-intermediate-event-none",
translate("Create Intermediate/Boundary Event")
),
"create.end-event": createAction("bpmn:EndEvent", "event", "bpmn-icon-end-event-none", translate("Create EndEvent")),
"create.exclusive-gateway": createAction("bpmn:ExclusiveGateway", "gateway", "bpmn-icon-gateway-none", translate("Create Gateway")),
"create.user-task": createAction("bpmn:UserTask", "activity", "bpmn-icon-user-task", translate("Create User Task")),
"create.data-object": createAction("bpmn:DataObjectReference", "data-object", "bpmn-icon-data-object", translate("Create DataObjectReference")),
"create.data-store": createAction("bpmn:DataStoreReference", "data-store", "bpmn-icon-data-store", translate("Create DataStoreReference")),
"create.subprocess-expanded": {
group: "activity",
className: "bpmn-icon-subprocess-expanded",
title: translate("Create expanded SubProcess"),
action: {
dragstart: createSubprocess,
click: createSubprocess
}
},
"create.participant-expanded": {
group: "collaboration",
className: "bpmn-icon-participant",
title: translate("Create Pool/Participant"),
action: {
dragstart: createParticipant,
click: createParticipant
}
},
"create.group": createAction("bpmn:Group", "artifact", "bpmn-icon-group", translate("Create Group"))
});
return actions;
};
CustomPalette.$inject = ["palette", "create", "elementFactory", "spaceTool", "lassoTool", "handTool", "globalConnect", "translate"];
CustomPalette.prototype = new F(); // 核心,将 F的实例赋值给子类
CustomPalette.prototype.constructor = CustomPalette; // 修复子类CustomPalette的构造器指向防止原型链的混乱

View File

@ -1,22 +0,0 @@
// import PaletteModule from "diagram-js/lib/features/palette";
// import CreateModule from "diagram-js/lib/features/create";
// import SpaceToolModule from "diagram-js/lib/features/space-tool";
// import LassoToolModule from "diagram-js/lib/features/lasso-tool";
// import HandToolModule from "diagram-js/lib/features/hand-tool";
// import GlobalConnectModule from "diagram-js/lib/features/global-connect";
// import translate from "diagram-js/lib/i18n/translate";
//
// import PaletteProvider from "./paletteProvider";
//
// export default {
// __depends__: [PaletteModule, CreateModule, SpaceToolModule, LassoToolModule, HandToolModule, GlobalConnectModule, translate],
// __init__: ["paletteProvider"],
// paletteProvider: ["type", PaletteProvider]
// };
import CustomPalette from "./CustomPalette";
export default {
__init__: ["paletteProvider"],
paletteProvider: ["type", CustomPalette]
};

View File

@ -1,160 +0,0 @@
import { assign } from "min-dash";
/**
* A palette provider for BPMN 2.0 elements.
*/
export default function PaletteProvider(palette, create, elementFactory, spaceTool, lassoTool, handTool, globalConnect, translate) {
this._palette = palette;
this._create = create;
this._elementFactory = elementFactory;
this._spaceTool = spaceTool;
this._lassoTool = lassoTool;
this._handTool = handTool;
this._globalConnect = globalConnect;
this._translate = translate;
palette.registerProvider(this);
}
PaletteProvider.$inject = ["palette", "create", "elementFactory", "spaceTool", "lassoTool", "handTool", "globalConnect", "translate"];
PaletteProvider.prototype.getPaletteEntries = function() {
const actions = {},
create = this._create,
elementFactory = this._elementFactory,
spaceTool = this._spaceTool,
lassoTool = this._lassoTool,
handTool = this._handTool,
globalConnect = this._globalConnect,
translate = this._translate
function createAction(type, group, className, title, options) {
function createListener(event) {
const shape = elementFactory.createShape(assign({ type: type }, options))
if (options) {
shape.businessObject.di.isExpanded = options.isExpanded;
}
create.start(event, shape);
}
const shortType = type.replace(/^bpmn:/, '')
return {
group: group,
className: className,
title: title || translate("Create {type}", { type: shortType }),
action: {
dragstart: createListener,
click: createListener
}
};
}
function createSubprocess(event) {
const subProcess = elementFactory.createShape({
type: 'bpmn:SubProcess',
x: 0,
y: 0,
isExpanded: true
})
const startEvent = elementFactory.createShape({
type: 'bpmn:StartEvent',
x: 40,
y: 82,
parent: subProcess
})
create.start(event, [subProcess, startEvent], {
hints: {
autoSelect: [startEvent]
}
});
}
function createParticipant(event) {
create.start(event, elementFactory.createParticipantShape());
}
assign(actions, {
"hand-tool": {
group: "tools",
className: "bpmn-icon-hand-tool",
title: translate("Activate the hand tool"),
action: {
click: function(event) {
handTool.activateHand(event);
}
}
},
"lasso-tool": {
group: "tools",
className: "bpmn-icon-lasso-tool",
title: translate("Activate the lasso tool"),
action: {
click: function(event) {
lassoTool.activateSelection(event);
}
}
},
"space-tool": {
group: "tools",
className: "bpmn-icon-space-tool",
title: translate("Activate the create/remove space tool"),
action: {
click: function(event) {
spaceTool.activateSelection(event);
}
}
},
"global-connect-tool": {
group: "tools",
className: "bpmn-icon-connection-multi",
title: translate("Activate the global connect tool"),
action: {
click: function(event) {
globalConnect.toggle(event);
}
}
},
"tool-separator": {
group: "tools",
separator: true
},
"create.start-event": createAction("bpmn:StartEvent", "event", "bpmn-icon-start-event-none", translate("Create StartEvent")),
"create.intermediate-event": createAction(
"bpmn:IntermediateThrowEvent",
"event",
"bpmn-icon-intermediate-event-none",
translate("Create Intermediate/Boundary Event")
),
"create.end-event": createAction("bpmn:EndEvent", "event", "bpmn-icon-end-event-none", translate("Create EndEvent")),
"create.exclusive-gateway": createAction("bpmn:ExclusiveGateway", "gateway", "bpmn-icon-gateway-none", translate("Create Gateway")),
"create.user-task": createAction("bpmn:UserTask", "activity", "bpmn-icon-user-task", translate("Create User Task")),
"create.data-object": createAction("bpmn:DataObjectReference", "data-object", "bpmn-icon-data-object", translate("Create DataObjectReference")),
"create.data-store": createAction("bpmn:DataStoreReference", "data-store", "bpmn-icon-data-store", translate("Create DataStoreReference")),
"create.subprocess-expanded": {
group: "activity",
className: "bpmn-icon-subprocess-expanded",
title: translate("Create expanded SubProcess"),
action: {
dragstart: createSubprocess,
click: createSubprocess
}
},
"create.participant-expanded": {
group: "collaboration",
className: "bpmn-icon-participant",
title: translate("Create Pool/Participant"),
action: {
dragstart: createParticipant,
click: createParticipant
}
},
"create.group": createAction("bpmn:Group", "artifact", "bpmn-icon-group", translate("Create Group"))
});
return actions;
};

View File

@ -1,41 +0,0 @@
// import translations from "./zh";
//
// export default function customTranslate(template, replacements) {
// replacements = replacements || {};
//
// // Translate
// template = translations[template] || template;
//
// // Replace
// return template.replace(/{([^}]+)}/g, function(_, key) {
// let str = replacements[key];
// if (
// translations[replacements[key]] !== null &&
// translations[replacements[key]] !== "undefined"
// ) {
// // eslint-disable-next-line no-mixed-spaces-and-tabs
// str = translations[replacements[key]];
// // eslint-disable-next-line no-mixed-spaces-and-tabs
// }
// return str || "{" + key + "}";
// });
// }
export default function customTranslate(translations) {
return function(template, replacements) {
replacements = replacements || {};
// Translate
template = translations[template] || template;
// Replace
return template.replace(/{([^}]+)}/g, function(_, key) {
let str = replacements[key];
if (translations[replacements[key]] !== null && translations[replacements[key]] !== undefined) {
// eslint-disable-next-line no-mixed-spaces-and-tabs
str = translations[replacements[key]];
// eslint-disable-next-line no-mixed-spaces-and-tabs
}
return str || "{" + key + "}";
});
};
}

View File

@ -1,238 +0,0 @@
/**
* This is a sample file that should be replaced with the actual translation.
*
* Checkout https://github.com/bpmn-io/bpmn-js-i18n for a list of available
* translations and labels to translate.
*/
export default {
// 添加部分
"Append EndEvent": "追加结束事件",
"Append Gateway": "追加网关",
"Append Task": "追加任务",
"Append Intermediate/Boundary Event": "追加中间抛出事件/边界事件",
"Activate the global connect tool": "激活全局连接工具",
"Append {type}": "添加 {type}",
"Add Lane above": "在上面添加道",
"Divide into two Lanes": "分割成两个道",
"Divide into three Lanes": "分割成三个道",
"Add Lane below": "在下面添加道",
"Append compensation activity": "追加补偿活动",
"Change type": "修改类型",
"Connect using Association": "使用关联连接",
"Connect using Sequence/MessageFlow or Association": "使用顺序/消息流或者关联连接",
"Connect using DataInputAssociation": "使用数据输入关联连接",
Remove: "移除",
"Activate the hand tool": "激活抓手工具",
"Activate the lasso tool": "激活套索工具",
"Activate the create/remove space tool": "激活创建/删除空间工具",
"Create expanded SubProcess": "创建扩展子过程",
"Create IntermediateThrowEvent/BoundaryEvent": "创建中间抛出事件/边界事件",
"Create Pool/Participant": "创建池/参与者",
"Parallel Multi Instance": "并行多重事件",
"Sequential Multi Instance": "时序多重事件",
DataObjectReference: "数据对象参考",
DataStoreReference: "数据存储参考",
Loop: "循环",
"Ad-hoc": "即席",
"Create {type}": "创建 {type}",
Task: "任务",
"Send Task": "发送任务",
"Receive Task": "接收任务",
"User Task": "用户任务",
"Manual Task": "手工任务",
"Business Rule Task": "业务规则任务",
"Service Task": "服务任务",
"Script Task": "脚本任务",
"Call Activity": "调用活动",
"Sub Process (collapsed)": "子流程(折叠的)",
"Sub Process (expanded)": "子流程(展开的)",
"Start Event": "开始事件",
StartEvent: "开始事件",
"Intermediate Throw Event": "中间事件",
"End Event": "结束事件",
EndEvent: "结束事件",
"Create StartEvent": "创建开始事件",
"Create EndEvent": "创建结束事件",
"Create Task": "创建任务",
"Create User Task": "创建用户任务",
"Create Gateway": "创建网关",
"Create DataObjectReference": "创建数据对象",
"Create DataStoreReference": "创建数据存储",
"Create Group": "创建分组",
"Create Intermediate/Boundary Event": "创建中间/边界事件",
"Message Start Event": "消息开始事件",
"Timer Start Event": "定时开始事件",
"Conditional Start Event": "条件开始事件",
"Signal Start Event": "信号开始事件",
"Error Start Event": "错误开始事件",
"Escalation Start Event": "升级开始事件",
"Compensation Start Event": "补偿开始事件",
"Message Start Event (non-interrupting)": "消息开始事件(非中断)",
"Timer Start Event (non-interrupting)": "定时开始事件(非中断)",
"Conditional Start Event (non-interrupting)": "条件开始事件(非中断)",
"Signal Start Event (non-interrupting)": "信号开始事件(非中断)",
"Escalation Start Event (non-interrupting)": "升级开始事件(非中断)",
"Message Intermediate Catch Event": "消息中间捕获事件",
"Message Intermediate Throw Event": "消息中间抛出事件",
"Timer Intermediate Catch Event": "定时中间捕获事件",
"Escalation Intermediate Throw Event": "升级中间抛出事件",
"Conditional Intermediate Catch Event": "条件中间捕获事件",
"Link Intermediate Catch Event": "链接中间捕获事件",
"Link Intermediate Throw Event": "链接中间抛出事件",
"Compensation Intermediate Throw Event": "补偿中间抛出事件",
"Signal Intermediate Catch Event": "信号中间捕获事件",
"Signal Intermediate Throw Event": "信号中间抛出事件",
"Message End Event": "消息结束事件",
"Escalation End Event": "定时结束事件",
"Error End Event": "错误结束事件",
"Cancel End Event": "取消结束事件",
"Compensation End Event": "补偿结束事件",
"Signal End Event": "信号结束事件",
"Terminate End Event": "终止结束事件",
"Message Boundary Event": "消息边界事件",
"Message Boundary Event (non-interrupting)": "消息边界事件(非中断)",
"Timer Boundary Event": "定时边界事件",
"Timer Boundary Event (non-interrupting)": "定时边界事件(非中断)",
"Escalation Boundary Event": "升级边界事件",
"Escalation Boundary Event (non-interrupting)": "升级边界事件(非中断)",
"Conditional Boundary Event": "条件边界事件",
"Conditional Boundary Event (non-interrupting)": "条件边界事件(非中断)",
"Error Boundary Event": "错误边界事件",
"Cancel Boundary Event": "取消边界事件",
"Signal Boundary Event": "信号边界事件",
"Signal Boundary Event (non-interrupting)": "信号边界事件(非中断)",
"Compensation Boundary Event": "补偿边界事件",
"Exclusive Gateway": "互斥网关",
"Parallel Gateway": "并行网关",
"Inclusive Gateway": "相容网关",
"Complex Gateway": "复杂网关",
"Event based Gateway": "事件网关",
Transaction: "转运",
"Sub Process": "子流程",
"Event Sub Process": "事件子流程",
"Collapsed Pool": "折叠池",
"Expanded Pool": "展开池",
// Errors
"no parent for {element} in {parent}": "在{parent}里,{element}没有父类",
"no shape type specified": "没有指定的形状类型",
"flow elements must be children of pools/participants": "流元素必须是池/参与者的子类",
"out of bounds release": "out of bounds release",
"more than {count} child lanes": "子道大于{count} ",
"element required": "元素不能为空",
"diagram not part of bpmn:Definitions": "流程图不符合bpmn规范",
"no diagram to display": "没有可展示的流程图",
"no process or collaboration to display": "没有可展示的流程/协作",
"element {element} referenced by {referenced}#{property} not yet drawn": "由{referenced}#{property}引用的{element}元素仍未绘制",
"already rendered {element}": "{element} 已被渲染",
"failed to import {element}": "导入{element}失败",
//属性面板的参数
Id: "编号",
Name: "名称",
General: "常规",
Details: "详情",
"Message Name": "消息名称",
Message: "消息",
Initiator: "创建者",
"Asynchronous Continuations": "持续异步",
"Asynchronous Before": "异步前",
"Asynchronous After": "异步后",
"Job Configuration": "工作配置",
Exclusive: "排除",
"Job Priority": "工作优先级",
"Retry Time Cycle": "重试时间周期",
Documentation: "文档",
"Element Documentation": "元素文档",
"History Configuration": "历史配置",
"History Time To Live": "历史的生存时间",
Forms: "表单",
"Form Key": "表单key",
"Form Fields": "表单字段",
"Business Key": "业务key",
"Form Field": "表单字段",
ID: "编号",
Type: "类型",
Label: "名称",
"Default Value": "默认值",
"Default Flow": "默认流转路径",
"Conditional Flow": "条件流转路径",
"Sequence Flow": "普通流转路径",
Validation: "校验",
"Add Constraint": "添加约束",
Config: "配置",
Properties: "属性",
"Add Property": "添加属性",
Value: "值",
Listeners: "监听器",
"Execution Listener": "执行监听",
"Event Type": "事件类型",
"Listener Type": "监听器类型",
"Java Class": "Java类",
Expression: "表达式",
"Must provide a value": "必须提供一个值",
"Delegate Expression": "代理表达式",
Script: "脚本",
"Script Format": "脚本格式",
"Script Type": "脚本类型",
"Inline Script": "内联脚本",
"External Script": "外部脚本",
Resource: "资源",
"Field Injection": "字段注入",
Extensions: "扩展",
"Input/Output": "输入/输出",
"Input Parameters": "输入参数",
"Output Parameters": "输出参数",
Parameters: "参数",
"Output Parameter": "输出参数",
"Timer Definition Type": "定时器定义类型",
"Timer Definition": "定时器定义",
Date: "日期",
Duration: "持续",
Cycle: "循环",
Signal: "信号",
"Signal Name": "信号名称",
Escalation: "升级",
Error: "错误",
"Link Name": "链接名称",
Condition: "条件名称",
"Variable Name": "变量名称",
"Variable Event": "变量事件",
"Specify more than one variable change event as a comma separated list.": "多个变量事件以逗号隔开",
"Wait for Completion": "等待完成",
"Activity Ref": "活动参考",
"Version Tag": "版本标签",
Executable: "可执行文件",
"External Task Configuration": "扩展任务配置",
"Task Priority": "任务优先级",
External: "外部",
Connector: "连接器",
"Must configure Connector": "必须配置连接器",
"Connector Id": "连接器编号",
Implementation: "实现方式",
"Field Injections": "字段注入",
Fields: "字段",
"Result Variable": "结果变量",
Topic: "主题",
"Configure Connector": "配置连接器",
"Input Parameter": "输入参数",
Assignee: "代理人",
"Candidate Users": "候选用户",
"Candidate Groups": "候选组",
"Due Date": "到期时间",
"Follow Up Date": "跟踪日期",
Priority: "优先级",
"The follow up date as an EL expression (e.g. ${someDate} or an ISO date (e.g. 2015-06-26T09:54:00)":
"跟踪日期必须符合EL表达式 ${someDate} ,或者一个ISO标准日期2015-06-26T09:54:00",
"The due date as an EL expression (e.g. ${someDate} or an ISO date (e.g. 2015-06-26T09:54:00)":
"跟踪日期必须符合EL表达式 ${someDate} ,或者一个ISO标准日期2015-06-26T09:54:00",
Variables: "变量",
"Candidate Starter Configuration": "候选人起动器配置",
"Candidate Starter Groups": "候选人起动器组",
"This maps to the process definition key.": "这映射到流程定义键。",
"Candidate Starter Users": "候选人起动器的用户",
"Specify more than one user as a comma separated list.": "指定多个用户作为逗号分隔的列表。",
"Tasklist Configuration": "Tasklist配置",
Startable: "启动",
"Specify more than one group as a comma separated list.": "指定多个组作为逗号分隔的列表。"
};

View File

@ -1,21 +0,0 @@
import MyProcessDesigner from "./designer";
import MyProcessPenal from "./penal";
import MyProcessViewer from './designer/index2';
const components = [MyProcessDesigner, MyProcessPenal, MyProcessViewer];
const install = function(Vue) {
components.forEach(component => {
Vue.component(component.name, component);
});
};
if (typeof window !== "undefined" && window.Vue) {
install(window.Vue);
}
export default {
version: "0.0.1",
install,
...components
};

View File

@ -1,48 +0,0 @@
<template>
<div class="my-process-palette">
<div class="test-button" @click="addTask" @mousedown="addTask">测试任务</div>
<div class="test-container" id="palette-container">1</div>
</div>
</template>
<script>
import { assign } from "min-dash";
export default {
name: "MyProcessPalette",
data() {
return {};
},
mounted() {},
methods: {
addTask(event, options = {}) {
const ElementFactory = window.bpmnInstances.elementFactory;
const create = window.bpmnInstances.modeler.get("create");
console.log(ElementFactory, create);
const shape = ElementFactory.createShape(assign({ type: "bpmn:UserTask" }, options));
if (options) {
shape.businessObject.di.isExpanded = options.isExpanded;
}
create.start(event, shape);
}
}
};
</script>
<style scoped lang="scss">
.my-process-palette {
box-sizing: border-box;
padding: 80px 20px 20px 20px;
.test-button {
box-sizing: border-box;
padding: 8px 16px;
border-radius: 4px;
border: 1px solid rgba(24, 144, 255, 0.8);
cursor: pointer;
}
}
</style>

View File

@ -1,197 +0,0 @@
<template>
<div class="process-panel__container" :style="{ width: `${this.width}px` }">
<el-collapse v-model="activeTab">
<el-collapse-item name="base">
<div slot="title" class="panel-tab__title"><i class="el-icon-info"></i>常规</div>
<element-base-info :id-edit-disabled="idEditDisabled" :business-object="elementBusinessObject" :type="elementType"
:model="model" />
</el-collapse-item>
<el-collapse-item name="condition" v-if="elementType === 'Process'" key="message">
<div slot="title" class="panel-tab__title"><i class="el-icon-s-comment"></i>消息与信号</div>
<signal-and-massage />
</el-collapse-item>
<el-collapse-item name="condition" v-if="conditionFormVisible" key="condition">
<div slot="title" class="panel-tab__title"><i class="el-icon-s-promotion"></i>流转条件</div>
<flow-condition :business-object="elementBusinessObject" :type="elementType" />
</el-collapse-item>
<el-collapse-item name="condition" v-if="formVisible" key="form">
<div slot="title" class="panel-tab__title"><i class="el-icon-s-order"></i>表单</div>
<!-- <element-form :id="elementId" :type="elementType" />-->
友情提示使用 <router-link target="_blank" :to="{path:'/bpm/manager/form'}"><el-link type="danger">流程表单</el-link> </router-link>
替代提供更好的表单设计功能
</el-collapse-item>
<el-collapse-item name="task" v-if="elementType.indexOf('Task') !== -1" key="task">
<div slot="title" class="panel-tab__title"><i class="el-icon-s-claim"></i>任务</div>
<element-task :id="elementId" :type="elementType" />
</el-collapse-item>
<el-collapse-item name="multiInstance" v-if="elementType.indexOf('Task') !== -1" key="multiInstance">
<div slot="title" class="panel-tab__title"><i class="el-icon-s-help"></i>多实例</div>
<element-multi-instance :business-object="elementBusinessObject" :type="elementType" />
</el-collapse-item>
<el-collapse-item name="listeners" key="listeners">
<div slot="title" class="panel-tab__title"><i class="el-icon-message-solid"></i>执行监听器</div>
<element-listeners :id="elementId" :type="elementType" />
</el-collapse-item>
<el-collapse-item name="taskListeners" v-if="elementType === 'UserTask'" key="taskListeners">
<div slot="title" class="panel-tab__title"><i class="el-icon-message-solid"></i>任务监听器</div>
<user-task-listeners :id="elementId" :type="elementType" />
</el-collapse-item>
<el-collapse-item name="extensions" key="extensions">
<div slot="title" class="panel-tab__title"><i class="el-icon-circle-plus"></i>扩展属性</div>
<element-properties :id="elementId" :type="elementType" />
</el-collapse-item>
<el-collapse-item name="other" key="other">
<div slot="title" class="panel-tab__title"><i class="el-icon-s-promotion"></i>其他</div>
<element-other-config :id="elementId" />
</el-collapse-item>
</el-collapse>
</div>
</template>
<script>
import ElementBaseInfo from "./base/ElementBaseInfo";
import ElementOtherConfig from "./other/ElementOtherConfig";
import ElementTask from "./task/ElementTask";
import ElementMultiInstance from "./multi-instance/ElementMultiInstance";
import FlowCondition from "./flow-condition/FlowCondition";
import SignalAndMassage from "./signal-message/SignalAndMessage";
import ElementListeners from "./listeners/ElementListeners";
import ElementProperties from "./properties/ElementProperties";
import ElementForm from "./form/ElementForm";
import UserTaskListeners from "./listeners/UserTaskListeners";
/**
* 侧边栏
* @Author MiyueFE
* @Home https://github.com/miyuesc
* @Date 2021年3月31日18:57:51
*/
export default {
name: "MyPropertiesPanel",
components: {
UserTaskListeners,
ElementForm,
ElementProperties,
ElementListeners,
SignalAndMassage,
FlowCondition,
ElementMultiInstance,
ElementTask,
ElementOtherConfig,
ElementBaseInfo
},
componentName: "MyPropertiesPanel",
props: {
bpmnModeler: Object,
prefix: {
type: String,
default: "camunda"
},
width: {
type: Number,
default: 480
},
idEditDisabled: {
type: Boolean,
default: false
},
model: Object, //
},
provide() {
return {
prefix: this.prefix,
width: this.width
};
},
data() {
return {
activeTab: "base",
elementId: "",
elementType: "",
elementBusinessObject: {}, // businessObject 使
conditionFormVisible: false, //
formVisible: false //
};
},
watch: {
elementId: {
handler() {
this.activeTab = "base";
}
}
},
created() {
this.initModels();
},
methods: {
initModels() {
// modeler moddle
if (!this.bpmnModeler) {
//
this.timer = setTimeout(() => this.initModels(), 10);
return;
}
if (this.timer) clearTimeout(this.timer);
window.bpmnInstances = {
modeler: this.bpmnModeler,
modeling: this.bpmnModeler.get("modeling"),
moddle: this.bpmnModeler.get("moddle"),
eventBus: this.bpmnModeler.get("eventBus"),
bpmnFactory: this.bpmnModeler.get("bpmnFactory"),
elementFactory: this.bpmnModeler.get("elementFactory"),
elementRegistry: this.bpmnModeler.get("elementRegistry"),
replace: this.bpmnModeler.get("replace"),
selection: this.bpmnModeler.get("selection")
};
this.getActiveElement();
},
getActiveElement() {
// bpmn:Process
this.initFormOnChanged(null);
this.bpmnModeler.on("import.done", e => {
this.initFormOnChanged(null);
});
//
this.bpmnModeler.on("selection.changed", ({ newSelection }) => {
this.initFormOnChanged(newSelection[0] || null);
});
this.bpmnModeler.on("element.changed", ({ element }) => {
// ""
if (element && element.id === this.elementId) {
this.initFormOnChanged(element);
}
});
},
//
initFormOnChanged(element) {
let activatedElement = element;
if (!activatedElement) {
activatedElement =
window.bpmnInstances.elementRegistry.find(el => el.type === "bpmn:Process") ??
window.bpmnInstances.elementRegistry.find(el => el.type === "bpmn:Collaboration");
}
if (!activatedElement) return;
console.log(`
----------
select element changed:
id: ${activatedElement.id}
type: ${activatedElement.businessObject.$type}
----------
`);
console.log("businessObject: ", activatedElement.businessObject);
window.bpmnInstances.bpmnElement = activatedElement;
this.bpmnElement = activatedElement;
this.elementId = activatedElement.id;
this.elementType = activatedElement.type.split(":")[1] || "";
this.elementBusinessObject = JSON.parse(JSON.stringify(activatedElement.businessObject));
this.conditionFormVisible = !!(
this.elementType === "SequenceFlow" &&
activatedElement.source &&
activatedElement.source.type.indexOf("StartEvent") === -1
);
this.formVisible = this.elementType === "UserTask" || this.elementType === "StartEvent";
},
beforeDestroy() {
window.bpmnInstances = null;
}
}
};
</script>

View File

@ -1,147 +0,0 @@
<template>
<div class="panel-tab__content">
<el-form
size="mini"
label-width="90px"
:model="model"
:rules="rules"
@submit.native.prevent
>
<div v-if="elementBaseInfo.$type === 'bpmn:Process'">
<!-- 如果是 Process 信息的时候使用自定义表单 -->
<el-link
href="https://doc.iocoder.cn/bpm/#_3-%E6%B5%81%E7%A8%8B%E5%9B%BE%E7%A4%BA%E4%BE%8B"
type="danger"
target="_blank"
>如何实现实现会签或签</el-link
>
<el-form-item label="流程标识" prop="key">
<el-input
v-model="model.key"
placeholder="请输入流标标识"
:disabled="model.id !== undefined && model.id.length > 0"
@change="handleKeyUpdate"
/>
</el-form-item>
<el-form-item label="流程名称" prop="name">
<el-input
v-model="model.name"
placeholder="请输入流程名称"
clearable
@change="handleNameUpdate"
/>
</el-form-item>
</div>
<div v-else>
<el-form-item label="ID">
<el-input
v-model="elementBaseInfo.id"
clearable
@change="updateBaseInfo('id')"
/>
</el-form-item>
<el-form-item label="名称">
<el-input
v-model="elementBaseInfo.name"
clearable
@change="updateBaseInfo('name')"
/>
</el-form-item>
</div>
</el-form>
</div>
</template>
<script>
export default {
name: "ElementBaseInfo",
props: {
businessObject: Object,
model: Object, //
},
data () {
return {
elementBaseInfo: {},
//
forms: [],
//
rules: {
key: [{ required: true, message: "流程标识不能为空", trigger: "blur" }],
name: [{ required: true, message: "流程名称不能为空", trigger: "blur" }],
},
}
},
watch: {
businessObject: {
immediate: false,
handler: function (val) {
if (val) {
this.$nextTick(() => this.resetBaseInfo())
}
}
},
// 'model.key': {
// immediate: false,
// handler: function (val) {
// this.handleKeyUpdate(val)
// }
// }
},
created () {
// bpmn 1 key name
setTimeout(() => {
this.handleKeyUpdate(this.model.key)
this.handleNameUpdate(this.model.name)
}, 1000)
},
methods: {
resetBaseInfo () {
this.bpmnElement = window?.bpmnInstances?.bpmnElement
this.elementBaseInfo = JSON.parse(JSON.stringify(this.bpmnElement.businessObject))
},
handleKeyUpdate (value) {
// value XML NCName
if (!value) {
return
}
if (!value.match(/[a-zA-Z_][\-_.0-9a-zA-Z$]*/)) {
console.log('key 不满足 XML NCName 规则,所以不进行赋值')
return
}
console.log('key 满足 XML NCName 规则,所以进行赋值')
// BPMN XML key id
this.elementBaseInfo['id'] = value
this.updateBaseInfo('id')
},
handleNameUpdate (value) {
if (!value) {
return
}
this.elementBaseInfo['name'] = value
this.updateBaseInfo('name')
},
handleDescriptionUpdate (value) {
// TODO documentation
// this.elementBaseInfo['documentation'] = value;
// this.updateBaseInfo('documentation');
},
updateBaseInfo (key) {
// elementBaseInfo
const attrObj = Object.create(null)
attrObj[key] = this.elementBaseInfo[key]
if (key === "id") {
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, {
id: this.elementBaseInfo[key],
di: { id: `${this.elementBaseInfo[key]}_di` }
})
} else {
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, attrObj)
}
}
},
beforeDestroy () {
this.bpmnElement = null
}
};
</script>

View File

@ -1,142 +0,0 @@
<template>
<div class="panel-tab__content">
<el-form :model="flowConditionForm" label-width="90px" size="mini" @submit.native.prevent>
<el-form-item label="流转类型">
<el-select v-model="flowConditionForm.type" @change="updateFlowType">
<el-option label="普通流转路径" value="normal" />
<el-option label="默认流转路径" value="default" />
<el-option label="条件流转路径" value="condition" />
</el-select>
</el-form-item>
<el-form-item label="条件格式" v-if="flowConditionForm.type === 'condition'" key="condition">
<el-select v-model="flowConditionForm.conditionType">
<el-option label="表达式" value="expression" />
<el-option label="脚本" value="script" />
</el-select>
</el-form-item>
<el-form-item label="表达式" v-if="flowConditionForm.conditionType && flowConditionForm.conditionType === 'expression'" key="express">
<el-input v-model="flowConditionForm.body" style="width:192px;" clearable @change="updateFlowCondition" />
</el-form-item>
<template v-if="flowConditionForm.conditionType && flowConditionForm.conditionType === 'script'">
<el-form-item label="脚本语言" key="language">
<el-input v-model="flowConditionForm.language" clearable @change="updateFlowCondition" />
</el-form-item>
<el-form-item label="脚本类型" key="scriptType">
<el-select v-model="flowConditionForm.scriptType">
<el-option label="内联脚本" value="inlineScript" />
<el-option label="外部脚本" value="externalScript" />
</el-select>
</el-form-item>
<el-form-item label="脚本" v-if="flowConditionForm.scriptType === 'inlineScript'" key="body">
<el-input v-model="flowConditionForm.body" type="textarea" clearable @change="updateFlowCondition" />
</el-form-item>
<el-form-item label="资源地址" v-if="flowConditionForm.scriptType === 'externalScript'" key="resource">
<el-input v-model="flowConditionForm.resource" clearable @change="updateFlowCondition" />
</el-form-item>
</template>
</el-form>
</div>
</template>
<script>
export default {
name: "FlowCondition",
props: {
businessObject: Object,
type: String
},
data() {
return {
flowConditionForm: {}
};
},
watch: {
businessObject: {
immediate: true,
handler() {
this.$nextTick(() => this.resetFlowCondition());
}
}
},
methods: {
resetFlowCondition() {
this.bpmnElement = window.bpmnInstances.bpmnElement;
this.bpmnElementSource = this.bpmnElement.source;
this.bpmnElementSourceRef = this.bpmnElement.businessObject.sourceRef;
if (this.bpmnElementSourceRef && this.bpmnElementSourceRef.default && this.bpmnElementSourceRef.default.id === this.bpmnElement.id) {
//
this.flowConditionForm = { type: "default" };
} else if (!this.bpmnElement.businessObject.conditionExpression) {
//
this.flowConditionForm = { type: "normal" };
} else {
//
const conditionExpression = this.bpmnElement.businessObject.conditionExpression;
this.flowConditionForm = { ...conditionExpression, type: "condition" };
// resource
if (this.flowConditionForm.resource) {
this.$set(this.flowConditionForm, "conditionType", "script");
this.$set(this.flowConditionForm, "scriptType", "externalScript");
return;
}
if (conditionExpression.language) {
this.$set(this.flowConditionForm, "conditionType", "script");
this.$set(this.flowConditionForm, "scriptType", "inlineScript");
return;
}
this.$set(this.flowConditionForm, "conditionType", "expression");
}
},
updateFlowType(flowType) {
//
if (flowType === "condition") {
this.flowConditionRef = window.bpmnInstances.moddle.create("bpmn:FormalExpression");
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, {
conditionExpression: this.flowConditionRef
});
return;
}
//
if (flowType === "default") {
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, {
conditionExpression: null
});
window.bpmnInstances.modeling.updateProperties(this.bpmnElementSource, {
default: this.bpmnElement
});
return;
}
// 线
if (this.bpmnElementSourceRef.default && this.bpmnElementSourceRef.default.id === this.bpmnElement.id) {
window.bpmnInstances.modeling.updateProperties(this.bpmnElementSource, {
default: null
});
}
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, {
conditionExpression: null
});
},
updateFlowCondition() {
let { conditionType, scriptType, body, resource, language } = this.flowConditionForm;
let condition;
if (conditionType === "expression") {
condition = window.bpmnInstances.moddle.create("bpmn:FormalExpression", { body });
} else {
if (scriptType === "inlineScript") {
condition = window.bpmnInstances.moddle.create("bpmn:FormalExpression", { body, language });
this.$set(this.flowConditionForm, "resource", "");
} else {
this.$set(this.flowConditionForm, "body", "");
condition = window.bpmnInstances.moddle.create("bpmn:FormalExpression", { resource, language });
}
}
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, { conditionExpression: condition });
}
},
beforeDestroy() {
this.bpmnElement = null;
this.bpmnElementSource = null;
this.bpmnElementSourceRef = null;
}
};
</script>

View File

@ -1,361 +0,0 @@
<template>
<div class="panel-tab__content">
<el-form size="mini" label-width="80px" @submit.native.prevent>
<el-form-item label="表单标识">
<el-input v-model="formKey" clearable @change="updateElementFormKey" />
</el-form-item>
<el-form-item label="业务标识">
<el-select v-model="businessKey" @change="updateElementBusinessKey">
<el-option v-for="i in fieldList" :key="i.id" :value="i.id" :label="i.label" />
<el-option label="无" value="" />
</el-select>
</el-form-item>
</el-form>
<!--字段列表-->
<div class="element-property list-property">
<el-divider><i class="el-icon-coin"></i> 表单字段</el-divider>
<el-table :data="fieldList" size="mini" max-height="240" border fit>
<el-table-column label="序号" type="index" width="50px" />
<el-table-column label="字段名称" prop="label" min-width="80px" show-overflow-tooltip />
<el-table-column label="字段类型" prop="type" min-width="80px" :formatter="row => fieldType[row.type] || row.type" show-overflow-tooltip />
<el-table-column label="默认值" prop="defaultValue" min-width="80px" show-overflow-tooltip />
<el-table-column label="操作" width="90px">
<template v-slot="{ row, $index }">
<el-button size="mini" type="text" @click="openFieldForm(row, $index)">编辑</el-button>
<el-divider direction="vertical" />
<el-button size="mini" type="text" style="color: #ff4d4f" @click="removeField(row, $index)">移除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="element-drawer__button">
<el-button size="mini" type="primary" icon="el-icon-plus" @click="openFieldForm(null, -1)">添加字段</el-button>
</div>
<!--字段配置侧边栏-->
<el-drawer :visible.sync="fieldModelVisible" title="字段配置" :size="`${width}px`" append-to-body destroy-on-close>
<el-form :model="formFieldForm" label-width="90px" size="mini" @submit.native.prevent>
<el-form-item label="字段ID">
<el-input v-model="formFieldForm.id" clearable />
</el-form-item>
<el-form-item label="类型">
<el-select v-model="formFieldForm.typeType" placeholder="请选择字段类型" clearable @change="changeFieldTypeType">
<el-option v-for="(value, key) of fieldType" :label="value" :value="key" :key="key" />
</el-select>
</el-form-item>
<el-form-item label="类型名称" v-if="formFieldForm.typeType === 'custom'">
<el-input v-model="formFieldForm.type" clearable />
</el-form-item>
<el-form-item label="名称">
<el-input v-model="formFieldForm.label" clearable />
</el-form-item>
<el-form-item label="时间格式" v-if="formFieldForm.typeType === 'date'">
<el-input v-model="formFieldForm.datePattern" clearable />
</el-form-item>
<el-form-item label="默认值">
<el-input v-model="formFieldForm.defaultValue" clearable />
</el-form-item>
</el-form>
<!-- 枚举值设置 -->
<template v-if="formFieldForm.type === 'enum'">
<el-divider key="enum-divider" />
<p class="listener-filed__title" key="enum-title">
<span><i class="el-icon-menu"></i>枚举值列表</span>
<el-button size="mini" type="primary" @click="openFieldOptionForm(null, -1, 'enum')">添加枚举值</el-button>
</p>
<el-table :data="fieldEnumList" size="mini" key="enum-table" max-height="240" border fit>
<el-table-column label="序号" width="50px" type="index" />
<el-table-column label="枚举值编号" prop="id" min-width="100px" show-overflow-tooltip />
<el-table-column label="枚举值名称" prop="name" min-width="100px" show-overflow-tooltip />
<el-table-column label="操作" width="90px">
<template v-slot="{ row, $index }">
<el-button size="mini" type="text" @click="openFieldOptionForm(row, $index, 'enum')">编辑</el-button>
<el-divider direction="vertical" />
<el-button size="mini" type="text" style="color: #ff4d4f" @click="removeFieldOptionItem(row, $index, 'enum')">移除</el-button>
</template>
</el-table-column>
</el-table>
</template>
<!-- 校验规则 -->
<el-divider key="validation-divider" />
<p class="listener-filed__title" key="validation-title">
<span><i class="el-icon-menu"></i>约束条件列表</span>
<el-button size="mini" type="primary" @click="openFieldOptionForm(null, -1, 'constraint')">添加约束</el-button>
</p>
<el-table :data="fieldConstraintsList" size="mini" key="validation-table" max-height="240" border fit>
<el-table-column label="序号" width="50px" type="index" />
<el-table-column label="约束名称" prop="name" min-width="100px" show-overflow-tooltip />
<el-table-column label="约束配置" prop="config" min-width="100px" show-overflow-tooltip />
<el-table-column label="操作" width="90px">
<template v-slot="{ row, $index }">
<el-button size="mini" type="text" @click="openFieldOptionForm(row, $index, 'constraint')">编辑</el-button>
<el-divider direction="vertical" />
<el-button size="mini" type="text" style="color: #ff4d4f" @click="removeFieldOptionItem(row, $index, 'constraint')">移除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 表单属性 -->
<el-divider key="property-divider" />
<p class="listener-filed__title" key="property-title">
<span><i class="el-icon-menu"></i>字段属性列表</span>
<el-button size="mini" type="primary" @click="openFieldOptionForm(null, -1, 'property')">添加属性</el-button>
</p>
<el-table :data="fieldPropertiesList" size="mini" key="property-table" max-height="240" border fit>
<el-table-column label="序号" width="50px" type="index" />
<el-table-column label="属性编号" prop="id" min-width="100px" show-overflow-tooltip />
<el-table-column label="属性值" prop="value" min-width="100px" show-overflow-tooltip />
<el-table-column label="操作" width="90px">
<template v-slot="{ row, $index }">
<el-button size="mini" type="text" @click="openFieldOptionForm(row, $index, 'property')">编辑</el-button>
<el-divider direction="vertical" />
<el-button size="mini" type="text" style="color: #ff4d4f" @click="removeFieldOptionItem(row, $index, 'property')">移除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 底部按钮 -->
<div class="element-drawer__button">
<el-button size="mini"> </el-button>
<el-button size="mini" type="primary" @click="saveField"> </el-button>
</div>
</el-drawer>
<el-dialog :visible.sync="fieldOptionModelVisible" :title="optionModelTitle" width="600px" append-to-body destroy-on-close>
<el-form :model="fieldOptionForm" size="mini" label-width="96px" @submit.native.prevent>
<el-form-item label="编号/ID" v-if="fieldOptionType !== 'constraint'" key="option-id">
<el-input v-model="fieldOptionForm.id" clearable />
</el-form-item>
<el-form-item label="名称" v-if="fieldOptionType !== 'property'" key="option-name">
<el-input v-model="fieldOptionForm.name" clearable />
</el-form-item>
<el-form-item label="配置" v-if="fieldOptionType === 'constraint'" key="option-config">
<el-input v-model="fieldOptionForm.config" clearable />
</el-form-item>
<el-form-item label="值" v-if="fieldOptionType === 'property'" key="option-value">
<el-input v-model="fieldOptionForm.value" clearable />
</el-form-item>
</el-form>
<template slot="footer">
<el-button size="mini" @click="fieldOptionModelVisible = false"> </el-button>
<el-button size="mini" type="primary" @click="saveFieldOption"> </el-button>
</template>
</el-dialog>
</div>
</template>
<script>
export default {
name: "ElementForm",
props: {
id: String,
type: String
},
inject: {
prefix: "prefix",
width: "width"
},
data() {
return {
formKey: "",
businessKey: "",
optionModelTitle: "",
fieldList: [],
formFieldForm: {},
fieldType: {
long: "长整型",
string: "字符串",
boolean: "布尔类",
date: "日期类",
enum: "枚举类",
custom: "自定义类型"
},
formFieldIndex: -1, // -1
formFieldOptionIndex: -1, // -1
fieldModelVisible: false,
fieldOptionModelVisible: false,
fieldOptionForm: {}, //
fieldOptionType: "", //
fieldEnumList: [], //
fieldConstraintsList: [], //
fieldPropertiesList: [] //
};
},
watch: {
id: {
immediate: true,
handler(val) {
val && val.length && this.$nextTick(() => this.resetFormList());
}
}
},
methods: {
resetFormList() {
this.bpmnELement = window.bpmnInstances.bpmnElement;
this.formKey = this.bpmnELement.businessObject.formKey;
//
this.elExtensionElements =
this.bpmnELement.businessObject.get("extensionElements") || window.bpmnInstances.moddle.create("bpmn:ExtensionElements", { values: [] });
//
this.formData =
this.elExtensionElements.values.filter(ex => ex.$type === `${this.prefix}:FormData`)?.[0] ||
window.bpmnInstances.moddle.create(`${this.prefix}:FormData`, { fields: [] });
// businessKey formData
this.businessKey = this.formData.businessKey;
// 便
this.otherExtensions = this.elExtensionElements.values.filter(ex => ex.$type !== `${this.prefix}:FormData`);
//
this.fieldList = JSON.parse(JSON.stringify(this.formData.fields || []));
//
this.updateElementExtensions();
},
updateElementFormKey() {
window.bpmnInstances.modeling.updateProperties(this.bpmnELement, { formKey: this.formKey });
},
updateElementBusinessKey() {
window.bpmnInstances.modeling.updateModdleProperties(this.bpmnELement, this.formData, { businessKey: this.businessKey });
},
// type
changeFieldTypeType(type) {
this.$set(this.formFieldForm, "type", type === "custom" ? "" : type);
},
//
openFieldForm(field, index) {
this.formFieldIndex = index;
if (index !== -1) {
const FieldObject = this.formData.fields[index];
this.formFieldForm = JSON.parse(JSON.stringify(field));
//
this.$set(this.formFieldForm, "typeType", !this.fieldType[field.type] ? "custom" : field.type);
//
field.type === "enum" && (this.fieldEnumList = JSON.parse(JSON.stringify(FieldObject?.values || [])));
//
this.fieldConstraintsList = JSON.parse(JSON.stringify(FieldObject?.validation?.constraints || []));
//
this.fieldPropertiesList = JSON.parse(JSON.stringify(FieldObject?.properties?.values || []));
} else {
this.formFieldForm = {};
//
this.fieldEnumList = [];
//
this.fieldConstraintsList = [];
//
this.fieldPropertiesList = [];
}
this.fieldModelVisible = true;
},
//
openFieldOptionForm(option, index, type) {
this.fieldOptionModelVisible = true;
this.fieldOptionType = type;
this.formFieldOptionIndex = index;
if (type === "property") {
this.fieldOptionForm = option ? JSON.parse(JSON.stringify(option)) : {};
return (this.optionModelTitle = "属性配置");
}
if (type === "enum") {
this.fieldOptionForm = option ? JSON.parse(JSON.stringify(option)) : {};
return (this.optionModelTitle = "枚举值配置");
}
this.fieldOptionForm = option ? JSON.parse(JSON.stringify(option)) : {};
return (this.optionModelTitle = "约束条件配置");
},
//
saveFieldOption() {
if (this.formFieldOptionIndex === -1) {
if (this.fieldOptionType === "property") {
this.fieldPropertiesList.push(this.fieldOptionForm);
}
if (this.fieldOptionType === "constraint") {
this.fieldConstraintsList.push(this.fieldOptionForm);
}
if (this.fieldOptionType === "enum") {
this.fieldEnumList.push(this.fieldOptionForm);
}
} else {
this.fieldOptionType === "property" && this.fieldPropertiesList.splice(this.formFieldOptionIndex, 1, this.fieldOptionForm);
this.fieldOptionType === "constraint" && this.fieldConstraintsList.splice(this.formFieldOptionIndex, 1, this.fieldOptionForm);
this.fieldOptionType === "enum" && this.fieldEnumList.splice(this.formFieldOptionIndex, 1, this.fieldOptionForm);
}
this.fieldOptionModelVisible = false;
this.fieldOptionForm = {};
},
//
saveField() {
const { id, type, label, defaultValue, datePattern } = this.formFieldForm;
const Field = window.bpmnInstances.moddle.create(`${this.prefix}:FormField`, { id, type, label });
defaultValue && (Field.defaultValue = defaultValue);
datePattern && (Field.datePattern = datePattern);
//
if (this.fieldPropertiesList && this.fieldPropertiesList.length) {
const fieldPropertyList = this.fieldPropertiesList.map(fp => {
return window.bpmnInstances.moddle.create(`${this.prefix}:Property`, { id: fp.id, value: fp.value });
});
Field.properties = window.bpmnInstances.moddle.create(`${this.prefix}:Properties`, { values: fieldPropertyList });
}
//
if (this.fieldConstraintsList && this.fieldConstraintsList.length) {
const fieldConstraintList = this.fieldConstraintsList.map(fc => {
return window.bpmnInstances.moddle.create(`${this.prefix}:Constraint`, { name: fc.name, config: fc.config });
});
Field.validation = window.bpmnInstances.moddle.create(`${this.prefix}:Validation`, { constraints: fieldConstraintList });
}
//
if (this.fieldEnumList && this.fieldEnumList.length) {
Field.values = this.fieldEnumList.map(fe => {
return window.bpmnInstances.moddle.create(`${this.prefix}:Value`, { name: fe.name, id: fe.id });
});
}
//
if (this.formFieldIndex === -1) {
this.fieldList.push(this.formFieldForm);
this.formData.fields.push(Field);
} else {
this.fieldList.splice(this.formFieldIndex, 1, this.formFieldForm);
this.formData.fields.splice(this.formFieldIndex, 1, Field);
}
this.updateElementExtensions();
this.fieldModelVisible = false;
},
//
removeFieldOptionItem(option, index, type) {
if (type === "property") {
this.fieldPropertiesList.splice(index, 1);
return;
}
if (type === "enum") {
this.fieldEnumList.splice(index, 1);
return;
}
this.fieldConstraintsList.splice(index, 1);
},
//
removeField(field, index) {
this.fieldList.splice(index, 1);
this.formData.fields.splice(index, 1);
this.updateElementExtensions();
},
updateElementExtensions() {
//
const newElExtensionElements = window.bpmnInstances.moddle.create(`bpmn:ExtensionElements`, {
values: this.otherExtensions.concat(this.formData)
});
//
window.bpmnInstances.modeling.updateProperties(this.bpmnELement, {
extensionElements: newElExtensionElements
});
}
}
};
</script>

View File

@ -1,7 +0,0 @@
import MyPropertiesPanel from "./PropertiesPanel.vue";
MyPropertiesPanel.install = function(Vue) {
Vue.component(MyPropertiesPanel.name, MyPropertiesPanel);
};
export default MyPropertiesPanel;

View File

@ -1,296 +0,0 @@
<template>
<div class="panel-tab__content">
<el-table :data="elementListenersList" size="mini" border>
<el-table-column label="序号" width="50px" type="index" />
<el-table-column label="事件类型" min-width="100px" prop="event" />
<el-table-column label="监听器类型" min-width="100px" show-overflow-tooltip :formatter="row => listenerTypeObject[row.listenerType]" />
<el-table-column label="操作" width="90px">
<template v-slot="{ row, $index }">
<el-button size="mini" type="text" @click="openListenerForm(row, $index)">编辑</el-button>
<el-divider direction="vertical" />
<el-button size="mini" type="text" style="color: #ff4d4f" @click="removeListener(row, $index)">移除</el-button>
</template>
</el-table-column>
</el-table>
<div class="element-drawer__button">
<el-button size="mini" type="primary" icon="el-icon-plus" @click="openListenerForm(null)">添加监听器</el-button>
</div>
<!-- 监听器 编辑/创建 部分 -->
<el-drawer :visible.sync="listenerFormModelVisible" title="执行监听器" :size="`${width}px`" append-to-body destroy-on-close>
<el-form size="mini" :model="listenerForm" label-width="96px" ref="listenerFormRef" @submit.native.prevent>
<el-form-item label="事件类型" prop="event" :rules="{ required: true, trigger: ['blur', 'change'] }">
<el-select v-model="listenerForm.event">
<el-option label="start" value="start" />
<el-option label="end" value="end" />
</el-select>
</el-form-item>
<el-form-item label="监听器类型" prop="listenerType" :rules="{ required: true, trigger: ['blur', 'change'] }">
<el-select v-model="listenerForm.listenerType">
<el-option v-for="i in Object.keys(listenerTypeObject)" :key="i" :label="listenerTypeObject[i]" :value="i" />
</el-select>
</el-form-item>
<el-form-item
v-if="listenerForm.listenerType === 'classListener'"
label="Java类"
prop="class"
key="listener-class"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerForm.class" clearable />
</el-form-item>
<el-form-item
v-if="listenerForm.listenerType === 'expressionListener'"
label="表达式"
prop="expression"
key="listener-expression"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerForm.expression" clearable />
</el-form-item>
<el-form-item
v-if="listenerForm.listenerType === 'delegateExpressionListener'"
label="代理表达式"
prop="delegateExpression"
key="listener-delegate"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerForm.delegateExpression" clearable />
</el-form-item>
<template v-if="listenerForm.listenerType === 'scriptListener'">
<el-form-item
label="脚本格式"
prop="scriptFormat"
key="listener-script-format"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本格式' }"
>
<el-input v-model="listenerForm.scriptFormat" clearable />
</el-form-item>
<el-form-item
label="脚本类型"
prop="scriptType"
key="listener-script-type"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请选择脚本类型' }"
>
<el-select v-model="listenerForm.scriptType">
<el-option label="内联脚本" value="inlineScript" />
<el-option label="外部脚本" value="externalScript" />
</el-select>
</el-form-item>
<el-form-item
v-if="listenerForm.scriptType === 'inlineScript'"
label="脚本内容"
prop="value"
key="listener-script"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本内容' }"
>
<el-input v-model="listenerForm.value" clearable />
</el-form-item>
<el-form-item
v-if="listenerForm.scriptType === 'externalScript'"
label="资源地址"
prop="resource"
key="listener-resource"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写资源地址' }"
>
<el-input v-model="listenerForm.resource" clearable />
</el-form-item>
</template>
</el-form>
<el-divider />
<p class="listener-filed__title">
<span><i class="el-icon-menu"></i>注入字段</span>
<el-button size="mini" type="primary" @click="openListenerFieldForm(null)">添加字段</el-button>
</p>
<el-table :data="fieldsListOfListener" size="mini" max-height="240" border fit style="flex: none">
<el-table-column label="序号" width="50px" type="index" />
<el-table-column label="字段名称" min-width="100px" prop="name" />
<el-table-column label="字段类型" min-width="80px" show-overflow-tooltip :formatter="row => fieldTypeObject[row.fieldType]" />
<el-table-column label="字段值/表达式" min-width="100px" show-overflow-tooltip :formatter="row => row.string || row.expression" />
<el-table-column label="操作" width="100px">
<template v-slot="{ row, $index }">
<el-button size="mini" type="text" @click="openListenerFieldForm(row, $index)">编辑</el-button>
<el-divider direction="vertical" />
<el-button size="mini" type="text" style="color: #ff4d4f" @click="removeListenerField(row, $index)">移除</el-button>
</template>
</el-table-column>
</el-table>
<div class="element-drawer__button">
<el-button size="mini" @click="listenerFormModelVisible = false"> </el-button>
<el-button size="mini" type="primary" @click="saveListenerConfig"> </el-button>
</div>
</el-drawer>
<!-- 注入西段 编辑/创建 部分 -->
<el-dialog title="字段配置" :visible.sync="listenerFieldFormModelVisible" width="600px" append-to-body destroy-on-close>
<el-form :model="listenerFieldForm" size="mini" label-width="96px" ref="listenerFieldFormRef" style="height: 136px" @submit.native.prevent>
<el-form-item label="字段名称:" prop="name" :rules="{ required: true, trigger: ['blur', 'change'] }">
<el-input v-model="listenerFieldForm.name" clearable />
</el-form-item>
<el-form-item label="字段类型:" prop="fieldType" :rules="{ required: true, trigger: ['blur', 'change'] }">
<el-select v-model="listenerFieldForm.fieldType">
<el-option v-for="i in Object.keys(fieldTypeObject)" :key="i" :label="fieldTypeObject[i]" :value="i" />
</el-select>
</el-form-item>
<el-form-item
v-if="listenerFieldForm.fieldType === 'string'"
label="字段值:"
prop="string"
key="field-string"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerFieldForm.string" clearable />
</el-form-item>
<el-form-item
v-if="listenerFieldForm.fieldType === 'expression'"
label="表达式:"
prop="expression"
key="field-expression"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerFieldForm.expression" clearable />
</el-form-item>
</el-form>
<template slot="footer">
<el-button size="mini" @click="listenerFieldFormModelVisible = false"> </el-button>
<el-button size="mini" type="primary" @click="saveListenerFiled"> </el-button>
</template>
</el-dialog>
</div>
</template>
<script>
import { createListenerObject, updateElementExtensions } from "../../utils";
import { initListenerType, initListenerForm, listenerType, fieldType } from "./utilSelf";
export default {
name: "ElementListeners",
props: {
id: String,
type: String
},
inject: {
prefix: "prefix",
width: "width"
},
data() {
return {
elementListenersList: [], //
listenerForm: {}, //
listenerFormModelVisible: false, //
fieldsListOfListener: [],
listenerFieldForm: {}, //
listenerFieldFormModelVisible: false, //
editingListenerIndex: -1, // -1
editingListenerFieldIndex: -1, // -1
listenerTypeObject: listenerType,
fieldTypeObject: fieldType
};
},
watch: {
id: {
immediate: true,
handler(val) {
val && val.length && this.$nextTick(() => this.resetListenersList());
}
}
},
methods: {
resetListenersList() {
this.bpmnElement = window.bpmnInstances.bpmnElement;
this.otherExtensionList = [];
this.bpmnElementListeners =
this.bpmnElement.businessObject?.extensionElements?.values?.filter(ex => ex.$type === `${this.prefix}:ExecutionListener`) ?? [];
this.elementListenersList = this.bpmnElementListeners.map(listener => initListenerType(listener));
},
//
openListenerForm(listener, index) {
if (listener) {
this.listenerForm = initListenerForm(listener);
this.editingListenerIndex = index;
} else {
this.listenerForm = {};
this.editingListenerIndex = -1; //
}
if (listener && listener.fields) {
this.fieldsListOfListener = listener.fields.map(field => ({ ...field, fieldType: field.string ? "string" : "expression" }));
} else {
this.fieldsListOfListener = [];
this.$set(this.listenerForm, "fields", []);
}
//
this.listenerFormModelVisible = true;
this.$nextTick(() => {
if (this.$refs["listenerFormRef"]) this.$refs["listenerFormRef"].clearValidate();
});
},
//
openListenerFieldForm(field, index) {
this.listenerFieldForm = field ? JSON.parse(JSON.stringify(field)) : {};
this.editingListenerFieldIndex = field ? index : -1;
this.listenerFieldFormModelVisible = true;
this.$nextTick(() => {
if (this.$refs["listenerFieldFormRef"]) this.$refs["listenerFieldFormRef"].clearValidate();
});
},
//
async saveListenerFiled() {
let validateStatus = await this.$refs["listenerFieldFormRef"].validate();
if (!validateStatus) return; //
if (this.editingListenerFieldIndex === -1) {
this.fieldsListOfListener.push(this.listenerFieldForm);
this.listenerForm.fields.push(this.listenerFieldForm);
} else {
this.fieldsListOfListener.splice(this.editingListenerFieldIndex, 1, this.listenerFieldForm);
this.listenerForm.fields.splice(this.editingListenerFieldIndex, 1, this.listenerFieldForm);
}
this.listenerFieldFormModelVisible = false;
this.$nextTick(() => (this.listenerFieldForm = {}));
},
//
removeListenerField(field, index) {
this.$confirm("确认移除该字段吗?", "提示", {
confirmButtonText: "确 认",
cancelButtonText: "取 消"
})
.then(() => {
this.fieldsListOfListener.splice(index, 1);
this.listenerForm.fields.splice(index, 1);
})
.catch(() => console.info("操作取消"));
},
//
removeListener(listener, index) {
this.$confirm("确认移除该监听器吗?", "提示", {
confirmButtonText: "确 认",
cancelButtonText: "取 消"
})
.then(() => {
this.bpmnElementListeners.splice(index, 1);
this.elementListenersList.splice(index, 1);
updateElementExtensions(this.bpmnElement, this.otherExtensionList.concat(this.bpmnElementListeners));
})
.catch(() => console.info("操作取消"));
},
//
async saveListenerConfig() {
let validateStatus = await this.$refs["listenerFormRef"].validate();
if (!validateStatus) return; //
const listenerObject = createListenerObject(this.listenerForm, false, this.prefix);
if (this.editingListenerIndex === -1) {
this.bpmnElementListeners.push(listenerObject);
this.elementListenersList.push(this.listenerForm);
} else {
this.bpmnElementListeners.splice(this.editingListenerIndex, 1, listenerObject);
this.elementListenersList.splice(this.editingListenerIndex, 1, this.listenerForm);
}
//
this.otherExtensionList = this.bpmnElement.businessObject?.extensionElements?.values?.filter(ex => ex.$type !== `${this.prefix}:ExecutionListener`) ?? [];
updateElementExtensions(this.bpmnElement, this.otherExtensionList.concat(this.bpmnElementListeners));
// 4.
this.listenerFormModelVisible = false;
this.listenerForm = {};
}
}
};
</script>

View File

@ -1,319 +0,0 @@
<template>
<div class="panel-tab__content">
<el-table :data="elementListenersList" size="mini" border>
<el-table-column label="序号" width="50px" type="index" />
<el-table-column label="事件类型" min-width="80px" show-overflow-tooltip :formatter="row => listenerEventTypeObject[row.event]" />
<el-table-column label="事件id" min-width="80px" prop="id" show-overflow-tooltip />
<el-table-column label="监听器类型" min-width="80px" show-overflow-tooltip :formatter="row => listenerTypeObject[row.listenerType]" />
<el-table-column label="操作" width="90px">
<template v-slot="{ row, $index }">
<el-button size="mini" type="text" @click="openListenerForm(row, $index)">编辑</el-button>
<el-divider direction="vertical" />
<el-button size="mini" type="text" style="color: #ff4d4f" @click="removeListener(row, $index)">移除</el-button>
</template>
</el-table-column>
</el-table>
<div class="element-drawer__button">
<el-button size="mini" type="primary" icon="el-icon-plus" @click="openListenerForm(null)">添加监听器</el-button>
</div>
<!-- 监听器 编辑/创建 部分 -->
<el-drawer :visible.sync="listenerFormModelVisible" title="任务监听器" :size="`${width}px`" append-to-body destroy-on-close>
<el-form size="mini" :model="listenerForm" label-width="96px" ref="listenerFormRef" @submit.native.prevent>
<el-form-item label="事件类型" prop="event" :rules="{ required: true, trigger: ['blur', 'change'] }">
<el-select v-model="listenerForm.event">
<el-option v-for="i in Object.keys(listenerEventTypeObject)" :key="i" :label="listenerEventTypeObject[i]" :value="i" />
</el-select>
</el-form-item>
<el-form-item label="监听器ID" prop="id" :rules="{ required: true, trigger: ['blur', 'change'] }">
<el-input v-model="listenerForm.id" clearable />
</el-form-item>
<el-form-item label="监听器类型" prop="listenerType" :rules="{ required: true, trigger: ['blur', 'change'] }">
<el-select v-model="listenerForm.listenerType">
<el-option v-for="i in Object.keys(listenerTypeObject)" :key="i" :label="listenerTypeObject[i]" :value="i" />
</el-select>
</el-form-item>
<el-form-item
v-if="listenerForm.listenerType === 'classListener'"
label="Java类"
prop="class"
key="listener-class"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerForm.class" clearable />
</el-form-item>
<el-form-item
v-if="listenerForm.listenerType === 'expressionListener'"
label="表达式"
prop="expression"
key="listener-expression"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerForm.expression" clearable />
</el-form-item>
<el-form-item
v-if="listenerForm.listenerType === 'delegateExpressionListener'"
label="代理表达式"
prop="delegateExpression"
key="listener-delegate"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerForm.delegateExpression" clearable />
</el-form-item>
<template v-if="listenerForm.listenerType === 'scriptListener'">
<el-form-item
label="脚本格式"
prop="scriptFormat"
key="listener-script-format"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本格式' }"
>
<el-input v-model="listenerForm.scriptFormat" clearable />
</el-form-item>
<el-form-item
label="脚本类型"
prop="scriptType"
key="listener-script-type"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请选择脚本类型' }"
>
<el-select v-model="listenerForm.scriptType">
<el-option label="内联脚本" value="inlineScript" />
<el-option label="外部脚本" value="externalScript" />
</el-select>
</el-form-item>
<el-form-item
v-if="listenerForm.scriptType === 'inlineScript'"
label="脚本内容"
prop="value"
key="listener-script"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本内容' }"
>
<el-input v-model="listenerForm.value" clearable />
</el-form-item>
<el-form-item
v-if="listenerForm.scriptType === 'externalScript'"
label="资源地址"
prop="resource"
key="listener-resource"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写资源地址' }"
>
<el-input v-model="listenerForm.resource" clearable />
</el-form-item>
</template>
<template v-if="listenerForm.event === 'timeout'">
<el-form-item label="定时器类型" prop="eventDefinitionType" key="eventDefinitionType">
<el-select v-model="listenerForm.eventDefinitionType">
<el-option label="日期" value="date" />
<el-option label="持续时长" value="duration" />
<el-option label="循环" value="cycle" />
<el-option label="无" value="null" />
</el-select>
</el-form-item>
<el-form-item
v-if="!!listenerForm.eventDefinitionType && listenerForm.eventDefinitionType !== 'null'"
label="定时器"
prop="eventTimeDefinitions"
key="eventTimeDefinitions"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写定时器配置' }"
>
<el-input v-model="listenerForm.eventTimeDefinitions" clearable />
</el-form-item>
</template>
</el-form>
<el-divider />
<p class="listener-filed__title">
<span><i class="el-icon-menu"></i>注入字段</span>
<el-button size="mini" type="primary" @click="openListenerFieldForm(null)">添加字段</el-button>
</p>
<el-table :data="fieldsListOfListener" size="mini" max-height="240" border fit style="flex: none">
<el-table-column label="序号" width="50px" type="index" />
<el-table-column label="字段名称" min-width="100px" prop="name" />
<el-table-column label="字段类型" min-width="80px" show-overflow-tooltip :formatter="row => fieldTypeObject[row.fieldType]" />
<el-table-column label="字段值/表达式" min-width="100px" show-overflow-tooltip :formatter="row => row.string || row.expression" />
<el-table-column label="操作" width="100px">
<template v-slot="{ row, $index }">
<el-button size="mini" type="text" @click="openListenerFieldForm(row, $index)">编辑</el-button>
<el-divider direction="vertical" />
<el-button size="mini" type="text" style="color: #ff4d4f" @click="removeListenerField(row, $index)">移除</el-button>
</template>
</el-table-column>
</el-table>
<div class="element-drawer__button">
<el-button size="mini" @click="listenerFormModelVisible = false"> </el-button>
<el-button size="mini" type="primary" @click="saveListenerConfig"> </el-button>
</div>
</el-drawer>
<!-- 注入西段 编辑/创建 部分 -->
<el-dialog title="字段配置" :visible.sync="listenerFieldFormModelVisible" width="600px" append-to-body destroy-on-close>
<el-form :model="listenerFieldForm" size="mini" label-width="96px" ref="listenerFieldFormRef" style="height: 136px" @submit.native.prevent>
<el-form-item label="字段名称:" prop="name" :rules="{ required: true, trigger: ['blur', 'change'] }">
<el-input v-model="listenerFieldForm.name" clearable />
</el-form-item>
<el-form-item label="字段类型:" prop="fieldType" :rules="{ required: true, trigger: ['blur', 'change'] }">
<el-select v-model="listenerFieldForm.fieldType">
<el-option v-for="i in Object.keys(fieldTypeObject)" :key="i" :label="fieldTypeObject[i]" :value="i" />
</el-select>
</el-form-item>
<el-form-item
v-if="listenerFieldForm.fieldType === 'string'"
label="字段值:"
prop="string"
key="field-string"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerFieldForm.string" clearable />
</el-form-item>
<el-form-item
v-if="listenerFieldForm.fieldType === 'expression'"
label="表达式:"
prop="expression"
key="field-expression"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerFieldForm.expression" clearable />
</el-form-item>
</el-form>
<template slot="footer">
<el-button size="mini" @click="listenerFieldFormModelVisible = false"> </el-button>
<el-button size="mini" type="primary" @click="saveListenerFiled"> </el-button>
</template>
</el-dialog>
</div>
</template>
<script>
import { createListenerObject, updateElementExtensions } from "../../utils";
import { initListenerForm, initListenerType, eventType, listenerType, fieldType } from "./utilSelf";
export default {
name: "UserTaskListeners",
props: {
id: String,
type: String
},
inject: {
prefix: "prefix",
width: "width"
},
data() {
return {
elementListenersList: [],
listenerEventTypeObject: eventType,
listenerTypeObject: listenerType,
listenerFormModelVisible: false,
listenerForm: {},
fieldTypeObject: fieldType,
fieldsListOfListener: [],
listenerFieldFormModelVisible: false, //
editingListenerIndex: -1, // -1
editingListenerFieldIndex: -1, // -1
listenerFieldForm: {} //
};
},
watch: {
id: {
immediate: true,
handler(val) {
val && val.length && this.$nextTick(() => this.resetListenersList());
}
}
},
methods: {
resetListenersList() {
this.bpmnElement = window.bpmnInstances.bpmnElement;
this.otherExtensionList = [];
this.bpmnElementListeners = this.bpmnElement.businessObject?.extensionElements?.values?.filter(ex => ex.$type === `${this.prefix}:TaskListener`) ?? [];
this.elementListenersList = this.bpmnElementListeners.map(listener => initListenerType(listener));
},
openListenerForm(listener, index) {
if (listener) {
this.listenerForm = initListenerForm(listener);
this.editingListenerIndex = index;
} else {
this.listenerForm = {};
this.editingListenerIndex = -1; //
}
if (listener && listener.fields) {
this.fieldsListOfListener = listener.fields.map(field => ({ ...field, fieldType: field.string ? "string" : "expression" }));
} else {
this.fieldsListOfListener = [];
this.$set(this.listenerForm, "fields", []);
}
//
this.listenerFormModelVisible = true;
this.$nextTick(() => {
if (this.$refs["listenerFormRef"]) this.$refs["listenerFormRef"].clearValidate();
});
},
//
removeListener(listener, index) {
this.$confirm("确认移除该监听器吗?", "提示", {
confirmButtonText: "确 认",
cancelButtonText: "取 消"
})
.then(() => {
this.bpmnElementListeners.splice(index, 1);
this.elementListenersList.splice(index, 1);
updateElementExtensions(this.bpmnElement, this.otherExtensionList.concat(this.bpmnElementListeners));
})
.catch(() => console.info("操作取消"));
},
//
async saveListenerConfig() {
let validateStatus = await this.$refs["listenerFormRef"].validate();
if (!validateStatus) return; //
const listenerObject = createListenerObject(this.listenerForm, true, this.prefix);
if (this.editingListenerIndex === -1) {
this.bpmnElementListeners.push(listenerObject);
this.elementListenersList.push(this.listenerForm);
} else {
this.bpmnElementListeners.splice(this.editingListenerIndex, 1, listenerObject);
this.elementListenersList.splice(this.editingListenerIndex, 1, this.listenerForm);
}
//
this.otherExtensionList = this.bpmnElement.businessObject?.extensionElements?.values?.filter(ex => ex.$type !== `${this.prefix}:TaskListener`) ?? [];
updateElementExtensions(this.bpmnElement, this.otherExtensionList.concat(this.bpmnElementListeners));
// 4.
this.listenerFormModelVisible = false;
this.listenerForm = {};
},
//
openListenerFieldForm(field, index) {
this.listenerFieldForm = field ? JSON.parse(JSON.stringify(field)) : {};
this.editingListenerFieldIndex = field ? index : -1;
this.listenerFieldFormModelVisible = true;
this.$nextTick(() => {
if (this.$refs["listenerFieldFormRef"]) this.$refs["listenerFieldFormRef"].clearValidate();
});
},
//
async saveListenerFiled() {
let validateStatus = await this.$refs["listenerFieldFormRef"].validate();
if (!validateStatus) return; //
if (this.editingListenerFieldIndex === -1) {
this.fieldsListOfListener.push(this.listenerFieldForm);
this.listenerForm.fields.push(this.listenerFieldForm);
} else {
this.fieldsListOfListener.splice(this.editingListenerFieldIndex, 1, this.listenerFieldForm);
this.listenerForm.fields.splice(this.editingListenerFieldIndex, 1, this.listenerFieldForm);
}
this.listenerFieldFormModelVisible = false;
this.$nextTick(() => (this.listenerFieldForm = {}));
},
//
removeListenerField(field, index) {
this.$confirm("确认移除该字段吗?", "提示", {
confirmButtonText: "确 认",
cancelButtonText: "取 消"
})
.then(() => {
this.fieldsListOfListener.splice(index, 1);
this.listenerForm.fields.splice(index, 1);
})
.catch(() => console.info("操作取消"));
}
}
};
</script>

View File

@ -1,178 +0,0 @@
export const template = isTaskListener => {
return `
<div class="panel-tab__content">
<el-table :data="elementListenersList" size="mini" border>
<el-table-column label="序号" width="50px" type="index" />
<el-table-column label="事件类型" min-width="100px" prop="event" />
<el-table-column label="监听器类型" min-width="100px" show-overflow-tooltip :formatter="row => listenerTypeObject[row.listenerType]" />
<el-table-column label="操作" width="90px">
<template v-slot="{ row, $index }">
<el-button size="mini" type="text" @click="openListenerForm(row, $index)">编辑</el-button>
<el-divider direction="vertical" />
<el-button size="mini" type="text" style="color: #ff4d4f" @click="removeListener(row, $index)">移除</el-button>
</template>
</el-table-column>
</el-table>
<div class="element-drawer__button">
<el-button size="mini" type="primary" icon="el-icon-plus" @click="openListenerForm(null)">添加监听器</el-button>
</div>
<!-- 监听器 编辑/创建 部分 -->
<el-drawer :visible.sync="listenerFormModelVisible" title="执行监听器" :size="width + 'px'" append-to-body destroy-on-close>
<el-form size="mini" :model="listenerForm" label-width="96px" ref="listenerFormRef" @submit.native.prevent>
<el-form-item label="事件类型" prop="event" :rules="{ required: true, trigger: ['blur', 'change'] }">
<el-select v-model="listenerForm.event">
<el-option label="start" value="start" />
<el-option label="end" value="end" />
</el-select>
</el-form-item>
<el-form-item label="监听器类型" prop="listenerType" :rules="{ required: true, trigger: ['blur', 'change'] }">
<el-select v-model="listenerForm.listenerType">
<el-option v-for="i in Object.keys(listenerTypeObject)" :key="i" :label="listenerTypeObject[i]" :value="i" />
</el-select>
</el-form-item>
<el-form-item
v-if="listenerForm.listenerType === 'classListener'"
label="Java类"
prop="class"
key="listener-class"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerForm.class" clearable />
</el-form-item>
<el-form-item
v-if="listenerForm.listenerType === 'expressionListener'"
label="表达式"
prop="expression"
key="listener-expression"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerForm.expression" clearable />
</el-form-item>
<el-form-item
v-if="listenerForm.listenerType === 'delegateExpressionListener'"
label="代理表达式"
prop="delegateExpression"
key="listener-delegate"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerForm.delegateExpression" clearable />
</el-form-item>
<template v-if="listenerForm.listenerType === 'scriptListener'">
<el-form-item
label="脚本格式"
prop="scriptFormat"
key="listener-script-format"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本格式' }"
>
<el-input v-model="listenerForm.scriptFormat" clearable />
</el-form-item>
<el-form-item
label="脚本类型"
prop="scriptType"
key="listener-script-type"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请选择脚本类型' }"
>
<el-select v-model="listenerForm.scriptType">
<el-option label="内联脚本" value="inlineScript" />
<el-option label="外部脚本" value="externalScript" />
</el-select>
</el-form-item>
<el-form-item
v-if="listenerForm.scriptType === 'inlineScript'"
label="脚本内容"
prop="value"
key="listener-script"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本内容' }"
>
<el-input v-model="listenerForm.value" clearable />
</el-form-item>
<el-form-item
v-if="listenerForm.scriptType === 'externalScript'"
label="资源地址"
prop="resource"
key="listener-resource"
:rules="{ required: true, trigger: ['blur', 'change'], message: '请填写资源地址' }"
>
<el-input v-model="listenerForm.resource" clearable />
</el-form-item>
</template>
${
isTaskListener
? "<el-form-item label='定时器类型' prop='eventDefinitionType' key='eventDefinitionType'>" +
"<el-select v-model='listenerForm.eventDefinitionType'>" +
"<el-option label='日期' value='date' />" +
"<el-option label='持续时长' value='duration' />" +
"<el-option label='循环' value='cycle' />" +
"<el-option label='无' value='' />" +
"</el-select>" +
"</el-form-item>" +
"<el-form-item v-if='!!listenerForm.eventDefinitionType' label='定时器' prop='eventDefinitions' key='eventDefinitions'>" +
"<el-input v-model='listenerForm.eventDefinitions' clearable />" +
"</el-form-item>"
: ""
}
</el-form>
<el-divider />
<p class="listener-filed__title">
<span><i class="el-icon-menu"></i></span>
<el-button size="mini" type="primary" @click="openListenerFieldForm(null)">添加字段</el-button>
</p>
<el-table :data="fieldsListOfListener" size="mini" max-height="240" border fit style="flex: none">
<el-table-column label="序号" width="50px" type="index" />
<el-table-column label="字段名称" min-width="100px" prop="name" />
<el-table-column label="字段类型" min-width="80px" show-overflow-tooltip :formatter="row => fieldTypeObject[row.fieldType]" />
<el-table-column label="字段值/表达式" min-width="100px" show-overflow-tooltip :formatter="row => row.string || row.expression" />
<el-table-column label="操作" width="100px">
<template v-slot="{ row, $index }">
<el-button size="mini" type="text" @click="openListenerFieldForm(row, $index)">编辑</el-button>
<el-divider direction="vertical" />
<el-button size="mini" type="text" style="color: #ff4d4f" @click="removeListenerField(row, $index)">移除</el-button>
</template>
</el-table-column>
</el-table>
<div class="element-drawer__button">
<el-button size="mini" @click="listenerFormModelVisible = false"> </el-button>
<el-button size="mini" type="primary" @click="saveListenerConfig"> </el-button>
</div>
</el-drawer>
<!-- 注入西段 编辑/创建 部分 -->
<el-dialog title="字段配置" :visible.sync="listenerFieldFormModelVisible" width="600px" append-to-body destroy-on-close>
<el-form :model="listenerFieldForm" size="mini" label-width="96px" ref="listenerFieldFormRef" style="height: 136px" @submit.native.prevent>
<el-form-item label="字段名称:" prop="name" :rules="{ required: true, trigger: ['blur', 'change'] }">
<el-input v-model="listenerFieldForm.name" clearable />
</el-form-item>
<el-form-item label="字段类型:" prop="fieldType" :rules="{ required: true, trigger: ['blur', 'change'] }">
<el-select v-model="listenerFieldForm.fieldType">
<el-option v-for="i in Object.keys(fieldTypeObject)" :key="i" :label="fieldTypeObject[i]" :value="i" />
</el-select>
</el-form-item>
<el-form-item
v-if="listenerFieldForm.fieldType === 'string'"
label="字段值:"
prop="string"
key="field-string"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerFieldForm.string" clearable />
</el-form-item>
<el-form-item
v-if="listenerFieldForm.fieldType === 'expression'"
label="表达式:"
prop="expression"
key="field-expression"
:rules="{ required: true, trigger: ['blur', 'change'] }"
>
<el-input v-model="listenerFieldForm.expression" clearable />
</el-form-item>
</el-form>
<template slot="footer">
<el-button size="mini" @click="listenerFieldFormModelVisible = false"> </el-button>
<el-button size="mini" type="primary" @click="saveListenerFiled"> </el-button>
</template>
</el-dialog>
</div>
`;
};

View File

@ -1,62 +0,0 @@
// 初始化表单数据
export function initListenerForm(listener) {
let self = {
...listener
};
if (listener.script) {
self = {
...listener,
...listener.script,
scriptType: listener.script.resource ? "externalScript" : "inlineScript"
};
}
if (listener.event === "timeout" && listener.eventDefinitions) {
if (listener.eventDefinitions.length) {
let k = "";
for (let key in listener.eventDefinitions[0]) {
console.log(listener.eventDefinitions, key);
if (key.indexOf("time") !== -1) {
k = key;
self.eventDefinitionType = key.replace("time", "").toLowerCase();
}
}
console.log(k);
self.eventTimeDefinitions = listener.eventDefinitions[0][k].body;
}
}
return self;
}
export function initListenerType(listener) {
let listenerType;
if (listener.class) listenerType = "classListener";
if (listener.expression) listenerType = "expressionListener";
if (listener.delegateExpression) listenerType = "delegateExpressionListener";
if (listener.script) listenerType = "scriptListener";
return {
...JSON.parse(JSON.stringify(listener)),
...(listener.script ?? {}),
listenerType: listenerType
};
}
export const listenerType = {
classListener: "Java 类",
expressionListener: "表达式",
delegateExpressionListener: "代理表达式",
scriptListener: "脚本"
};
export const eventType = {
create: "创建",
assignment: "指派",
complete: "完成",
delete: "删除",
update: "更新",
timeout: "超时"
};
export const fieldType = {
string: "字符串",
expression: "表达式"
};

View File

@ -1,192 +0,0 @@
<template>
<div class="panel-tab__content">
<el-form size="mini" label-width="90px" @submit.native.prevent>
<el-form-item label="回路特性">
<el-select v-model="loopCharacteristics" @change="changeLoopCharacteristicsType">
<!--bpmn:MultiInstanceLoopCharacteristics-->
<el-option label="并行多重事件" value="ParallelMultiInstance" />
<el-option label="时序多重事件" value="SequentialMultiInstance" />
<!--bpmn:StandardLoopCharacteristics-->
<el-option label="循环事件" value="StandardLoop" />
<el-option label="无" value="Null" />
</el-select>
</el-form-item>
<template v-if="loopCharacteristics === 'ParallelMultiInstance' || loopCharacteristics === 'SequentialMultiInstance'">
<el-form-item label="循环基数" key="loopCardinality">
<el-input v-model="loopInstanceForm.loopCardinality" clearable @change="updateLoopCardinality" />
</el-form-item>
<el-form-item label="集合" key="collection" v-show="false">
<el-input v-model="loopInstanceForm.collection" clearable @change="updateLoopBase" />
</el-form-item>
<el-form-item label="元素变量" key="elementVariable">
<el-input v-model="loopInstanceForm.elementVariable" clearable @change="updateLoopBase" />
</el-form-item>
<el-form-item label="完成条件" key="completionCondition">
<el-input v-model="loopInstanceForm.completionCondition" clearable @change="updateLoopCondition" />
</el-form-item>
<el-form-item label="异步状态" key="async">
<el-checkbox v-model="loopInstanceForm.asyncBefore" label="异步前" @change="updateLoopAsync('asyncBefore')" />
<el-checkbox v-model="loopInstanceForm.asyncAfter" label="异步后" @change="updateLoopAsync('asyncAfter')" />
<el-checkbox
v-model="loopInstanceForm.exclusive"
v-if="loopInstanceForm.asyncAfter || loopInstanceForm.asyncBefore"
label="排除"
@change="updateLoopAsync('exclusive')"
/>
</el-form-item>
<el-form-item label="重试周期" prop="timeCycle" v-if="loopInstanceForm.asyncAfter || loopInstanceForm.asyncBefore" key="timeCycle">
<el-input v-model="loopInstanceForm.timeCycle" clearable @change="updateLoopTimeCycle" />
</el-form-item>
</template>
</el-form>
</div>
</template>
<script>
export default {
name: "ElementMultiInstance",
props: {
businessObject: Object,
type: String
},
inject: {
prefix: "prefix"
},
data() {
return {
loopCharacteristics: "",
//
defaultLoopInstanceForm: {
completionCondition: "",
loopCardinality: "",
extensionElements: [],
asyncAfter: false,
asyncBefore: false,
exclusive: false
},
loopInstanceForm: {}
};
},
watch: {
businessObject: {
immediate: true,
handler(val) {
this.bpmnElement = window.bpmnInstances.bpmnElement;
this.getElementLoop(val);
}
}
},
methods: {
getElementLoop(businessObject) {
if (!businessObject.loopCharacteristics) {
this.loopCharacteristics = "Null";
this.loopInstanceForm = {};
return;
}
if (businessObject.loopCharacteristics.$type === "bpmn:StandardLoopCharacteristics") {
this.loopCharacteristics = "StandardLoop";
this.loopInstanceForm = {};
return;
}
if (businessObject.loopCharacteristics.isSequential) {
this.loopCharacteristics = "SequentialMultiInstance";
} else {
this.loopCharacteristics = "ParallelMultiInstance";
}
//
this.loopInstanceForm = {
...this.defaultLoopInstanceForm,
...businessObject.loopCharacteristics,
completionCondition: businessObject.loopCharacteristics?.completionCondition?.body ?? "",
loopCardinality: businessObject.loopCharacteristics?.loopCardinality?.body ?? ""
};
// businessObject loopCharacteristics
this.multiLoopInstance = window.bpmnInstances.bpmnElement.businessObject.loopCharacteristics;
//
if (
businessObject.loopCharacteristics.extensionElements &&
businessObject.loopCharacteristics.extensionElements.values &&
businessObject.loopCharacteristics.extensionElements.values.length
) {
this.$set(this.loopInstanceForm, "timeCycle", businessObject.loopCharacteristics.extensionElements.values[0].body);
}
},
changeLoopCharacteristicsType(type) {
// this.loopInstanceForm = { ...this.defaultLoopInstanceForm }; //
//
if (type === "Null") {
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, { loopCharacteristics: null });
return;
}
//
if (type === "StandardLoop") {
const loopCharacteristicsObject = window.bpmnInstances.moddle.create("bpmn:StandardLoopCharacteristics");
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, {
loopCharacteristics: loopCharacteristicsObject
});
this.multiLoopInstance = null;
return;
}
//
if (type === "SequentialMultiInstance") {
this.multiLoopInstance = window.bpmnInstances.moddle.create("bpmn:MultiInstanceLoopCharacteristics", { isSequential: true });
} else {
this.multiLoopInstance = window.bpmnInstances.moddle.create("bpmn:MultiInstanceLoopCharacteristics", { collection: "${coll_userList}" });
}
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, {
loopCharacteristics: this.multiLoopInstance
});
},
//
updateLoopCardinality(cardinality) {
let loopCardinality = null;
if (cardinality && cardinality.length) {
loopCardinality = window.bpmnInstances.moddle.create("bpmn:FormalExpression", { body: cardinality });
}
window.bpmnInstances.modeling.updateModdleProperties(this.bpmnElement, this.multiLoopInstance, { loopCardinality });
},
//
updateLoopCondition(condition) {
let completionCondition = null;
if (condition && condition.length) {
completionCondition = window.bpmnInstances.moddle.create("bpmn:FormalExpression", { body: condition });
}
window.bpmnInstances.modeling.updateModdleProperties(this.bpmnElement, this.multiLoopInstance, { completionCondition });
},
//
updateLoopTimeCycle(timeCycle) {
const extensionElements = window.bpmnInstances.moddle.create("bpmn:ExtensionElements", {
values: [
window.bpmnInstances.moddle.create(`${this.prefix}:FailedJobRetryTimeCycle`, {
body: timeCycle
})
]
});
window.bpmnInstances.modeling.updateModdleProperties(this.bpmnElement, this.multiLoopInstance, { extensionElements });
},
//
updateLoopBase() {
window.bpmnInstances.modeling.updateModdleProperties(this.bpmnElement, this.multiLoopInstance, {
collection: this.loopInstanceForm.collection || null,
elementVariable: this.loopInstanceForm.elementVariable || null
});
},
//
updateLoopAsync(key) {
const { asyncBefore, asyncAfter } = this.loopInstanceForm;
let asyncAttr = Object.create(null);
if (!asyncBefore && !asyncAfter) {
this.$set(this.loopInstanceForm, "exclusive", false);
asyncAttr = { asyncBefore: false, asyncAfter: false, exclusive: false, extensionElements: null };
} else {
asyncAttr[key] = this.loopInstanceForm[key];
}
window.bpmnInstances.modeling.updateModdleProperties(this.bpmnElement, this.multiLoopInstance, asyncAttr);
}
},
beforeDestroy() {
this.multiLoopInstance = null;
this.bpmnElement = null;
}
};
</script>

View File

@ -1,59 +0,0 @@
<template>
<div class="panel-tab__content">
<div class="element-property input-property">
<div class="element-property__label">元素文档</div>
<div class="element-property__value">
<el-input
type="textarea"
v-model="documentation"
size="mini"
resize="vertical"
:autosize="{ minRows: 2, maxRows: 4 }"
@input="updateDocumentation"
@blur="updateDocumentation"
/>
</div>
</div>
</div>
</template>
<script>
export default {
name: "ElementOtherConfig",
props: {
id: String
},
data() {
return {
documentation: ""
};
},
watch: {
id: {
immediate: true,
handler: function(id) {
if (id && id.length) {
this.$nextTick(() => {
const documentations = window.bpmnInstances.bpmnElement.businessObject?.documentation;
this.documentation = documentations && documentations.length ? documentations[0].text : "";
});
} else {
this.documentation = "";
}
}
}
},
methods: {
updateDocumentation() {
(this.bpmnElement && this.bpmnElement.id === this.id) || (this.bpmnElement = window.bpmnInstances.elementRegistry.get(this.id));
const documentation = window.bpmnInstances.bpmnFactory.create("bpmn:Documentation", { text: this.documentation });
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, {
documentation: [documentation]
});
}
},
beforeDestroy() {
this.bpmnElement = null;
}
};
</script>

View File

@ -1,135 +0,0 @@
<template>
<div class="panel-tab__content">
<el-table :data="elementPropertyList" size="mini" max-height="240" border fit>
<el-table-column label="序号" width="50px" type="index" />
<el-table-column label="属性名" prop="name" min-width="100px" show-overflow-tooltip />
<el-table-column label="属性值" prop="value" min-width="100px" show-overflow-tooltip />
<el-table-column label="操作" width="90px">
<template v-slot="{ row, $index }">
<el-button size="mini" type="text" @click="openAttributesForm(row, $index)">编辑</el-button>
<el-divider direction="vertical" />
<el-button size="mini" type="text" style="color: #ff4d4f" @click="removeAttributes(row, $index)">移除</el-button>
</template>
</el-table-column>
</el-table>
<div class="element-drawer__button">
<el-button size="mini" type="primary" icon="el-icon-plus" @click="openAttributesForm(null, -1)">添加属性</el-button>
</div>
<el-dialog :visible.sync="propertyFormModelVisible" title="属性配置" width="600px" append-to-body destroy-on-close>
<el-form :model="propertyForm" label-width="80px" size="mini" ref="attributeFormRef" @submit.native.prevent>
<el-form-item label="属性名:" prop="name">
<el-input v-model="propertyForm.name" clearable />
</el-form-item>
<el-form-item label="属性值:" prop="value">
<el-input v-model="propertyForm.value" clearable />
</el-form-item>
</el-form>
<template slot="footer">
<el-button size="mini" @click="propertyFormModelVisible = false"> </el-button>
<el-button size="mini" type="primary" @click="saveAttribute"> </el-button>
</template>
</el-dialog>
</div>
</template>
<script>
export default {
name: "ElementProperties",
props: {
id: String,
type: String
},
inject: {
prefix: "prefix",
width: "width"
},
data() {
return {
elementPropertyList: [],
propertyForm: {},
editingPropertyIndex: -1,
propertyFormModelVisible: false
};
},
watch: {
id: {
immediate: true,
handler(val) {
val && val.length && this.resetAttributesList();
}
}
},
methods: {
resetAttributesList() {
this.bpmnElement = window.bpmnInstances.bpmnElement;
this.otherExtensionList = []; //
this.bpmnElementProperties =
this.bpmnElement.businessObject?.extensionElements?.values?.filter(ex => {
if (ex.$type !== `${this.prefix}:Properties`) {
this.otherExtensionList.push(ex);
}
return ex.$type === `${this.prefix}:Properties`;
}) ?? [];
//
this.bpmnElementPropertyList = this.bpmnElementProperties.reduce((pre, current) => pre.concat(current.values), []);
//
this.elementPropertyList = JSON.parse(JSON.stringify(this.bpmnElementPropertyList ?? []));
},
openAttributesForm(attr, index) {
this.editingPropertyIndex = index;
this.propertyForm = index === -1 ? {} : JSON.parse(JSON.stringify(attr));
this.propertyFormModelVisible = true;
this.$nextTick(() => {
if (this.$refs["attributeFormRef"]) this.$refs["attributeFormRef"].clearValidate();
});
},
removeAttributes(attr, index) {
this.$confirm("确认移除该属性吗?", "提示", {
confirmButtonText: "确 认",
cancelButtonText: "取 消"
})
.then(() => {
this.elementPropertyList.splice(index, 1);
this.bpmnElementPropertyList.splice(index, 1);
//
const propertiesObject = window.bpmnInstances.moddle.create(`${this.prefix}:Properties`, {
values: this.bpmnElementPropertyList
});
this.updateElementExtensions(propertiesObject);
this.resetAttributesList();
})
.catch(() => console.info("操作取消"));
},
saveAttribute() {
const { name, value } = this.propertyForm;
console.log(this.bpmnElementPropertyList);
if (this.editingPropertyIndex !== -1) {
window.bpmnInstances.modeling.updateModdleProperties(this.bpmnElement, this.bpmnElementPropertyList[this.editingPropertyIndex], {
name,
value
});
} else {
//
const newPropertyObject = window.bpmnInstances.moddle.create(`${this.prefix}:Property`, { name, value });
//
const propertiesObject = window.bpmnInstances.moddle.create(`${this.prefix}:Properties`, {
values: this.bpmnElementPropertyList.concat([newPropertyObject])
});
this.updateElementExtensions(propertiesObject);
}
this.propertyFormModelVisible = false;
this.resetAttributesList();
},
updateElementExtensions(properties) {
const extensions = window.bpmnInstances.moddle.create("bpmn:ExtensionElements", {
values: this.otherExtensionList.concat([properties])
});
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, {
extensionElements: extensions
});
}
}
};
</script>

View File

@ -1,104 +0,0 @@
<template>
<div class="panel-tab__content">
<div class="panel-tab__content--title">
<span><i class="el-icon-menu" style="margin-right: 8px; color: #555555"></i>消息列表</span>
<el-button size="mini" type="primary" icon="el-icon-plus" @click="openModel('message')">创建新消息</el-button>
</div>
<el-table :data="messageList" size="mini" border>
<el-table-column type="index" label="序号" width="60px" />
<el-table-column label="消息ID" prop="id" max-width="300px" show-overflow-tooltip />
<el-table-column label="消息名称" prop="name" max-width="300px" show-overflow-tooltip />
</el-table>
<div class="panel-tab__content--title" style="padding-top: 8px; margin-top: 8px; border-top: 1px solid #eeeeee">
<span><i class="el-icon-menu" style="margin-right: 8px; color: #555555"></i>信号列表</span>
<el-button size="mini" type="primary" icon="el-icon-plus" @click="openModel('signal')">创建新信号</el-button>
</div>
<el-table :data="signalList" size="mini" border>
<el-table-column type="index" label="序号" width="60px" />
<el-table-column label="信号ID" prop="id" max-width="300px" show-overflow-tooltip />
<el-table-column label="信号名称" prop="name" max-width="300px" show-overflow-tooltip />
</el-table>
<el-dialog :visible.sync="modelVisible" :title="modelConfig.title" :close-on-click-modal="false" width="400px" append-to-body destroy-on-close>
<el-form :model="modelObjectForm" size="mini" label-width="90px" @submit.native.prevent>
<el-form-item :label="modelConfig.idLabel">
<el-input v-model="modelObjectForm.id" clearable />
</el-form-item>
<el-form-item :label="modelConfig.nameLabel">
<el-input v-model="modelObjectForm.name" clearable />
</el-form-item>
</el-form>
<template slot="footer">
<el-button size="mini" @click="modelVisible = false"> </el-button>
<el-button size="mini" type="primary" @click="addNewObject"> </el-button>
</template>
</el-dialog>
</div>
</template>
<script>
export default {
name: "SignalAndMassage",
data() {
return {
signalList: [],
messageList: [],
modelVisible: false,
modelType: "",
modelObjectForm: {}
};
},
computed: {
modelConfig() {
if (this.modelType === "message") {
return { title: "创建消息", idLabel: "消息ID", nameLabel: "消息名称" };
} else {
return { title: "创建信号", idLabel: "信号ID", nameLabel: "信号名称" };
}
}
},
mounted() {
this.initDataList();
},
methods: {
initDataList() {
this.rootElements = window.bpmnInstances.modeler.getDefinitions().rootElements;
this.messageIdMap = {};
this.signalIdMap = {};
this.messageList = [];
this.signalList = [];
this.rootElements.forEach(el => {
if (el.$type === "bpmn:Message") {
this.messageIdMap[el.id] = true;
this.messageList.push({ ...el });
}
if (el.$type === "bpmn:Signal") {
this.signalIdMap[el.id] = true;
this.signalList.push({ ...el });
}
});
},
openModel(type) {
this.modelType = type;
this.modelObjectForm = {};
this.modelVisible = true;
},
addNewObject() {
if (this.modelType === "message") {
if (this.messageIdMap[this.modelObjectForm.id]) {
return this.$message.error("该消息已存在请修改id后重新保存");
}
const messageRef = window.bpmnInstances.moddle.create("bpmn:Message", this.modelObjectForm);
this.rootElements.push(messageRef);
} else {
if (this.signalIdMap[this.modelObjectForm.id]) {
return this.$message.error("该信号已存在请修改id后重新保存");
}
const signalRef = window.bpmnInstances.moddle.create("bpmn:Signal", this.modelObjectForm);
this.rootElements.push(signalRef);
}
this.modelVisible = false;
this.initDataList();
}
}
};
</script>

View File

@ -1,72 +0,0 @@
<template>
<div class="panel-tab__content">
<el-form size="mini" label-width="90px" @submit.native.prevent>
<el-form-item label="异步延续">
<el-checkbox v-model="taskConfigForm.asyncBefore" label="异步前" @change="changeTaskAsync" />
<el-checkbox v-model="taskConfigForm.asyncAfter" label="异步后" @change="changeTaskAsync" />
<el-checkbox v-model="taskConfigForm.exclusive" v-if="taskConfigForm.asyncAfter || taskConfigForm.asyncBefore" label="排除" @change="changeTaskAsync" />
</el-form-item>
<component :is="witchTaskComponent" v-bind="$props" />
</el-form>
</div>
</template>
<script>
import UserTask from "./task-components/UserTask";
import ScriptTask from "./task-components/ScriptTask";
import ReceiveTask from "./task-components/ReceiveTask";
export default {
name: "ElementTaskConfig",
components: { UserTask, ScriptTask, ReceiveTask },
props: {
id: String,
type: String
},
data() {
return {
taskConfigForm: {
asyncAfter: false,
asyncBefore: false,
exclusive: false
},
witchTaskComponent: "",
installedComponent: {
//
// messageRef
//
UserTask: "UserTask", //
ScriptTask: "ScriptTask", //
ReceiveTask: "ReceiveTask" //
}
};
},
watch: {
id: {
immediate: true,
handler() {
this.bpmnElement = window.bpmnInstances.bpmnElement;
this.taskConfigForm.asyncBefore = this.bpmnElement?.businessObject?.asyncBefore;
this.taskConfigForm.asyncAfter = this.bpmnElement?.businessObject?.asyncAfter;
this.taskConfigForm.exclusive = this.bpmnElement?.businessObject?.exclusive;
}
},
type: {
immediate: true,
handler() {
this.witchTaskComponent = this.installedComponent[this.type];
}
}
},
methods: {
changeTaskAsync() {
if (!this.taskConfigForm.asyncBefore && !this.taskConfigForm.asyncAfter) {
this.taskConfigForm.exclusive = false;
}
window.bpmnInstances.modeling.updateProperties(window.bpmnInstances.bpmnElement, {
...this.taskConfigForm
});
}
}
};
</script>

View File

@ -1,97 +0,0 @@
<template>
<div style="margin-top: 16px">
<el-form-item label="消息实例">
<div style="display: flex; align-items: center; justify-content: space-between; flex-wrap: nowrap">
<el-select v-model="bindMessageId" @change="updateTaskMessage">
<el-option v-for="id in Object.keys(messageMap)" :value="id" :label="messageMap[id]" :key="id" />
</el-select>
<el-button size="mini" type="primary" icon="el-icon-plus" style="margin-left: 8px" @click="openMessageModel" />
</div>
</el-form-item>
<el-dialog :visible.sync="messageModelVisible" :close-on-click-modal="false" title="创建新消息" width="400px" append-to-body destroy-on-close>
<el-form :model="newMessageForm" size="mini" label-width="90px" @submit.native.prevent>
<el-form-item label="消息ID">
<el-input v-model="newMessageForm.id" clearable />
</el-form-item>
<el-form-item label="消息名称">
<el-input v-model="newMessageForm.name" clearable />
</el-form-item>
</el-form>
<template slot="footer">
<el-button size="mini" type="primary" @click="createNewMessage"> </el-button>
</template>
</el-dialog>
</div>
</template>
<script>
export default {
name: "ReceiveTask",
props: {
id: String,
type: String
},
data() {
return {
bindMessageId: "",
newMessageForm: {},
messageMap: {},
messageModelVisible: false
};
},
watch: {
id: {
immediate: true,
handler() {
this.$nextTick(() => this.getBindMessage());
}
}
},
created() {
this.bpmnMessageRefsMap = Object.create(null);
this.bpmnRootElements = window.bpmnInstances.modeler.getDefinitions().rootElements;
this.bpmnRootElements
.filter(el => el.$type === "bpmn:Message")
.forEach(m => {
this.bpmnMessageRefsMap[m.id] = m;
this.$set(this.messageMap, m.id, m.name);
});
this.$set(this.messageMap, "-1", "无"); //
},
methods: {
getBindMessage() {
this.bpmnElement = window.bpmnInstances.bpmnElement;
this.bindMessageId = this.bpmnElement.businessObject?.messageRef?.id || "-1";
},
openMessageModel() {
this.messageModelVisible = true;
this.newMessageForm = {};
},
createNewMessage() {
if (this.messageMap[this.newMessageForm.id]) {
this.$message.error("该消息已存在请修改id后重新保存");
return;
}
const newMessage = window.bpmnInstances.moddle.create("bpmn:Message", this.newMessageForm);
this.bpmnRootElements.push(newMessage);
this.$set(this.messageMap, this.newMessageForm.id, this.newMessageForm.name);
this.bpmnMessageRefsMap[this.newMessageForm.id] = newMessage;
this.messageModelVisible = false;
},
updateTaskMessage(messageId) {
if (messageId === "-1") {
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, {
messageRef: null
});
} else {
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, {
messageRef: this.bpmnMessageRefsMap[messageId]
});
}
}
},
beforeDestroy() {
this.bpmnElement = null;
}
};
</script>

View File

@ -1,85 +0,0 @@
<template>
<div style="margin-top: 16px">
<el-form-item label="脚本格式">
<el-input v-model="scriptTaskForm.scriptFormat" clearable @input="updateElementTask()" @change="updateElementTask()" />
</el-form-item>
<el-form-item label="脚本类型">
<el-select v-model="scriptTaskForm.scriptType">
<el-option label="内联脚本" value="inline" />
<el-option label="外部资源" value="external" />
</el-select>
</el-form-item>
<el-form-item label="脚本" v-show="scriptTaskForm.scriptType === 'inline'">
<el-input
v-model="scriptTaskForm.script"
type="textarea"
resize="vertical"
:autosize="{ minRows: 2, maxRows: 4 }"
clearable
@input="updateElementTask()"
@change="updateElementTask()"
/>
</el-form-item>
<el-form-item label="资源地址" v-show="scriptTaskForm.scriptType === 'external'">
<el-input v-model="scriptTaskForm.resource" clearable @input="updateElementTask()" @change="updateElementTask()" />
</el-form-item>
<el-form-item label="结果变量">
<el-input v-model="scriptTaskForm.resultVariable" clearable @input="updateElementTask()" @change="updateElementTask()" />
</el-form-item>
</div>
</template>
<script>
export default {
name: "ScriptTask",
props: {
id: String,
type: String
},
data() {
return {
defaultTaskForm: {
scriptFormat: "",
script: "",
resource: "",
resultVariable: ""
},
scriptTaskForm: {}
};
},
watch: {
id: {
immediate: true,
handler() {
this.bpmnElement = window.bpmnInstances.bpmnElement;
this.$nextTick(() => this.resetTaskForm());
}
}
},
methods: {
resetTaskForm() {
for (let key in this.defaultTaskForm) {
let value = this.bpmnElement?.businessObject[key] || this.defaultTaskForm[key];
this.$set(this.scriptTaskForm, key, value);
}
this.$set(this.scriptTaskForm, "scriptType", this.scriptTaskForm.script ? "inline" : "external");
},
updateElementTask() {
let taskAttr = Object.create(null);
taskAttr.scriptFormat = this.scriptTaskForm.scriptFormat || null;
taskAttr.resultVariable = this.scriptTaskForm.resultVariable || null;
if (this.scriptTaskForm.scriptType === "inline") {
taskAttr.script = this.scriptTaskForm.script || null;
taskAttr.resource = null;
} else {
taskAttr.resource = this.scriptTaskForm.resource || null;
taskAttr.script = null;
}
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, taskAttr);
}
},
beforeDestroy() {
this.bpmnElement = null;
}
};
</script>

View File

@ -1,89 +0,0 @@
<template>
<div style="margin-top: 16px">
<!-- <el-form-item label="处理用户">-->
<!-- <el-select v-model="userTaskForm.assignee" @change="updateElementTask('assignee')">-->
<!-- <el-option v-for="ak in mockData" :key="'ass-' + ak" :label="`用户${ak}`" :value="`user${ak}`" />-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<!-- <el-form-item label="候选用户">-->
<!-- <el-select v-model="userTaskForm.candidateUsers" multiple collapse-tags @change="updateElementTask('candidateUsers')">-->
<!-- <el-option v-for="uk in mockData" :key="'user-' + uk" :label="`用户${uk}`" :value="`user${uk}`" />-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<!-- <el-form-item label="候选分组">-->
<!-- <el-select v-model="userTaskForm.candidateGroups" multiple collapse-tags @change="updateElementTask('candidateGroups')">-->
<!-- <el-option v-for="gk in mockData" :key="'ass-' + gk" :label="`分组${gk}`" :value="`group${gk}`" />-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<el-form-item label="到期时间">
<el-input v-model="userTaskForm.dueDate" clearable @change="updateElementTask('dueDate')" />
</el-form-item>
<el-form-item label="跟踪时间">
<el-input v-model="userTaskForm.followUpDate" clearable @change="updateElementTask('followUpDate')" />
</el-form-item>
<el-form-item label="优先级">
<el-input v-model="userTaskForm.priority" clearable @change="updateElementTask('priority')" />
</el-form-item>
友情提示任务的分配规则使用
<router-link target="_blank" :to="{path:'/bpm/manager/model'}"><el-link type="danger">流程模型</el-link> </router-link>
下的分配规则替代提供指定角色部门负责人部门成员岗位工作组自定义脚本等 7 种维护的任务分配维度更加灵活
</div>
</template>
<script>
export default {
name: "UserTask",
props: {
id: String,
type: String
},
data() {
return {
defaultTaskForm: {
assignee: "",
candidateUsers: [],
candidateGroups: [],
dueDate: "",
followUpDate: "",
priority: ""
},
userTaskForm: {},
mockData: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
};
},
watch: {
id: {
immediate: true,
handler() {
this.bpmnElement = window.bpmnInstances.bpmnElement;
this.$nextTick(() => this.resetTaskForm());
}
}
},
methods: {
resetTaskForm() {
for (let key in this.defaultTaskForm) {
let value;
if (key === "candidateUsers" || key === "candidateGroups") {
value = this.bpmnElement?.businessObject[key] ? this.bpmnElement.businessObject[key].split(",") : [];
} else {
value = this.bpmnElement?.businessObject[key] || this.defaultTaskForm[key];
}
this.$set(this.userTaskForm, key, value);
}
},
updateElementTask(key) {
const taskAttr = Object.create(null);
if (key === "candidateUsers" || key === "candidateGroups") {
taskAttr[key] = this.userTaskForm[key] && this.userTaskForm[key].length ? this.userTaskForm[key].join() : null;
} else {
taskAttr[key] = this.userTaskForm[key] || null;
}
window.bpmnInstances.modeling.updateProperties(this.bpmnElement, taskAttr);
}
},
beforeDestroy() {
this.bpmnElement = null;
}
};
</script>

View File

@ -1,70 +0,0 @@
/* 改变主题色变量 */
$--color-primary: #1890ff;
$--color-danger: #ff4d4f;
/* 改变 icon 字体路径变量,必需 */
$--font-path: '~element-ui/lib/theme-chalk/fonts';
@import "~element-ui/packages/theme-chalk/src/index";
.el-table td,
.el-table th {
color: #333;
}
.el-drawer__header {
padding: 16px 16px 8px 16px;
margin: 0;
line-height: 24px;
font-size: 18px;
color: #303133;
box-sizing: border-box;
border-bottom: 1px solid #e8e8e8;
}
div[class^="el-drawer"]:focus,
span:focus {
outline: none;
}
.el-drawer__body {
box-sizing: border-box;
padding: 16px;
width: 100%;
overflow-y: auto;
}
.el-dialog {
margin-top: 50vh !important;
transform: translateY(-50%);
overflow: hidden;
}
.el-dialog__wrapper {
overflow: hidden;
max-height: 100vh;
}
.el-dialog__header {
padding: 16px 16px 8px 16px;
box-sizing: border-box;
border-bottom: 1px solid #e8e8e8;
}
.el-dialog__body {
padding: 16px;
max-height: 80vh;
box-sizing: border-box;
overflow-y: auto;
}
.el-dialog__footer {
padding: 16px;
box-sizing: border-box;
border-top: 1px solid #e8e8e8;
}
.el-dialog__close {
font-weight: 600;
}
.el-select {
width: 100%;
}
.el-divider:not(.el-divider--horizontal) {
margin: 0 8px ;
}
.el-divider.el-divider--horizontal {
margin: 16px 0;
}

View File

@ -1,2 +0,0 @@
@import "./process-designer.scss";
@import "./process-panel.scss";

View File

@ -1,156 +0,0 @@
@import "~bpmn-js-token-simulation/assets/css/bpmn-js-token-simulation.css";
@import "~bpmn-js-token-simulation/assets/css/font-awesome.min.css";
@import "~bpmn-js-token-simulation/assets/css/normalize.css";
// 边框被 token-simulation 样式覆盖了
.djs-palette {
background: var(--palette-background-color);
border: solid 1px var(--palette-border-color) !important;
border-radius: 2px;
}
.my-process-designer {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
box-sizing: border-box;
.my-process-designer__header {
width: 100%;
min-height: 36px;
.el-button {
text-align: center;
}
.el-button-group {
margin: 4px;
}
.el-tooltip__popper {
.el-button {
width: 100%;
text-align: left;
padding-left: 8px;
padding-right: 8px;
}
.el-button:hover {
background: rgba(64, 158, 255, 0.8);
color: #ffffff;
}
}
.align {
position: relative;
i {
&:after {
content: "|";
position: absolute;
transform: rotate(90deg) translate(200%, 60%);
}
}
}
.align.align-left i {
transform: rotate(90deg);
}
.align.align-right i {
transform: rotate(-90deg);
}
.align.align-top i {
transform: rotate(180deg);
}
.align.align-bottom i {
transform: rotate(0deg);
}
.align.align-center i {
transform: rotate(90deg);
&:after {
transform: rotate(90deg) translate(0, 60%);
}
}
.align.align-middle i {
transform: rotate(0deg);
&:after {
transform: rotate(90deg) translate(0, 60%);
}
}
}
.my-process-designer__container {
display: inline-flex;
width: 100%;
flex: 1;
.my-process-designer__canvas {
flex: 1;
height: 100%;
position: relative;
background: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHBhdHRlcm4gaWQ9ImEiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgcGF0dGVyblVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHBhdGggZD0iTTAgMTBoNDBNMTAgMHY0ME0wIDIwaDQwTTIwIDB2NDBNMCAzMGg0ME0zMCAwdjQwIiBmaWxsPSJub25lIiBzdHJva2U9IiNlMGUwZTAiIG9wYWNpdHk9Ii4yIi8+PHBhdGggZD0iTTQwIDBIMHY0MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZTBlMGUwIi8+PC9wYXR0ZXJuPjwvZGVmcz48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+")
repeat !important;
div.toggle-mode {
display: none;
}
}
.my-process-designer__property-panel {
height: 100%;
overflow: scroll;
overflow-y: auto;
z-index: 10;
* {
box-sizing: border-box;
}
}
svg {
width: 100%;
height: 100%;
min-height: 100%;
overflow: hidden;
}
}
}
//侧边栏配置
.djs-palette.open {
.djs-palette-entries {
div[class^="bpmn-icon-"]:before,
div[class*="bpmn-icon-"]:before {
line-height: unset;
}
div.entry {
position: relative;
}
div.entry:hover {
&::after {
width: max-content;
content: attr(title);
vertical-align: text-bottom;
position: absolute;
right: -10px;
top: 0;
bottom: 0;
overflow: hidden;
transform: translateX(100%);
font-size: 0.5em;
display: inline-block;
text-decoration: inherit;
font-variant: normal;
text-transform: none;
background: #fafafa;
box-shadow: 0 0 6px #eeeeee;
border: 1px solid #cccccc;
box-sizing: border-box;
padding: 0 16px;
border-radius: 4px;
z-index: 100;
}
}
}
}
pre {
margin: 0;
height: 100%;
overflow: hidden;
max-height: calc(80vh - 32px);
overflow-y: auto;
}
.hljs {
word-break: break-word;
white-space: pre-wrap;
}
.hljs * {
font-family: Consolas, Monaco, monospace;
}

View File

@ -1,107 +0,0 @@
.process-panel__container {
box-sizing: border-box;
padding: 0 8px;
border-left: 1px solid #eeeeee;
box-shadow: 0 0 8px #cccccc;
max-height: 100%;
overflow-y: scroll;
}
.panel-tab__title {
font-weight: 600;
padding: 0 8px;
font-size: 1.1em;
line-height: 1.2em;
i {
margin-right: 8px;
font-size: 1.2em;
}
}
.panel-tab__content {
width: 100%;
box-sizing: border-box;
border-top: 1px solid #eeeeee;
padding: 8px 16px;
.panel-tab__content--title {
display: flex;
justify-content: space-between;
padding-bottom: 8px;
span {
flex: 1;
text-align: left;
}
}
}
.element-property {
width: 100%;
display: flex;
align-items: flex-start;
margin: 8px 0;
.element-property__label {
display: block;
width: 90px;
text-align: right;
overflow: hidden;
padding-right: 12px;
line-height: 32px;
font-size: 14px;
box-sizing: border-box;
}
.element-property__value {
flex: 1;
line-height: 32px;
}
.el-form-item {
width: 100%;
margin-bottom: 0;
padding-bottom: 18px;
}
}
.list-property {
flex-direction: column;
.element-listener-item {
width: 100%;
display: inline-grid;
grid-template-columns: 16px auto 32px 32px;
grid-column-gap: 8px;
}
.element-listener-item + .element-listener-item {
margin-top: 8px;
}
}
.listener-filed__title {
display: inline-flex;
width: 100%;
justify-content: space-between;
align-items: center;
margin-top: 0;
span {
width: 200px;
text-align: left;
font-size: 14px;
}
i {
margin-right: 8px;
}
}
.element-drawer__button {
margin-top: 8px;
width: 100%;
display: inline-flex;
justify-content: space-around;
}
.element-drawer__button > .el-button {
width: 100%;
}
.el-collapse-item__content {
padding-bottom: 0;
}
.el-input.is-disabled .el-input__inner {
color: #999999;
}
.el-form-item.el-form-item--mini {
margin-bottom: 0;
& + .el-form-item {
margin-top: 16px;
}
}

View File

@ -1,69 +0,0 @@
// 创建监听器实例
export function createListenerObject(options, isTask, prefix) {
const listenerObj = Object.create(null);
listenerObj.event = options.event;
isTask && (listenerObj.id = options.id); // 任务监听器特有的 id 字段
switch (options.listenerType) {
case "scriptListener":
listenerObj.script = createScriptObject(options, prefix);
break;
case "expressionListener":
listenerObj.expression = options.expression;
break;
case "delegateExpressionListener":
listenerObj.delegateExpression = options.delegateExpression;
break;
default:
listenerObj.class = options.class;
}
// 注入字段
if (options.fields) {
listenerObj.fields = options.fields.map(field => {
return createFieldObject(field, prefix);
});
}
// 任务监听器的 定时器 设置
if (isTask && options.event === "timeout" && !!options.eventDefinitionType) {
const timeDefinition = window.bpmnInstances.moddle.create("bpmn:FormalExpression", { body: options.eventTimeDefinitions });
const TimerEventDefinition = window.bpmnInstances.moddle.create("bpmn:TimerEventDefinition", {
id: `TimerEventDefinition_${uuid(8)}`,
[`time${options.eventDefinitionType.replace(/^\S/, s => s.toUpperCase())}`]: timeDefinition
});
listenerObj.eventDefinitions = [TimerEventDefinition];
}
return window.bpmnInstances.moddle.create(`${prefix}:${isTask ? "TaskListener" : "ExecutionListener"}`, listenerObj);
}
// 创建 监听器的注入字段 实例
export function createFieldObject(option, prefix) {
const { name, fieldType, string, expression } = option;
const fieldConfig = fieldType === "string" ? { name, string } : { name, expression };
return window.bpmnInstances.moddle.create(`${prefix}:Field`, fieldConfig);
}
// 创建脚本实例
export function createScriptObject(options, prefix) {
const { scriptType, scriptFormat, value, resource } = options;
const scriptConfig = scriptType === "inlineScript" ? { scriptFormat, value } : { scriptFormat, resource };
return window.bpmnInstances.moddle.create(`${prefix}:Script`, scriptConfig);
}
// 更新元素扩展属性
export function updateElementExtensions(element, extensionList) {
const extensions = window.bpmnInstances.moddle.create("bpmn:ExtensionElements", {
values: extensionList
});
window.bpmnInstances.modeling.updateProperties(element, {
extensionElements: extensions
});
}
// 创建一个id
export function uuid(length = 8, chars) {
let result = "";
let charsString = chars || "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (let i = length; i > 0; --i) {
result += charsString[Math.floor(Math.random() * charsString.length)];
}
return result;
}

View File

@ -1,5 +0,0 @@
const hljs = require("highlight.js/lib/core");
hljs.registerLanguage("xml", require("highlight.js/lib/languages/xml"));
hljs.registerLanguage("json", require("highlight.js/lib/languages/json"));
module.exports = hljs;

View File

@ -1,14 +0,0 @@
import BpmnRenderer from "bpmn-js/lib/draw/BpmnRenderer";
export default function CustomRenderer(config, eventBus, styles, pathMap, canvas, textRenderer) {
BpmnRenderer.call(this, config, eventBus, styles, pathMap, canvas, textRenderer, 2000);
this.handlers["label"] = function() {
return null;
};
}
const F = function() {}; // 核心,利用空对象作为中介;
F.prototype = BpmnRenderer.prototype; // 核心将父类的原型赋值给空对象F
CustomRenderer.prototype = new F(); // 核心,将 F的实例赋值给子类
CustomRenderer.prototype.constructor = CustomRenderer; // 修复子类CustomRenderer的构造器指向防止原型链的混乱

View File

@ -1,6 +0,0 @@
import CustomRenderer from "./CustomRenderer";
export default {
__init__: ["customRenderer"],
customRenderer: ["type", CustomRenderer]
};

View File

@ -1,16 +0,0 @@
import BpmnRules from "bpmn-js/lib/features/rules/BpmnRules";
import inherits from "inherits";
export default function CustomRules(eventBus) {
BpmnRules.call(this, eventBus);
}
inherits(CustomRules, BpmnRules);
CustomRules.prototype.canDrop = function() {
return false;
};
CustomRules.prototype.canMove = function() {
return false;
};

View File

@ -1,6 +0,0 @@
import CustomRules from "./CustomRules";
export default {
__init__: ["customRules"],
customRules: ["type", CustomRules]
};

View File

@ -1,25 +0,0 @@
/**
* This is a sample file that should be replaced with the actual translation.
*
* Checkout https://github.com/bpmn-io/bpmn-js-i18n for a list of available
* translations and labels to translate.
*/
export default {
"Exclusive Gateway": "Exklusives Gateway",
"Parallel Gateway": "Paralleles Gateway",
"Inclusive Gateway": "Inklusives Gateway",
"Complex Gateway": "Komplexes Gateway",
"Event based Gateway": "Ereignis-basiertes Gateway",
"Message Start Event": "消息启动事件",
"Timer Start Event": "定时启动事件",
"Conditional Start Event": "条件启动事件",
"Signal Start Event": "信号启动事件",
"Error Start Event": "错误启动事件",
"Escalation Start Event": "升级启动事件",
"Compensation Start Event": "补偿启动事件",
"Message Start Event (non-interrupting)": "消息启动事件 (非中断)",
"Timer Start Event (non-interrupting)": "定时启动事件 (非中断)",
"Conditional Start Event (non-interrupting)": "条件启动事件 (非中断)",
"Signal Start Event (non-interrupting)": "信号启动事件 (非中断)",
"Escalation Start Event (non-interrupting)": "升级启动事件 (非中断)"
};

View File

@ -1,39 +0,0 @@
//outside.js
const ctx = "@@clickoutsideContext";
export default {
bind(el, binding, vnode) {
const ele = el;
const documentHandler = e => {
if (!vnode.context || ele.contains(e.target)) {
return false;
}
// 调用指令回调
if (binding.expression) {
vnode.context[el[ctx].methodName](e);
} else {
el[ctx].bindingFn(e);
}
};
// 将方法添加到ele
ele[ctx] = {
documentHandler,
methodName: binding.expression,
bindingFn: binding.value
};
setTimeout(() => {
document.addEventListener("touchstart", documentHandler); // 为document绑定事件
});
},
update(el, binding) {
const ele = el;
ele[ctx].methodName = binding.expression;
ele[ctx].bindingFn = binding.value;
},
unbind(el) {
document.removeEventListener("touchstart", el[ctx].documentHandler); // 解绑
delete el[ctx];
}
};

View File

@ -1,10 +0,0 @@
export function debounce(fn, delay = 500) {
let timer;
return function(...args) {
if (timer) {
clearTimeout(timer);
timer = null;
}
timer = setTimeout(fn.bind(this, ...args), delay);
};
}

View File

@ -1,63 +0,0 @@
class Log {
static type = ["primary", "success", "warn", "error", "info"];
static typeColor(type = "default") {
let color = "";
switch (type) {
case "primary":
color = "#2d8cf0";
break;
case "success":
color = "#19be6b";
break;
case "info":
color = "#909399";
break;
case "warn":
color = "#ff9900";
break;
case "error":
color = "#f03f14";
break;
case "default":
color = "#35495E";
break;
default:
color = type;
break;
}
return color;
}
static print(text, type = "default", back = false) {
if (typeof text === "object") {
// 如果是對象則調用打印對象方式
console.dir(text);
return;
}
if (back) {
// 如果是打印帶背景圖的
console.log(`%c ${text} `, `background:${this.typeColor(type)}; padding: 2px; border-radius: 4px;color: #fff;`);
} else {
console.log(`%c ${text} `, `color: ${this.typeColor(type)};`);
}
}
static pretty(title, text, type = "primary") {
if (typeof text === "object") {
console.log(
`%c ${title} %c`,
`background:${this.typeColor(type)};border:1px solid ${this.typeColor(type)}; padding: 1px; border-radius: 4px 0 0 4px; color: #fff;`
);
console.dir(text);
return;
}
console.log(
`%c ${title} %c ${text} %c`,
`background:${this.typeColor(type)};border:1px solid ${this.typeColor(type)}; padding: 1px; border-radius: 4px 0 0 4px; color: #fff;`,
`border:1px solid ${this.typeColor(type)}; padding: 1px; border-radius: 0 4px 4px 0; color: ${this.typeColor(type)};`,
"background:transparent"
);
}
}
export default Log;

View File

@ -1,50 +0,0 @@
function xmlStr2XmlObj(xmlStr) {
let xmlObj = {};
if (document.all) {
const xmlDom = new window.ActiveXObject("Microsoft.XMLDOM");
xmlDom.loadXML(xmlStr);
xmlObj = xmlDom;
} else {
xmlObj = new DOMParser().parseFromString(xmlStr, "text/xml");
}
return xmlObj;
}
function xml2json(xml) {
try {
let obj = {};
if (xml.children.length > 0) {
for (let i = 0; i < xml.children.length; i++) {
const item = xml.children.item(i);
const nodeName = item.nodeName;
if (typeof obj[nodeName] == "undefined") {
obj[nodeName] = xml2json(item);
} else {
if (typeof obj[nodeName].push == "undefined") {
const old = obj[nodeName];
obj[nodeName] = [];
obj[nodeName].push(old);
}
obj[nodeName].push(xml2json(item));
}
}
} else {
obj = xml.textContent;
}
return obj;
} catch (e) {
console.log(e.message);
}
}
function xmlObj2json(xml) {
const xmlObj = xmlStr2XmlObj(xml);
console.log(xmlObj);
let jsonObj = {};
if (xmlObj.childNodes.length > 0) {
jsonObj = xml2json(xmlObj);
}
return jsonObj;
}
export default xmlObj2json;

View File

@ -1,630 +0,0 @@
// 表单属性【右面板】
export const formConf = {
formRef: 'elForm',
formModel: 'formData',
size: 'medium',
labelPosition: 'right',
labelWidth: 100,
formRules: 'rules',
gutter: 15,
disabled: false,
span: 24,
formBtns: true
}
// 输入型组件 【左面板】
export const inputComponents = [
{
// 组件的自定义配置
__config__: {
label: '单行文本',
labelWidth: null,
showLabel: true,
changeTag: true,
tag: 'el-input',
tagIcon: 'input',
defaultValue: undefined,
required: true,
layout: 'colFormItem',
span: 24,
document: 'https://element.eleme.cn/#/zh-CN/component/input',
// 正则校验规则
regList: []
},
// 组件的插槽属性
__slot__: {
prepend: '',
append: ''
},
// 其余的为可直接写在组件标签上的属性
placeholder: '请输入',
style: { width: '100%' },
clearable: true,
'prefix-icon': '',
'suffix-icon': '',
maxlength: null,
'show-word-limit': false,
readonly: false,
disabled: false
},
{
__config__: {
label: '多行文本',
labelWidth: null,
showLabel: true,
tag: 'el-input',
tagIcon: 'textarea',
defaultValue: undefined,
required: true,
layout: 'colFormItem',
span: 24,
regList: [],
changeTag: true,
document: 'https://element.eleme.cn/#/zh-CN/component/input'
},
type: 'textarea',
placeholder: '请输入',
autosize: {
minRows: 4,
maxRows: 4
},
style: { width: '100%' },
maxlength: null,
'show-word-limit': false,
readonly: false,
disabled: false
},
{
__config__: {
label: '密码',
showLabel: true,
labelWidth: null,
changeTag: true,
tag: 'el-input',
tagIcon: 'password',
defaultValue: undefined,
layout: 'colFormItem',
span: 24,
required: true,
regList: [],
document: 'https://element.eleme.cn/#/zh-CN/component/input'
},
__slot__: {
prepend: '',
append: ''
},
placeholder: '请输入',
'show-password': true,
style: { width: '100%' },
clearable: true,
'prefix-icon': '',
'suffix-icon': '',
maxlength: null,
'show-word-limit': false,
readonly: false,
disabled: false
},
{
__config__: {
label: '计数器',
showLabel: true,
changeTag: true,
labelWidth: null,
tag: 'el-input-number',
tagIcon: 'number',
defaultValue: undefined,
span: 24,
layout: 'colFormItem',
required: true,
regList: [],
document: 'https://element.eleme.cn/#/zh-CN/component/input-number'
},
placeholder: '',
min: undefined,
max: undefined,
step: 1,
'step-strictly': false,
precision: undefined,
'controls-position': '',
disabled: false
},
{
__config__: {
label: '编辑器',
showLabel: true,
changeTag: true,
labelWidth: null,
tag: 'tinymce',
tagIcon: 'rich-text',
defaultValue: null,
span: 24,
layout: 'colFormItem',
required: true,
regList: [],
document: 'http://tinymce.ax-z.cn'
},
placeholder: '请输入',
height: 300, // 编辑器高度
branding: false // 隐藏右下角品牌烙印
}
]
// 选择型组件 【左面板】
export const selectComponents = [
{
__config__: {
label: '下拉选择',
showLabel: true,
labelWidth: null,
tag: 'el-select',
tagIcon: 'select',
layout: 'colFormItem',
span: 24,
required: true,
regList: [],
changeTag: true,
document: 'https://element.eleme.cn/#/zh-CN/component/select'
},
__slot__: {
options: [{
label: '选项一',
value: 1
}, {
label: '选项二',
value: 2
}]
},
placeholder: '请选择',
style: { width: '100%' },
clearable: true,
disabled: false,
filterable: false,
multiple: false
},
{
__config__: {
label: '级联选择',
url: 'https://www.fastmock.site/mock/f8d7a54fb1e60561e2f720d5a810009d/fg/cascaderList',
method: 'get',
dataPath: 'list',
dataConsumer: 'options',
showLabel: true,
labelWidth: null,
tag: 'el-cascader',
tagIcon: 'cascader',
layout: 'colFormItem',
defaultValue: [],
dataType: 'dynamic',
span: 24,
required: true,
regList: [],
changeTag: true,
document: 'https://element.eleme.cn/#/zh-CN/component/cascader'
},
options: [{
id: 1,
value: 1,
label: '选项1',
children: [{
id: 2,
value: 2,
label: '选项1-1'
}]
}],
placeholder: '请选择',
style: { width: '100%' },
props: {
props: {
multiple: false,
label: 'label',
value: 'value',
children: 'children'
}
},
'show-all-levels': true,
disabled: false,
clearable: true,
filterable: false,
separator: '/'
},
{
__config__: {
label: '单选框组',
labelWidth: null,
showLabel: true,
tag: 'el-radio-group',
tagIcon: 'radio',
changeTag: true,
defaultValue: undefined,
layout: 'colFormItem',
span: 24,
optionType: 'default',
regList: [],
required: true,
border: false,
document: 'https://element.eleme.cn/#/zh-CN/component/radio'
},
__slot__: {
options: [{
label: '选项一',
value: 1
}, {
label: '选项二',
value: 2
}]
},
style: {},
size: 'medium',
disabled: false
},
{
__config__: {
label: '多选框组',
tag: 'el-checkbox-group',
tagIcon: 'checkbox',
defaultValue: [],
span: 24,
showLabel: true,
labelWidth: null,
layout: 'colFormItem',
optionType: 'default',
required: true,
regList: [],
changeTag: true,
border: false,
document: 'https://element.eleme.cn/#/zh-CN/component/checkbox'
},
__slot__: {
options: [{
label: '选项一',
value: 1
}, {
label: '选项二',
value: 2
}]
},
style: {},
size: 'medium',
min: null,
max: null,
disabled: false
},
{
__config__: {
label: '开关',
tag: 'el-switch',
tagIcon: 'switch',
defaultValue: false,
span: 24,
showLabel: true,
labelWidth: null,
layout: 'colFormItem',
required: true,
regList: [],
changeTag: true,
document: 'https://element.eleme.cn/#/zh-CN/component/switch'
},
style: {},
disabled: false,
'active-text': '',
'inactive-text': '',
'active-color': null,
'inactive-color': null,
'active-value': true,
'inactive-value': false
},
{
__config__: {
label: '滑块',
tag: 'el-slider',
tagIcon: 'slider',
defaultValue: null,
span: 24,
showLabel: true,
layout: 'colFormItem',
labelWidth: null,
required: true,
regList: [],
changeTag: true,
document: 'https://element.eleme.cn/#/zh-CN/component/slider'
},
disabled: false,
min: 0,
max: 100,
step: 1,
'show-stops': false,
range: false
},
{
__config__: {
label: '时间选择',
tag: 'el-time-picker',
tagIcon: 'time',
defaultValue: null,
span: 24,
showLabel: true,
layout: 'colFormItem',
labelWidth: null,
required: true,
regList: [],
changeTag: true,
document: 'https://element.eleme.cn/#/zh-CN/component/time-picker'
},
placeholder: '请选择',
style: { width: '100%' },
disabled: false,
clearable: true,
'picker-options': {
selectableRange: '00:00:00-23:59:59'
},
format: 'HH:mm:ss',
'value-format': 'HH:mm:ss'
},
{
__config__: {
label: '时间范围',
tag: 'el-time-picker',
tagIcon: 'time-range',
span: 24,
showLabel: true,
labelWidth: null,
layout: 'colFormItem',
defaultValue: null,
required: true,
regList: [],
changeTag: true,
document: 'https://element.eleme.cn/#/zh-CN/component/time-picker'
},
style: { width: '100%' },
disabled: false,
clearable: true,
'is-range': true,
'range-separator': '至',
'start-placeholder': '开始时间',
'end-placeholder': '结束时间',
format: 'HH:mm:ss',
'value-format': 'HH:mm:ss'
},
{
__config__: {
label: '日期选择',
tag: 'el-date-picker',
tagIcon: 'date',
defaultValue: null,
showLabel: true,
labelWidth: null,
span: 24,
layout: 'colFormItem',
required: true,
regList: [],
changeTag: true,
document: 'https://element.eleme.cn/#/zh-CN/component/date-picker'
},
placeholder: '请选择',
type: 'date',
style: { width: '100%' },
disabled: false,
clearable: true,
format: 'yyyy-MM-dd',
'value-format': 'yyyy-MM-dd',
readonly: false
},
{
__config__: {
label: '日期范围',
tag: 'el-date-picker',
tagIcon: 'date-range',
defaultValue: null,
span: 24,
showLabel: true,
labelWidth: null,
required: true,
layout: 'colFormItem',
regList: [],
changeTag: true,
document: 'https://element.eleme.cn/#/zh-CN/component/date-picker'
},
style: { width: '100%' },
type: 'daterange',
'range-separator': '至',
'start-placeholder': '开始日期',
'end-placeholder': '结束日期',
disabled: false,
clearable: true,
format: 'yyyy-MM-dd',
'value-format': 'yyyy-MM-dd',
readonly: false
},
{
__config__: {
label: '评分',
tag: 'el-rate',
tagIcon: 'rate',
defaultValue: 0,
span: 24,
showLabel: true,
labelWidth: null,
layout: 'colFormItem',
required: true,
regList: [],
changeTag: true,
document: 'https://element.eleme.cn/#/zh-CN/component/rate'
},
style: {},
max: 5,
'allow-half': false,
'show-text': false,
'show-score': false,
disabled: false
},
{
__config__: {
label: '颜色选择',
tag: 'el-color-picker',
tagIcon: 'color',
span: 24,
defaultValue: null,
showLabel: true,
labelWidth: null,
layout: 'colFormItem',
required: true,
regList: [],
changeTag: true,
document: 'https://element.eleme.cn/#/zh-CN/component/color-picker'
},
'show-alpha': false,
'color-format': '',
disabled: false,
size: 'medium'
},
{
__config__: {
label: '上传',
tag: 'el-upload',
tagIcon: 'upload',
layout: 'colFormItem',
defaultValue: null,
showLabel: true,
labelWidth: null,
required: true,
span: 24,
showTip: false,
buttonText: '点击上传',
regList: [],
changeTag: true,
fileSize: 2,
sizeUnit: 'MB',
document: 'https://element.eleme.cn/#/zh-CN/component/upload'
},
__slot__: {
'list-type': true
},
// action: process.env.VUE_APP_BASE_API + "/admin-api/infra/file/upload", // 请求地址
action: '/infra/file/upload', // 请求地址
disabled: false,
accept: '',
name: 'file',
'auto-upload': true,
'list-type': 'text',
multiple: false
}
]
// 布局型组件 【左面板】
export const layoutComponents = [
{
__config__: {
layout: 'rowFormItem',
tagIcon: 'row',
label: '行容器',
layoutTree: true,
document: 'https://element.eleme.cn/#/zh-CN/component/layout#row-attributes'
},
type: 'default',
justify: 'start',
align: 'top'
},
{
__config__: {
label: '按钮',
showLabel: true,
changeTag: true,
labelWidth: null,
tag: 'el-button',
tagIcon: 'button',
span: 24,
layout: 'colFormItem',
document: 'https://element.eleme.cn/#/zh-CN/component/button'
},
__slot__: {
default: '主要按钮'
},
type: 'primary',
icon: 'el-icon-search',
round: false,
size: 'medium',
plain: false,
circle: false,
disabled: false
},
{
__config__: {
layout: 'colFormItem',
tagIcon: 'table',
tag: 'el-table',
document: 'https://element.eleme.cn/#/zh-CN/component/table',
span: 24,
formId: 101,
renderKey: 1595761764203,
componentName: 'row101',
showLabel: true,
changeTag: true,
labelWidth: null,
label: '表格[开发中]',
dataType: 'dynamic',
method: 'get',
dataPath: 'list',
dataConsumer: 'data',
url: 'https://www.fastmock.site/mock/f8d7a54fb1e60561e2f720d5a810009d/fg/tableData',
children: [{
__config__: {
layout: 'raw',
tag: 'el-table-column',
renderKey: 15957617660153
},
prop: 'date',
label: '日期'
}, {
__config__: {
layout: 'raw',
tag: 'el-table-column',
renderKey: 15957617660152
},
prop: 'address',
label: '地址'
}, {
__config__: {
layout: 'raw',
tag: 'el-table-column',
renderKey: 15957617660151
},
prop: 'name',
label: '名称'
}, {
__config__: {
layout: 'raw',
tag: 'el-table-column',
renderKey: 1595774496335,
children: [
{
__config__: {
label: '按钮',
tag: 'el-button',
tagIcon: 'button',
layout: 'raw',
renderKey: 1595779809901
},
__slot__: {
default: '主要按钮'
},
type: 'primary',
icon: 'el-icon-search',
round: false,
size: 'medium'
}
]
},
label: '操作'
}]
},
data: [],
directives: [{
name: 'loading',
value: true
}],
border: true,
type: 'default',
justify: 'start',
align: 'top'
}
]

View File

@ -1,18 +0,0 @@
const styles = {
'el-rate': '.el-rate{display: inline-block; vertical-align: text-top;}',
'el-upload': '.el-upload__tip{line-height: 1.2;}'
}
function addCss(cssList, el) {
const css = styles[el.__config__.tag]
css && cssList.indexOf(css) === -1 && cssList.push(css)
if (el.__config__.children) {
el.__config__.children.forEach(el2 => addCss(cssList, el2))
}
}
export function makeUpCss(conf) {
const cssList = []
conf.fields.forEach(el => addCss(cssList, el))
return cssList.join('\n')
}

View File

@ -1,37 +0,0 @@
export default [
{
__config__: {
label: '单行文本',
labelWidth: null,
showLabel: true,
changeTag: true,
tag: 'el-input',
tagIcon: 'input',
defaultValue: undefined,
required: true,
layout: 'colFormItem',
span: 24,
document: 'https://element.eleme.cn/#/zh-CN/component/input',
// 正则校验规则
regList: [{
pattern: '/^1(3|4|5|7|8|9)\\d{9}$/',
message: '手机号格式错误'
}]
},
// 组件的插槽属性
__slot__: {
prepend: '',
append: ''
},
__vModel__: 'mobile',
placeholder: '请输入手机号',
style: { width: '100%' },
clearable: true,
'prefix-icon': 'el-icon-mobile',
'suffix-icon': '',
maxlength: 11,
'show-word-limit': true,
readonly: false,
disabled: false
}
]

View File

@ -1,399 +0,0 @@
/* eslint-disable max-len */
import ruleTrigger from './ruleTrigger'
let confGlobal
let someSpanIsNot24
export function dialogWrapper(str) {
return `<el-dialog v-bind="$attrs" v-on="$listeners" @open="onOpen" @close="onClose" title="Dialog Titile">
${str}
<div slot="footer">
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="handelConfirm">确定</el-button>
</div>
</el-dialog>`
}
export function vueTemplate(str) {
return `<template>
<div>
${str}
</div>
</template>`
}
export function vueScript(str) {
return `<script>
${str}
</script>`
}
export function cssStyle(cssStr) {
return `<style>
${cssStr}
</style>`
}
function buildFormTemplate(scheme, child, type) {
let labelPosition = ''
if (scheme.labelPosition !== 'right') {
labelPosition = `label-position="${scheme.labelPosition}"`
}
const disabled = scheme.disabled ? `:disabled="${scheme.disabled}"` : ''
let str = `<el-form ref="${scheme.formRef}" :model="${scheme.formModel}" :rules="${scheme.formRules}" size="${scheme.size}" ${disabled} label-width="${scheme.labelWidth}px" ${labelPosition}>
${child}
${buildFromBtns(scheme, type)}
</el-form>`
if (someSpanIsNot24) {
str = `<el-row :gutter="${scheme.gutter}">
${str}
</el-row>`
}
return str
}
function buildFromBtns(scheme, type) {
let str = ''
if (scheme.formBtns && type === 'file') {
str = `<el-form-item size="large">
<el-button type="primary" @click="submitForm">提交</el-button>
<el-button @click="resetForm">重置</el-button>
</el-form-item>`
if (someSpanIsNot24) {
str = `<el-col :span="24">
${str}
</el-col>`
}
}
return str
}
// span不为24的用el-col包裹
function colWrapper(scheme, str) {
if (someSpanIsNot24 || scheme.__config__.span !== 24) {
return `<el-col :span="${scheme.__config__.span}">
${str}
</el-col>`
}
return str
}
const layouts = {
colFormItem(scheme) {
const config = scheme.__config__
let labelWidth = ''
let label = `label="${config.label}"`
if (config.labelWidth && config.labelWidth !== confGlobal.labelWidth) {
labelWidth = `label-width="${config.labelWidth}px"`
}
if (config.showLabel === false) {
labelWidth = 'label-width="0"'
label = ''
}
const required = !ruleTrigger[config.tag] && config.required ? 'required' : ''
const tagDom = tags[config.tag] ? tags[config.tag](scheme) : null
let str = `<el-form-item ${labelWidth} ${label} prop="${scheme.__vModel__}" ${required}>
${tagDom}
</el-form-item>`
str = colWrapper(scheme, str)
return str
},
rowFormItem(scheme) {
const config = scheme.__config__
const type = scheme.type === 'default' ? '' : `type="${scheme.type}"`
const justify = scheme.type === 'default' ? '' : `justify="${scheme.justify}"`
const align = scheme.type === 'default' ? '' : `align="${scheme.align}"`
const gutter = scheme.gutter ? `:gutter="${scheme.gutter}"` : ''
const children = config.children.map(el => layouts[el.__config__.layout](el))
let str = `<el-row ${type} ${justify} ${align} ${gutter}>
${children.join('\n')}
</el-row>`
str = colWrapper(scheme, str)
return str
}
}
const tags = {
'el-button': el => {
const {
tag, disabled
} = attrBuilder(el)
const type = el.type ? `type="${el.type}"` : ''
const icon = el.icon ? `icon="${el.icon}"` : ''
const round = el.round ? 'round' : ''
const size = el.size ? `size="${el.size}"` : ''
const plain = el.plain ? 'plain' : ''
const circle = el.circle ? 'circle' : ''
let child = buildElButtonChild(el)
if (child) child = `\n${child}\n` // 换行
return `<${tag} ${type} ${icon} ${round} ${size} ${plain} ${disabled} ${circle}>${child}</${tag}>`
},
'el-input': el => {
const {
tag, disabled, vModel, clearable, placeholder, width
} = attrBuilder(el)
const maxlength = el.maxlength ? `:maxlength="${el.maxlength}"` : ''
const showWordLimit = el['show-word-limit'] ? 'show-word-limit' : ''
const readonly = el.readonly ? 'readonly' : ''
const prefixIcon = el['prefix-icon'] ? `prefix-icon='${el['prefix-icon']}'` : ''
const suffixIcon = el['suffix-icon'] ? `suffix-icon='${el['suffix-icon']}'` : ''
const showPassword = el['show-password'] ? 'show-password' : ''
const type = el.type ? `type="${el.type}"` : ''
const autosize = el.autosize && el.autosize.minRows
? `:autosize="{minRows: ${el.autosize.minRows}, maxRows: ${el.autosize.maxRows}}"`
: ''
let child = buildElInputChild(el)
if (child) child = `\n${child}\n` // 换行
return `<${tag} ${vModel} ${type} ${placeholder} ${maxlength} ${showWordLimit} ${readonly} ${disabled} ${clearable} ${prefixIcon} ${suffixIcon} ${showPassword} ${autosize} ${width}>${child}</${tag}>`
},
'el-input-number': el => {
const {
tag, disabled, vModel, placeholder
} = attrBuilder(el)
const controlsPosition = el['controls-position'] ? `controls-position=${el['controls-position']}` : ''
const min = el.min ? `:min='${el.min}'` : ''
const max = el.max ? `:max='${el.max}'` : ''
const step = el.step ? `:step='${el.step}'` : ''
const stepStrictly = el['step-strictly'] ? 'step-strictly' : ''
const precision = el.precision ? `:precision='${el.precision}'` : ''
return `<${tag} ${vModel} ${placeholder} ${step} ${stepStrictly} ${precision} ${controlsPosition} ${min} ${max} ${disabled}></${tag}>`
},
'el-select': el => {
const {
tag, disabled, vModel, clearable, placeholder, width
} = attrBuilder(el)
const filterable = el.filterable ? 'filterable' : ''
const multiple = el.multiple ? 'multiple' : ''
let child = buildElSelectChild(el)
if (child) child = `\n${child}\n` // 换行
return `<${tag} ${vModel} ${placeholder} ${disabled} ${multiple} ${filterable} ${clearable} ${width}>${child}</${tag}>`
},
'el-radio-group': el => {
const { tag, disabled, vModel } = attrBuilder(el)
const size = `size="${el.size}"`
let child = buildElRadioGroupChild(el)
if (child) child = `\n${child}\n` // 换行
return `<${tag} ${vModel} ${size} ${disabled}>${child}</${tag}>`
},
'el-checkbox-group': el => {
const { tag, disabled, vModel } = attrBuilder(el)
const size = `size="${el.size}"`
const min = el.min ? `:min="${el.min}"` : ''
const max = el.max ? `:max="${el.max}"` : ''
let child = buildElCheckboxGroupChild(el)
if (child) child = `\n${child}\n` // 换行
return `<${tag} ${vModel} ${min} ${max} ${size} ${disabled}>${child}</${tag}>`
},
'el-switch': el => {
const { tag, disabled, vModel } = attrBuilder(el)
const activeText = el['active-text'] ? `active-text="${el['active-text']}"` : ''
const inactiveText = el['inactive-text'] ? `inactive-text="${el['inactive-text']}"` : ''
const activeColor = el['active-color'] ? `active-color="${el['active-color']}"` : ''
const inactiveColor = el['inactive-color'] ? `inactive-color="${el['inactive-color']}"` : ''
const activeValue = el['active-value'] !== true ? `:active-value='${JSON.stringify(el['active-value'])}'` : ''
const inactiveValue = el['inactive-value'] !== false ? `:inactive-value='${JSON.stringify(el['inactive-value'])}'` : ''
return `<${tag} ${vModel} ${activeText} ${inactiveText} ${activeColor} ${inactiveColor} ${activeValue} ${inactiveValue} ${disabled}></${tag}>`
},
'el-cascader': el => {
const {
tag, disabled, vModel, clearable, placeholder, width
} = attrBuilder(el)
const options = el.options ? `:options="${el.__vModel__}Options"` : ''
const props = el.props ? `:props="${el.__vModel__}Props"` : ''
const showAllLevels = el['show-all-levels'] ? '' : ':show-all-levels="false"'
const filterable = el.filterable ? 'filterable' : ''
const separator = el.separator === '/' ? '' : `separator="${el.separator}"`
return `<${tag} ${vModel} ${options} ${props} ${width} ${showAllLevels} ${placeholder} ${separator} ${filterable} ${clearable} ${disabled}></${tag}>`
},
'el-slider': el => {
const { tag, disabled, vModel } = attrBuilder(el)
const min = el.min ? `:min='${el.min}'` : ''
const max = el.max ? `:max='${el.max}'` : ''
const step = el.step ? `:step='${el.step}'` : ''
const range = el.range ? 'range' : ''
const showStops = el['show-stops'] ? `:show-stops="${el['show-stops']}"` : ''
return `<${tag} ${min} ${max} ${step} ${vModel} ${range} ${showStops} ${disabled}></${tag}>`
},
'el-time-picker': el => {
const {
tag, disabled, vModel, clearable, placeholder, width
} = attrBuilder(el)
const startPlaceholder = el['start-placeholder'] ? `start-placeholder="${el['start-placeholder']}"` : ''
const endPlaceholder = el['end-placeholder'] ? `end-placeholder="${el['end-placeholder']}"` : ''
const rangeSeparator = el['range-separator'] ? `range-separator="${el['range-separator']}"` : ''
const isRange = el['is-range'] ? 'is-range' : ''
const format = el.format ? `format="${el.format}"` : ''
const valueFormat = el['value-format'] ? `value-format="${el['value-format']}"` : ''
const pickerOptions = el['picker-options'] ? `:picker-options='${JSON.stringify(el['picker-options'])}'` : ''
return `<${tag} ${vModel} ${isRange} ${format} ${valueFormat} ${pickerOptions} ${width} ${placeholder} ${startPlaceholder} ${endPlaceholder} ${rangeSeparator} ${clearable} ${disabled}></${tag}>`
},
'el-date-picker': el => {
const {
tag, disabled, vModel, clearable, placeholder, width
} = attrBuilder(el)
const startPlaceholder = el['start-placeholder'] ? `start-placeholder="${el['start-placeholder']}"` : ''
const endPlaceholder = el['end-placeholder'] ? `end-placeholder="${el['end-placeholder']}"` : ''
const rangeSeparator = el['range-separator'] ? `range-separator="${el['range-separator']}"` : ''
const format = el.format ? `format="${el.format}"` : ''
const valueFormat = el['value-format'] ? `value-format="${el['value-format']}"` : ''
const type = el.type === 'date' ? '' : `type="${el.type}"`
const readonly = el.readonly ? 'readonly' : ''
return `<${tag} ${type} ${vModel} ${format} ${valueFormat} ${width} ${placeholder} ${startPlaceholder} ${endPlaceholder} ${rangeSeparator} ${clearable} ${readonly} ${disabled}></${tag}>`
},
'el-rate': el => {
const { tag, disabled, vModel } = attrBuilder(el)
const max = el.max ? `:max='${el.max}'` : ''
const allowHalf = el['allow-half'] ? 'allow-half' : ''
const showText = el['show-text'] ? 'show-text' : ''
const showScore = el['show-score'] ? 'show-score' : ''
return `<${tag} ${vModel} ${max} ${allowHalf} ${showText} ${showScore} ${disabled}></${tag}>`
},
'el-color-picker': el => {
const { tag, disabled, vModel } = attrBuilder(el)
const size = `size="${el.size}"`
const showAlpha = el['show-alpha'] ? 'show-alpha' : ''
const colorFormat = el['color-format'] ? `color-format="${el['color-format']}"` : ''
return `<${tag} ${vModel} ${size} ${showAlpha} ${colorFormat} ${disabled}></${tag}>`
},
'el-upload': el => {
const { tag } = el.__config__
const disabled = el.disabled ? ':disabled=\'true\'' : ''
const action = el.action ? `:action="${el.__vModel__}Action"` : ''
const multiple = el.multiple ? 'multiple' : ''
const listType = el['list-type'] !== 'text' ? `list-type="${el['list-type']}"` : ''
const accept = el.accept ? `accept="${el.accept}"` : ''
const name = el.name !== 'file' ? `name="${el.name}"` : ''
const autoUpload = el['auto-upload'] === false ? ':auto-upload="false"' : ''
const beforeUpload = `:before-upload="${el.__vModel__}BeforeUpload"`
const fileList = `:file-list="${el.__vModel__}fileList"`
const ref = `ref="${el.__vModel__}"`
let child = buildElUploadChild(el)
if (child) child = `\n${child}\n` // 换行
return `<${tag} ${ref} ${fileList} ${action} ${autoUpload} ${multiple} ${beforeUpload} ${listType} ${accept} ${name} ${disabled}>${child}</${tag}>`
},
tinymce: el => {
const { tag, vModel, placeholder } = attrBuilder(el)
const height = el.height ? `:height="${el.height}"` : ''
const branding = el.branding ? `:branding="${el.branding}"` : ''
return `<${tag} ${vModel} ${placeholder} ${height} ${branding}></${tag}>`
}
}
function attrBuilder(el) {
return {
tag: el.__config__.tag,
vModel: `v-model="${confGlobal.formModel}.${el.__vModel__}"`,
clearable: el.clearable ? 'clearable' : '',
placeholder: el.placeholder ? `placeholder="${el.placeholder}"` : '',
width: el.style && el.style.width ? ':style="{width: \'100%\'}"' : '',
disabled: el.disabled ? ':disabled=\'true\'' : ''
}
}
// el-buttin 子级
function buildElButtonChild(scheme) {
const children = []
const slot = scheme.__slot__ || {}
if (slot.default) {
children.push(slot.default)
}
return children.join('\n')
}
// el-input 子级
function buildElInputChild(scheme) {
const children = []
const slot = scheme.__slot__
if (slot && slot.prepend) {
children.push(`<template slot="prepend">${slot.prepend}</template>`)
}
if (slot && slot.append) {
children.push(`<template slot="append">${slot.append}</template>`)
}
return children.join('\n')
}
// el-select 子级
function buildElSelectChild(scheme) {
const children = []
const slot = scheme.__slot__
if (slot && slot.options && slot.options.length) {
children.push(`<el-option v-for="(item, index) in ${scheme.__vModel__}Options" :key="index" :label="item.label" :value="item.value" :disabled="item.disabled"></el-option>`)
}
return children.join('\n')
}
// el-radio-group 子级
function buildElRadioGroupChild(scheme) {
const children = []
const slot = scheme.__slot__
const config = scheme.__config__
if (slot && slot.options && slot.options.length) {
const tag = config.optionType === 'button' ? 'el-radio-button' : 'el-radio'
const border = config.border ? 'border' : ''
children.push(`<${tag} v-for="(item, index) in ${scheme.__vModel__}Options" :key="index" :label="item.value" :disabled="item.disabled" ${border}>{{item.label}}</${tag}>`)
}
return children.join('\n')
}
// el-checkbox-group 子级
function buildElCheckboxGroupChild(scheme) {
const children = []
const slot = scheme.__slot__
const config = scheme.__config__
if (slot && slot.options && slot.options.length) {
const tag = config.optionType === 'button' ? 'el-checkbox-button' : 'el-checkbox'
const border = config.border ? 'border' : ''
children.push(`<${tag} v-for="(item, index) in ${scheme.__vModel__}Options" :key="index" :label="item.value" :disabled="item.disabled" ${border}>{{item.label}}</${tag}>`)
}
return children.join('\n')
}
// el-upload 子级
function buildElUploadChild(scheme) {
const list = []
const config = scheme.__config__
if (scheme['list-type'] === 'picture-card') list.push('<i class="el-icon-plus"></i>')
else list.push(`<el-button size="small" type="primary" icon="el-icon-upload">${config.buttonText}</el-button>`)
if (config.showTip) list.push(`<div slot="tip" class="el-upload__tip">只能上传不超过 ${config.fileSize}${config.sizeUnit}${scheme.accept}文件</div>`)
return list.join('\n')
}
/**
* 组装html代码入口函数
* @param {Object} formConfig 整个表单配置
* @param {String} type 生成类型文件或弹窗等
*/
export function makeUpHtml(formConfig, type) {
const htmlList = []
confGlobal = formConfig
// 判断布局是否都沾满了24个栅格以备后续简化代码结构
someSpanIsNot24 = formConfig.fields.some(item => item.__config__.span !== 24)
// 遍历渲染每个组件成html
formConfig.fields.forEach(el => {
htmlList.push(layouts[el.__config__.layout](el))
})
const htmlStr = htmlList.join('\n')
// 将组件代码放进form标签
let temp = buildFormTemplate(formConfig, htmlStr, type)
// dialog标签包裹代码
if (type === 'dialog') {
temp = dialogWrapper(temp)
}
confGlobal = null
return temp
}

View File

@ -1,271 +0,0 @@
import { isArray } from 'util'
import { exportDefault, titleCase, deepClone } from '@/utils'
import ruleTrigger from './ruleTrigger'
const units = {
KB: '1024',
MB: '1024 / 1024',
GB: '1024 / 1024 / 1024'
}
let confGlobal
const inheritAttrs = {
file: '',
dialog: 'inheritAttrs: false,'
}
/**
* 组装js 入口函数
* @param {Object} formConfig 整个表单配置
* @param {String} type 生成类型文件或弹窗等
*/
export function makeUpJs(formConfig, type) {
confGlobal = formConfig = deepClone(formConfig)
const dataList = []
const ruleList = []
const optionsList = []
const propsList = []
const methodList = mixinMethod(type)
const uploadVarList = []
const created = []
formConfig.fields.forEach(el => {
buildAttributes(el, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created)
})
const script = buildexport(
formConfig,
type,
dataList.join('\n'),
ruleList.join('\n'),
optionsList.join('\n'),
uploadVarList.join('\n'),
propsList.join('\n'),
methodList.join('\n'),
created.join('\n')
)
confGlobal = null
return script
}
// 构建组件属性
function buildAttributes(scheme, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created) {
const config = scheme.__config__
const slot = scheme.__slot__
buildData(scheme, dataList)
buildRules(scheme, ruleList)
// 特殊处理options属性
if (scheme.options || (slot && slot.options && slot.options.length)) {
buildOptions(scheme, optionsList)
if (config.dataType === 'dynamic') {
const model = `${scheme.__vModel__}Options`
const options = titleCase(model)
const methodName = `get${options}`
buildOptionMethod(methodName, model, methodList, scheme)
callInCreated(methodName, created)
}
}
// 处理props
if (scheme.props && scheme.props.props) {
buildProps(scheme, propsList)
}
// 处理el-upload的action
if (scheme.action && config.tag === 'el-upload') {
uploadVarList.push(
`${scheme.__vModel__}Action: '${scheme.action}',
${scheme.__vModel__}fileList: [],`
)
methodList.push(buildBeforeUpload(scheme))
// 非自动上传时,生成手动上传的函数
if (!scheme['auto-upload']) {
methodList.push(buildSubmitUpload(scheme))
}
}
// 构建子级组件属性
if (config.children) {
config.children.forEach(item => {
buildAttributes(item, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created)
})
}
}
// 在Created调用函数
function callInCreated(methodName, created) {
created.push(`this.${methodName}()`)
}
// 混入处理函数
function mixinMethod(type) {
const list = []; const
minxins = {
file: confGlobal.formBtns ? {
submitForm: `submitForm() {
this.$refs['${confGlobal.formRef}'].validate(valid => {
if(!valid) return
// TODO 提交表单
})
},`,
resetForm: `resetForm() {
this.$refs['${confGlobal.formRef}'].resetFields()
},`
} : null,
dialog: {
onOpen: 'onOpen() {},',
onClose: `onClose() {
this.$refs['${confGlobal.formRef}'].resetFields()
},`,
close: `close() {
this.$emit('update:visible', false)
},`,
handelConfirm: `handelConfirm() {
this.$refs['${confGlobal.formRef}'].validate(valid => {
if(!valid) return
this.close()
})
},`
}
}
const methods = minxins[type]
if (methods) {
Object.keys(methods).forEach(key => {
list.push(methods[key])
})
}
return list
}
// 构建data
function buildData(scheme, dataList) {
const config = scheme.__config__
if (scheme.__vModel__ === undefined) return
const defaultValue = JSON.stringify(config.defaultValue)
dataList.push(`${scheme.__vModel__}: ${defaultValue},`)
}
// 构建校验规则
function buildRules(scheme, ruleList) {
const config = scheme.__config__
if (scheme.__vModel__ === undefined) return
const rules = []
if (ruleTrigger[config.tag]) {
if (config.required) {
const type = isArray(config.defaultValue) ? 'type: \'array\',' : ''
let message = isArray(config.defaultValue) ? `请至少选择一个${config.label}` : scheme.placeholder
if (message === undefined) message = `${config.label}不能为空`
rules.push(`{ required: true, ${type} message: '${message}', trigger: '${ruleTrigger[config.tag]}' }`)
}
if (config.regList && isArray(config.regList)) {
config.regList.forEach(item => {
if (item.pattern) {
rules.push(
`{ pattern: ${eval(item.pattern)}, message: '${item.message}', trigger: '${ruleTrigger[config.tag]}' }`
)
}
})
}
ruleList.push(`${scheme.__vModel__}: [${rules.join(',')}],`)
}
}
// 构建options
function buildOptions(scheme, optionsList) {
if (scheme.__vModel__ === undefined) return
// el-cascader直接有options属性其他组件都是定义在slot中所以有两处判断
let { options } = scheme
if (!options) options = scheme.__slot__.options
if (scheme.__config__.dataType === 'dynamic') { options = [] }
const str = `${scheme.__vModel__}Options: ${JSON.stringify(options)},`
optionsList.push(str)
}
function buildProps(scheme, propsList) {
const str = `${scheme.__vModel__}Props: ${JSON.stringify(scheme.props.props)},`
propsList.push(str)
}
// el-upload的BeforeUpload
function buildBeforeUpload(scheme) {
const config = scheme.__config__
const unitNum = units[config.sizeUnit]; let rightSizeCode = ''; let acceptCode = ''; const
returnList = []
if (config.fileSize) {
rightSizeCode = `let isRightSize = file.size / ${unitNum} < ${config.fileSize}
if(!isRightSize){
this.$message.error('文件大小超过 ${config.fileSize}${config.sizeUnit}')
}`
returnList.push('isRightSize')
}
if (scheme.accept) {
acceptCode = `let isAccept = new RegExp('${scheme.accept}').test(file.type)
if(!isAccept){
this.$message.error('应该选择${scheme.accept}类型的文件')
}`
returnList.push('isAccept')
}
const str = `${scheme.__vModel__}BeforeUpload(file) {
${rightSizeCode}
${acceptCode}
return ${returnList.join('&&')}
},`
return returnList.length ? str : ''
}
// el-upload的submit
function buildSubmitUpload(scheme) {
const str = `submitUpload() {
this.$refs['${scheme.__vModel__}'].submit()
},`
return str
}
function buildOptionMethod(methodName, model, methodList, scheme) {
const config = scheme.__config__
const str = `${methodName}() {
// 注意this.$axios是通过Vue.prototype.$axios = axios挂载产生的
this.$axios({
method: '${config.method}',
url: '${config.url}'
}).then(resp => {
var { data } = resp
this.${model} = data.${config.dataPath}
})
},`
methodList.push(str)
}
// js整体拼接
function buildexport(conf, type, data, rules, selectOptions, uploadVar, props, methods, created) {
const str = `${exportDefault}{
${inheritAttrs[type]}
components: {},
props: [],
data () {
return {
${conf.formModel}: {
${data}
},
${conf.formRules}: {
${rules}
},
${uploadVar}
${selectOptions}
${props}
}
},
computed: {},
watch: {},
created () {
${created}
},
mounted () {},
methods: {
${methods}
}
}`
return str
}

View File

@ -1,16 +0,0 @@
/**
* 用于生成表单校验指定正则规则的触发方式
* 未在此处声明无触发方式的组件将不生成rule
*/
export default {
'el-input': 'blur',
'el-input-number': 'blur',
'el-select': 'change',
'el-radio-group': 'change',
'el-checkbox-group': 'change',
'el-cascader': 'change',
'el-time-picker': 'change',
'el-date-picker': 'change',
'el-rate': 'change',
tinymce: 'blur'
}

View File

@ -0,0 +1,60 @@
/**
* 本文件保存一些 BaseTable 会用到的组件
*/
// 操作按钮
export const TableBtn = {
name: 'TableBtn',
props: ['injectData'],
data() {
return {};
},
methods: {
handleClick() {
this.$emit('emitData', {
action: this.injectData.label,
value: this.injectData,
});
},
},
render: function (h) {
return (
<el-button
type="text"
onClick={this.handleClick}>
{this.injectData.entryText}
</el-button>
);
},
};
// 余量
export const RemainBox = {
name: 'RemainBox',
props: ['injectData'],
data() {
return {};
},
computed: {
value() {
return this.injectData[this.injectData.prop] || null;
},
color() {
if (this.value) {
const v = +this.value;
return v < 0 ? '#FF5454' : v >= 0 && v < 2 ? '#FFD767' : '#37D97F';
}
return 'unset';
},
},
render: function (h) {
return (
<div
style={`background: ${
this.color
}; position:absolute; inset: 0; padding: 0 10px; display: flex; align-items: center; color: ${'#fff'}`}>
{this.injectData[this.injectData.prop]?.toFixed(0) || ''}
</div>
);
},
};

View File

@ -1,3 +0,0 @@
## 简介
富文本编辑器tinymce的一个vue版本封装。使用cdn动态脚本引入的方式加载。

View File

@ -1,8 +0,0 @@
/* eslint-disable max-len */
export const plugins = [
'advlist anchor autolink autosave code codesample directionality emoticons fullscreen hr image imagetools insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textpattern visualblocks visualchars wordcount'
]
export const toolbar = [
'code searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote removeformat subscript superscript codesample hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen'
]

View File

@ -1,38 +0,0 @@
<template>
<div>
<Tinymce v-model="defaultValue" :height="300" placeholder="在这里输入文字" />
</div>
</template>
<script>
import Tinymce from '../index.vue'
export default {
components: {
Tinymce
},
props: {
},
data() {
return {
defaultValue: '<p>配置文档参阅http://tinymce.ax-z.cn</p>'
}
},
computed: {
},
watch: {
},
created() {
},
mounted() {
},
methods: {
}
}
</script>

View File

@ -1,3 +0,0 @@
import Index from './index.vue'
export default Index

View File

@ -1,88 +0,0 @@
<template>
<textarea :id="tinymceId" style="visibility: hidden" />
</template>
<script>
import loadTinymce from '@/utils/loadTinymce'
import { plugins, toolbar } from './config'
import { debounce } from 'throttle-debounce'
let num = 1
export default {
props: {
id: {
type: String,
default: () => {
num === 10000 && (num = 1)
return `tinymce${+new Date()}${num++}`
}
},
value: {
default: ''
}
},
data() {
return {
tinymceId: this.id
}
},
mounted() {
loadTinymce(tinymce => {
// eslint-disable-next-line global-require
require('./zh_CN')
let conf = {
selector: `#${this.tinymceId}`,
language: 'zh_CN',
menubar: 'file edit insert view format table',
plugins,
toolbar,
height: 300,
branding: false,
object_resizing: false,
end_container_on_empty_block: true,
powerpaste_word_import: 'clean',
code_dialog_height: 450,
code_dialog_width: 1000,
advlist_bullet_styles: 'square',
advlist_number_styles: 'default',
default_link_target: '_blank',
link_title: false,
nonbreaking_force_tab: true
}
conf = Object.assign(conf, this.$attrs)
conf.init_instance_callback = editor => {
if (this.value) editor.setContent(this.value)
this.vModel(editor)
}
tinymce.init(conf)
})
},
destroyed() {
this.destroyTinymce()
},
methods: {
vModel(editor) {
// setContent
const debounceSetContent = debounce(250, editor.setContent)
this.$watch('value', (val, prevVal) => {
if (editor && val !== prevVal && val !== editor.getContent()) {
if (typeof val !== 'string') val = val.toString()
debounceSetContent.call(editor, val)
}
})
editor.on('change keyup undo redo', () => {
this.$emit('input', editor.getContent())
})
},
destroyTinymce() {
if (!window.tinymce) return
const tinymce = window.tinymce.get(this.tinymceId)
if (tinymce) {
tinymce.destroy()
}
}
}
}
</script>

View File

@ -1,28 +0,0 @@
{
"name": "form-gen-tinymce",
"version": "1.0.0",
"description": "富文本编辑器tinymce的一个vue版本封装。使用cdn动态脚本引入的方式加载。",
"main": "lib/form-gen-tinymce.umd.js",
"directories": {
"example": "example"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/JakHuang/form-generator.git"
},
"keywords": [
"tinymce-vue"
],
"dependencies": {
"throttle-debounce": "^2.1.0"
},
"author": "jakHuang",
"license": "MIT",
"bugs": {
"url": "https://github.com/JakHuang/form-generator/issues"
},
"homepage": "https://github.com/JakHuang/form-generator/blob/dev/src/components/tinymce"
}

View File

@ -1,420 +0,0 @@
/* eslint-disable */
tinymce.addI18n('zh_CN',{
"Redo": "\u91cd\u505a",
"Undo": "\u64a4\u9500",
"Cut": "\u526a\u5207",
"Copy": "\u590d\u5236",
"Paste": "\u7c98\u8d34",
"Select all": "\u5168\u9009",
"New document": "\u65b0\u6587\u4ef6",
"Ok": "\u786e\u5b9a",
"Cancel": "\u53d6\u6d88",
"Visual aids": "\u7f51\u683c\u7ebf",
"Bold": "\u7c97\u4f53",
"Italic": "\u659c\u4f53",
"Underline": "\u4e0b\u5212\u7ebf",
"Strikethrough": "\u5220\u9664\u7ebf",
"Superscript": "\u4e0a\u6807",
"Subscript": "\u4e0b\u6807",
"Clear formatting": "\u6e05\u9664\u683c\u5f0f",
"Align left": "\u5de6\u8fb9\u5bf9\u9f50",
"Align center": "\u4e2d\u95f4\u5bf9\u9f50",
"Align right": "\u53f3\u8fb9\u5bf9\u9f50",
"Justify": "\u4e24\u7aef\u5bf9\u9f50",
"Bullet list": "\u9879\u76ee\u7b26\u53f7",
"Numbered list": "\u7f16\u53f7\u5217\u8868",
"Decrease indent": "\u51cf\u5c11\u7f29\u8fdb",
"Increase indent": "\u589e\u52a0\u7f29\u8fdb",
"Close": "\u5173\u95ed",
"Formats": "\u683c\u5f0f",
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "\u4f60\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301\u6253\u5f00\u526a\u8d34\u677f\uff0c\u8bf7\u4f7f\u7528Ctrl+X\/C\/V\u7b49\u5feb\u6377\u952e\u3002",
"Headers": "\u6807\u9898",
"Header 1": "\u6807\u98981",
"Header 2": "\u6807\u98982",
"Header 3": "\u6807\u98983",
"Header 4": "\u6807\u98984",
"Header 5": "\u6807\u98985",
"Header 6": "\u6807\u98986",
"Headings": "\u6807\u9898",
"Heading 1": "\u6807\u98981",
"Heading 2": "\u6807\u98982",
"Heading 3": "\u6807\u98983",
"Heading 4": "\u6807\u98984",
"Heading 5": "\u6807\u98985",
"Heading 6": "\u6807\u98986",
"Preformatted": "\u9884\u5148\u683c\u5f0f\u5316\u7684",
"Div": "Div",
"Pre": "Pre",
"Code": "\u4ee3\u7801",
"Paragraph": "\u6bb5\u843d",
"Blockquote": "\u5f15\u6587\u533a\u5757",
"Inline": "\u6587\u672c",
"Blocks": "\u57fa\u5757",
"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "\u5f53\u524d\u4e3a\u7eaf\u6587\u672c\u7c98\u8d34\u6a21\u5f0f\uff0c\u518d\u6b21\u70b9\u51fb\u53ef\u4ee5\u56de\u5230\u666e\u901a\u7c98\u8d34\u6a21\u5f0f\u3002",
"Fonts": "\u5b57\u4f53",
"Font Sizes": "\u5b57\u53f7",
"Class": "\u7c7b\u578b",
"Browse for an image": "\u6d4f\u89c8\u56fe\u50cf",
"OR": "\u6216",
"Drop an image here": "\u62d6\u653e\u4e00\u5f20\u56fe\u50cf\u81f3\u6b64",
"Upload": "\u4e0a\u4f20",
"Block": "\u5757",
"Align": "\u5bf9\u9f50",
"Default": "\u9ed8\u8ba4",
"Circle": "\u7a7a\u5fc3\u5706",
"Disc": "\u5b9e\u5fc3\u5706",
"Square": "\u65b9\u5757",
"Lower Alpha": "\u5c0f\u5199\u82f1\u6587\u5b57\u6bcd",
"Lower Greek": "\u5c0f\u5199\u5e0c\u814a\u5b57\u6bcd",
"Lower Roman": "\u5c0f\u5199\u7f57\u9a6c\u5b57\u6bcd",
"Upper Alpha": "\u5927\u5199\u82f1\u6587\u5b57\u6bcd",
"Upper Roman": "\u5927\u5199\u7f57\u9a6c\u5b57\u6bcd",
"Anchor...": "\u951a\u70b9...",
"Name": "\u540d\u79f0",
"Id": "\u6807\u8bc6\u7b26",
"Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.": "\u6807\u8bc6\u7b26\u5e94\u8be5\u4ee5\u5b57\u6bcd\u5f00\u5934\uff0c\u540e\u8ddf\u5b57\u6bcd\u3001\u6570\u5b57\u3001\u7834\u6298\u53f7\u3001\u70b9\u3001\u5192\u53f7\u6216\u4e0b\u5212\u7ebf\u3002",
"You have unsaved changes are you sure you want to navigate away?": "\u4f60\u8fd8\u6709\u6587\u6863\u5c1a\u672a\u4fdd\u5b58\uff0c\u786e\u5b9a\u8981\u79bb\u5f00\uff1f",
"Restore last draft": "\u6062\u590d\u4e0a\u6b21\u7684\u8349\u7a3f",
"Special character...": "\u7279\u6b8a\u5b57\u7b26...",
"Source code": "\u6e90\u4ee3\u7801",
"Insert\/Edit code sample": "\u63d2\u5165\/\u7f16\u8f91\u4ee3\u7801\u793a\u4f8b",
"Language": "\u8bed\u8a00",
"Code sample...": "\u793a\u4f8b\u4ee3\u7801...",
"Color Picker": "\u9009\u8272\u5668",
"R": "R",
"G": "G",
"B": "B",
"Left to right": "\u4ece\u5de6\u5230\u53f3",
"Right to left": "\u4ece\u53f3\u5230\u5de6",
"Emoticons...": "\u8868\u60c5\u7b26\u53f7...",
"Metadata and Document Properties": "\u5143\u6570\u636e\u548c\u6587\u6863\u5c5e\u6027",
"Title": "\u6807\u9898",
"Keywords": "\u5173\u952e\u8bcd",
"Description": "\u63cf\u8ff0",
"Robots": "\u673a\u5668\u4eba",
"Author": "\u4f5c\u8005",
"Encoding": "\u7f16\u7801",
"Fullscreen": "\u5168\u5c4f",
"Action": "\u64cd\u4f5c",
"Shortcut": "\u5feb\u6377\u952e",
"Help": "\u5e2e\u52a9",
"Address": "\u5730\u5740",
"Focus to menubar": "\u79fb\u52a8\u7126\u70b9\u5230\u83dc\u5355\u680f",
"Focus to toolbar": "\u79fb\u52a8\u7126\u70b9\u5230\u5de5\u5177\u680f",
"Focus to element path": "\u79fb\u52a8\u7126\u70b9\u5230\u5143\u7d20\u8def\u5f84",
"Focus to contextual toolbar": "\u79fb\u52a8\u7126\u70b9\u5230\u4e0a\u4e0b\u6587\u83dc\u5355",
"Insert link (if link plugin activated)": "\u63d2\u5165\u94fe\u63a5 (\u5982\u679c\u94fe\u63a5\u63d2\u4ef6\u5df2\u6fc0\u6d3b)",
"Save (if save plugin activated)": "\u4fdd\u5b58(\u5982\u679c\u4fdd\u5b58\u63d2\u4ef6\u5df2\u6fc0\u6d3b)",
"Find (if searchreplace plugin activated)": "\u67e5\u627e(\u5982\u679c\u67e5\u627e\u66ff\u6362\u63d2\u4ef6\u5df2\u6fc0\u6d3b)",
"Plugins installed ({0}):": "\u5df2\u5b89\u88c5\u63d2\u4ef6 ({0}):",
"Premium plugins:": "\u4f18\u79c0\u63d2\u4ef6\uff1a",
"Learn more...": "\u4e86\u89e3\u66f4\u591a...",
"You are using {0}": "\u4f60\u6b63\u5728\u4f7f\u7528 {0}",
"Plugins": "\u63d2\u4ef6",
"Handy Shortcuts": "\u5feb\u6377\u952e",
"Horizontal line": "\u6c34\u5e73\u5206\u5272\u7ebf",
"Insert\/edit image": "\u63d2\u5165\/\u7f16\u8f91\u56fe\u7247",
"Image description": "\u56fe\u7247\u63cf\u8ff0",
"Source": "\u5730\u5740",
"Dimensions": "\u5927\u5c0f",
"Constrain proportions": "\u4fdd\u6301\u7eb5\u6a2a\u6bd4",
"General": "\u666e\u901a",
"Advanced": "\u9ad8\u7ea7",
"Style": "\u6837\u5f0f",
"Vertical space": "\u5782\u76f4\u8fb9\u8ddd",
"Horizontal space": "\u6c34\u5e73\u8fb9\u8ddd",
"Border": "\u8fb9\u6846",
"Insert image": "\u63d2\u5165\u56fe\u7247",
"Image...": "\u56fe\u7247...",
"Image list": "\u56fe\u7247\u5217\u8868",
"Rotate counterclockwise": "\u9006\u65f6\u9488\u65cb\u8f6c",
"Rotate clockwise": "\u987a\u65f6\u9488\u65cb\u8f6c",
"Flip vertically": "\u5782\u76f4\u7ffb\u8f6c",
"Flip horizontally": "\u6c34\u5e73\u7ffb\u8f6c",
"Edit image": "\u7f16\u8f91\u56fe\u7247",
"Image options": "\u56fe\u7247\u9009\u9879",
"Zoom in": "\u653e\u5927",
"Zoom out": "\u7f29\u5c0f",
"Crop": "\u88c1\u526a",
"Resize": "\u8c03\u6574\u5927\u5c0f",
"Orientation": "\u65b9\u5411",
"Brightness": "\u4eae\u5ea6",
"Sharpen": "\u9510\u5316",
"Contrast": "\u5bf9\u6bd4\u5ea6",
"Color levels": "\u989c\u8272\u5c42\u6b21",
"Gamma": "\u4f3d\u9a6c\u503c",
"Invert": "\u53cd\u8f6c",
"Apply": "\u5e94\u7528",
"Back": "\u540e\u9000",
"Insert date\/time": "\u63d2\u5165\u65e5\u671f\/\u65f6\u95f4",
"Date\/time": "\u65e5\u671f\/\u65f6\u95f4",
"Insert\/Edit Link": "\u63d2\u5165\/\u7f16\u8f91\u94fe\u63a5",
"Insert\/edit link": "\u63d2\u5165\/\u7f16\u8f91\u94fe\u63a5",
"Text to display": "\u663e\u793a\u6587\u5b57",
"Url": "\u5730\u5740",
"Open link in...": "\u94fe\u63a5\u6253\u5f00\u4f4d\u7f6e...",
"Current window": "\u5f53\u524d\u7a97\u53e3",
"None": "\u65e0",
"New window": "\u5728\u65b0\u7a97\u53e3\u6253\u5f00",
"Remove link": "\u5220\u9664\u94fe\u63a5",
"Anchors": "\u951a\u70b9",
"Link...": "\u94fe\u63a5...",
"Paste or type a link": "\u7c98\u8d34\u6216\u8f93\u5165\u94fe\u63a5",
"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "\u4f60\u6240\u586b\u5199\u7684URL\u5730\u5740\u4e3a\u90ae\u4ef6\u5730\u5740\uff0c\u9700\u8981\u52a0\u4e0amailto:\u524d\u7f00\u5417\uff1f",
"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "\u4f60\u6240\u586b\u5199\u7684URL\u5730\u5740\u5c5e\u4e8e\u5916\u90e8\u94fe\u63a5\uff0c\u9700\u8981\u52a0\u4e0ahttp:\/\/:\u524d\u7f00\u5417\uff1f",
"Link list": "\u94fe\u63a5\u5217\u8868",
"Insert video": "\u63d2\u5165\u89c6\u9891",
"Insert\/edit video": "\u63d2\u5165\/\u7f16\u8f91\u89c6\u9891",
"Insert\/edit media": "\u63d2\u5165\/\u7f16\u8f91\u5a92\u4f53",
"Alternative source": "\u955c\u50cf",
"Alternative source URL": "\u66ff\u4ee3\u6765\u6e90\u7f51\u5740",
"Media poster (Image URL)": "\u5c01\u9762(\u56fe\u7247\u5730\u5740)",
"Paste your embed code below:": "\u5c06\u5185\u5d4c\u4ee3\u7801\u7c98\u8d34\u5728\u4e0b\u9762:",
"Embed": "\u5185\u5d4c",
"Media...": "\u591a\u5a92\u4f53...",
"Nonbreaking space": "\u4e0d\u95f4\u65ad\u7a7a\u683c",
"Page break": "\u5206\u9875\u7b26",
"Paste as text": "\u7c98\u8d34\u4e3a\u6587\u672c",
"Preview": "\u9884\u89c8",
"Print...": "\u6253\u5370...",
"Save": "\u4fdd\u5b58",
"Find": "\u67e5\u627e",
"Replace with": "\u66ff\u6362\u4e3a",
"Replace": "\u66ff\u6362",
"Replace all": "\u5168\u90e8\u66ff\u6362",
"Previous": "\u4e0a\u4e00\u4e2a",
"Next": "\u4e0b\u4e00\u4e2a",
"Find and replace...": "\u67e5\u627e\u5e76\u66ff\u6362...",
"Could not find the specified string.": "\u672a\u627e\u5230\u641c\u7d22\u5185\u5bb9.",
"Match case": "\u533a\u5206\u5927\u5c0f\u5199",
"Find whole words only": "\u5168\u5b57\u5339\u914d",
"Spell check": "\u62fc\u5199\u68c0\u67e5",
"Ignore": "\u5ffd\u7565",
"Ignore all": "\u5168\u90e8\u5ffd\u7565",
"Finish": "\u5b8c\u6210",
"Add to Dictionary": "\u6dfb\u52a0\u5230\u5b57\u5178",
"Insert table": "\u63d2\u5165\u8868\u683c",
"Table properties": "\u8868\u683c\u5c5e\u6027",
"Delete table": "\u5220\u9664\u8868\u683c",
"Cell": "\u5355\u5143\u683c",
"Row": "\u884c",
"Column": "\u5217",
"Cell properties": "\u5355\u5143\u683c\u5c5e\u6027",
"Merge cells": "\u5408\u5e76\u5355\u5143\u683c",
"Split cell": "\u62c6\u5206\u5355\u5143\u683c",
"Insert row before": "\u5728\u4e0a\u65b9\u63d2\u5165",
"Insert row after": "\u5728\u4e0b\u65b9\u63d2\u5165",
"Delete row": "\u5220\u9664\u884c",
"Row properties": "\u884c\u5c5e\u6027",
"Cut row": "\u526a\u5207\u884c",
"Copy row": "\u590d\u5236\u884c",
"Paste row before": "\u7c98\u8d34\u5230\u4e0a\u65b9",
"Paste row after": "\u7c98\u8d34\u5230\u4e0b\u65b9",
"Insert column before": "\u5728\u5de6\u4fa7\u63d2\u5165",
"Insert column after": "\u5728\u53f3\u4fa7\u63d2\u5165",
"Delete column": "\u5220\u9664\u5217",
"Cols": "\u5217",
"Rows": "\u884c",
"Width": "\u5bbd",
"Height": "\u9ad8",
"Cell spacing": "\u5355\u5143\u683c\u5916\u95f4\u8ddd",
"Cell padding": "\u5355\u5143\u683c\u5185\u8fb9\u8ddd",
"Show caption": "\u663e\u793a\u6807\u9898",
"Left": "\u5de6\u5bf9\u9f50",
"Center": "\u5c45\u4e2d",
"Right": "\u53f3\u5bf9\u9f50",
"Cell type": "\u5355\u5143\u683c\u7c7b\u578b",
"Scope": "\u8303\u56f4",
"Alignment": "\u5bf9\u9f50\u65b9\u5f0f",
"H Align": "\u6c34\u5e73\u5bf9\u9f50",
"V Align": "\u5782\u76f4\u5bf9\u9f50",
"Top": "\u9876\u90e8\u5bf9\u9f50",
"Middle": "\u5782\u76f4\u5c45\u4e2d",
"Bottom": "\u5e95\u90e8\u5bf9\u9f50",
"Header cell": "\u8868\u5934\u5355\u5143\u683c",
"Row group": "\u884c\u7ec4",
"Column group": "\u5217\u7ec4",
"Row type": "\u884c\u7c7b\u578b",
"Header": "\u8868\u5934",
"Body": "\u8868\u4f53",
"Footer": "\u8868\u5c3e",
"Border color": "\u8fb9\u6846\u989c\u8272",
"Insert template...": "\u63d2\u5165\u6a21\u677f...",
"Templates": "\u6a21\u677f",
"Template": "\u6a21\u677f",
"Text color": "\u6587\u5b57\u989c\u8272",
"Background color": "\u80cc\u666f\u8272",
"Custom...": "\u81ea\u5b9a\u4e49...",
"Custom color": "\u81ea\u5b9a\u4e49\u989c\u8272",
"No color": "\u65e0",
"Remove color": "\u79fb\u9664\u989c\u8272",
"Table of Contents": "\u5185\u5bb9\u5217\u8868",
"Show blocks": "\u663e\u793a\u533a\u5757\u8fb9\u6846",
"Show invisible characters": "\u663e\u793a\u4e0d\u53ef\u89c1\u5b57\u7b26",
"Word count": "\u5b57\u6570",
"Count": "\u8ba1\u6570",
"Document": "\u6587\u6863",
"Selection": "\u9009\u62e9",
"Words": "\u5355\u8bcd",
"Words: {0}": "\u5b57\u6570\uff1a{0}",
"{0} words": "{0} \u5b57",
"File": "\u6587\u4ef6",
"Edit": "\u7f16\u8f91",
"Insert": "\u63d2\u5165",
"View": "\u89c6\u56fe",
"Format": "\u683c\u5f0f",
"Table": "\u8868\u683c",
"Tools": "\u5de5\u5177",
"Powered by {0}": "\u7531{0}\u9a71\u52a8",
"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "\u5728\u7f16\u8f91\u533a\u6309ALT-F9\u6253\u5f00\u83dc\u5355\uff0c\u6309ALT-F10\u6253\u5f00\u5de5\u5177\u680f\uff0c\u6309ALT-0\u67e5\u770b\u5e2e\u52a9",
"Image title": "\u56fe\u7247\u6807\u9898",
"Border width": "\u8fb9\u6846\u5bbd\u5ea6",
"Border style": "\u8fb9\u6846\u6837\u5f0f",
"Error": "\u9519\u8bef",
"Warn": "\u8b66\u544a",
"Valid": "\u6709\u6548",
"To open the popup, press Shift+Enter": "\u6309Shitf+Enter\u952e\u6253\u5f00\u5bf9\u8bdd\u6846",
"Rich Text Area. Press ALT-0 for help.": "\u7f16\u8f91\u533a\u3002\u6309Alt+0\u952e\u6253\u5f00\u5e2e\u52a9\u3002",
"System Font": "\u7cfb\u7edf\u5b57\u4f53",
"Failed to upload image: {0}": "\u56fe\u7247\u4e0a\u4f20\u5931\u8d25: {0}",
"Failed to load plugin: {0} from url {1}": "\u63d2\u4ef6\u52a0\u8f7d\u5931\u8d25: {0} \u6765\u81ea\u94fe\u63a5 {1}",
"Failed to load plugin url: {0}": "\u63d2\u4ef6\u52a0\u8f7d\u5931\u8d25 \u94fe\u63a5: {0}",
"Failed to initialize plugin: {0}": "\u63d2\u4ef6\u521d\u59cb\u5316\u5931\u8d25: {0}",
"example": "\u793a\u4f8b",
"Search": "\u641c\u7d22",
"All": "\u5168\u90e8",
"Currency": "\u8d27\u5e01",
"Text": "\u6587\u5b57",
"Quotations": "\u5f15\u7528",
"Mathematical": "\u6570\u5b66",
"Extended Latin": "\u62c9\u4e01\u8bed\u6269\u5145",
"Symbols": "\u7b26\u53f7",
"Arrows": "\u7bad\u5934",
"User Defined": "\u81ea\u5b9a\u4e49",
"dollar sign": "\u7f8e\u5143\u7b26\u53f7",
"currency sign": "\u8d27\u5e01\u7b26\u53f7",
"euro-currency sign": "\u6b27\u5143\u7b26\u53f7",
"colon sign": "\u5192\u53f7",
"cruzeiro sign": "\u514b\u9c81\u8d5b\u7f57\u5e01\u7b26\u53f7",
"french franc sign": "\u6cd5\u90ce\u7b26\u53f7",
"lira sign": "\u91cc\u62c9\u7b26\u53f7",
"mill sign": "\u5bc6\u5c14\u7b26\u53f7",
"naira sign": "\u5948\u62c9\u7b26\u53f7",
"peseta sign": "\u6bd4\u585e\u5854\u7b26\u53f7",
"rupee sign": "\u5362\u6bd4\u7b26\u53f7",
"won sign": "\u97e9\u5143\u7b26\u53f7",
"new sheqel sign": "\u65b0\u8c22\u514b\u5c14\u7b26\u53f7",
"dong sign": "\u8d8a\u5357\u76fe\u7b26\u53f7",
"kip sign": "\u8001\u631d\u57fa\u666e\u7b26\u53f7",
"tugrik sign": "\u56fe\u683c\u91cc\u514b\u7b26\u53f7",
"drachma sign": "\u5fb7\u62c9\u514b\u9a6c\u7b26\u53f7",
"german penny symbol": "\u5fb7\u56fd\u4fbf\u58eb\u7b26\u53f7",
"peso sign": "\u6bd4\u7d22\u7b26\u53f7",
"guarani sign": "\u74dc\u62c9\u5c3c\u7b26\u53f7",
"austral sign": "\u6fb3\u5143\u7b26\u53f7",
"hryvnia sign": "\u683c\u91cc\u592b\u5c3c\u4e9a\u7b26\u53f7",
"cedi sign": "\u585e\u5730\u7b26\u53f7",
"livre tournois sign": "\u91cc\u5f17\u5f17\u5c14\u7b26\u53f7",
"spesmilo sign": "spesmilo\u7b26\u53f7",
"tenge sign": "\u575a\u6208\u7b26\u53f7",
"indian rupee sign": "\u5370\u5ea6\u5362\u6bd4",
"turkish lira sign": "\u571f\u8033\u5176\u91cc\u62c9",
"nordic mark sign": "\u5317\u6b27\u9a6c\u514b",
"manat sign": "\u9a6c\u7eb3\u7279\u7b26\u53f7",
"ruble sign": "\u5362\u5e03\u7b26\u53f7",
"yen character": "\u65e5\u5143\u5b57\u6837",
"yuan character": "\u4eba\u6c11\u5e01\u5143\u5b57\u6837",
"yuan character, in hong kong and taiwan": "\u5143\u5b57\u6837\uff08\u6e2f\u53f0\u5730\u533a\uff09",
"yen\/yuan character variant one": "\u5143\u5b57\u6837\uff08\u5927\u5199\uff09",
"Loading emoticons...": "\u52a0\u8f7d\u8868\u60c5\u7b26\u53f7...",
"Could not load emoticons": "\u4e0d\u80fd\u52a0\u8f7d\u8868\u60c5\u7b26\u53f7",
"People": "\u4eba\u7c7b",
"Animals and Nature": "\u52a8\u7269\u548c\u81ea\u7136",
"Food and Drink": "\u98df\u7269\u548c\u996e\u54c1",
"Activity": "\u6d3b\u52a8",
"Travel and Places": "\u65c5\u6e38\u548c\u5730\u70b9",
"Objects": "\u7269\u4ef6",
"Flags": "\u65d7\u5e1c",
"Characters": "\u5b57\u7b26",
"Characters (no spaces)": "\u5b57\u7b26(\u65e0\u7a7a\u683c)",
"{0} characters": "{0} \u4e2a\u5b57\u7b26",
"Error: Form submit field collision.": "\u9519\u8bef: \u8868\u5355\u63d0\u4ea4\u5b57\u6bb5\u51b2\u7a81\u3002",
"Error: No form element found.": "\u9519\u8bef: \u6ca1\u6709\u8868\u5355\u63a7\u4ef6\u3002",
"Update": "\u66f4\u65b0",
"Color swatch": "\u989c\u8272\u6837\u672c",
"Turquoise": "\u9752\u7eff\u8272",
"Green": "\u7eff\u8272",
"Blue": "\u84dd\u8272",
"Purple": "\u7d2b\u8272",
"Navy Blue": "\u6d77\u519b\u84dd",
"Dark Turquoise": "\u6df1\u84dd\u7eff\u8272",
"Dark Green": "\u6df1\u7eff\u8272",
"Medium Blue": "\u4e2d\u84dd\u8272",
"Medium Purple": "\u4e2d\u7d2b\u8272",
"Midnight Blue": "\u6df1\u84dd\u8272",
"Yellow": "\u9ec4\u8272",
"Orange": "\u6a59\u8272",
"Red": "\u7ea2\u8272",
"Light Gray": "\u6d45\u7070\u8272",
"Gray": "\u7070\u8272",
"Dark Yellow": "\u6697\u9ec4\u8272",
"Dark Orange": "\u6df1\u6a59\u8272",
"Dark Red": "\u6df1\u7ea2\u8272",
"Medium Gray": "\u4e2d\u7070\u8272",
"Dark Gray": "\u6df1\u7070\u8272",
"Light Green": "\u6d45\u7eff\u8272",
"Light Yellow": "\u6d45\u9ec4\u8272",
"Light Red": "\u6d45\u7ea2\u8272",
"Light Purple": "\u6d45\u7d2b\u8272",
"Light Blue": "\u6d45\u84dd\u8272",
"Dark Purple": "\u6df1\u7d2b\u8272",
"Dark Blue": "\u6df1\u84dd\u8272",
"Black": "\u9ed1\u8272",
"White": "\u767d\u8272",
"Switch to or from fullscreen mode": "\u5207\u6362\u5168\u5c4f\u6a21\u5f0f",
"Open help dialog": "\u6253\u5f00\u5e2e\u52a9\u5bf9\u8bdd\u6846",
"history": "\u5386\u53f2",
"styles": "\u6837\u5f0f",
"formatting": "\u683c\u5f0f\u5316",
"alignment": "\u5bf9\u9f50",
"indentation": "\u7f29\u8fdb",
"permanent pen": "\u8bb0\u53f7\u7b14",
"comments": "\u5907\u6ce8",
"Format Painter": "\u683c\u5f0f\u5237",
"Insert\/edit iframe": "\u63d2\u5165\/\u7f16\u8f91\u6846\u67b6",
"Capitalization": "\u5927\u5199",
"lowercase": "\u5c0f\u5199",
"UPPERCASE": "\u5927\u5199",
"Title Case": "\u9996\u5b57\u6bcd\u5927\u5199",
"Permanent Pen Properties": "\u6c38\u4e45\u7b14\u5c5e\u6027",
"Permanent pen properties...": "\u6c38\u4e45\u7b14\u5c5e\u6027...",
"Font": "\u5b57\u4f53",
"Size": "\u5b57\u53f7",
"More...": "\u66f4\u591a...",
"Spellcheck Language": "\u62fc\u5199\u68c0\u67e5\u8bed\u8a00",
"Select...": "\u9009\u62e9...",
"Preferences": "\u9996\u9009\u9879",
"Yes": "\u662f",
"No": "\u5426",
"Keyboard Navigation": "\u952e\u76d8\u6307\u5f15",
"Version": "\u7248\u672c",
"Anchor": "\u951a\u70b9",
"Special character": "\u7279\u6b8a\u7b26\u53f7",
"Code sample": "\u4ee3\u7801\u793a\u4f8b",
"Color": "\u989c\u8272",
"Emoticons": "\u8868\u60c5",
"Document properties": "\u6587\u6863\u5c5e\u6027",
"Image": "\u56fe\u7247",
"Insert link": "\u63d2\u5165\u94fe\u63a5",
"Target": "\u6253\u5f00\u65b9\u5f0f",
"Link": "\u94fe\u63a5",
"Poster": "\u5c01\u9762",
"Media": "\u5a92\u4f53",
"Print": "\u6253\u5370",
"Prev": "\u4e0a\u4e00\u4e2a",
"Find and replace": "\u67e5\u627e\u548c\u66ff\u6362",
"Whole words": "\u5168\u5b57\u5339\u914d",
"Spellcheck": "\u62fc\u5199\u68c0\u67e5",
"Caption": "\u6807\u9898",
"Insert template": "\u63d2\u5165\u6a21\u677f"
});

View File

@ -1,6 +1,7 @@
<template>
<div class="navbar">
<hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
<hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container"
@toggleClick="toggleSideBar" />
<breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!topNav" />
<top-nav id="topmenu-container" class="topmenu-container" v-if="topNav" />
@ -8,41 +9,6 @@
<div style="padding-top: 5px; padding-right: 38px;">
<navbar-right :blackTitle='true' />
</div>
<!-- <div class="right-menu"> -->
<!-- <template v-if="device!=='mobile'"> -->
<!-- <search id="header-search" class="right-menu-item" /> -->
<!-- 站内信 -->
<!-- <notify-message class="right-menu-item hover-effect" /> -->
<!-- <screenfull id="screenfull" class="right-menu-item hover-effect" /> -->
<!-- <el-tooltip content="布局大小" effect="dark" placement="bottom">
<size-select id="size-select" class="right-menu-item hover-effect" />
</el-tooltip> -->
<!-- </template> -->
<!-- <el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click">
<div class="avatar-wrapper"> -->
<!-- <img :src="avatar" class="user-avatar"> -->
<!-- <span v-if="nickname" class="user-nickname">{{ nickname }}</span>
<i class="el-icon-caret-bottom" />
</div>
<el-dropdown-menu slot="dropdown">
<router-link to="/user/profile">
<el-dropdown-item>个人中心</el-dropdown-item>
</router-link> -->
<!-- <el-dropdown-item @click.native="setting = true">
<span>布局设置</span>
</el-dropdown-item> -->
<!-- <el-dropdown-item divided @click.native="logout">
<span>退出登录</span>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown> -->
<!-- </div> -->
</div>
</template>
@ -55,7 +21,6 @@ import Screenfull from '@/components/Screenfull'
import SizeSelect from '@/components/SizeSelect'
import Search from '@/components/HeaderSearch'
import NotifyMessage from '@/layout/components/Message'
// import {getPath} from "@/utils/ruoyi";
import NavbarRight from './NavbarRight.vue'
export default {
@ -117,7 +82,7 @@ export default {
box-shadow: 0 1px 4px rgba(0, 21, 41, .08);
.hamburger-container {
line-height: 52px;
line-height: 44px;
height: 100%;
float: left;
cursor: pointer;
@ -185,6 +150,7 @@ export default {
height: 35px;
border-radius: 50%;
}
.user-nickname {
margin-left: 5px;
font-size: 14px;

View File

@ -8,17 +8,15 @@
<tags-view v-if="needTagsView" />
</div>
<app-main />
<div class="main-footer" style="color: #C7C7C7; user-select: none; font-size: 14px; letter-spacing: 1px; height: 30px; display: grid; place-content: center;">&copy; 中建材智能自动化研究院有限公司</div>
<right-panel>
<settings />
</right-panel>
<div class="main-footer"
style="color: #C7C7C7; user-select: none; font-size: 14px; letter-spacing: 1px; height: 30px; display: grid; place-content: center;">
&copy; 中建材智能自动化研究院有限公司</div>
</div>
</div>
</template>
<script>
import RightPanel from '@/components/RightPanel'
import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components'
import { AppMain, Navbar, Sidebar, TagsView } from './components'
import ResizeMixin from './mixin/ResizeHandler'
import { mapState } from 'vuex'
import variables from '@/assets/styles/variables.scss'
@ -28,8 +26,6 @@ export default {
components: {
AppMain,
Navbar,
RightPanel,
Settings,
Sidebar,
TagsView
},

View File

@ -64,12 +64,10 @@ Vue.prototype.searchBarWidth = function (name, num) {
// 全局组件挂载
Vue.component('DictTag', DictTag);
Vue.component('DocAlert', DocAlert);
Vue.component('Pagination', Pagination);
Vue.component('RightToolbar', RightToolbar);
// 字典标签组件
import DictTag from '@/components/DictTag';
import DocAlert from '@/components/DocAlert';
// 头部标签插件
import VueMeta from 'vue-meta';
import CodeBrickZj from 'code-brick-zj';

View File

@ -0,0 +1,18 @@
export default {
data() {
return {
tableH: this.tableHeight(260),
};
},
created() {
window.addEventListener('resize', this._setTableHeight);
},
destroyed() {
window.removeEventListener('resize', this._setTableHeight);
},
methods: {
_setTableHeight() {
this.tableH = this.tableHeight(260);
},
},
};

View File

@ -1,5 +1,7 @@
$editorTabsborderColor: #121315;
body, html{
body,
html {
margin: 0;
padding: 0;
background: #F2F4F9;
@ -9,19 +11,23 @@ body, html{
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji;
}
input, textarea{
input,
textarea {
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji;
}
.editor-tabs {
background: $editorTabsborderColor;
.el-tabs__header {
margin: 0;
border-bottom-color: $editorTabsborderColor;
.el-tabs__nav {
border-color: $editorTabsborderColor;
}
}
.el-tabs__item {
height: 32px;
line-height: 32px;
@ -31,17 +37,21 @@ input, textarea{
margin-right: 5px;
user-select: none;
}
.el-tabs__item.is-active {
background: #1e1e1e;
border-bottom-color: #1e1e1e !important;
color: #fff;
}
.el-icon-edit {
color: #f1fa8c;
}
.el-icon-document {
color: #a95812;
}
:focus.is-active.is-focus:not(:active) {
box-shadow: none;
border-radius: 0;
@ -54,28 +64,34 @@ input, textarea{
padding: 12px 18px 15px 15px;
}
}
.el-scrollbar__wrap {
box-sizing: border-box;
overflow-x: hidden !important;
margin-bottom: 0 !important;
}
.center-tabs {
.el-tabs__header {
margin-bottom: 0 !important;
}
.el-tabs__item {
width: 50%;
text-align: center;
}
.el-tabs__nav {
width: 100%;
}
}
.reg-item {
padding: 12px 6px;
background: #f8f8f8;
position: relative;
border-radius: 4px;
.close-btn {
position: absolute;
right: -6px;
@ -91,18 +107,22 @@ input, textarea{
z-index: 1;
cursor: pointer;
font-size: 12px;
&:hover {
background: rgba(210, 23, 23, 0.5)
}
}
&+.reg-item {
margin-top: 18px;
}
}
.action-bar {
& .el-button+.el-button {
margin-left: 15px;
}
& i {
font-size: 20px;
vertical-align: middle;
@ -114,15 +134,19 @@ input, textarea{
.custom-tree-node {
width: 100%;
font-size: 14px;
.node-operation {
float: right;
}
i[class*="el-icon"]+i[class*="el-icon"] {
margin-left: 6px;
}
.el-icon-plus {
color: #409EFF;
}
.el-icon-delete {
color: #157a0c;
}
@ -136,76 +160,7 @@ input, textarea{
display: inline-block;
vertical-align: text-top;
}
.el-upload__tip {
line-height: 1.2;
}
// 滚动条
::-webkit-scrollbar {
width: 8px;
height: 8px;
background-color: transparent;
}
::-webkit-scrollbar-track-piece {
background-color:rgba(144,147,153,0);
}
::-webkit-scrollbar-corner {
background-color:rgba(144,147,153,0);
}
::-webkit-scrollbar-track {
width: 6px;
background: rgba(144,147,153,0);
-webkit-border-radius: 2em;
-moz-border-radius: 2em;
border-radius: 2em;
}
::-webkit-scrollbar-thumb {
background-color: #EDEDED;
background-clip: padding-box;
min-height: 28px;
-webkit-border-radius: 2em;
-moz-border-radius: 2em;
border-radius: 2em;
transition: background-color .3s;
cursor: pointer;
}
::-webkit-scrollbar-thumb:hover {
background-color: #D9D9D9;
}
// 抽屉head区域---start
.el-drawer__header {
padding-bottom: 20px;
padding-left: 30px;
margin-bottom: 23px;
font-size: 20px;
font-weight: 500;
color: rgba(0,0,0,0.85);
border-bottom: 1px solid rgba(233, 233, 233, 1);
}
.el-drawer__header > :first-child::before {
content: '';
display: inline-block;
width: 4px;
height: 24px;
background-color: #0b58ff;
margin-right: 8px;
vertical-align: middle;
}
// 抽屉head区域---end
// 弹出框上下分布去掉label的padding-bottom
.el-form--label-top .el-form-item__label {
padding: 0;
}
// 大屏滚动表格
.dv-scroll-board .rows .ceil, .dv-scroll-board .header .header-item {
border-right: 1px solid rgba(13, 23, 40, 1);
}
.dv-scroll-board .rows .ceil:last-child, .dv-scroll-board .header .header-item:last-child {
border-right: none;
}

View File

@ -2,7 +2,7 @@
* @Author: zwq
* @Date: 2021-07-19 15:18:30
* @LastEditors: zhp
* @LastEditTime: 2024-03-26 09:57:35
* @LastEditTime: 2024-03-28 15:28:07
* @Description:
-->
<template>
@ -16,35 +16,32 @@
许昌安彩AGV原片周转看板
<h3 class="unit">单位河南汇融数字科技有限公司</h3>
<h3 class="time">{{ times }}</h3>
<!-- <el-button
type="text"
class="title-button"
:style="{ right: 33 + 'px', top: 37 + 'px' }"
@click="changeFullScreen"
>
<svg-icon v-if="isFullScreen" icon-class="unFullScreenView" />
<svg-icon v-else icon-class="fullScreenView" />
</el-button> -->
<el-button type="text" class="title-button" :style="{ right: 18 + 'px', top: 26 + 'px', fontSize: '32px' }"
@click="changeFullScreen">
<svg-icon width="32" height="32" v-if="isFullScreen" icon-class="unFullScreenView" />
<svg-icon width="32" height="32" v-else icon-class="fullScreenView" />
</el-button>
</el-row>
<el-row class="container-main flex-col" type="flex">
<el-row :style="{ padding: '0 ' + 9 + 'px' }" :gutter="15 * beilv" type="flex" class="flex-1">
<el-col :style="{ margin: 8 + 'px' + ' 0' }" :span="12">
<base-container :beilv="1" :size="'middle'" :title="'搬运任务'" :title-icon="'task'" :back="'energy'">
<base-table1 :page="1" :limit="999" :show-index="false" :beilv="1" :table-config="qualityYearTableProps"
:table-data="qualityYearList" />
<base-container :beilv="1" :size="'eqStatus'" :title="'搬运任务'" :title-icon="'task'" :back="'energy'">
<!-- <base-table1 :page="1" :limit="999" :show-index="false" :beilv="1" :table-config="qualityYearTableProps"
:table-data="qualityYearList" /> -->
<dv-scroll-board :config="taskConfig" style="width:100%;height:350px" ref='taskScrollBoard' />
</base-container>
</el-col>
<el-col :style="{ margin: 8 + 'px' + ' 0' }" :span="12">
<base-container :beilv="1" :size="'middle'" :title="'周转进度'" :title-icon="'order'" :back="'energy'">
<div style="width:100%; overflow: hidden scroll;">
<base-container :beilv="1" :size="'eqStatus'" :title="'周转进度'" :title-icon="'order'" :back="'energy'">
<div class="order" style="width:100%; overflow: hidden scroll;height: 350px;">
<el-row v-for="op in orderProcessList" :key="op.id" style="margin-bottom: 1em">
<p v-if="op.outRate === 1" class="now-secondary-title" style="color:#4679FD">
<i class="el-icon-check" />
{{ op.name }}
</p>
<p v-else class="now-secondary-title">{{ op.name }}</p>
<el-progress define-back-color="rgba(32, 57, 96, 1)" text-color="white" :percentage="op.outRate * 100"
class="custom-progress-bar" />
<el-progress :stroke-width="10" define-back-color="rgba(32, 57, 96, 1)" text-color="white"
:percentage="op.outRate * 100" class="custom-progress-bar" />
</el-row>
</div>
</base-container>
@ -53,17 +50,19 @@
<el-row :style="{ padding: '0 ' + 9 + 'px' }" :gutter="12 * beilv" type="flex" class="flex-1">
<el-col :style="{ margin: 8 + 'px' + ' 0' }" :span="12">
<base-container :beilv="1" :height="256" :size="'middle'" :title="'库存管理'" :title-icon="'productLine'"
<base-container :beilv="1" :height="280" :size="'eqStatus'" :title="'库存管理'" :title-icon="'productLine'"
:back="'energy'">
<base-table :page="1" :limit="999" :show-index="false" :beilv="1" :table-config="inventoryTableProps"
:table-data="inventoryList" />
<!-- <base-table :page="1" :limit="999" :show-index="false" :beilv="1" :table-config="inventoryTableProps"
:table-data="inventoryList" /> -->
<dv-scroll-board :config="inventoryConfig" style="width:100%;height:380px" ref='inventoryScrollBoard' />
</base-container>
</el-col>
<el-col :style="{ margin: 8 + 'px' + ' 0' }" :span="12">
<base-container :beilv="1" :height="318 + 338 + 16" :size="'middle'" :title="'库位信息'" :title-icon="'info'"
<base-container :beilv="1" :height="318 + 338 + 16" :size="'eqStatus'" :title="'库位信息'" :title-icon="'info'"
:back="'energy'">
<base-table2 :page="1" :limit="999" :show-index="false" :beilv="1" :table-config="locationTableProps"
:table-data="locationList" />
<!-- <base-table2 :page="1" :limit="999" :show-index="false" :beilv="1" :table-config="locationTableProps"
:table-data="locationList" /> -->
<dv-scroll-board :config="locationConfig" style="width:100%;height:380px" ref='locationScrollBoard' />
</base-container>
</el-col>
</el-row>
@ -191,6 +190,15 @@ const inventoryList = [
{
eqName: ' 螺丝刀', eqCode: '备件库', level: '', product: ' 123', productCode: 'WLXX20220919000147', unit: '个', time: '2023年9月10日'
},
{
eqName: ' 清洗剂', eqCode: '备件库', level: '200mm', product: ' 123', productCode: 'WLXX20220919000147', unit: '瓶', time: '2023年9月10日'
},
{
eqName: ' 清洗剂', eqCode: '备件库', level: '200mm', product: ' 123', productCode: 'WLXX20220919000147', unit: '瓶', time: '2023年9月10日'
},
{
eqName: ' 清洗剂', eqCode: '备件库', level: '200mm', product: ' 123', productCode: 'WLXX20220919000147', unit: '瓶', time: '2023年9月10日'
},
{
eqName: ' 清洗剂', eqCode: '备件库', level: '200mm', product: ' 123', productCode: 'WLXX20220919000147', unit: '瓶', time: '2023年9月10日'
}
@ -267,6 +275,39 @@ export default {
inventoryTableProps,
inventoryList,
locationList,
taskConfig: {
header: ['序号', '作业号', '执行叉车', '库位', '成品规格', '成品编码', '时间'],
headerBGC: 'rgba(32, 55, 96, 0.8)',
oddRowBGC: 'rgba(32, 55, 96, 0.8)',
evenRowBGC: 'rgba(14, 32, 62, 0.8)',
columnWidth: [80, 120, 90, 140, 140, 150,130],
align: ['center'],
data: [],
// index:true,
rowNum: 10
},
inventoryConfig: {
header: ['序号', '物件名称', '存放区域', '规格', '数量', '单位', '编码', '入库时间'],
headerBGC: 'rgba(32, 55, 96, 0.8)',
oddRowBGC: 'rgba(32, 55, 96, 0.8)',
evenRowBGC: 'rgba(14, 32, 62, 0.8)',
columnWidth: [80, 100, 90, 140, 80, 70, 180, 120],
align: ['center'],
data: [],
// index:true,
rowNum: 10
},
locationConfig: {
header: ['序号', '库位名称', '存放物件名称', '数量', '存放位置', '编码', '单位', '入库时间'],
headerBGC: 'rgba(32, 55, 96, 0.8)',
oddRowBGC: 'rgba(32, 55, 96, 0.8)',
evenRowBGC: 'rgba(14, 32, 62, 0.8)',
columnWidth: [80, 100, 120, 80, 100, 180, 70, 120],
align: ['center'],
data: [],
// index:true,
rowNum: 10
},
locationTableProps,
qualityYearList,
isFullScreen: false,
@ -294,6 +335,20 @@ export default {
{
name: '作业号RQ20230911',
outRate: '0.4'
},
{
name: '作业号RQ20230911',
outRate: '0.4'
},
{
name: '作业号RQ20230911',
outRate: '0.4'
}, {
name: '作业号RQ20230911',
outRate: '0.4'
}, {
name: '作业号RQ20230911',
outRate: '0.4'
}
],
// qualityTableProps1,
@ -316,6 +371,16 @@ export default {
},
watch: {
isFullScreen: function (val) {
if (val) {
const _this = this;
_this.beilv2 = document.documentElement.clientWidth / 1920
console.log(_this.beilv2);
} else {
const _this = this;
_this.beilv2 = document.documentElement.clientWidth / 1920
}
},
clientWidth(val) {
if (!this.timer) {
this.clientWidth = val
@ -343,6 +408,9 @@ export default {
}, 86400000)
},
mounted() {
this.getTask()
this.getInventoryData()
this.getLocationData()
const _this = this;
window.onresize = () => {
return (() => {
@ -355,6 +423,60 @@ export default {
getTimes() {
setInterval(this.getTimesInterval, 1000);
},
getTask() {
let eqArr = this.qualityYearList.map((item, index) => [
`<span style="color:rgba(255,255,255,0.5)" >${index + 1 || ''}
</span>`,
// formatDate(item.planStartTime) || '',
`
<span style="color:rgba(255,255,255,0.5)" >${item.eqName || ''}
</span>`,
`<span style="color:rgba(255,255,255,0.5)">${item.eqCode || ''}</span>`,
`<span style="color:rgba(255,255,255,0.5)">${item.level || ''}</span>`,
`<span style="color:rgba(255,255,255,0.5)">${item.product || ''}</span>`,
`<span style="color:rgba(255,255,255,0.5)">${item.productCode || ''}</span>`,
`<span style="color:rgba(255,255,255,0.5)">${item.time || ''}</span>`,
])
this.taskConfig.data = eqArr
this.$refs['taskScrollBoard'].updateRows(eqArr)
},
getInventoryData() {
let eqArr = this.inventoryList.map((item, index) => [
`<span style="color:rgba(255,255,255,0.5)" >${index + 1 || ''}
</span>`,
// formatDate(item.planStartTime) || '',
`
<span style="color:rgba(255,255,255,0.5)" >${item.eqName || ''}
</span>`,
`<span style="color:rgba(255,255,255,0.5)">${item.eqCode || ''}</span>`,
`<span style="color:rgba(255,255,255,0.5)">${item.level || ''}</span>`,
`<span style="color:rgba(255,255,255,0.5)">${item.product || ''}</span>`,
`<span style="color:rgba(255,255,255,0.5)">${item.unit || ''}</span>`,
`<span style="color:rgba(255,255,255,0.5)">${item.productCode || ''}</span>`,
`<span style="color:rgba(255,255,255,0.5)">${item.time || ''}</span>`,
])
this.inventoryConfig.data = eqArr
this.$refs['inventoryScrollBoard'].updateRows(eqArr)
},
getLocationData() {
let eqArr = this.locationList.map((item, index) => [
`<span style="color:rgba(255,255,255,0.5)" >${index + 1 || ''}
</span>`,
// formatDate(item.planStartTime) || '',
`
<span style="color:rgba(255,255,255,0.5)" >${item.eqName || ''}
</span>`,
`<span style="color:rgba(255,255,255,0.5)">${item.eqCode || ''}</span>`,
`<span style="color:rgba(255,255,255,0.5)">${item.product || ''}</span>`,
`<span style="color:rgba(255,255,255,0.5)">${item.level || ''}</span>`,
`<span style="color:rgba(255,255,255,0.5)">${item.productCode || ''}</span>`,
`<span style="color:rgba(255,255,255,0.5)">${item.unit || ''}</span>`,
`<span style="color:rgba(255,255,255,0.5)">${item.time || ''}</span>`,
])
this.locationConfig.data = eqArr
this.$refs['locationScrollBoard'].updateRows(eqArr)
},
getTimesInterval: function () {
let _this = this;
let year = new Date().getFullYear(); //
@ -383,25 +505,25 @@ export default {
this.isFullScreen = screenfull.isFullscreen
},
init() {
if (screenfull.enabled) {
if (screenfull.isEnabled) {
screenfull.on('change', this.change)
}
},
destroy() {
if (screenfull.enabled) {
if (screenfull.isEnabled) {
screenfull.off('change', this.change)
}
},
changeFullScreen() {
console.log(this.beilv);
if (!screenfull.enabled) {
if (!screenfull.isEnabled) {
this.$message({
message: 'you browser can not work',
type: 'warning'
})
return false
}
screenfull.toggle(this.$refs.container)
screenfull.toggle()
}
}
}
@ -410,6 +532,9 @@ export default {
<style lang="scss" scoped>
.visual-container {
width: 1920px;
height: 1080px;
@ -418,25 +543,28 @@ export default {
// opacity: .8;
.container-title {
width: 100%;
background: url('../../assets/img/OperationalOverview/title.png') no-repeat;
background: url('../../assets/img/OperationalOverview/AGV.png') no-repeat;
background-size: 100% 100%;
color: #00fff0;
text-align: center;
word-spacing:8px;
letter-spacing: 8px;
// word-spacing: 8px;
position: relative;
.unit {
position: absolute;
left: 290px;
left: 240px;
top: 25px;
color: rgba($color: #ffffff, $alpha: 8);
color: rgba(255, 255, 255, 0.80);
font-size: 20px;
letter-spacing: 0px;
}
.time {
position: absolute;
left: 1360px;
left: 1400px;
top: 25px;
color: rgba($color: #ffffff, $alpha: 8);
color: rgba(255, 255, 255, 0.80);
font-size: 20px;
letter-spacing: 0px;
}
.title-button {
color: #00fff0;
@ -489,7 +617,9 @@ export default {
// .container-main {
// padding: 5px;
// }
.order::-webkit-scrollbar{
display: none
}
</style>
<style lang="scss" >

View File

@ -1,7 +1,7 @@
<!--
* @Author: zhp
* @Date: 2024-01-29 16:50:26
* @LastEditTime: 2024-03-26 18:00:34
* @LastEditTime: 2024-03-28 16:35:49
* @LastEditors: zhp
* @Description:
-->
@ -17,15 +17,11 @@
许昌安彩冷端看板
<h3 class="unit">单位河南汇融数字科技有限公司</h3>
<h3 class="time">{{ times }}</h3>
<!-- <el-button
type="text"
class="title-button"
:style="{ right: 33 + 'px', top: 37 + 'px' }"
@click="changeFullScreen"
>
<svg-icon v-if="isFullScreen" icon-class="unFullScreenView" />
<svg-icon v-else icon-class="fullScreenView" />
</el-button> -->
<el-button type="text" class="title-button" :style="{ right: 18 + 'px', top: 26 + 'px',fontSize:'32px'}"
@click="changeFullScreen">
<svg-icon width="32" height="32" v-if="isFullScreen" icon-class="unFullScreenView" />
<svg-icon width="32" height="32" v-else icon-class="fullScreenView" />
</el-button>
</el-row>
<el-row class="container-main flex-col" type="flex">
<el-row :style="{ padding: '0 ' + 9 + 'px' }" :gutter="15" type="flex" class="flex-1">
@ -61,15 +57,26 @@
<el-row :style="{ padding: '0 ' + 9 + 'px' }" :gutter="10" type="flex" class="flex-1">
<el-col :style="{ margin: 8 + 'px' + ' 0' }" :span="12">
<base-container :no-content-padding="true" :height="256" :title="'废片 缺陷数据'" :size="'middle'"
<base-container :no-content-padding="true" :height="256" :title="'废片 缺陷数据'" :size="'eqStatus'"
:title-icon="'scrap'">
<!-- <div style="width: 45%;position: absolute; top: 3em; right: 3em;">
<top-radio-group />
</div> -->
<!-- <el-row :gutter="9"> -->
<!-- <el-col :style="{ margin: 8 + 'px' + ' 0' }" :span="24"> -->
<pile-bar-chart ref="pileChart" :name-list="EnergyMonitoringNameList" :data-list="EnergyMonitoringList"
:height="359" />
<pile-bar-chart style="margin-bottom: -15px" ref="firstPileChart" :height="90" />
<second-pile-bar-chart style="margin-bottom: -15px" id=" 'second' " ref="secondPileChart" :height="90" />
<third-pile-bar-chart style="margin-bottom: -15px" id=" 'third' " ref="thirdPileChart" :height="90" />
<fourth-pile-bar-chart style="margin-bottom: -15px" id=" 'fourth' " ref="fourthPileChart" :height="90" />
<fifth-pile-bar-chart style="margin-bottom: -15px" id=" 'fifth' " ref="fifthPileChart" :height="100" />
<!-- <pile-bar-chart ref="secondPileChart"
:height="90" />
<pile-bar-chart ref="thirdPileChart"
:height="90" />
<pile-bar-chart ref="fourthPileChart"
:height="90" />
<pile-bar-chart ref="fifthPileChart"
:height="90" /> -->
<!-- </el-col> -->
<!-- <el-col :style="{ margin: 8 + 'px' + ' 0' }" :span="12">
<base-table3
@ -90,21 +97,21 @@
</div> -->
<!-- 像下面这样表格里的limit值也许可以用js动态计算出来 -->
<el-col :span="8" style="">
<div style="font-size:20px;margin: 5px 0 10px 0">熔化风机</div>
<div style="color:rgba(82, 255, 248, 1);font-size:20px;margin: 5px 0 10px 0">熔化风机</div>
<!-- <base-table1 :page="1" :limit="999" :show-index="false" :table-config="EqMonitoringPropsFun"
:table-data="funList" /> -->
<dv-scroll-board :config="funConfig" style="width:100%;height:310px" ref='funScrollBoard' />
</el-col>
<span class="eqLine"></span>
<el-col :span="8">
<div style="font-size:20px;margin: 5px 0 10px 0;">退火风机</div>
<div style="color:rgba(82, 255, 248, 1);font-size:20px;margin: 5px 0 10px 0;">退火风机</div>
<!-- <base-table1 :page="1" :limit="999" :show-index="false" :table-config="EqMonitoringPropsFun"
:table-data="annealFunList" /> -->
<dv-scroll-board :config="annealFunConfig" style="width:100%;height:310px" ref='annealFunScrollBoard' />
</el-col>
<span class="eqLineTwo"></span>
<el-col :span="8" style="float: right;">
<div style="font-size:20px;margin: 5px 0 10px 0;">产线设备</div>
<div style="color:rgba(82, 255, 248, 1);font-size:20px;margin: 5px 0 10px 0;">产线设备</div>
<!-- <base-table1 :page="1" :limit="999" :show-index="false" :table-config="EqMonitoringProps"
:table-data="realEqList" /> -->
<dv-scroll-board :config="realEqConfig" style="width:100%;height:310px" ref='realEqScrollBoard' />
@ -136,6 +143,11 @@ import baseContainer from './components/baseContainer'
import baseTable1 from './components/baseTable'
import screenfull from 'screenfull'
import pileBarChart from './components/pileBarChart'
import secondPileBarChart from './components/pileBarChart'
import thirdPileBarChart from './components/pileBarChart'
import fourthPileBarChart from './components/pileBarChart'
import fifthPileBarChart from './components/pileBarChart'
import colorDiv from './components/colorDiv'
import moment from "moment";
import doubleYChart from './components/coldDoubleYChart'
@ -152,7 +164,11 @@ export default {
pileBarChart,
doubleYChart,
LinearBarChart,
ISRAChart
ISRAChart,
secondPileBarChart,
thirdPileBarChart ,
fourthPileBarChart,
fifthPileBarChart ,
},
data() {
return {
@ -256,6 +272,16 @@ export default {
},
watch: {
isFullScreen:function (val) {
if (val) {
const _this = this;
_this.beilv2 = document.documentElement.clientWidth / 1920
console.log(_this.beilv2);
} else {
const _this = this;
_this.beilv2 = document.documentElement.clientWidth / 1920
}
},
clientWidth(val) {
if (!this.timer) {
this.clientWidth = val
@ -275,6 +301,7 @@ export default {
setTimeout(() => {
window.location.reload()
}, 86400000)
// this.getData()
},
destroyed() {
this.CutWebsocketClose()
@ -287,21 +314,96 @@ export default {
}
},
mounted() {
console.log(moment(this.logoutTime - 28800000).format('HH:mm:ss'));
let nameList = []
let nameWasteList = []
let topNameList = []
let productList = []
let wasteList = []
let yieldList = []
// let sumAreaList = []
// let yieldList = []
// this.cutTableDataList =
let coldDetData = [
{
"first": 0.8834,
"lineName": "Y61",
"product": 0.8834,
"productArea": 35069.28,
"second": 0,
'sumArea': 38400,
'wastArea': 3330.72,
"yield": 0.9133
},
{
"first": 0.847,
"lineName": "Y62",
"product": 0.847,
"productArea": 26765.46,
"second": 0,
'sumArea': 1111111,
'wastArea': 22222,
"yield": 0.9133
},
{
"first": 0.8668,
"lineName": "Y63",
"product": 0.8668,
"productArea": 26448.46,
"second": 0,
'sumArea': 1111111,
'wastArea': 22222,
"yield": 0.9133
},
{
"first": 0.9064,
"lineName": "Y64",
"product": 0.9064,
"productArea": 26667.32,
"second": 0,
'sumArea': 1111111,
'wastArea': 22222,
"yield": 0.9133
},
{
"first": 0.8838,
"lineName": "Y65",
"product": 0.8838,
"productArea": 26554.32,
"second": 0,
'sumArea': 1111111,
'wastArea': 22222,
"yield": 0.9133
}
]
coldDetData.forEach((ele, index) => {
nameList.push(ele.lineName)
topNameList.push('产线: ' + ele.lineName + ' ' + '总面积:' + ele.sumArea)
productList.push(ele.productArea)
wasteList.push(ele.wastArea)
nameWasteList.push('缺陷面积:' + ele.wastArea)
yieldList.push({
name: '良品',
yield:ele.yield
})
// sumAreaList.push(ele.sumArea)
// yieldList.push((ele.yield * 100).toFixed(3))
})
this.$refs.firstPileChart.initChart(nameList, [topNameList[0]], [nameWasteList[0]], [productList[0]], [wasteList[0]])
this.$refs.secondPileChart.initChart(nameList, [topNameList[1]], [nameWasteList[1]], [productList[1]], [wasteList[1]])
this.$refs.thirdPileChart.initChart(nameList, [topNameList[2]], [nameWasteList[2]], [productList[2]], [wasteList[2]])
this.$refs.fourthPileChart.initChart(nameList, [topNameList[3]], [nameWasteList[3]], [productList[3]], [wasteList[3]])
this.$refs.fifthPileChart.initChart(nameList, [topNameList[4]], [nameWasteList[4]], [productList[4]], [wasteList[4]])
// this.$refs.productChart.initChart(nameList, yieldList, sumAreaList)
this.getTimes()
// console.log(moment(this.logoutTime - 28800000).format('HH:mm:ss'));
this.funInitWebSocket()
// if (num > 0) {
if (!this.wsIsOpen) {
getDcsMsg()
this.wsIsOpen = true
console.log('开启websocket==========')
}
// } else {
// }
this.CutInitWebSocket()
this.SJGInitWebSocket()
// this.getList()
this.getTimes()
const _this = this;
_this.beilv2 = document.documentElement.clientWidth / 1920
window.onresize = () => {
@ -312,6 +414,39 @@ export default {
}
},
methods: {
// getData() {
// let detData = [
// {
// name: '1',
// run: '',
// },
// {
// name: '2',
// run: '',
// },
// {
// name: '3',
// run: '',
// },
// {
// name: '4',
// run: '',
// },
// {
// name: '1',
// run: '',
// },
// ]
// this.realEqList = detData.map((item, index) => [
// // console.log(item)
// `<span style="color:rgba(255,255,255,0.5)" >${index + 1 || ''}
// </span>`,
// `<span style="color:rgba(255,255,255,0.5)">${item.name || ''}</span>`,
// `<span style="color:rgba(255,255,255,0.5)"><div style="${item.run == '' ? 'box-shadow: 0px 0px 2px 1px #2760FF;width:6px;height:6px;border-radius: 50%;background-color: #2760FF;float:left;margin:10px 10px 0 0 ' : 'box-shadow: 0px 0px 2px 1px #FFBD02;width:6px;height:6px;border-radius: 50%; background-color: #FFBD02;float:left;margin:10px 10px 0 0 '}"></div> ${item.run || ''}</span>`,
// ])
// this.realEqConfig.data = this.realEqList
// this.$refs['realEqScrollBoard'].updateRows(this.realEqList)
// },
CutWebsocketClose(e) {
this.Cutws.ws.onclose = (event) => { console.log(event );}
},
@ -386,11 +521,14 @@ export default {
`<span style="color:rgba(255,255,255,0.5)" >${index + 1 || ''}
</span>`,
`<span style="color:rgba(255,255,255,0.5)">${item.name || ''}</span>`,
`<span style="color:rgba(255,255,255,0.5)">${item.run || ''}</span>`,
`<span style="color:rgba(255,255,255,0.5)"><div style="${item.run == '运行' ? 'box-shadow: 0px 0px 2px 1px #2760FF;width:6px;height:6px;border-radius: 50%;background-color: #2760FF;float:left;margin:10px 10px 0 0 ' : 'box-shadow: 0px 0px 2px 1px #FFBD02;width:6px;height:6px;border-radius: 50%; background-color: #FFBD02;float:left;margin:10px 10px 0 0 '}"></div> ${item.run || ''}</span>`,
])
}
this.realEqConfig.data = this.realEqList
this.$nextTick(() => {
this.$refs['realEqScrollBoard'].updateRows(this.realEqList)
})
};
// if (typeof (WebSocket) === 'undefined') {
// alert('WebSocket')
@ -451,9 +589,13 @@ export default {
wasteList.push(ele.wastArea)
nameWasteList.push('缺陷面积:' + ele.wastArea)
sumAreaList.push(ele.sumArea)
yieldList.push((ele.yield * 100).toFixed(3))
yieldList.push(parseFloat((ele.yield * 100).toFixed(3)))
})
this.$refs.pileChart.initChart(nameList, topNameList, nameWasteList, productList, wasteList)
this.$refs.firstPileChart.initChart(nameList, [topNameList[0]], [nameWasteList[0]], [productList[0]], [wasteList[0]])
this.$refs.secondPileChart.initChart(nameList, [topNameList[1]], [nameWasteList[1]], [productList[1]], [wasteList[1]])
this.$refs.thirdPileChart.initChart(nameList, [topNameList[0]], [nameWasteList[0]], [productList[0]], [wasteList[0]])
this.$refs.fourthPileChart.initChart(nameList, [topNameList[0]], [nameWasteList[0]], [productList[0]], [wasteList[0]])
this.$refs.fifthPileChart.initChart(nameList, [topNameList[0]], [nameWasteList[0]], [productList[0]], [wasteList[0]])
this.$refs.productChart.initChart(nameList, yieldList, sumAreaList)
}
};
@ -495,7 +637,8 @@ export default {
</span>`,
`<span style="color:rgba(255,255,255,0.5)" >${i || ''}
</span>`,
`<span style="color:rgba(255,255,255,0.5)">${this.funWsData.data.annealFanInfo[i] || ''}</span>`,
`<span style="color:rgba(255,255,255,0.5)">${item.name || ''}</span>`,
`<span style="color:rgba(255,255,255,0.5)"><div style="${item.run == '运行' ? 'box-shadow: 0px 0px 2px 1px #2760FF;width:6px;height:6px;border-radius: 50%;background-color: #2760FF;float:left;margin:10px 10px 0 0 ' : 'box-shadow: 0px 0px 2px 1px #FFBD02;width:6px;height:6px;border-radius: 50%; background-color: #FFBD02;float:left;margin:10px 10px 0 0 '}"></div> ${item.run || ''}</span>`,
])
}
this.annealFunConfig.data = arr
@ -509,7 +652,8 @@ export default {
arr.push([
`<span style="color:rgba(255,255,255,0.5)" >${index || ''}</span>`,
`<span style="color:rgba(255,255,255,0.5)" >${i || ''}</span>`,
`<span style="color:rgba(255,255,255,0.5)">${this.funWsData.data.fanInfo[i] || ''}</span>`,
`<span style="color:rgba(255,255,255,0.5)">${item.name || ''}</span>`,
`<span style="color:rgba(255,255,255,0.5)"><div style="${item.run == '运行' ? 'box-shadow: 0px 0px 2px 1px #2760FF;width:6px;height:6px;border-radius: 50%;background-color: #2760FF;float:left;margin:10px 10px 0 0 ' : 'box-shadow: 0px 0px 2px 1px #FFBD02;width:6px;height:6px;border-radius: 50%; background-color: #FFBD02;float:left;margin:10px 10px 0 0 '}"></div> ${item.run || ''}</span>`,
])
}
this.funConfig.data = arr
@ -594,106 +738,34 @@ export default {
// console.log(size[0] + '*' + size[1] + '*' + size[2]);
return size[0] + '*' + size[1] + '*' + size[2]
},
//
// cutWebsocketOnMessage(e) {
// this.cutWsData = e?.data ? JSON.parse(e?.data) : {}
// if (this.cutWsData.type === 'cutting' && this.cutWsData.name === 'table') {
// let cutArr = this.cutWsData.productHourData.map((item, index) => [
// `<span style="color:rgba(255,255,255,0.7)" >${index + 1 || ''}
// </span>`,
// `<span style="color:rgba(255,255,255,0.7)" >${item.lineName || ''}
// </span>`,
// `<span style="color:rgba(255,255,255,0.7)">${this.formatTime(item.time) || ''}</span>`,
// `<span style="color:rgba(255,255,255,0.7)">${this.getSize(item.size) || ''}</span>`,
// `<span style="color:rgba(255,255,255,0.7)">${item.productArea + '' || ''}</span>`,
// `<span style="color:rgba(255,255,255,0.7)">${item.wasteArea + '' || ''}</span>`,
// `<div style = "${(item.product * 100).toFixed(2) > 91 ? 'display:block;color:#00FFF7' : 'display:none;'}">${(item.product * 100).toFixed(2) + '%' || ''}</div>
// <div style = "${(item.product * 100).toFixed(2) < 91 ? 'display:block; color:rgba(255, 209, 96, 1)' : 'display:none;'}">${(item.product * 100).toFixed(2) + '%' || ''}</div>`
// ])
// this.cutConfig.data = cutArr
// this.$refs['cutScrollBoard'].updateRows(cutArr)
// } else if (this.cutWsData.type === 'cutting' && this.cutWsData.name === 'chart' && this.cutWsData.dateType === 'day') {
// let nameList = []
// let nameWasteList = []
// let topNameList = []
// let productList = []
// let wasteList = []
// let sumAreaList = []
// let yieldList = []
// // this.cutTableDataList =
// this.cutWsData.coldDetData.forEach((ele, index) => {
// nameList.push(ele.lineName)
// topNameList.push('线: ' + ele.lineName + ' ' + ':' + ele.sumArea)
// productList.push(ele.productArea)
// wasteList.push(ele.wastArea)
// nameWasteList.push(':' + ele.wastArea)
// sumAreaList.push(ele.sumArea)
// yieldList.push((ele.yield *100).toFixed(3))
// })
// this.$refs.pileChart.initChart(nameList, topNameList, nameWasteList, productList, wasteList)
// this.$refs.productChart.initChart(nameList, yieldList, sumAreaList)
// }
// },
// SJGWebsocketOnOpen() {
// console.log('socket')
// this.SJGWebsocket.onmessage()
// },
//
// SJGWebsocketOnError(e) {
// this.SJGInitWebSocket()
// },
//
// SJGWebsocketOnMessage(e) {
// this.SJGWsData = e?.data ? JSON.parse(e?.data) : {}
// if (this.SJGWsData.type === 'isra') {
// console.log('222222', this.SJGWsData.detData)
// console.log(this.SJGWsData.detData);
// let chartData = this.SJGWsData.detData.map((item, index) => {
// return {
// name: item.type,
// num:item.num
// }
// })
// this.$refs['ISRAChart'].updateChart(chartData)
// } else if (this.SJGWsData.type === 'equipment') {
// this.realEqList = this.SJGWsData.detData.map((ele, index) =>[
// // console.log(item)
// `<span style="color:rgba(255,255,255,0.5)" >${index + 1 || ''}
// </span>`,
// `<span style="color:rgba(255,255,255,0.5)">${ele.name || ''}</span>`,
// `<span style="color:rgba(255,255,255,0.5)">${ele.run || ''}</span>`,
// ])
// }
// this.realEqConfig.data = this.realEqList
// this.$refs['realEqScrollBoard'].updateRows(this.realEqList)
// },
windowWidth(value) {
this.clientWidth = value
this.beilv2 = this.clientWidth / 1920
},
change() {
console.log(this.isFullScreen);
this.isFullScreen = screenfull.isFullscreen
},
init() {
if (screenfull.enabled) {
if (screenfull.isEnabled) {
screenfull.on('change', this.change)
}
},
destroy() {
if (screenfull.enabled) {
if (screenfull.isEnabled) {
screenfull.off('change', this.change)
}
},
changeFullScreen() {
this.containerWidth = 223223223
if (!screenfull.enabled) {
// this.containerWidth = 223223223
if (!screenfull.isEnabled) {
this.$message({
message: 'you browser can not work',
type: 'warning'
})
return false
}
screenfull.toggle(this.$refs.container)
screenfull.toggle()
}
}
}
@ -714,13 +786,15 @@ export default {
background-size: 100% 100%;
color: rgba(0, 255, 247, 1);
text-align: center;
letter-spacing: 8px;
word-spacing: 8px;
.unit {
position: absolute;
left: 260px;
left: 290px;
top: 25px;
color: rgba(255, 255, 255, 0.80);
font-size: 20px;
letter-spacing: 0px;
}
.time {
@ -729,6 +803,7 @@ export default {
color: rgba(255, 255, 255, 0.80);
top: 25px;
font-size: 20px;
letter-spacing: 0px;
}
.title-button {
@ -780,6 +855,10 @@ export default {
top: 2em;
}
.screen-btn {
color: #00fff0;
font-size: 32px;
}
// .container-main {
// padding: 5px;
// }
@ -868,6 +947,7 @@ background: linear-gradient(to bottom,rgba(60,
margin-left: 3em;
}
}
</style>
<style scoped>
@ -926,4 +1006,5 @@ background: linear-gradient(to bottom,rgba(60,
.tooltip:hover .tooltiptext {
visibility: visible;
}
</style>

View File

@ -1,8 +1,8 @@
<!--
* @Author: zwq
* @Date: 2022-01-21 14:43:06
* @LastEditors: zwq
* @LastEditTime: 2022-01-24 13:27:41
* @LastEditors: zhp
* @LastEditTime: 2024-03-28 16:30:54
* @Description:
-->
<template>
@ -61,7 +61,7 @@ export default {
},
mounted() {
this.$nextTick(() => {
this.initChart()
// this.initChart()
})
},
beforeDestroy() {

View File

@ -2,7 +2,7 @@
* @Author: zwq
* @Date: 2022-01-21 14:43:06
* @LastEditors: zhp
* @LastEditTime: 2024-01-25 17:41:44
* @LastEditTime: 2024-03-28 16:45:24
* @Description:
-->
<template>
@ -90,6 +90,7 @@ export default {
bottom: 0,
itemHeight: 10,
itemWidth: 10,
icon:'roundRect',
formatter: function(name) {
let pieLegendVale = {}
lData.filter((item, index) => {

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