123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546 |
- <template>
- <div class="_fd-event">
- <el-badge :value="eventNum" type="warning" :hidden="eventNum < 1">
- <el-button size="small" @click="visible=true">{{ t('event.title') }}</el-button>
- </el-badge>
- <el-dialog class="_fd-event-dialog" :title="t('event.title')" v-model="visible" destroy-on-close
- :close-on-click-modal="false"
- append-to-body
- width="980px">
- <el-container class="_fd-event-con" style="height: 600px">
- <el-aside style="width:300px;">
- <el-container class="_fd-event-l">
- <el-header class="_fd-event-head" height="40px">
- <el-dropdown popper-class="_fd-event-dropdown" trigger="click" size="default"
- :placement="'bottom-start'">
- <span class="el-dropdown-link">
- <el-button link type="primary" size="default">
- {{ t('event.create') }}<i class="el-icon-arrow-down el-icon--right"></i>
- </el-button>
- </span>
- <template #dropdown>
- <el-dropdown-menu>
- <el-dropdown-item v-for="name in eventName" :key="name" @click="add(name)"
- :disabled="Object.keys(event).indexOf(name) > -1">
- <div class="_fd-event-item">
- <span>{{ name }}</span>
- <span class="_fd-label" v-if="eventInfo[name]">
- {{ eventInfo[name] }}
- </span>
- </div>
- </el-dropdown-item>
- <template v-for="(hook, idx) in hookList">
- <el-dropdown-item :divided="eventName.length > 0 && !idx"
- @click="add(hook)"
- :disabled="Object.keys(event).indexOf(hook) > -1">
- <div class="_fd-event-item">
- <div> {{ hook }}</div>
- <span class="_fd-label">
- {{ eventInfo[hook] }}
- </span>
- </div>
- </el-dropdown-item>
- </template>
- <el-dropdown-item :divided="eventName.length > 0" @click="cusEvent">
- <div>{{ t('props.custom') }}</div>
- </el-dropdown-item>
- </el-dropdown-menu>
- </template>
- </el-dropdown>
- </el-header>
- <el-main>
- <el-menu
- :default-active="defActive"
- v-model="activeData">
- <template v-for="(item, name) in event">
- <template v-if="Array.isArray(item)">
- <template v-for="(event, index) in item" :key="name + index">
- <el-menu-item :index="name + index">
- <div class="_fd-event-title"
- @click.stop="edit({name, item, index})">
- <div class="_fd-event-method">
- <span>function<span>{{
- name
- }}</span></span>
- <span class="_fd-label"
- v-if="eventInfo[name]">{{ eventInfo[name] }}</span>
- </div>
- <i class="fc-icon icon-delete"
- @click.stop="rm({name, item, index})"></i>
- </div>
- </el-menu-item>
- </template>
- </template>
- <el-menu-item v-else :index="name + 0">
- <div class="_fd-event-title" @click.stop="edit({name})">
- <div class="_fd-event-method">
- <span>function<span>{{
- name
- }}</span></span>
- <span class="_fd-label"
- v-if="eventInfo[name]">{{ eventInfo[name] }}</span>
- </div>
- <i class="fc-icon icon-delete" @click.stop="rm({name})"></i>
- </div>
- </el-menu-item>
- </template>
- <el-menu-item v-if="cus" style="padding-left: 10px;" index="custom">
- <div class="_fd-event-title" @click.stop>
- <el-input type="text" v-model="cusValue" size="default"
- @keydown.enter="addCus"
- :placeholder="t('event.placeholder')">
- </el-input>
- <div>
- <i class="fc-icon icon-add" @click.stop="addCus"></i>
- <i class="fc-icon icon-delete" @click.stop="closeCus"></i>
- </div>
- </div>
- </el-menu-item>
- </el-menu>
- </el-main>
- </el-container>
- </el-aside>
- <el-main>
- <el-container class="_fd-event-r">
- <el-header class="_fd-event-head" height="40px" v-if="activeData">
- <div><a target="_blank" href="https://form-create.com/v3/instance/">{{t('form.document')}}</a></div>
- <div>
- <el-button size="small" @click="close">{{ t('props.cancel') }}</el-button>
- <el-button size="small" type="primary" @click="save" color="#2f73ff">{{
- t('props.save')
- }}
- </el-button>
- </div>
- </el-header>
- <el-main v-if="activeData">
- <FnEditor ref="fn" v-model="eventStr" body :name="activeData.name"
- :args="fnArgs"
- style="height: 519px;"/>
- </el-main>
- </el-container>
- </el-main>
- </el-container>
- <template #footer>
- <div>
- <el-button size="default" @click="visible=false">{{ t('props.cancel') }}</el-button>
- <el-button type="primary" size="default" @click="submit" color="#2f73ff">{{
- t('props.ok')
- }}
- </el-button>
- </div>
- </template>
- </el-dialog>
- </div>
- </template>
- <script>
- import unique from '@form-create/utils/lib/unique';
- import deepExtend from '@form-create/utils/lib/deepextend';
- import is from '@form-create/utils/lib/type';
- import {defineComponent} from 'vue';
- import FnEditor from './FnEditor.vue';
- import errorMessage from '../utils/message';
- import {getInjectArg} from '../utils';
- const $T = '$FNX:';
- const isFNX = v => {
- return is.String(v) && v.indexOf($T) === 0;
- };
- export default defineComponent({
- name: 'EventConfig',
- emits: ['update:modelValue'],
- props: {
- modelValue: [Object, undefined, null],
- componentName: '',
- eventName: {
- type: Array,
- default: () => []
- }
- },
- inject: ['designer'],
- components: {
- FnEditor,
- },
- data() {
- return {
- visible: false,
- activeData: null,
- val: null,
- defActive: 'no',
- hookList: ['hook_load', 'hook_mounted', 'hook_deleted', 'hook_watch', 'hook_value', 'hook_hidden'],
- event: {},
- cus: false,
- cusValue: '',
- eventStr: '',
- };
- },
- computed: {
- t() {
- return this.designer.setupState.t;
- },
- activeRule() {
- return this.designer.setupState.activeRule;
- },
- eventInfo() {
- const info = {};
- this.eventName.forEach(v => {
- info[v] = this.t('com.' + this.componentName + '.event.' + v) || this.t('eventInfo.' + v) || '';
- })
- this.hookList.forEach(v => {
- info[v] = this.t('eventInfo.' + v) || '';
- })
- return info;
- },
- eventNum() {
- let num = 0;
- Object.keys(this.modelValue || {}).forEach(k => {
- num += Array.isArray(this.modelValue[k]) ? this.modelValue[k].length : 1;
- });
- const hooks = this.activeRule ? {...this.activeRule.hook || {}} : {};
- Object.keys(hooks).forEach(k => {
- num += Array.isArray(this.activeRule.hook[k]) ? this.activeRule.hook[k].length : 1;
- });
- return num;
- },
- fnArgs() {
- return [getInjectArg(this.t)];
- }
- },
- watch: {
- visible(v) {
- this.event = v ? this.loadFN() : {};
- if (!v) {
- this.destroy();
- this.closeCus();
- }
- },
- },
- methods: {
- addCus() {
- const val = this.cusValue && this.cusValue.trim();
- if (val) {
- this.closeCus();
- this.add(val);
- }
- },
- closeCus() {
- this.cus = false;
- this.cusValue = '';
- },
- cusEvent() {
- this.cus = true;
- },
- loadFN() {
- const e = deepExtend({}, this.modelValue || {});
- const hooks = this.activeRule ? {...this.activeRule.hook || {}} : {};
- Object.keys(hooks).forEach(k => {
- e['hook_' + k] = hooks[k];
- })
- const val = {};
- Object.keys(e).forEach(k => {
- if (Array.isArray(e[k])) {
- const data = [];
- e[k].forEach(v => {
- if (isFNX(v)) {
- data.push(v.replace($T, ''));
- } else if (is.Function(v) && isFNX(v.__json)) {
- data.push(v.__json.replace($T, ''));
- } else if (v && v.indexOf('$GLOBAL:') === 0) {
- data.push(v);
- }
- });
- val[k] = data;
- } else if (isFNX(e[k])) {
- val[k] = [e[k].replace($T, '')];
- } else if (is.Function(e[k]) && isFNX(e[k].__json)) {
- val[k] = [e[k].__json.replace($T, '')];
- } else if (e[k] && e[k].indexOf('$GLOBAL:') === 0) {
- val[k] = [e[k]];
- }
- });
- return val;
- },
- parseFN(e) {
- const on = {};
- const hooks = {};
- Object.keys(e).forEach(k => {
- const lst = [];
- e[k].forEach((v, i) => {
- lst[i] = v.indexOf('$GLOBAL:') !== 0 ? ($T + v) : v;
- });
- if (lst.length > 0) {
- if (k.indexOf('hook_') > -1) {
- hooks[k.replace('hook_', '')] = lst.length === 1 ? lst[0] : lst;
- } else {
- on[k] = lst.length === 1 ? lst[0] : lst;
- }
- }
- });
- return {hooks, on};
- },
- add(name) {
- let data = {};
- if (Array.isArray(this.event[name])) {
- this.event[name].push('');
- data = {
- name,
- item: this.event[name],
- index: this.event[name].length - 1,
- };
- } else if (this.event[name]) {
- const arr = [this.event[name], ''];
- this.event[name] = arr;
- data = {
- name,
- item: arr,
- index: 1,
- };
- } else {
- const arr = [''];
- this.event[name] = arr;
- data = {
- name,
- item: arr,
- index: 0,
- };
- }
- if (!this.activeData) {
- this.edit(data);
- }
- },
- edit(data) {
- data.key = unique();
- if (data.item) {
- this.val = data.item[data.index];
- } else {
- this.val = this.event[data.name];
- }
- this.activeData = data;
- this.eventStr = this.val;
- this.defActive = data.name + (data.index || 0);
- },
- save() {
- if (!this.$refs.fn.save()) {
- return;
- }
- const str = this.eventStr;
- if (this.activeData.item) {
- this.activeData.item[this.activeData.index] = str;
- } else {
- this.event[this.activeData.name] = str;
- }
- this.destroy();
- },
- rm(data) {
- if (data.index !== undefined) {
- data.item.splice(data.index, 1);
- } else {
- this.$delete(this.event, data.name);
- }
- if (this.defActive === (data.name + (data.index || 0))) {
- this.destroy();
- }
- },
- destroy() {
- this.activeData = null;
- this.val = null;
- this.defActive = 'no';
- },
- close() {
- this.destroy();
- },
- submit() {
- if (this.activeData) {
- return errorMessage(this.t('event.saveMsg'));
- }
- const {on, hooks} = this.parseFN(this.event);
- this.$emit('update:modelValue', on);
- this.activeRule.hook = hooks;
- this.visible = false;
- this.destroy();
- this.closeCus();
- },
- },
- beforeCreate() {
- window.$inject = {
- $f: {},
- rule: [],
- self: {},
- option: {},
- inject: {},
- args: [],
- };
- }
- });
- </script>
- <style>
- ._fd-event .el-button {
- font-weight: 400;
- width: 100%;
- border-color: #2E73FF;
- color: #2E73FF;
- }
- ._fd-event .el-badge {
- width: 100%;
- }
- ._fd-event-dialog .el-dialog__body {
- padding: 10px 20px;
- }
- ._fd-event-con .el-main {
- padding: 0;
- }
- ._fd-event-l, ._fd-event-r {
- display: flex;
- flex-direction: column;
- flex: 1;
- height: 100%;
- border: 1px solid #ececec;
- }
- ._fd-event-dropdown .el-dropdown-menu {
- max-height: 500px;
- overflow: auto;
- }
- ._fd-event-head {
- display: flex;
- padding: 5px 15px;
- border-bottom: 1px solid #eee;
- background: #f8f9ff;
- align-items: center;
- }
- ._fd-event-head .el-button.is-link {
- color: #2f73ff;
- }
- ._fd-event-r {
- border-left: 0 none;
- }
- ._fd-event-r ._fd-event-head {
- justify-content: space-between;
- }
- ._fd-event-l > .el-main, ._fd-event-r > .el-main {
- display: flex;
- flex-direction: row;
- flex: 1;
- flex-basis: auto;
- box-sizing: border-box;
- min-width: 0;
- width: 100%;
- }
- ._fd-event-r > .el-main {
- flex-direction: column;
- }
- ._fd-event-item {
- display: flex;
- flex-direction: column;
- justify-content: center;
- max-width: 250px;
- font-size: 14px;
- overflow: hidden;
- white-space: pre-wrap;
- }
- ._fd-event-item ._fd-label {
- font-size: 12px;
- color: #AAAAAA;
- }
- ._fd-event-l .el-menu {
- padding: 0 10px 5px;
- border-right: 0 none;
- width: 100%;
- border-top: 0 none;
- overflow: auto;
- }
- ._fd-event-l .el-menu-item.is-active {
- background: #e4e7ed;
- color: #303133;
- }
- ._fd-event-l .el-menu-item {
- height: auto;
- line-height: 1em;
- border: 1px solid #ECECEC;
- border-radius: 5px;
- padding: 0;
- margin-top: 5px;
- }
- ._fd-event-method {
- display: flex;
- flex-direction: column;
- justify-content: center;
- width: 225px;
- font-size: 14px;
- font-family: monospace;
- color: #9D238C;
- overflow: hidden;
- white-space: pre-wrap;
- }
- ._fd-event-method ._fd-label {
- margin-top: 4px;
- color: #AAAAAA;
- font-size: 12px;
- }
- ._fd-event-method > span:first-child, ._fd-fn-list-method > span:first-child {
- color: #9D238C;
- }
- ._fd-event-method > span:first-child > span, ._fd-fn-list-method > span:first-child > span {
- color: #000;
- margin-left: 10px;
- }
- ._fd-event-title {
- display: flex;
- align-items: center;
- justify-content: space-between;
- width: 100%;
- padding: 10px 0;
- }
- ._fd-event-title .fc-icon {
- margin-right: 6px;
- font-size: 18px;
- color: #282828;
- }
- ._fd-event-title .el-input {
- width: 200px;
- }
- ._fd-event-title .el-input__wrapper {
- box-shadow: none;
- }
- ._fd-event-title .el-menu-item.is-active i {
- color: #282828;
- }
- ._fd-event-con .CodeMirror {
- height: 100%;
- width: 100%;
- }
- ._fd-event-con .CodeMirror-wrap pre.CodeMirror-line {
- padding-left: 20px;
- }
- </style>
|