├── babel.config.js ├── public ├── favicon.ico └── index.html ├── src ├── assets │ ├── edit.png │ ├── flow.png │ ├── logo.png │ ├── delete.png │ ├── icon-ask.png │ ├── logo copy.png │ ├── node-img.png │ ├── icon-single.png │ ├── node-close.png │ ├── node-timer.png │ ├── block-preview.png │ ├── icon-multiple.png │ ├── icon-operation.png │ ├── icon-trigger.png │ ├── grid-background.png │ └── icon-destination.png ├── router.js ├── main.js ├── components │ ├── node │ │ ├── destinationNode.vue │ │ ├── singleNode.vue │ │ ├── askNode.vue │ │ ├── operationNode.vue │ │ ├── multipleNode.vue │ │ └── triggerNode.vue │ ├── miniView │ │ └── miniView.vue │ ├── tool.vue │ ├── node_form.vue │ ├── node.vue │ └── jumpRelationContainer │ │ └── jumpRelationContainer.vue ├── store.js ├── App.vue ├── utils │ ├── util.js │ └── filter.js ├── scss │ └── node.scss └── views │ └── Home.vue ├── .editorconfig ├── .gitignore ├── vue.config.js ├── README.md └── package.json /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee-won/vue-jsPlumb-case/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /src/assets/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee-won/vue-jsPlumb-case/HEAD/src/assets/edit.png -------------------------------------------------------------------------------- /src/assets/flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee-won/vue-jsPlumb-case/HEAD/src/assets/flow.png -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee-won/vue-jsPlumb-case/HEAD/src/assets/logo.png -------------------------------------------------------------------------------- /src/assets/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee-won/vue-jsPlumb-case/HEAD/src/assets/delete.png -------------------------------------------------------------------------------- /src/assets/icon-ask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee-won/vue-jsPlumb-case/HEAD/src/assets/icon-ask.png -------------------------------------------------------------------------------- /src/assets/logo copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee-won/vue-jsPlumb-case/HEAD/src/assets/logo copy.png -------------------------------------------------------------------------------- /src/assets/node-img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee-won/vue-jsPlumb-case/HEAD/src/assets/node-img.png -------------------------------------------------------------------------------- /src/assets/icon-single.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee-won/vue-jsPlumb-case/HEAD/src/assets/icon-single.png -------------------------------------------------------------------------------- /src/assets/node-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee-won/vue-jsPlumb-case/HEAD/src/assets/node-close.png -------------------------------------------------------------------------------- /src/assets/node-timer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee-won/vue-jsPlumb-case/HEAD/src/assets/node-timer.png -------------------------------------------------------------------------------- /src/assets/block-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee-won/vue-jsPlumb-case/HEAD/src/assets/block-preview.png -------------------------------------------------------------------------------- /src/assets/icon-multiple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee-won/vue-jsPlumb-case/HEAD/src/assets/icon-multiple.png -------------------------------------------------------------------------------- /src/assets/icon-operation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee-won/vue-jsPlumb-case/HEAD/src/assets/icon-operation.png -------------------------------------------------------------------------------- /src/assets/icon-trigger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee-won/vue-jsPlumb-case/HEAD/src/assets/icon-trigger.png -------------------------------------------------------------------------------- /src/assets/grid-background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee-won/vue-jsPlumb-case/HEAD/src/assets/grid-background.png -------------------------------------------------------------------------------- /src/assets/icon-destination.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lee-won/vue-jsPlumb-case/HEAD/src/assets/icon-destination.png -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,jsx,ts,tsx,vue}] 2 | indent_style = space 3 | indent_size = 2 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | -------------------------------------------------------------------------------- /src/router.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import Home from './views/Home.vue' 4 | 5 | Vue.use(Router) 6 | 7 | export default new Router({ 8 | // mode: 'history', 9 | base: process.env.BASE_URL, 10 | routes: [{ 11 | path: '/', 12 | name: 'home', 13 | component: Home 14 | }] 15 | }) -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | module.exports = { 3 | lintOnSave: false, 4 | configureWebpack: { 5 | plugins: [ 6 | new webpack.ProvidePlugin({ 7 | $: 'jquery', 8 | jQuery: 'jquery', 9 | 'windows.jQuery': 'jquery', 10 | Popper: ['popper.js', 'default'] 11 | }) 12 | ] 13 | } 14 | } -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | import store from './store' 5 | import $ from 'jquery' 6 | import '@/utils/filter' 7 | 8 | import ElementUI from 'element-ui' 9 | import 'element-ui/lib/theme-chalk/index.css' 10 | 11 | Vue.use(ElementUI) 12 | 13 | Vue.config.productionTip = false 14 | 15 | new Vue({ 16 | router, 17 | store, 18 | render: h => h(App) 19 | }).$mount('#app') -------------------------------------------------------------------------------- /src/components/node/destinationNode.vue: -------------------------------------------------------------------------------- 1 | 6 | 21 | 27 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | js-plumb 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### 该项目模仿的是某机器人供应商关于多轮聊天的流程配置功能。虽然阉割了大量的业务逻辑功能,但是关于 jsPlumb 的实际应用还是很全面的。 2 | 3 | ![img](https://github.com/lee-won/vue-jsPlumb-case/blob/master/src/assets/flow.png) 4 | 5 | ## Project setup 6 | 7 | ``` 8 | npm install 9 | ``` 10 | 11 | ### Compiles and hot-reloads for development 12 | 13 | ``` 14 | npm run serve 15 | ``` 16 | 17 | ### Compiles and minifies for production 18 | 19 | ``` 20 | npm run build 21 | ``` 22 | 23 | ### Run your tests 24 | 25 | ``` 26 | npm run test 27 | ``` 28 | 29 | ### Lints and fixes files 30 | 31 | ``` 32 | npm run lint 33 | ``` 34 | 35 | ### Customize configuration 36 | 37 | See [Configuration Reference](https://cli.vuejs.org/config/). 38 | -------------------------------------------------------------------------------- /src/components/miniView/miniView.vue: -------------------------------------------------------------------------------- 1 | 6 | 11 | 35 | -------------------------------------------------------------------------------- /src/store.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | Vue.use(Vuex) 5 | 6 | export default new Vuex.Store({ 7 | state: { 8 | nodeList: [], 9 | scrollPosition: {} 10 | }, 11 | getters: { 12 | getNodeList: state => { 13 | return state.nodeList 14 | }, 15 | getScrollPosition: state => { 16 | return state.scrollPosition 17 | } 18 | }, 19 | mutations: { 20 | setNodeList(state, payload) { 21 | state.nodeList = payload 22 | }, 23 | setScrollPosition(state, payload) { 24 | state.scrollPosition = payload 25 | } 26 | }, 27 | actions: { 28 | listenNodeListChange(context, payload) { 29 | context.commit('setNodeList', payload) 30 | }, 31 | listenScrollPosition(context, payload) { 32 | context.commit('setScrollPosition', payload) 33 | } 34 | } 35 | }) -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 45 | -------------------------------------------------------------------------------- /src/utils/util.js: -------------------------------------------------------------------------------- 1 | export const util = { 2 | deepCopy(obj, cache = []) { 3 | function find(list, f) { 4 | return list.filter(f)[0] 5 | } 6 | // just return if obj is immutable value 7 | if (obj === null || typeof obj !== 'object') { 8 | return obj 9 | } 10 | 11 | // if obj is hit, it is in circular structure 12 | const hit = find(cache, c => c.original === obj) 13 | if (hit) { 14 | return hit.copy 15 | } 16 | 17 | const copy = Array.isArray(obj) ? [] : {} 18 | // put the copy into cache at first 19 | // because we want to refer it in recursive deepCopy 20 | cache.push({ 21 | original: obj, 22 | copy 23 | }) 24 | 25 | Object.keys(obj).forEach(key => { 26 | copy[key] = this.deepCopy(obj[key], cache) 27 | }) 28 | 29 | return copy 30 | }, 31 | getRandomId() { 32 | return Math.random().toString().substring(3, 7) 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /src/components/node/singleNode.vue: -------------------------------------------------------------------------------- 1 | 22 | 37 | 40 | -------------------------------------------------------------------------------- /src/components/node/askNode.vue: -------------------------------------------------------------------------------- 1 | 22 | 37 | 40 | -------------------------------------------------------------------------------- /src/components/node/operationNode.vue: -------------------------------------------------------------------------------- 1 | 22 | 37 | 40 | -------------------------------------------------------------------------------- /src/components/node/multipleNode.vue: -------------------------------------------------------------------------------- 1 | 22 | 37 | 40 | -------------------------------------------------------------------------------- /src/scss/node.scss: -------------------------------------------------------------------------------- 1 | .node-content { 2 | .gray { 3 | font-size: 12px; 4 | color: #687c8a; 5 | font-weight: bold; 6 | margin-right: 10px; 7 | } 8 | .blue { 9 | font-size: 12px; 10 | color: rgb(31, 119, 243); 11 | font-weight: bold; 12 | margin-right: 10px; 13 | } 14 | .slot, 15 | .branch-jump { 16 | text-align: left; 17 | height: 30px; 18 | display: flex; 19 | align-items: center; 20 | padding: 0 10px; 21 | position: relative; 22 | &:hover { 23 | background: #eee; 24 | .visual-endpoint-dom { 25 | background: rgb(31, 119, 243); 26 | border: none; 27 | } 28 | } 29 | .visual-endpoint-dom { 30 | position: absolute; 31 | top: 50%; 32 | right: -8px; 33 | width: 14px; 34 | height: 14px; 35 | margin-top: -9px; 36 | border-width: 3px; 37 | border-style: solid; 38 | border-color: rgb(142, 156, 168); 39 | border-image: initial; 40 | border-radius: 8px; 41 | background: rgb(255, 255, 255); 42 | box-sizing: border-box; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/components/node/triggerNode.vue: -------------------------------------------------------------------------------- 1 | 13 | 28 | 63 | -------------------------------------------------------------------------------- /src/utils/filter.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | const conditions = [{ 3 | value: 1, 4 | label: '等于' 5 | }, 6 | { 7 | value: 2, 8 | label: '不等于' 9 | }, 10 | { 11 | value: 3, 12 | label: '大于' 13 | }, 14 | { 15 | value: 4, 16 | label: '大于等于' 17 | }, 18 | { 19 | value: 5, 20 | label: '小于' 21 | }, 22 | { 23 | value: 6, 24 | label: '小于等于' 25 | }, 26 | { 27 | value: 7, 28 | label: '包含' 29 | }, 30 | { 31 | value: 8, 32 | label: '不包含' 33 | }, 34 | { 35 | value: 9, 36 | label: '属于实体' 37 | }, 38 | { 39 | value: 10, 40 | label: '不属于实体' 41 | }, 42 | { 43 | value: 11, 44 | label: '符合正则' 45 | }, 46 | { 47 | value: 12, 48 | label: '不符合正则' 49 | }, 50 | { 51 | value: 13, 52 | label: '不满足条件' 53 | }, 54 | { 55 | value: 500, 56 | label: '异常' 57 | }, 58 | { 59 | value: 200, 60 | label: '有结果' 61 | }, 62 | { 63 | value: 201, 64 | label: '无结果' 65 | } 66 | ] 67 | Vue.filter('setRuleEnumCode', (code) => { 68 | const temp = conditions.filter((item) => { 69 | return item.value === code 70 | }) 71 | console.log(code, temp, 1111) 72 | 73 | return temp[0].label 74 | }) -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "js-plumb", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "core-js": "^2.6.5", 12 | "element-ui": "^2.12.0", 13 | "jquery": "^3.4.1", 14 | "jsplumb": "^2.9.2", 15 | "vue": "^2.6.10", 16 | "vue-router": "^3.0.3", 17 | "vuedraggable": "^2.23.1", 18 | "vuex": "^3.0.1" 19 | }, 20 | "devDependencies": { 21 | "@vue/cli-plugin-babel": "^3.11.0", 22 | "@vue/cli-plugin-eslint": "^3.11.0", 23 | "@vue/cli-service": "^3.11.0", 24 | "@vue/eslint-config-standard": "^4.0.0", 25 | "babel-eslint": "^10.0.1", 26 | "eslint": "^5.16.0", 27 | "eslint-plugin-vue": "^5.0.0", 28 | "node-sass": "^4.9.0", 29 | "sass-loader": "^7.1.0", 30 | "vue-template-compiler": "^2.6.10" 31 | }, 32 | "eslintConfig": { 33 | "root": true, 34 | "env": { 35 | "node": true, 36 | "jquery": true 37 | }, 38 | "extends": [ 39 | "plugin:vue/essential", 40 | "@vue/standard" 41 | ], 42 | "rules": {}, 43 | "parserOptions": { 44 | "parser": "babel-eslint" 45 | } 46 | }, 47 | "postcss": { 48 | "plugins": { 49 | "autoprefixer": {} 50 | } 51 | }, 52 | "browserslist": [ 53 | "> 1%", 54 | "last 2 versions" 55 | ] 56 | } 57 | -------------------------------------------------------------------------------- /src/components/tool.vue: -------------------------------------------------------------------------------- 1 | 15 | 99 | 135 | -------------------------------------------------------------------------------- /src/components/node_form.vue: -------------------------------------------------------------------------------- 1 | 56 | 57 | 120 | 121 | 148 | -------------------------------------------------------------------------------- /src/components/node.vue: -------------------------------------------------------------------------------- 1 | 41 | 42 | 108 | 109 | 211 | -------------------------------------------------------------------------------- /src/components/jumpRelationContainer/jumpRelationContainer.vue: -------------------------------------------------------------------------------- 1 | 80 | 205 | 321 | -------------------------------------------------------------------------------- /src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 47 | 48 | 548 | 614 | --------------------------------------------------------------------------------