Compare commits

..

61 Commits

Author SHA1 Message Date
Loki 676d9a969c 👍 新增渔场 2023-11-17 11:30:30 +08:00
Loki 70bbdab4e6 👍 新增代码生成器 2023-07-01 14:37:15 +08:00
lyt cbc705f4da 新增商品缓存 2023-07-01 14:36:53 +08:00
lyt f646ebdb0b 解决新增商品切换页面缓存问题 2023-07-01 14:36:52 +08:00
lyt ad37b47ede 新建商品清空表单 2023-07-01 14:36:52 +08:00
WIN-ISA1S7G2S9M\Administrator 56730da156 修改秒杀商品拼团商品规格图片问题,商品词条增加搜索 2023-07-01 14:36:52 +08:00
sj 4c7362a05f 售后物流 2023-07-01 14:36:51 +08:00
sj 0c9d6942c8 支持缓存及会员等级修改 2023-07-01 14:36:49 +08:00
sj 975d24764b 优化商品清理缓存等 2022-12-01 14:53:35 +08:00
sj e7554d863c 优惠券发放增加提示 2022-11-30 18:32:16 +08:00
sj 4d93aae5d5 支持优惠券发放 2022-11-30 16:30:03 +08:00
sj a2082879ef 修复下架商品点击跳转偶尔失灵问题 2022-11-30 14:22:49 +08:00
sj faea52e6f9 修复拼团页面缓存问题 2022-11-30 11:53:29 +08:00
1304317391@qq.com ac6ccbbb16 拼团秒杀砍价支持链接图 2022-11-28 19:08:06 +08:00
1304317391@qq.com cb95aad42f 商品增加链接图 2022-11-28 15:31:50 +08:00
1304317391@qq.com 0bd17e1b34 优化页面缓存,增加订单取消 2022-11-25 23:16:32 +08:00
1304317391@qq.com 63c39e1359 砍价操作优化 2022-11-24 19:25:42 +08:00
1304317391@qq.com 61d8d39da0 商品支持多列表独立排序,评测可不需要商品 2022-11-23 20:32:17 +08:00
1304317391@qq.com d3faa07a88 订单报表功能支持 2022-11-21 19:43:36 +08:00
sj e257c559f7 增加缓存清除 2022-11-19 14:24:05 +08:00
sj 08281203b0 修复会员等级修改 2022-11-18 13:37:55 +08:00
sj bd20e911fd 支持缓存及会员等级修改 2022-11-17 11:32:11 +08:00
sj b152f7899b 删除多余代码 2022-11-15 15:17:22 +08:00
sj 6954e3bf8c 优化商品查询方法 2022-11-14 16:20:13 +08:00
sj a0aec27ffc 品牌选择框支持搜索 2022-11-11 16:26:25 +08:00
sj 5f1aa2d11f 多规格属性同步改为同步当前行下面所有行 2022-11-10 17:20:58 +08:00
sj 4103c2c107 多规格属性同步改为仅同步下个规格 2022-11-10 15:44:07 +08:00
sj f73b2fd168 增加多规格属性同步按钮 2022-11-10 11:54:18 +08:00
sj 87363f0223 优化秒杀时间配置 2022-11-09 18:21:11 +08:00
sj c4aa10e2a9 优化秒杀时间配置 2022-11-09 18:04:53 +08:00
sj fa41413b88 优化榜单排序 2022-11-08 13:48:36 +08:00
sj 83b2ce4e62 商品增加榜单设置 2022-11-05 19:15:15 +08:00
sj 5f04f583c5 增加品牌馆滚动条 2022-11-03 16:13:44 +08:00
sj cd0b65067e 商品增加小程序底部栏配置 2022-11-02 17:06:50 +08:00
sj b77de18506 修复富文本框按顺序上传,更新榜单增加时间字段 2022-11-01 14:23:15 +08:00
sj 6a2910c927 商品增加无理由退款等配置,去除专家单位限制 2022-10-31 18:35:04 +08:00
sj 1fe8b75ea5 优化页面与提示 2022-10-29 18:45:46 +08:00
sj 18bd0e9f19 修复评测并增加商品参数字段 2022-10-28 19:39:45 +08:00
sj 7c213069d8 为图片上传框增加最大高度及滚动条 2022-10-28 10:26:24 +08:00
sj 8118ddcf4b 评测进行更改 2022-10-27 18:47:32 +08:00
sj 46437af817 修复文本框链接问题 2022-10-25 20:34:38 +08:00
sj 76f6039a1d 修改商品详情上传及评测视频 2022-10-25 20:17:32 +08:00
sj 3d61423374 修改商品详情上传及评测视频 2022-10-25 18:34:45 +08:00
sj 8a01cf1021 修改登录页面 2022-10-24 14:13:46 +08:00
sj db2e7d8b24 修改登录页面 2022-10-24 14:06:57 +08:00
sj 7e4aa23926 增加常见问题、关于我们等配置 2022-10-21 19:01:49 +08:00
sj 5d11378f41 修复后台浏览记录界面 2022-10-17 11:01:21 +08:00
sj 3174c1c54d 修复专家评测模块 2022-10-14 16:57:31 +08:00
sj 78f26b76c4 修复优惠券时间问题 2022-10-13 14:58:34 +08:00
sj d4c0e7926c 问题:热榜商品选择器框内回显问题 2022-10-12 11:10:16 +08:00
sj eb5877bbd3 修复营销活动 2022-09-30 18:31:40 +08:00
sj 36efe2efac 增加商品词条模块 2022-09-29 17:04:00 +08:00
sj e81c4987ba 修复评测后台回显 2022-09-27 17:09:11 +08:00
sj a7dabdf8e1 新增评测模块 2022-09-22 09:34:30 +08:00
sj 7e76feff54 修复页面显示问题 2022-09-21 10:15:36 +08:00
sj 3e3cb64443 优惠券时间限制修改 2022-09-20 14:44:21 +08:00
sj 461183909e 增加专家模块 2022-09-19 17:59:00 +08:00
sj 40464254ce 商品的品牌管理修改 2022-09-17 18:42:33 +08:00
sj 2bf312d793 增加商品的品牌管理 2022-09-16 16:36:15 +08:00
sj 65169fb6f5 页面修改 2022-09-09 18:29:28 +08:00
sj 5db02efc4c 页面修改 2022-09-09 18:29:11 +08:00
175 changed files with 27141 additions and 19058 deletions
+3 -3
View File
@@ -4,10 +4,10 @@ NODE_ENV = development
ENV = 'staging'
# 页面标题
VUE_APP_TITLE = 农场管理系统
VUE_APP_TITLE = 后台管理系统
# 农场管理系统/测试环境
VUE_APP_BASE_API = 'http://127.0.0.1:48080'
# 后台管理系统/测试环境
VUE_APP_BASE_API = 'http://192.168.10.129:48080'
# 根据服务器或域名修改
PUBLIC_PATH = '/admin-ui/'
+4 -2
View File
@@ -2,10 +2,12 @@
ENV = 'development'
# 页面标题
VUE_APP_TITLE = 农场管理系统
VUE_APP_TITLE = 后台管理系统
# 农场管理系统/开发环境
# 后台管理系统/开发环境
VUE_APP_BASE_API = 'http://192.168.10.129:48080'
# VUE_APP_BASE_API = 'http://yudao.test.yixinhuixiang.com'
# 路由懒加载
VUE_CLI_BABEL_TRANSPILE_MODULES = true
+2 -2
View File
@@ -2,9 +2,9 @@
ENV = 'production'
# 页面标题
VUE_APP_TITLE = 农场管理系统
VUE_APP_TITLE = 后台管理系统
# 农场管理系统/生产环境
# 后台管理系统/生产环境
VUE_APP_BASE_API = '/admin-api'
# 根据服务器或域名修改
+2 -2
View File
@@ -1,12 +1,12 @@
NODE_ENV = production
# 页面标题
VUE_APP_TITLE = 农场管理系统
VUE_APP_TITLE = 后台管理系统
# 测试环境配置
ENV = 'staging'
# 农场管理系统/测试环境
# 后台管理系统/测试环境
VUE_APP_BASE_API = 'http://api-dashboard.yudao.iocoder.cn'
# 静态资源地址
+2 -1
View File
@@ -19,4 +19,5 @@ selenium-debug.log
*.sln
*.local
# package-lock.json
package-lock.json
yarn.lock
+8
View File
@@ -0,0 +1,8 @@
### 2023年7月1日 zyh新增)
- 新增一个BXG模块里的代码生成器 .这个生成器后端部分暂时还有一些报错
- 菜单SQL请让后端放进vue-pro的menu表:
```
INSERT INTO `vue_pro`.`system_menu` (`id`, `name`, `permission`, `menu_type`, `hidden`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1884, 'BXG生成器', '', 2, 0, 0, 1600, 'generator', 'people', 'bxg/tools/generator/index', 0, '1', '2023-06-28 12:00:09', '1', '2023-06-28 12:05:21', b'0');
INSERT INTO `vue_pro`.`system_menu` (`id`, `name`, `permission`, `menu_type`, `hidden`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1885, 'genconfig', '', 2, 0, 0, 1600, 'generator/config/:tableName', '#', 'bxg/tools/generator/config', 0, '1', '2023-06-28 14:43:47', '1', '2023-06-28 15:09:27', b'0');
INSERT INTO `vue_pro`.`system_menu` (`id`, `name`, `permission`, `menu_type`, `hidden`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1886, 'preview', '', 2, 0, 0, 1600, 'generator/config/:tableName', '#', 'bxg/tools/generator/config', 0, '1', '2023-06-28 14:56:46', '1', '2023-06-28 15:09:45', b'0');
```
+1
View File
@@ -1,3 +1,4 @@
client_max_body_size 500m;
server {
listen 80;
listen [::]:80;
+8431 -8501
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "yudao-ui-admin",
"version": "1.6.2-snapshot",
"description": "农场管理系统",
"description": "后台管理系统",
"author": "芋道",
"license": "MIT",
"scripts": {
+29 -27
View File
@@ -1,25 +1,24 @@
(function () {
/* eslint-disable */
if (window.frameElement.id) {
let parent = window.parent,
var parent = window.parent;
//dialog对象
dialog = parent.$EDITORUI[window.frameElement.id.replace( /_iframe$/, '' )];
//当前打开dialog的编辑器实例
editor = dialog.editor;
dialog = parent.$EDITORUI[window.frameElement.id.replace(/_iframe$/, '')],
UE = parent.UE;
editor = dialog.editor,
domUtils = UE.dom.domUtils;
UE = parent.UE,
utils = UE.utils;
domUtils = UE.dom.domUtils,
browser = UE.browser;
utils = UE.utils,
browser = UE.browser,
/* eslint-disable */
ajax = UE.ajax,
ajax = UE.ajax;
$G = function ( id ) {
return document.getElementById( id )
},
};
//focus元素
$focus = function ( node ) {
setTimeout( function () {
if ( browser.ie ) {
@@ -33,21 +32,22 @@
};
window.nowEditor = {editor: editor, dialog: dialog};
utils.loadFile(document,{
href: editor.options.themePath + editor.options.theme + '/dialogbase.css?cache=' + Math.random(),
tag: 'link',
type: 'text/css',
rel: 'stylesheet'
href:editor.options.themePath + editor.options.theme + "/dialogbase.css?cache="+Math.random(),
tag:"link",
type:"text/css",
rel:"stylesheet"
});
var lang = editor.getLang(dialog.className.split('-')[2]);
lang = editor.getLang(dialog.className.split( "-" )[2]);
if(lang){
domUtils.on(window,'load',function () {
var langImgPath = editor.options.langPath + editor.options.lang + '/images/';
var langImgPath = editor.options.langPath + editor.options.lang + "/images/";
//针对静态资源
for (var i in lang['static']) {
for ( var i in lang["static"] ) {
var dom = $G( i );
if(!dom) continue;
let tagName = dom.tagName,
content = lang['static'][i];
var tagName = dom.tagName,
content = lang["static"][i];
if(content.src){
//clone
content = utils.extend({},content,false);
@@ -55,19 +55,19 @@
}
if(content.style){
content = utils.extend({},content,false);
content.style = content.style.replace(/url\s*\(/g, 'url(' + langImgPath)
content.style = content.style.replace(/url\s*\(/g,"url(" + langImgPath)
}
switch ( tagName.toLowerCase() ) {
case 'var':
case "var":
dom.parentNode.replaceChild( document.createTextNode( content ), dom );
break;
case 'select':
case "select":
var ops = dom.options;
for ( var j = 0, oj; oj = ops[j]; ) {
oj.innerHTML = content.options[j++];
}
for ( var p in content ) {
p != 'options' && dom.setAttribute(p, content[p]);
p != "options" && dom.setAttribute( p, content[p] );
}
break;
default :
@@ -76,5 +76,7 @@
}
} );
}
}
})();
+2 -2
View File
@@ -256,7 +256,7 @@ var scrawl = function (options) {
if (img) {
if (!scaleCon) {
picBoard.style.cssText = "position:relative;z-index:1;"+picBoard.style.cssText;
picBoard.style.cssText = "position:relative;z-index:999;"+picBoard.style.cssText;
img.style.cssText = "position: absolute;top:" + (canvas.height - img.height) / 2 + "px;left:" + (canvas.width - img.width) / 2 + "px;";
var scale = new ScaleBoy();
picBoard.appendChild(scale.init());
@@ -268,7 +268,7 @@ var scrawl = function (options) {
picBoard.style.zIndex = "";
} else {
scaleCon.style.visibility = "visible";
picBoard.style.cssText += "position:relative;z-index:1";
picBoard.style.cssText += "position:relative;z-index:999";
}
}
}
Binary file not shown.
+202 -273
View File
@@ -7,96 +7,25 @@
*/
UE.I18N['en'] = {
'labelMap':{
'anchor': 'Anchor',
'undo': 'Undo',
'redo': 'Redo',
'bold': 'Bold',
'indent': 'Indent',
'snapscreen': 'SnapScreen',
'italic': 'Italic',
'underline': 'Underline',
'strikethrough': 'Strikethrough',
'subscript': 'SubScript',
'fontborder': 'text border',
'superscript': 'SuperScript',
'formatmatch': 'Format Match',
'source': 'Source',
'blockquote': 'BlockQuote',
'pasteplain': 'PastePlain',
'selectall': 'SelectAll',
'print': 'Print',
'preview': 'Preview',
'horizontal': 'Horizontal',
'removeformat': 'RemoveFormat',
'time': 'Time',
'date': 'Date',
'unlink': 'Unlink',
'insertrow': 'InsertRow',
'insertcol': 'InsertCol',
'mergeright': 'MergeRight',
'mergedown': 'MergeDown',
'deleterow': 'DeleteRow',
'deletecol': 'DeleteCol',
'splittorows': 'SplitToRows',
'insertcode': 'insert code',
'splittocols': 'SplitToCols',
'splittocells': 'SplitToCells',
'deletecaption': 'DeleteCaption',
'inserttitle': 'InsertTitle',
'mergecells': 'MergeCells',
'deletetable': 'DeleteTable',
'cleardoc': 'Clear',
'insertparagraphbeforetable': 'InsertParagraphBeforeTable',
'fontfamily': 'FontFamily',
'fontsize': 'FontSize',
'paragraph': 'Paragraph',
'simpleupload': 'Single Image',
'insertimage': 'Multi Image',
'edittable': 'Edit Table',
'edittd': 'Edit Td',
'link': 'Link',
'emotion': 'Emotion',
'spechars': 'Spechars',
'searchreplace': 'SearchReplace',
'map': 'BaiduMap',
'gmap': 'GoogleMap',
'insertvideo': 'Video',
'help': 'Help',
'justifyleft': 'JustifyLeft',
'justifyright': 'JustifyRight',
'justifycenter': 'JustifyCenter',
'justifyjustify': 'Justify',
'forecolor': 'FontColor',
'backcolor': 'BackColor',
'insertorderedlist': 'OL',
'insertunorderedlist': 'UL',
'fullscreen': 'FullScreen',
'directionalityltr': 'EnterFromLeft',
'directionalityrtl': 'EnterFromRight',
'rowspacingtop': 'RowSpacingTop',
'rowspacingbottom': 'RowSpacingBottom',
'pagebreak': 'PageBreak',
'insertframe': 'Iframe',
'imagenone': 'Default',
'imageleft': 'ImageLeft',
'imageright': 'ImageRight',
'attachment': 'Attachment',
'imagecenter': 'ImageCenter',
'wordimage': 'WordImage',
'lineheight': 'LineHeight',
'edittip': 'EditTip',
'customstyle': 'CustomStyle',
'scrawl': 'Scrawl',
'autotypeset': 'AutoTypeset',
'webapp': 'WebAPP',
'touppercase': 'UpperCase',
'tolowercase': 'LowerCase',
'template': 'Template',
'background': 'Background',
'inserttable': 'InsertTable',
'music': 'Music',
'charts': 'charts',
'drafts': 'Load from Drafts'
'anchor':'Anchor', 'undo':'Undo', 'redo':'Redo', 'bold':'Bold', 'indent':'Indent', 'snapscreen':'SnapScreen',
'italic':'Italic', 'underline':'Underline', 'strikethrough':'Strikethrough', 'subscript':'SubScript','fontborder':'text border',
'superscript':'SuperScript', 'formatmatch':'Format Match', 'source':'Source', 'blockquote':'BlockQuote',
'pasteplain':'PastePlain', 'selectall':'SelectAll', 'print':'Print', 'preview':'Preview',
'horizontal':'Horizontal', 'removeformat':'RemoveFormat', 'time':'Time', 'date':'Date',
'unlink':'Unlink', 'insertrow':'InsertRow', 'insertcol':'InsertCol', 'mergeright':'MergeRight', 'mergedown':'MergeDown',
'deleterow':'DeleteRow', 'deletecol':'DeleteCol', 'splittorows':'SplitToRows','insertcode':'insert code',
'splittocols':'SplitToCols', 'splittocells':'SplitToCells','deletecaption':'DeleteCaption','inserttitle':'InsertTitle',
'mergecells':'MergeCells', 'deletetable':'DeleteTable', 'cleardoc':'Clear', 'insertparagraphbeforetable':"InsertParagraphBeforeTable",
'fontfamily':'FontFamily', 'fontsize':'FontSize', 'paragraph':'Paragraph','simpleupload':'Single Image','insertimage':'Multi Image','edittable':'Edit Table', 'edittd':'Edit Td','link':'Link',
'emotion':'Emotion', 'spechars':'Spechars', 'searchreplace':'SearchReplace', 'map':'BaiduMap', 'gmap':'GoogleMap',
'insertvideo':'Video', 'help':'Help', 'justifyleft':'JustifyLeft', 'justifyright':'JustifyRight', 'justifycenter':'JustifyCenter',
'justifyjustify':'Justify', 'forecolor':'FontColor', 'backcolor':'BackColor', 'insertorderedlist':'OL',
'insertunorderedlist':'UL', 'fullscreen':'FullScreen', 'directionalityltr':'EnterFromLeft', 'directionalityrtl':'EnterFromRight',
'rowspacingtop':'RowSpacingTop', 'rowspacingbottom':'RowSpacingBottom', 'pagebreak':'PageBreak', 'insertframe':'Iframe', 'imagenone':'Default',
'imageleft':'ImageLeft', 'imageright':'ImageRight', 'attachment':'Attachment', 'imagecenter':'ImageCenter', 'wordimage':'WordImage',
'lineheight':'LineHeight','edittip':'EditTip','customstyle':'CustomStyle', 'scrawl':'Scrawl', 'autotypeset':'AutoTypeset',
'webapp':'WebAPP', 'touppercase':'UpperCase', 'tolowercase':'LowerCase','template':'Template','background':'Background','inserttable':'InsertTable',
'music':'Music', 'charts': 'charts','drafts': 'Load from Drafts'
},
'insertorderedlist':{
'num':'1,2,3...',
@@ -142,34 +71,34 @@ UE.I18N['en'] = {
'exceedSizeError': 'File Size Exceed',
'exceedTypeError': 'File Type Not Allow',
'jsonEncodeError': 'Server Return Format Error',
'loading': 'loading...',
'loadError': 'load error',
'errorLoadConfig': 'Server config not loaded, upload can not work.'
'loading':"loading...",
'loadError':"load error",
'errorLoadConfig': 'Server config not loaded, upload can not work.',
},
'simpleupload':{
'exceedSizeError': 'File Size Exceed',
'exceedTypeError': 'File Type Not Allow',
'jsonEncodeError': 'Server Return Format Error',
'loading': 'loading...',
'loadError': 'load error',
'errorLoadConfig': 'Server config not loaded, upload can not work.'
'loading':"loading...",
'loadError':"load error",
'errorLoadConfig': 'Server config not loaded, upload can not work.',
},
'elementPathTip': 'Path',
'wordCountTip': 'Word Count',
'elementPathTip':"Path",
'wordCountTip':"Word Count",
'wordCountMsg':'{#count} characters entered,{#leave} left. ',
'wordOverFlowMsg':'<span style="color:red;">The number of characters has exceeded allowable maximum values, the server may refuse to save!</span>',
'ok': 'OK',
'cancel': 'Cancel',
'closeDialog': 'closeDialog',
'tableDrag': 'You must import the file uiUtils.js before drag! ',
'autofloatMsg': 'The plugin AutoFloat depends on EditorUI!',
'ok':"OK",
'cancel':"Cancel",
'closeDialog':"closeDialog",
'tableDrag':"You must import the file uiUtils.js before drag! ",
'autofloatMsg':"The plugin AutoFloat depends on EditorUI!",
'loadconfigError': 'Get server config error.',
'loadconfigFormatError': 'Server config format error.',
'loadconfigHttpError': 'Get server config http error.',
'snapScreen_plugin':{
'browserMsg': 'Only IE supported!',
'callBackErrorMsg': 'The callback data is wrong,please check the config!',
'uploadErrorMsg': 'Upload error,please check your server environment! '
'browserMsg':"Only IE supported!",
'callBackErrorMsg':"The callback data is wrong,please check the config!",
'uploadErrorMsg':"Upload error,please check your server environment! "
},
'insertcode':{
'as3':'ActionScript 3',
@@ -197,31 +126,31 @@ UE.I18N['en'] = {
'vb':'Visual Basic',
'xml':'XML'
},
'confirmClear': 'Do you confirm to clear the Document?',
'confirmClear':"Do you confirm to clear the Document?",
'contextMenu':{
'delete': 'Delete',
'selectall': 'Select all',
'deletecode': 'Delete Code',
'cleardoc': 'Clear Document',
'confirmclear': 'Do you confirm to clear the Document?',
'unlink': 'Unlink',
'paragraph': 'Paragraph',
'edittable': 'Table property',
'delete':"Delete",
'selectall':"Select all",
'deletecode':"Delete Code",
'cleardoc':"Clear Document",
'confirmclear':"Do you confirm to clear the Document?",
'unlink':"Unlink",
'paragraph':"Paragraph",
'edittable':"Table property",
'aligncell':'Align cell',
'aligntable':'Table alignment',
'tableleft':'Left float',
'tablecenter':'Center',
'tableright':'Right float',
'aligntd':'Cell alignment',
'edittd': 'Cell property',
'edittd':"Cell property",
'setbordervisible':'set table edge visible',
'table': 'Table',
'table':"Table",
'justifyleft':'Justify Left',
'justifyright':'Justify Right',
'justifycenter':'Justify Center',
'justifyjustify':'Default',
'deletetable': 'Delete table',
'insertparagraphbefore': 'InsertedBeforeLine',
'deletetable':"Delete table",
'insertparagraphbefore':"InsertedBeforeLine",
'insertparagraphafter':'InsertedAfterLine',
'inserttable':'Insert table',
'insertcaption':'Insert caption',
@@ -232,19 +161,19 @@ UE.I18N['en'] = {
'deletetitlecol':'Delete Title Col',
'averageDiseRow':'AverageDise Row',
'averageDisCol':'AverageDis Col',
'deleterow': 'Delete row',
'deletecol': 'Delete col',
'insertrow': 'Insert row',
'insertcol': 'Insert col',
'deleterow':"Delete row",
'deletecol':"Delete col",
'insertrow':"Insert row",
'insertcol':"Insert col",
'insertrownext':'Insert Row Next',
'insertcolnext':'Insert Col Next',
'mergeright': 'Merge right',
'mergeleft': 'Merge left',
'mergedown': 'Merge down',
'mergecells': 'Merge cells',
'splittocells': 'Split to cells',
'splittocols': 'Split to Cols',
'splittorows': 'Split to Rows',
'mergeright':"Merge right",
'mergeleft':"Merge left",
'mergedown':"Merge down",
'mergecells':"Merge cells",
'splittocells':"Split to cells",
'splittocols':"Split to Cols",
'splittorows':"Split to Rows",
'tablesort':'Table sorting',
'enablesort':'Sorting Enable',
'disablesort':'Sorting Disable',
@@ -260,14 +189,14 @@ UE.I18N['en'] = {
'unsetbackground':'Cancel Bk interlaced',
'redandblue':'Blue and red',
'threecolorgradient':'Three-color gradient',
'copy': 'Copy(Ctrl + c)',
'copy':"Copy(Ctrl + c)",
'copymsg':"Browser does not support. Please use 'Ctrl + c' instead!",
'paste': 'Paste(Ctrl + v)',
'paste':"Paste(Ctrl + v)",
'pastemsg':"Browser does not support. Please use 'Ctrl + v' instead!"
},
'copymsg': "Browser does not support. Please use 'Ctrl + c' instead!",
'pastemsg': "Browser does not support. Please use 'Ctrl + v' instead!",
'anthorMsg': 'Link',
'anthorMsg':"Link",
'clearColor':'Clear',
'standardColor':'Standard color',
'themeColor':'Theme color',
@@ -281,27 +210,27 @@ UE.I18N['en'] = {
'clear':'Clear',
'anchorMsg':'Anchor',
'delete':'Delete',
'clickToUpload': 'Click to upload',
'clickToUpload':"Click to upload",
'unset':'Language hasn\'t been set!',
't_row':'row',
't_col':'col',
'pasteOpt':'Paste Option',
'pasteSourceFormat': 'Keep Source Formatting',
'pasteSourceFormat':"Keep Source Formatting",
'tagFormat':'Keep tag',
'pasteTextFormat':'Keep Text only',
'more':'More',
'autoTypeSet':{
'mergeLine': 'Merge empty line',
'delLine': 'Del empty line',
'removeFormat': 'Remove format',
'indent': 'Indent',
'alignment': 'Alignment',
'imageFloat': 'Image float',
'removeFontsize': 'Remove font size',
'removeFontFamily': 'Remove fontFamily',
'removeHtml': 'Remove redundant HTML code',
'pasteFilter': 'Paste filter',
'run': 'Done',
'mergeLine':"Merge empty line",
'delLine':"Del empty line",
'removeFormat':"Remove format",
'indent':"Indent",
'alignment':"Alignment",
'imageFloat':"Image float",
'removeFontsize':"Remove font size",
'removeFontFamily':"Remove fontFamily",
'removeHtml':"Remove redundant HTML code",
'pasteFilter':"Paste filter",
'run':"Done",
'symbol':'Symbol Conversion',
'bdc2sb':'Full-width to Half-width',
'tobdc':'Half-width to Full-width'
@@ -318,33 +247,33 @@ UE.I18N['en'] = {
'lang_background_netimg':'Net-Image',
'lang_background_align':'Align Type',
'lang_background_position':'Position',
'repeatType': { 'options': ['Center', 'Repeat-x', 'Repeat-y', 'Tile', 'Custom'] }
'repeatType':{'options':["Center", "Repeat-x", "Repeat-y", "Tile","Custom"]}
},
'noUploadImage': 'No pictures has been uploaded',
'noUploadImage':"No pictures has been uploaded",
'toggleSelect':'Change the active state by click!\n Image Size: '
},
//===============dialog i18N=======================
'insertimage':{
'static':{
'lang_tab_remote': 'Insert',
'lang_tab_upload': 'Local',
'lang_tab_online': 'Manager',
'lang_tab_search': 'Search',
'lang_input_url': 'Address:',
'lang_input_size': 'Size:',
'lang_input_width': 'Width',
'lang_input_height': 'Height',
'lang_input_border': 'Border:',
'lang_input_vhspace': 'Margins:',
'lang_input_title': 'Title:',
'lang_tab_remote':"Insert",
'lang_tab_upload':"Local",
'lang_tab_online':"Manager",
'lang_tab_search':"Search",
'lang_input_url':"Address:",
'lang_input_size':"Size:",
'lang_input_width':"Width",
'lang_input_height':"Height",
'lang_input_border':"Border:",
'lang_input_vhspace':"Margins:",
'lang_input_title':"Title:",
'lang_input_align':'Image Float Style:',
'lang_imgLoading': 'Loading...',
'lang_start_upload': 'Start Upload',
'lock': { 'title': 'Lock rate' },
'searchType': { 'title': 'ImageType', 'options': ['News', 'Wallpaper', 'emotions', 'photo'] },
'searchTxt': { 'value': 'Enter the search keyword!' },
'searchBtn': { 'value': 'Search' },
'searchReset': { 'value': 'Clear' },
'lang_imgLoading':"Loading...",
'lang_start_upload':"Start Upload",
'lock':{'title':"Lock rate"},
'searchType':{'title':"ImageType", 'options':["News", "Wallpaper", "emotions", "photo"]},
'searchTxt':{'value':"Enter the search keyword!"},
'searchBtn':{'value':"Search"},
'searchReset':{'value':"Clear"},
'noneAlign':{'title':'None Float'},
'leftAlign':{'title':'Left Float'},
'rightAlign':{'title':'Right Float'},
@@ -373,20 +302,20 @@ UE.I18N['en'] = {
'errorUploadRetry':'Upload Error, Please Retry.',
'errorHttp':'Http Error',
'errorServerUpload':'Server Result Error.',
'remoteLockError': 'Cannot Lock the Proportion between width and height',
'numError': 'Please enter the correct Num. e.g 123,400',
'imageUrlError': 'The image format may be wrong!',
'imageLoadError': 'Error,please check the network or URL',
'searchRemind': 'Enter the search keyword!',
'searchLoading': 'Image is loading,please wait...',
'remoteLockError':"Cannot Lock the Proportion between width and height",
'numError':"Please enter the correct Num. e.g 123,400",
'imageUrlError':"The image format may be wrong!",
'imageLoadError':"Error,please check the network or URL",
'searchRemind':"Enter the search keyword!",
'searchLoading':"Image is loading,please wait...",
'searchRetry':" Sorry,can't find the image,please try again!"
},
'attachment':{
'static':{
'lang_tab_upload': 'Upload',
'lang_tab_online': 'Online',
'lang_start_upload': 'Start upload',
'lang_drop_remind': 'You can drop files here, a single maximum of 300 files'
'lang_start_upload':"Start upload",
'lang_drop_remind':"You can drop files here, a single maximum of 300 files"
},
'uploadSelectFile':'Select File',
'uploadAddFile':'Add File',
@@ -414,36 +343,36 @@ UE.I18N['en'] = {
'insertvideo':{
'static':{
'lang_tab_insertV': 'Video',
'lang_tab_searchV': 'Search',
'lang_tab_uploadV': 'Upload',
'lang_video_url': ' URL ',
'lang_video_size': 'Video Size',
'lang_videoW': 'Width',
'lang_videoH': 'Height',
'lang_alignment': 'Alignment',
'videoSearchTxt': { 'value': 'Enter the search keyword!' },
'videoType': { 'options': ['All', 'Hot', 'Entertainment', 'Funny', 'Sports', 'Science', 'variety'] },
'videoSearchBtn': { 'value': 'Search in Baidu' },
'videoSearchReset': { 'value': 'Clear result' },
'lang_tab_insertV':"Video",
'lang_tab_searchV':"Search",
'lang_tab_uploadV':"Upload",
'lang_video_url':" URL ",
'lang_video_size':"Video Size",
'lang_videoW':"Width",
'lang_videoH':"Height",
'lang_alignment':"Alignment",
'videoSearchTxt':{'value':"Enter the search keyword!"},
'videoType':{'options':["All", "Hot", "Entertainment", "Funny", "Sports", "Science", "variety"]},
'videoSearchBtn':{'value':"Search in Baidu"},
'videoSearchReset':{'value':"Clear result"},
'lang_input_fileStatus':' No file uploaded!',
'startUpload': { 'style': 'background:url(upload.png) no-repeat;' },
'startUpload':{'style':"background:url(upload.png) no-repeat;"},
'lang_upload_size': 'Video Size',
'lang_upload_width': 'Width',
'lang_upload_height': 'Height',
'lang_upload_alignment': 'Alignment',
'lang_format_advice': 'Recommends mp4 format.'
'lang_upload_size':"Video Size",
'lang_upload_width':"Width",
'lang_upload_height':"Height",
'lang_upload_alignment':"Alignment",
'lang_format_advice':"Recommends mp4 format."
},
'numError': 'Please enter the correct Num. e.g 123,400',
'floatLeft': 'Float left',
'floatRight': 'Float right',
'default': 'Default',
'block': 'Display in block',
'urlError': 'The video url format may be wrong!',
'loading': ' &nbsp;The video is loading, please wait…',
'clickToSelect': 'Click to select',
'numError':"Please enter the correct Num. e.g 123,400",
'floatLeft':"Float left",
'floatRight':"Float right",
'default':"Default",
'block':"Display in block",
'urlError':"The video url format may be wrong!",
'loading':" &nbsp;The video is loading, please wait…",
'clickToSelect':"Click to select",
'goToSource':'Visit source video ',
'noVideo':" &nbsp; &nbsp;Sorry,can't find the video,please try again!",
@@ -498,10 +427,10 @@ UE.I18N['en'] = {
'errorServerUpload':'Server Result Error.'
},
'webapp':{
'tip1': 'This function provided by Baidu APP,please apply for baidu APPKey webmaster first!',
'tip2': 'And then open the file ueditor.config.js to set it! ',
'applyFor': 'APPLY FOR',
'anthorApi': 'Baidu API'
'tip1':"This function provided by Baidu APP,please apply for baidu APPKey webmaster first!",
'tip2':"And then open the file ueditor.config.js to set it! ",
'applyFor':"APPLY FOR",
'anthorApi':"Baidu API"
},
'template':{
'static':{
@@ -509,31 +438,31 @@ UE.I18N['en'] = {
'lang_template_clear' : 'Keep Content',
'lang_template_select':'Select Template'
},
'blank': 'Blank',
'blog': 'Blog',
'resume': 'Resume',
'richText': 'Rich Text',
'scrPapers': 'Scientific Papers'
'blank':"Blank",
'blog':"Blog",
'resume':"Resume",
'richText':"Rich Text",
'scrPapers':"Scientific Papers"
},
scrawl:{
'static':{
'lang_input_previousStep': 'Previous',
'lang_input_nextsStep': 'Next',
'lang_input_previousStep':"Previous",
'lang_input_nextsStep':"Next",
'lang_input_clear':'Clear',
'lang_input_addPic':'AddImage',
'lang_input_ScalePic':'ScaleImage',
'lang_input_removePic':'RemoveImage',
'J_imgTxt':{title:'Add background image'}
},
'noScarwl': 'No paint, a white paper...',
'scrawlUpLoading': 'Image is uploading, please wait...',
'continueBtn': 'Try again',
'imageError': 'Image failed to load!',
'noScarwl':"No paint, a white paper...",
'scrawlUpLoading':"Image is uploading, please wait...",
'continueBtn':"Try again",
'imageError':"Image failed to load!",
'backgroundUploading':'Image is uploading,please wait...'
},
'music':{
'static':{
'lang_input_tips': 'Input singer/song/album, search you interested in music!',
'lang_input_tips':"Input singer/song/album, search you interested in music!",
'J_searchBtn':{value:'Search songs'}
},
'emptyTxt':'Not search to the relevant music results, please change a keyword try.',
@@ -585,7 +514,7 @@ UE.I18N['en'] = {
'static':{
'lang_input_address':'Address:',
'lang_input_search':'Search',
'address': { value: 'Beijing' }
'address':{value:"Beijing"}
},
searchError:'Unable to locate the address!'
},
@@ -593,7 +522,7 @@ UE.I18N['en'] = {
'static':{
'lang_input_about':'About',
'lang_input_shortcuts':'Shortcuts',
'lang_input_introduction': 'UEditor is developed by Baidu Co.ltd. It is lightweight, customizable , focusing on user experience and etc. , UEditor is based on open source BSD license , allowing free use and redistribution.',
'lang_input_introduction':"UEditor is developed by Baidu Co.ltd. It is lightweight, customizable , focusing on user experience and etc. , UEditor is based on open source BSD license , allowing free use and redistribution.",
'lang_Txt_shortcuts':'Shortcuts',
'lang_Txt_func':'Function',
'lang_Txt_bold':'Bold',
@@ -617,7 +546,7 @@ UE.I18N['en'] = {
'lang_input_isScroll':'Enable scrollbars',
'lang_input_frameborder':'Show frame border',
'lang_input_alignMode':'Alignment',
'align': { title: 'Alignment', options: ['Default', 'Left', 'Right', 'Center'] }
'align':{title:"Alignment", options:["Default", "Left", "Right", "Center"]}
},
'enterAddress':'Please enter an address!'
},
@@ -633,56 +562,56 @@ UE.I18N['en'] = {
},
map:{
'static':{
lang_city: 'City',
lang_address: 'Address',
city: { value: 'Beijing' },
lang_search: 'Search',
lang_dynamicmap: 'Dynamic map'
lang_city:"City",
lang_address:"Address",
city:{value:"Beijing"},
lang_search:"Search",
lang_dynamicmap:"Dynamic map"
},
cityMsg: 'Please enter the city name!',
cityMsg:"Please enter the city name!",
errorMsg:"Can't find the place!"
},
searchreplace:{
'static':{
lang_tab_search: 'Search',
lang_tab_replace: 'Replace',
lang_search1: 'Search',
lang_search2: 'Search',
lang_replace: 'Replace',
lang_tab_search:"Search",
lang_tab_replace:"Replace",
lang_search1:"Search",
lang_search2:"Search",
lang_replace:"Replace",
lang_searchReg:'Support regular expression ,which starts and ends with a slash ,for example "/expression/"',
lang_searchReg1:'Support regular expression ,which starts and ends with a slash ,for example "/expression/"',
lang_case_sensitive1: 'Case sense',
lang_case_sensitive2: 'Case sense',
nextFindBtn: { value: 'Next' },
preFindBtn: { value: 'Preview' },
nextReplaceBtn: { value: 'Next' },
preReplaceBtn: { value: 'Preview' },
repalceBtn: { value: 'Replace' },
repalceAllBtn: { value: 'Replace all' }
lang_case_sensitive1:"Case sense",
lang_case_sensitive2:"Case sense",
nextFindBtn:{value:"Next"},
preFindBtn:{value:"Preview"},
nextReplaceBtn:{value:"Next"},
preReplaceBtn:{value:"Preview"},
repalceBtn:{value:"Replace"},
repalceAllBtn:{value:"Replace all"}
},
getEnd: 'Has the search to the bottom!',
getStart: 'Has the search to the top!',
countMsg: 'Altogether replaced {#count} character(s)!'
getEnd:"Has the search to the bottom!",
getStart:"Has the search to the top!",
countMsg:"Altogether replaced {#count} character(s)!"
},
snapscreen:{
'static':{
lang_showMsg: 'You should install the UEditor screenshots program first!',
lang_download: 'Download!',
lang_step1: 'Step1:Download the program and then run it',
lang_step2: 'Step2:After complete install,try to click the button again'
lang_showMsg:"You should install the UEditor screenshots program first!",
lang_download:"Download!",
lang_step1:"Step1:Download the program and then run it",
lang_step2:"Step2:After complete install,try to click the button again"
}
},
spechars:{
'static':{},
tsfh: 'Special',
lmsz: 'Roman',
szfh: 'Numeral',
rwfh: 'Japanese',
xlzm: 'The Greek',
ewzm: 'Russian',
pyzm: 'Phonetic',
yyyb: 'English',
zyzf: 'Others'
tsfh:"Special",
lmsz:"Roman",
szfh:"Numeral",
rwfh:"Japanese",
xlzm:"The Greek",
ewzm:"Russian",
pyzm:"Phonetic",
yyyb:"English",
zyzf:"Others"
},
'edittable':{
'static':{
@@ -692,7 +621,7 @@ UE.I18N['en'] = {
'lang_insertTitleCol':'Add table title col',
'lang_tableSize':'Automatically adjust table size',
'lang_autoSizeContent':'Adaptive by form text',
'lang_orderbycontent': 'Table of contents sortable',
'lang_orderbycontent':"Table of contents sortable",
'lang_autoSizePage':'Page width adaptive',
'lang_example':'Example',
'lang_borderStyle':'Table Border',
@@ -720,30 +649,30 @@ UE.I18N['en'] = {
},
wordimage:{
'static':{
lang_resave: 'The re-save step',
uploadBtn: { src: 'upload.png', alt: 'Upload' },
clipboard: { style: 'background: url(copy.png) -153px -1px no-repeat;' },
lang_step: ' 1. Click top button to copy the url and then open the dialog to paste it. 2. Open after choose photos uploaded process.'
lang_resave:"The re-save step",
uploadBtn:{src:"upload.png", alt:"Upload"},
clipboard:{style:"background: url(copy.png) -153px -1px no-repeat;"},
lang_step:" 1. Click top button to copy the url and then open the dialog to paste it. 2. Open after choose photos uploaded process."
},
fileType: 'Image',
flashError: 'Flash initialization failed!',
netError: 'Network error! Please try again!',
copySuccess: 'URL has been copied!',
fileType:"Image",
flashError:"Flash initialization failed!",
netError:"Network error! Please try again!",
copySuccess:"URL has been copied!",
'flashI18n':{
lang:encodeURI( '{"UploadingState":"totalNum: ${a},uploadComplete: ${b}", "BeforeUpload":"waitingNum: ${a}", "ExceedSize":"Size exceed${a}", "ErrorInPreview":"Preview failed", "DefaultDescription":"Description", "LoadingImage":"Loading..."}' ),
uploadingTF:encodeURI( '{"font":"Arial", "size":12, "color":"0x000", "bold":"true", "italic":"false", "underline":"false"}' ),
imageTF:encodeURI( '{"font":"Arial", "size":11, "color":"red", "bold":"false", "italic":"false", "underline":"false"}' ),
textEncoding: 'utf-8',
addImageSkinURL: 'addImage.png',
allDeleteBtnUpSkinURL: 'allDeleteBtnUpSkin.png',
allDeleteBtnHoverSkinURL: 'allDeleteBtnHoverSkin.png',
rotateLeftBtnEnableSkinURL: 'rotateLeftEnable.png',
rotateLeftBtnDisableSkinURL: 'rotateLeftDisable.png',
rotateRightBtnEnableSkinURL: 'rotateRightEnable.png',
rotateRightBtnDisableSkinURL: 'rotateRightDisable.png',
deleteBtnEnableSkinURL: 'deleteEnable.png',
deleteBtnDisableSkinURL: 'deleteDisable.png',
textEncoding:"utf-8",
addImageSkinURL:"addImage.png",
allDeleteBtnUpSkinURL:"allDeleteBtnUpSkin.png",
allDeleteBtnHoverSkinURL:"allDeleteBtnHoverSkin.png",
rotateLeftBtnEnableSkinURL:"rotateLeftEnable.png",
rotateLeftBtnDisableSkinURL:"rotateLeftDisable.png",
rotateRightBtnEnableSkinURL:"rotateRightEnable.png",
rotateRightBtnDisableSkinURL:"rotateRightDisable.png",
deleteBtnEnableSkinURL:"deleteEnable.png",
deleteBtnDisableSkinURL:"deleteDisable.png",
backgroundURL:'',
listBackgroundURL:'',
buttonURL:'button.png'
+372
View File
@@ -0,0 +1,372 @@
<?php
/**
* Created by JetBrains PhpStorm.
* User: taoqili
* Date: 12-7-18
* Time: 上午11: 32
* UEditor编辑器通用上传类
*/
class Uploader
{
private $fileField; //文件域名
private $file; //文件上传对象
private $base64; //文件上传对象
private $config; //配置信息
private $oriName; //原始文件名
private $fileName; //新文件名
private $fullName; //完整文件名,即从当前配置目录开始的URL
private $filePath; //完整文件名,即从当前配置目录开始的URL
private $fileSize; //文件大小
private $fileType; //文件类型
private $stateInfo; //上传状态信息,
private $stateMap = array( //上传状态映射表,国际化用户需考虑此处数据的国际化
"SUCCESS", //上传成功标记,在UEditor中内不可改变,否则flash判断会出错
"文件大小超出 upload_max_filesize 限制",
"文件大小超出 MAX_FILE_SIZE 限制",
"文件未被完整上传",
"没有文件被上传",
"上传文件为空",
"ERROR_TMP_FILE" => "临时文件错误",
"ERROR_TMP_FILE_NOT_FOUND" => "找不到临时文件",
"ERROR_SIZE_EXCEED" => "文件大小超出网站限制",
"ERROR_TYPE_NOT_ALLOWED" => "文件类型不允许",
"ERROR_CREATE_DIR" => "目录创建失败",
"ERROR_DIR_NOT_WRITEABLE" => "目录没有写权限",
"ERROR_FILE_MOVE" => "文件保存时出错",
"ERROR_FILE_NOT_FOUND" => "找不到上传文件",
"ERROR_WRITE_CONTENT" => "写入文件内容错误",
"ERROR_UNKNOWN" => "未知错误",
"ERROR_DEAD_LINK" => "链接不可用",
"ERROR_HTTP_LINK" => "链接不是http链接",
"ERROR_HTTP_CONTENTTYPE" => "链接contentType不正确",
"INVALID_URL" => "非法 URL",
"INVALID_IP" => "非法 IP"
);
/**
* 构造函数
* @param string $fileField 表单名称
* @param array $config 配置项
* @param bool $base64 是否解析base64编码,可省略。若开启,则$fileField代表的是base64编码的字符串表单名
*/
public function __construct($fileField, $config, $type = "upload")
{
$this->fileField = $fileField;
$this->config = $config;
$this->type = $type;
if ($type == "remote") {
$this->saveRemote();
} else if($type == "base64") {
$this->upBase64();
} else {
$this->upFile();
}
$this->stateMap['ERROR_TYPE_NOT_ALLOWED'] = iconv('unicode', 'utf-8', $this->stateMap['ERROR_TYPE_NOT_ALLOWED']);
}
/**
* 上传文件的主处理方法
* @return mixed
*/
private function upFile()
{
$file = $this->file = $_FILES[$this->fileField];
if (!$file) {
$this->stateInfo = $this->getStateInfo("ERROR_FILE_NOT_FOUND");
return;
}
if ($this->file['error']) {
$this->stateInfo = $this->getStateInfo($file['error']);
return;
} else if (!file_exists($file['tmp_name'])) {
$this->stateInfo = $this->getStateInfo("ERROR_TMP_FILE_NOT_FOUND");
return;
} else if (!is_uploaded_file($file['tmp_name'])) {
$this->stateInfo = $this->getStateInfo("ERROR_TMPFILE");
return;
}
$this->oriName = $file['name'];
$this->fileSize = $file['size'];
$this->fileType = $this->getFileExt();
$this->fullName = $this->getFullName();
$this->filePath = $this->getFilePath();
$this->fileName = $this->getFileName();
$dirname = dirname($this->filePath);
//检查文件大小是否超出限制
if (!$this->checkSize()) {
$this->stateInfo = $this->getStateInfo("ERROR_SIZE_EXCEED");
return;
}
//检查是否不允许的文件格式
if (!$this->checkType()) {
$this->stateInfo = $this->getStateInfo("ERROR_TYPE_NOT_ALLOWED");
return;
}
//创建目录失败
if (!file_exists($dirname) && !mkdir($dirname, 0777, true)) {
$this->stateInfo = $this->getStateInfo("ERROR_CREATE_DIR");
return;
} else if (!is_writeable($dirname)) {
$this->stateInfo = $this->getStateInfo("ERROR_DIR_NOT_WRITEABLE");
return;
}
//移动文件
if (!(move_uploaded_file($file["tmp_name"], $this->filePath) && file_exists($this->filePath))) { //移动失败
$this->stateInfo = $this->getStateInfo("ERROR_FILE_MOVE");
} else { //移动成功
$this->stateInfo = $this->stateMap[0];
}
}
/**
* 处理base64编码的图片上传
* @return mixed
*/
private function upBase64()
{
$base64Data = $_POST[$this->fileField];
$img = base64_decode($base64Data);
$this->oriName = $this->config['oriName'];
$this->fileSize = strlen($img);
$this->fileType = $this->getFileExt();
$this->fullName = $this->getFullName();
$this->filePath = $this->getFilePath();
$this->fileName = $this->getFileName();
$dirname = dirname($this->filePath);
//检查文件大小是否超出限制
if (!$this->checkSize()) {
$this->stateInfo = $this->getStateInfo("ERROR_SIZE_EXCEED");
return;
}
//创建目录失败
if (!file_exists($dirname) && !mkdir($dirname, 0777, true)) {
$this->stateInfo = $this->getStateInfo("ERROR_CREATE_DIR");
return;
} else if (!is_writeable($dirname)) {
$this->stateInfo = $this->getStateInfo("ERROR_DIR_NOT_WRITEABLE");
return;
}
//移动文件
if (!(file_put_contents($this->filePath, $img) && file_exists($this->filePath))) { //移动失败
$this->stateInfo = $this->getStateInfo("ERROR_WRITE_CONTENT");
} else { //移动成功
$this->stateInfo = $this->stateMap[0];
}
}
/**
* 拉取远程图片
* @return mixed
*/
private function saveRemote()
{
$imgUrl = htmlspecialchars($this->fileField);
$imgUrl = str_replace("&amp;", "&", $imgUrl);
//http开头验证
if (strpos($imgUrl, "http") !== 0) {
$this->stateInfo = $this->getStateInfo("ERROR_HTTP_LINK");
return;
}
preg_match('/(^https*:\/\/[^:\/]+)/', $imgUrl, $matches);
$host_with_protocol = count($matches) > 1 ? $matches[1] : '';
// 判断是否是合法 url
if (!filter_var($host_with_protocol, FILTER_VALIDATE_URL)) {
$this->stateInfo = $this->getStateInfo("INVALID_URL");
return;
}
preg_match('/^https*:\/\/(.+)/', $host_with_protocol, $matches);
$host_without_protocol = count($matches) > 1 ? $matches[1] : '';
// 此时提取出来的可能是 ip 也有可能是域名,先获取 ip
$ip = gethostbyname($host_without_protocol);
// 判断是否是私有 ip
if(!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) {
$this->stateInfo = $this->getStateInfo("INVALID_IP");
return;
}
//获取请求头并检测死链
$heads = get_headers($imgUrl, 1);
if (!(stristr($heads[0], "200") && stristr($heads[0], "OK"))) {
$this->stateInfo = $this->getStateInfo("ERROR_DEAD_LINK");
return;
}
//格式验证(扩展名验证和Content-Type验证)
$fileType = strtolower(strrchr($imgUrl, '.'));
if (!in_array($fileType, $this->config['allowFiles']) || !isset($heads['Content-Type']) || !stristr($heads['Content-Type'], "image")) {
$this->stateInfo = $this->getStateInfo("ERROR_HTTP_CONTENTTYPE");
return;
}
//打开输出缓冲区并获取远程图片
ob_start();
$context = stream_context_create(
array('http' => array(
'follow_location' => false // don't follow redirects
))
);
readfile($imgUrl, false, $context);
$img = ob_get_contents();
ob_end_clean();
preg_match("/[\/]([^\/]*)[\.]?[^\.\/]*$/", $imgUrl, $m);
$this->oriName = $m ? $m[1]:"";
$this->fileSize = strlen($img);
$this->fileType = $this->getFileExt();
$this->fullName = $this->getFullName();
$this->filePath = $this->getFilePath();
$this->fileName = $this->getFileName();
$dirname = dirname($this->filePath);
//检查文件大小是否超出限制
if (!$this->checkSize()) {
$this->stateInfo = $this->getStateInfo("ERROR_SIZE_EXCEED");
return;
}
//创建目录失败
if (!file_exists($dirname) && !mkdir($dirname, 0777, true)) {
$this->stateInfo = $this->getStateInfo("ERROR_CREATE_DIR");
return;
} else if (!is_writeable($dirname)) {
$this->stateInfo = $this->getStateInfo("ERROR_DIR_NOT_WRITEABLE");
return;
}
//移动文件
if (!(file_put_contents($this->filePath, $img) && file_exists($this->filePath))) { //移动失败
$this->stateInfo = $this->getStateInfo("ERROR_WRITE_CONTENT");
} else { //移动成功
$this->stateInfo = $this->stateMap[0];
}
}
/**
* 上传错误检查
* @param $errCode
* @return string
*/
private function getStateInfo($errCode)
{
return !$this->stateMap[$errCode] ? $this->stateMap["ERROR_UNKNOWN"] : $this->stateMap[$errCode];
}
/**
* 获取文件扩展名
* @return string
*/
private function getFileExt()
{
return strtolower(strrchr($this->oriName, '.'));
}
/**
* 重命名文件
* @return string
*/
private function getFullName()
{
//替换日期事件
$t = time();
$d = explode('-', date("Y-y-m-d-H-i-s"));
$format = $this->config["pathFormat"];
$format = str_replace("{yyyy}", $d[0], $format);
$format = str_replace("{yy}", $d[1], $format);
$format = str_replace("{mm}", $d[2], $format);
$format = str_replace("{dd}", $d[3], $format);
$format = str_replace("{hh}", $d[4], $format);
$format = str_replace("{ii}", $d[5], $format);
$format = str_replace("{ss}", $d[6], $format);
$format = str_replace("{time}", $t, $format);
//过滤文件名的非法自负,并替换文件名
$oriName = substr($this->oriName, 0, strrpos($this->oriName, '.'));
$oriName = preg_replace("/[\|\?\"\<\>\/\*\\\\]+/", '', $oriName);
$format = str_replace("{filename}", $oriName, $format);
//替换随机字符串
$randNum = rand(1, 10000000000) . rand(1, 10000000000);
if (preg_match("/\{rand\:([\d]*)\}/i", $format, $matches)) {
$format = preg_replace("/\{rand\:[\d]*\}/i", substr($randNum, 0, $matches[1]), $format);
}
$ext = $this->getFileExt();
return $format . $ext;
}
/**
* 获取文件名
* @return string
*/
private function getFileName () {
return substr($this->filePath, strrpos($this->filePath, '/') + 1);
}
/**
* 获取文件完整路径
* @return string
*/
private function getFilePath()
{
$fullname = $this->fullName;
$rootPath = $_SERVER['DOCUMENT_ROOT'];
if (substr($fullname, 0, 1) != '/') {
$fullname = '/' . $fullname;
}
return $rootPath . $fullname;
}
/**
* 文件类型检测
* @return bool
*/
private function checkType()
{
return in_array($this->getFileExt(), $this->config["allowFiles"]);
}
/**
* 文件大小检测
* @return bool
*/
private function checkSize()
{
return $this->fileSize <= ($this->config["maxSize"]);
}
/**
* 获取当前上传成功文件的各项信息
* @return array
*/
public function getFileInfo()
{
return array(
"state" => $this->stateInfo,
"url" => $this->fullName,
"title" => $this->fileName,
"original" => $this->oriName,
"type" => $this->fileType,
"size" => $this->fileSize
);
}
}
+44
View File
@@ -0,0 +1,44 @@
<?php
/**
* 抓取远程图片
* User: Jinqn
* Date: 14-04-14
* Time: 下午19:18
*/
set_time_limit(0);
include("Uploader.class.php");
/* 上传配置 */
$config = array(
"pathFormat" => $CONFIG['catcherPathFormat'],
"maxSize" => $CONFIG['catcherMaxSize'],
"allowFiles" => $CONFIG['catcherAllowFiles'],
"oriName" => "remote.png"
);
$fieldName = $CONFIG['catcherFieldName'];
/* 抓取远程图片 */
$list = array();
if (isset($_POST[$fieldName])) {
$source = $_POST[$fieldName];
} else {
$source = $_GET[$fieldName];
}
foreach ($source as $imgUrl) {
$item = new Uploader($imgUrl, $config, "remote");
$info = $item->getFileInfo();
array_push($list, array(
"state" => $info["state"],
"url" => $info["url"],
"size" => $info["size"],
"title" => htmlspecialchars($info["title"]),
"original" => htmlspecialchars($info["original"]),
"source" => htmlspecialchars($imgUrl)
));
}
/* 返回抓取数据 */
return json_encode(array(
'state'=> count($list) ? 'SUCCESS':'ERROR',
'list'=> $list
));
+92
View File
@@ -0,0 +1,92 @@
<?php
/**
* 获取已上传的文件列表
* User: Jinqn
* Date: 14-04-09
* Time: 上午10:17
*/
include "Uploader.class.php";
/* 判断类型 */
switch ($_GET['action']) {
/* 列出文件 */
case 'listfile':
$allowFiles = $CONFIG['fileManagerAllowFiles'];
$listSize = $CONFIG['fileManagerListSize'];
$path = $CONFIG['fileManagerListPath'];
break;
/* 列出图片 */
case 'listimage':
default:
$allowFiles = $CONFIG['imageManagerAllowFiles'];
$listSize = $CONFIG['imageManagerListSize'];
$path = $CONFIG['imageManagerListPath'];
}
$allowFiles = substr(str_replace(".", "|", join("", $allowFiles)), 1);
/* 获取参数 */
$size = isset($_GET['size']) ? htmlspecialchars($_GET['size']) : $listSize;
$start = isset($_GET['start']) ? htmlspecialchars($_GET['start']) : 0;
$end = $start + $size;
/* 获取文件列表 */
$path = $_SERVER['DOCUMENT_ROOT'] . (substr($path, 0, 1) == "/" ? "":"/") . $path;
$files = getfiles($path, $allowFiles);
if (!count($files)) {
return json_encode(array(
"state" => "no match file",
"list" => array(),
"start" => $start,
"total" => count($files)
));
}
/* 获取指定范围的列表 */
$len = count($files);
for ($i = min($end, $len) - 1, $list = array(); $i < $len && $i >= 0 && $i >= $start; $i--){
$list[] = $files[$i];
}
//倒序
//for ($i = $end, $list = array(); $i < $len && $i < $end; $i++){
// $list[] = $files[$i];
//}
/* 返回数据 */
$result = json_encode(array(
"state" => "SUCCESS",
"list" => $list,
"start" => $start,
"total" => count($files)
));
return $result;
/**
* 遍历获取目录下的指定类型的文件
* @param $path
* @param array $files
* @return array
*/
function getfiles($path, $allowFiles, &$files = array())
{
if (!is_dir($path)) return null;
if(substr($path, strlen($path) - 1) != '/') $path .= '/';
$handle = opendir($path);
while (false !== ($file = readdir($handle))) {
if ($file != '.' && $file != '..') {
$path2 = $path . $file;
if (is_dir($path2)) {
getfiles($path2, $allowFiles, $files);
} else {
if (preg_match("/\.(".$allowFiles.")$/i", $file)) {
$files[] = array(
'url'=> substr($path2, strlen($_SERVER['DOCUMENT_ROOT'])),
'mtime'=> filemtime($path2)
);
}
}
}
}
return $files;
}
+66
View File
@@ -0,0 +1,66 @@
<?php
/**
* 上传附件和上传视频
* User: Jinqn
* Date: 14-04-09
* Time: 上午10:17
*/
include "Uploader.class.php";
/* 上传配置 */
$base64 = "upload";
switch (htmlspecialchars($_GET['action'])) {
case 'uploadimage':
$config = array(
"pathFormat" => $CONFIG['imagePathFormat'],
"maxSize" => $CONFIG['imageMaxSize'],
"allowFiles" => $CONFIG['imageAllowFiles']
);
$fieldName = $CONFIG['imageFieldName'];
break;
case 'uploadscrawl':
$config = array(
"pathFormat" => $CONFIG['scrawlPathFormat'],
"maxSize" => $CONFIG['scrawlMaxSize'],
"allowFiles" => $CONFIG['scrawlAllowFiles'],
"oriName" => "scrawl.png"
);
$fieldName = $CONFIG['scrawlFieldName'];
$base64 = "base64";
break;
case 'uploadvideo':
$config = array(
"pathFormat" => $CONFIG['videoPathFormat'],
"maxSize" => $CONFIG['videoMaxSize'],
"allowFiles" => $CONFIG['videoAllowFiles']
);
$fieldName = $CONFIG['videoFieldName'];
break;
case 'uploadfile':
default:
$config = array(
"pathFormat" => $CONFIG['filePathFormat'],
"maxSize" => $CONFIG['fileMaxSize'],
"allowFiles" => $CONFIG['fileAllowFiles']
);
$fieldName = $CONFIG['fileFieldName'];
break;
}
/* 生成上传实例对象并完成上传 */
$up = new Uploader($fieldName, $config, $base64);
/**
* 得到上传文件所对应的各个参数,数组结构
* array(
* "state" => "", //上传状态,上传成功时必须返回"SUCCESS"
* "url" => "", //返回的地址
* "title" => "", //新文件名
* "original" => "", //原始文件名
* "type" => "" //文件类型
* "size" => "", //文件大小
* )
*/
/* 返回数据 */
return json_encode($up->getFileInfo());
+94
View File
@@ -0,0 +1,94 @@
/* ,使 */
{
/* */
"imageActionName": "uploadimage", /* action */
"imageFieldName": "upfile", /* */
"imageMaxSize": 2048000, /* B */
"imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* */
"imageCompressEnable": true, /* ,true */
"imageCompressBorder": 1600, /* */
"imageInsertAlign": "none", /* */
"imageUrlPrefix": "", /* 访 */
"imagePathFormat": "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* , */
/* {filename} , */
/* {rand:6} , */
/* {time} */
/* {yyyy} */
/* {yy} */
/* {mm} */
/* {dd} */
/* {hh} */
/* {ii} */
/* {ss} */
/* \ : * ? " < > | */
/* 具请体看线上文档: fex.baidu.com/ueditor/#use-format_upload_filename */
/* 涂鸦图片上传配置项 */
"scrawlActionName": "uploadscrawl", /* 执行上传涂鸦的action名称 */
"scrawlFieldName": "upfile", /* 提交的图片表单名称 */
"scrawlPathFormat": "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
"scrawlMaxSize": 2048000, /* 上传大小限制,单位B */
"scrawlUrlPrefix": "", /* 图片访问路径前缀 */
"scrawlInsertAlign": "none",
/* 截图工具上传 */
"snapscreenActionName": "uploadimage", /* 执行上传截图的action名称 */
"snapscreenPathFormat": "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
"snapscreenUrlPrefix": "", /* 图片访问路径前缀 */
"snapscreenInsertAlign": "none", /* 插入的图片浮动方式 */
/* 抓取远程图片配置 */
"catcherLocalDomain": ["127.0.0.1", "localhost", "img.baidu.com"],
"catcherActionName": "catchimage", /* 执行抓取远程图片的action名称 */
"catcherFieldName": "source", /* 提交的图片列表表单名称 */
"catcherPathFormat": "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
"catcherUrlPrefix": "", /* 图片访问路径前缀 */
"catcherMaxSize": 2048000, /* 上传大小限制,单位B */
"catcherAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取图片格式显示 */
/* 上传视频配置 */
"videoActionName": "uploadvideo", /* 执行上传视频的action名称 */
"videoFieldName": "upfile", /* 提交的视频表单名称 */
"videoPathFormat": "/ueditor/php/upload/video/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
"videoUrlPrefix": "", /* 视频访问路径前缀 */
"videoMaxSize": 102400000, /* 上传大小限制,单位B,默认100MB */
"videoAllowFiles": [
".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid"], /* 上传视频格式显示 */
/* 上传文件配置 */
"fileActionName": "uploadfile", /* controller里,执行上传视频的action名称 */
"fileFieldName": "upfile", /* 提交的文件表单名称 */
"filePathFormat": "/ueditor/php/upload/file/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
"fileUrlPrefix": "", /* 文件访问路径前缀 */
"fileMaxSize": 51200000, /* 上传大小限制,单位B,默认50MB */
"fileAllowFiles": [
".png", ".jpg", ".jpeg", ".gif", ".bmp",
".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
], /* 上传文件格式显示 */
/* 列出指定目录下的图片 */
"imageManagerActionName": "listimage", /* 执行图片管理的action名称 */
"imageManagerListPath": "/ueditor/php/upload/image/", /* 指定要列出图片的目录 */
"imageManagerListSize": 20, /* 每次列出文件数量 */
"imageManagerUrlPrefix": "", /* 图片访问路径前缀 */
"imageManagerInsertAlign": "none", /* 插入的图片浮动方式 */
"imageManagerAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 列出的文件类型 */
/* 列出指定目录下的文件 */
"fileManagerActionName": "listfile", /* 执行文件管理的action名称 */
"fileManagerListPath": "/ueditor/php/upload/file/", /* 指定要列出文件的目录 */
"fileManagerUrlPrefix": "", /* 文件访问路径前缀 */
"fileManagerListSize": 20, /* 每次列出文件数量 */
"fileManagerAllowFiles": [
".png", ".jpg", ".jpeg", ".gif", ".bmp",
".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
] /* */
}
+59
View File
@@ -0,0 +1,59 @@
<?php
//header('Access-Control-Allow-Origin: http://www.baidu.com'); //设置http://www.baidu.com允许跨域访问
//header('Access-Control-Allow-Headers: X-Requested-With,X_Requested_With'); //设置允许的跨域header
date_default_timezone_set("Asia/chongqing");
error_reporting(E_ERROR);
header("Content-Type: text/html; charset=utf-8");
$CONFIG = json_decode(preg_replace("/\/\*[\s\S]+?\*\//", "", file_get_contents("config.json")), true);
$action = $_GET['action'];
switch ($action) {
case 'config':
$result = json_encode($CONFIG);
break;
/* 上传图片 */
case 'uploadimage':
/* 上传涂鸦 */
case 'uploadscrawl':
/* 上传视频 */
case 'uploadvideo':
/* 上传文件 */
case 'uploadfile':
$result = include("action_upload.php");
break;
/* 列出图片 */
case 'listimage':
$result = include("action_list.php");
break;
/* 列出文件 */
case 'listfile':
$result = include("action_list.php");
break;
/* 抓取远程文件 */
case 'catchimage':
$result = include("action_crawler.php");
break;
default:
$result = json_encode(array(
'state'=> '请求地址出错'
));
break;
}
/* 输出结果 */
if (isset($_GET["callback"])) {
if (preg_match("/^[\w_]+$/", $_GET["callback"])) {
echo htmlspecialchars($_GET["callback"]) . '(' . $result . ')';
} else {
echo json_encode(array(
'state'=> 'callback参数不合法'
));
}
} else {
echo $result;
}
@@ -133,7 +133,6 @@ div.edui-box {
}
/*UI工具栏、编辑区域、底部*/
.edui-default .edui-editor {
z-index: 1 !important;
border: 1px solid #d4d4d4;
background-color: white;
position: relative;
Binary file not shown.
Binary file not shown.
Binary file not shown.
+5 -4
View File
@@ -25082,10 +25082,11 @@ UE.ui = baidu.editor.ui = {};
} else {
layer.style.position = 'fixed';
}
layer.style.left = '0';
layer.style.left = '30';
layer.style.top = '0';
layer.style.width = '0';
layer.style.width = '50';
layer.style.height = '0';
layer.style.zIndex="5000!important;"
}
return layer;
},
@@ -25113,8 +25114,8 @@ UE.ui = baidu.editor.ui = {};
function updateFixedOffset(){
var layer = document.getElementById('edui_fixedlayer');
uiUtils.setViewportOffset(layer, {
left: 0,
top: 0
left: 666,
top: 888
});
// layer.style.display = 'none';
// layer.style.display = 'block';
+51 -26
View File
@@ -10,6 +10,7 @@
**************************提示********************************/
(function () {
/**
* 编辑器资源文件根路径。它所表示的含义是:以编辑器实例化页面为当前路径,指向编辑器资源文件(即dialog等文件夹)的路径。
* 鉴于很多同学在使用编辑器的时候出现的种种路径问题,此处强烈建议大家使用"相对于网站根目录的相对路径"进行配置。
@@ -26,20 +27,26 @@
window.UEDITOR_CONFIG = {
//为编辑器实例添加一个路径,这个不能被注释
UEDITOR_HOME_URL: URL,
UEDITOR_HOME_URL: URL
// 服务器统一请求接口路径
serverUrl: URL + 'php/controller.php',
, serverUrl: URL + "php/controller.php"
//工具栏上的所有的功能按钮和下拉框,可以在new编辑器的实例时选择自己需要的重新定义
toolbars: [[
'source', '|', 'undo', 'redo', '|',
'bold', 'italic', 'underline', 'strikethrough', '|', 'superscript', 'subscript', '|', 'forecolor', 'backcolor', '|',
'removeformat', '|', 'insertorderedlist', 'insertunorderedlist', '|', 'selectall', 'cleardoc', 'paragraph', '|',
'fontfamily', 'fontsize', '|', 'justifyleft', 'justifycenter', 'justifyright', 'justifyjustify', '|',
'link', 'unlink', '|', 'emotion', '|',
'|', 'horizontal', 'print', 'preview', 'fullscreen', 'drafts', 'formula'
]],
, toolbars: [[
'fullscreen', 'source', '|', 'undo', 'redo', '|',
'bold', 'italic', 'underline', 'fontborder', 'strikethrough', 'superscript', 'subscript', 'removeformat', 'formatmatch', 'autotypeset', 'blockquote', 'pasteplain', '|', 'forecolor', 'backcolor', 'insertorderedlist', 'insertunorderedlist', 'selectall', 'cleardoc', '|',
'rowspacingtop', 'rowspacingbottom', 'lineheight', '|',
'customstyle', 'paragraph', 'fontfamily', 'fontsize', '|',
'directionalityltr', 'directionalityrtl', 'indent', '|',
'justifyleft', 'justifycenter', 'justifyright', 'justifyjustify', '|', 'touppercase', 'tolowercase', '|',
'link', 'unlink', 'anchor', '|', 'imagenone', 'imageleft', 'imageright', 'imagecenter', '|',
// 'simpleupload', 'insertimage',
'emotion', 'scrawl', 'insertvideo', 'music', 'attachment', 'map', 'gmap', 'insertframe', 'insertcode', 'webapp', 'pagebreak', 'template', 'background', '|',
'horizontal', 'date', 'time', 'spechars', 'snapscreen', 'wordimage', '|',
'inserttable', 'deletetable', 'insertparagraphbeforetable', 'insertrow', 'deleterow', 'insertcol', 'deletecol', 'mergecells', 'mergeright', 'mergedown', 'splittocells', 'splittorows', 'splittocols', 'charts', '|',
'print', 'preview', 'searchreplace', 'drafts', 'help'
]]
//当鼠标放在工具栏上时显示的tooltip提示,留空支持自动多语言配置,否则以配置值为准
//,labelMap:{
// 'anchor':'', 'undo':''
@@ -55,7 +62,7 @@
//,theme:'default'
//,themePath:URL +"themes/"
//, zIndex : 900 //编辑器层级的基数,默认是900
// ,zIndex : 9999 //编辑器层级的基数,默认是900
//针对getAllHtml方法,会在对应的head标签中增加该编码设置。
//,charset:"utf-8"
@@ -318,6 +325,8 @@
//表格是否可以拖拽
//,tableDragable: true
//sourceEditor
//源码的查看方式,codemirror 是代码高亮,textarea是文本框,默认是codemirror
//注意默认codemirror只能在ie8+和非ie中使用
@@ -348,13 +357,13 @@
//,rgb2Hex:true //默认产出的数据中的color自动从rgb格式变成16进制格式
// xss 过滤是否开启,inserthtml等操作
xssFilterRules: true,
,xssFilterRules: true
//input xss过滤
inputXssFilter: true,
,inputXssFilter: true
//output xss过滤
outputXssFilter: true,
,outputXssFilter: true
// xss过滤白名单 名单来源: https://raw.githubusercontent.com/leizongmin/js-xss/master/lib/default.js
whiteList: {
,whiteList: {
a: ['target', 'href', 'title', 'class', 'style'],
abbr: ['title', 'class', 'style'],
address: ['class', 'style'],
@@ -422,52 +431,68 @@
};
function getUEBasePath(docUrl, confUrl) {
return getBasePath(docUrl || self.document.URL || self.location.href, confUrl || getConfigFilePath());
}
function getConfigFilePath() {
var configPath = document.getElementsByTagName('script');
return configPath[ configPath.length - 1 ].src;
}
function getBasePath(docUrl, confUrl) {
var basePath = confUrl;
if (/^(\/|\\\\)/.test(confUrl)) {
basePath = /^.+?\w(\/|\\\\)/.exec(docUrl)[0] + confUrl.replace(/^(\/|\\\\)/, '');
} else if (!/^[a-z]+:/i.test(confUrl)) {
docUrl = docUrl.split('#')[0].split('?')[0].replace(/[^\\\/]+$/, '');
basePath = docUrl + '' + confUrl;
if (/^(\/|\\\\)/.test(confUrl)) {
basePath = /^.+?\w(\/|\\\\)/.exec(docUrl)[0] + confUrl.replace(/^(\/|\\\\)/, '');
} else if (!/^[a-z]+:/i.test(confUrl)) {
docUrl = docUrl.split("#")[0].split("?")[0].replace(/[^\\\/]+$/, '');
basePath = docUrl + "" + confUrl;
}
return optimizationPath(basePath);
}
function optimizationPath(path) {
let protocol = /^[a-z]+:\/\//.exec(path)[ 0 ],
var protocol = /^[a-z]+:\/\//.exec(path)[ 0 ],
tmp = null,
res = [];
path = path.replace(protocol, '').split('?')[0].split('#')[0];
path = path.replace(protocol, "").split("?")[0].split("#")[0];
path = path.replace(/\\/g, '/').split(/\//);
path[ path.length - 1 ] = '';
path[ path.length - 1 ] = "";
while (path.length) {
if ((tmp = path.shift()) === '..') {
if (( tmp = path.shift() ) === "..") {
res.pop();
} else if (tmp !== '.') {
} else if (tmp !== ".") {
res.push(tmp);
}
}
return protocol + res.join('/');
return protocol + res.join("/");
}
window.UE = {
getUEBasePath: getUEBasePath
};
})();
-9
View File
@@ -1,9 +0,0 @@
import request from '@/utils/request'
export function getActivityList(query) {
return request({
url: '/bpm/activity/list',
method: 'get',
params: query
})
}
-24
View File
@@ -1,24 +0,0 @@
import request from '@/utils/request'
export function getProcessDefinitionPage(query) {
return request({
url: '/bpm/process-definition/page',
method: 'get',
params: query
})
}
export function getProcessDefinitionList(query) {
return request({
url: '/bpm/process-definition/list',
method: 'get',
params: query
})
}
export function getProcessDefinitionBpmnXML(id) {
return request({
url: '/bpm/process-definition/get-bpmn-xml?id=' + id,
method: 'get'
})
}
-52
View File
@@ -1,52 +0,0 @@
import request from '@/utils/request'
// 创建工作流的表单定义
export function createForm(data) {
return request({
url: '/bpm/form/create',
method: 'post',
data: data
})
}
// 更新工作流的表单定义
export function updateForm(data) {
return request({
url: '/bpm/form/update',
method: 'put',
data: data
})
}
// 删除工作流的表单定义
export function deleteForm(id) {
return request({
url: '/bpm/form/delete?id=' + id,
method: 'delete'
})
}
// 获得工作流的表单定义
export function getForm(id) {
return request({
url: '/bpm/form/get?id=' + id,
method: 'get'
})
}
// 获得工作流的表单定义分页
export function getFormPage(query) {
return request({
url: '/bpm/form/page',
method: 'get',
params: query
})
}
// 获得动态表单的精简列表
export function getSimpleForms() {
return request({
url: '/bpm/form/list-all-simple',
method: 'get'
})
}
-27
View File
@@ -1,27 +0,0 @@
import request from '@/utils/request'
// 创建请假申请
export function createLeave(data) {
return request({
url: '/bpm/oa/leave/create',
method: 'post',
data: data
})
}
// 获得请假申请
export function getLeave(id) {
return request({
url: '/bpm/oa/leave/get?id=' + id,
method: 'get'
})
}
// 获得请假申请分页
export function getLeavePage(query) {
return request({
url: '/bpm/oa/leave/page',
method: 'get',
params: query
})
}
-58
View File
@@ -1,58 +0,0 @@
import request from '@/utils/request'
export function getModelPage(query) {
return request({
url: '/bpm/model/page',
method: 'get',
params: query
})
}
export function getModel(id) {
return request({
url: '/bpm/model/get?id=' + id,
method: 'get'
})
}
export function updateModel(data) {
return request({
url: '/bpm/model/update',
method: 'PUT',
data: data
})
}
// 任务状态修改
export function updateModelState(id, state) {
return request({
url: '/bpm/model/update-state',
method: 'put',
data: {
id,
state
}
})
}
export function createModel(data) {
return request({
url: '/bpm/model/create',
method: 'POST',
data: data
})
}
export function deleteModel(id) {
return request({
url: '/bpm/model/delete?id=' + id,
method: 'DELETE'
})
}
export function deployModel(id) {
return request({
url: '/bpm/model/deploy?id=' + id,
method: 'POST'
})
}
-35
View File
@@ -1,35 +0,0 @@
import request from '@/utils/request'
export function getMyProcessInstancePage(query) {
return request({
url: '/bpm/process-instance/my-page',
method: 'get',
params: query
})
}
export function createProcessInstance(data) {
return request({
url: '/bpm/process-instance/create',
method: 'POST',
data: data
})
}
export function cancelProcessInstance(id, reason) {
return request({
url: '/bpm/process-instance/cancel',
method: 'DELETE',
data: {
id,
reason
}
})
}
export function getProcessInstance(id) {
return request({
url: '/bpm/process-instance/get?id=' + id,
method: 'get',
})
}
-56
View File
@@ -1,56 +0,0 @@
import request from '@/utils/request'
export function getTodoTaskPage(query) {
return request({
url: '/bpm/task/todo-page',
method: 'get',
params: query
})
}
export function getDoneTaskPage(query) {
return request({
url: '/bpm/task/done-page',
method: 'get',
params: query
})
}
export function completeTask(data) {
return request({
url: '/bpm/task/complete',
method: 'PUT',
data: data
})
}
export function approveTask(data) {
return request({
url: '/bpm/task/approve',
method: 'PUT',
data: data
})
}
export function rejectTask(data) {
return request({
url: '/bpm/task/reject',
method: 'PUT',
data: data
})
}
export function updateTaskAssignee(data) {
return request({
url: '/bpm/task/update-assignee',
method: 'PUT',
data: data
})
}
export function getTaskListByProcessInstanceId(processInstanceId) {
return request({
url: '/bpm/task/list-by-process-instance-id?processInstanceId=' + processInstanceId,
method: 'get',
})
}
-25
View File
@@ -1,25 +0,0 @@
import request from '@/utils/request'
export function getTaskAssignRuleList(query) {
return request({
url: '/bpm/task-assign-rule/list',
method: 'get',
params: query
})
}
export function createTaskAssignRule(data) {
return request({
url: '/bpm/task-assign-rule/create',
method: 'post',
data: data
})
}
export function updateTaskAssignRule(data) {
return request({
url: '/bpm/task-assign-rule/update',
method: 'put',
data: data
})
}
-52
View File
@@ -1,52 +0,0 @@
import request from '@/utils/request'
// 创建用户组
export function createUserGroup(data) {
return request({
url: '/bpm/user-group/create',
method: 'post',
data: data
})
}
// 更新用户组
export function updateUserGroup(data) {
return request({
url: '/bpm/user-group/update',
method: 'put',
data: data
})
}
// 删除用户组
export function deleteUserGroup(id) {
return request({
url: '/bpm/user-group/delete?id=' + id,
method: 'delete'
})
}
// 获得用户组
export function getUserGroup(id) {
return request({
url: '/bpm/user-group/get?id=' + id,
method: 'get'
})
}
// 获得用户组分页
export function getUserGroupPage(query) {
return request({
url: '/bpm/user-group/page',
method: 'get',
params: query
})
}
// 获取用户组精简信息列表
export function listSimpleUserGroups() {
return request({
url: '/bpm/user-group/list-all-simple',
method: 'get'
})
}
+27
View File
@@ -0,0 +1,27 @@
import request from '@/utils/request'
export function add(data) {
return request({
url: '/bxg/api/fish',
method: 'post',
data
})
}
export function del(ids) {
return request({
url: '/bxg/api/fish/',
method: 'delete',
data: ids
})
}
export function edit(data) {
return request({
url: '/bxg/api/fish',
method: 'put',
data
})
}
export default { add, edit, del }
+27
View File
@@ -0,0 +1,27 @@
import request from '@/utils/request'
export function add(data) {
return request({
url: '/bxg/api/fishImage',
method: 'post',
data
})
}
export function del(ids) {
return request({
url: '/bxg/api/fishImage/',
method: 'delete',
data: ids
})
}
export function edit(data) {
return request({
url: '/bxg/api/fishImage',
method: 'put',
data
})
}
export default { add, edit, del }
+27
View File
@@ -0,0 +1,27 @@
import request from '@/utils/request'
export function add(data) {
return request({
url: '/bxg/api/fishPlace',
method: 'post',
data
})
}
export function del(ids) {
return request({
url: '/bxg/api/fishPlace/',
method: 'delete',
data: ids
})
}
export function edit(data) {
return request({
url: '/bxg/api/fishPlace',
method: 'put',
data
})
}
export default { add, edit, del }
+27
View File
@@ -0,0 +1,27 @@
import request from '@/utils/request'
export function add(data) {
return request({
url: '/bxg/api/fishPush',
method: 'post',
data
})
}
export function del(ids) {
return request({
url: '/bxg/api/fishPush/',
method: 'delete',
data: ids
})
}
export function edit(data) {
return request({
url: '/bxg/api/fishPush',
method: 'put',
data
})
}
export default { add, edit, del }
+1 -1
View File
@@ -2,7 +2,7 @@ import request from '@/utils/request'
export function add(data, id) {
return request({
url: `/api/yxStoreProductRule/save/${id}`,
url: `/bxg/api/yxStoreProductRule/save/${id}`,
method: 'post',
data
})
+10 -1
View File
@@ -8,6 +8,15 @@ export function getData(data) {
})
}
export function getRefundInfo(data) {
return request({
url: '/bxg/api/yxStoreAfterSales/order/express',
method: 'post',
data
})
}
export function salesCheck(data) {
return request({
url: '/bxg/api/yxStoreAfterSales/salesCheck',
@@ -17,7 +26,7 @@ export function salesCheck(data) {
}
export function rebackMoney(params) {
return request({
return request({ //打款退钱
url: '/bxg/api/yxStoreAfterSales/makeMoney',
method: 'post',
params
+7
View File
@@ -15,6 +15,13 @@ export function del(id) {
})
}
export function getBargainInfo(id) {
return request({
url: '/bxg/api/yxStoreBargain/info/' + id,
method: 'get'
})
}
export function edit(data) {
return request({
url: '/bxg/api/yxStoreBargain',
+27
View File
@@ -0,0 +1,27 @@
import request from '@/utils/request'
export function add(data) {
return request({
url: 'bxg/api/yxStoreBrand',
method: 'post',
data
})
}
export function del(ids) {
return request({
url: 'bxg/api/yxStoreBrand/',
method: 'delete',
data: ids
})
}
export function edit(data) {
return request({
url: 'bxg/api/yxStoreBrand',
method: 'put',
data
})
}
export default { add, edit, del }
+9
View File
@@ -8,6 +8,15 @@ export function add(data) {
})
}
//发放优惠券
export function give(data) {
return request({
url: '/bxg/api/yxStoreCoupon/give',
method: 'post',
data
})
}
export function del(id) {
return request({
url: '/bxg/api/yxStoreCoupon/' + id,
+27
View File
@@ -0,0 +1,27 @@
import request from '@/utils/request'
export function add(data) {
return request({
url: 'bxg/api/yxStoreEntry',
method: 'post',
data
})
}
export function del(ids) {
return request({
url: 'bxg/api/yxStoreEntry/',
method: 'delete',
data: ids
})
}
export function edit(data) {
return request({
url: 'bxg/api/yxStoreEntry',
method: 'put',
data
})
}
export default { add, edit, del }
+27
View File
@@ -0,0 +1,27 @@
import request from '@/utils/request'
export function add(data) {
return request({
url: 'bxg/api/yxStoreHotList',
method: 'post',
data
})
}
export function del(ids) {
return request({
url: 'bxg/api/yxStoreHotList/',
method: 'delete',
data: ids
})
}
export function edit(data) {
return request({
url: 'bxg/api/yxStoreHotList',
method: 'put',
data
})
}
export default { add, edit, del }
+27
View File
@@ -0,0 +1,27 @@
import request from '@/utils/request'
export function add(data) {
return request({
url: 'bxg/api/yxStoreHotListRecord',
method: 'post',
data
})
}
export function del(ids) {
return request({
url: 'bxg/api/yxStoreHotListRecord/',
method: 'delete',
data: ids
})
}
export function edit(data) {
return request({
url: 'bxg/api/yxStoreHotListRecord',
method: 'put',
data
})
}
export default { add, edit, del }
+18
View File
@@ -23,6 +23,24 @@ export function edit(data) {
})
}
//订单通过审核
export function check(data) {
return request({
url: '/bxg/api/ordercheck',
method: 'put',
data
})
}
//未付款订单进行取消
export function cancel(data) {
return request({
url: '/bxg/api/orderCancel',
method: 'put',
data
})
}
export function updateDelivery(data) {
return request({
url: '/bxg/api/yxStoreOrder/updateDelivery',
+7
View File
@@ -81,3 +81,10 @@ export function getInfo(id) {
method: 'get'
})
}
export function getStoreProductAndCart() {
return request({
url: '/bxg/api/yxStoreProductAndCart',
method: 'get'
})
}
-54
View File
@@ -1,54 +0,0 @@
import request from '@/utils/request'
// 创建
export function createArea(data) {
return request({
url: '/farm/area/create',
method: 'post',
data: data
})
}
// 更新
export function updateArea(data) {
return request({
url: '/farm/area/update',
method: 'put',
data: data
})
}
// 删除
export function deleteArea(id) {
return request({
url: '/farm/area/delete?id=' + id,
method: 'delete'
})
}
// 获得
export function getArea(id) {
return request({
url: '/farm/area/get?id=' + id,
method: 'get'
})
}
// 获得分页
export function getAreaPage(query) {
return request({
url: '/farm/area/page',
method: 'get',
params: query
})
}
// 导出 Excel
export function exportAreaExcel(query) {
return request({
url: '/farm/area/export-excel',
method: 'get',
params: query,
responseType: 'blob'
})
}
-62
View File
@@ -1,62 +0,0 @@
import request from '@/utils/request'
// 创建
export function createCrop(data) {
return request({
url: '/farm/crop/create',
method: 'post',
data: data
})
}
// 更新
export function updateCrop(data) {
return request({
url: '/farm/crop/update',
method: 'put',
data: data
})
}
// 删除
export function deleteCrop(id) {
return request({
url: '/farm/crop/delete?id=' + id,
method: 'delete'
})
}
// 获得
export function getCrop(id) {
return request({
url: '/farm/crop/get?id=' + id,
method: 'get'
})
}
// 获得分页
export function getCropPage(query) {
return request({
url: '/farm/crop/page',
method: 'get',
params: query
})
}
// 导出 Excel
export function exportCropExcel(query) {
return request({
url: '/farm/crop/export-excel',
method: 'get',
params: query,
responseType: 'blob'
})
}
//获得ERP Material 列表
export function getMaterialList(){
return request({
url: '/farm/crop/getMaterialList',
method: 'get',
})
}
-54
View File
@@ -1,54 +0,0 @@
import request from '@/utils/request'
// 创建
export function createCropRecord(data) {
return request({
url: '/farm/crop-record/create',
method: 'post',
data: data
})
}
// 更新
export function updateCropRecord(data) {
return request({
url: '/farm/crop-record/update',
method: 'put',
data: data
})
}
// 删除
export function deleteCropRecord(id) {
return request({
url: '/farm/crop-record/delete?id=' + id,
method: 'delete'
})
}
// 获得
export function getCropRecord(id) {
return request({
url: '/farm/crop-record/get?id=' + id,
method: 'get'
})
}
// 获得分页
export function getCropRecordPage(query) {
return request({
url: '/farm/crop-record/page',
method: 'get',
params: query
})
}
// 导出 Excel
export function exportCropRecordExcel(query) {
return request({
url: '/farm/crop-record/export-excel',
method: 'get',
params: query,
responseType: 'blob'
})
}
-54
View File
@@ -1,54 +0,0 @@
import request from '@/utils/request'
// 创建农场任务讨论
export function createDiscuss(data) {
return request({
url: '/farm/discuss/create',
method: 'post',
data: data
})
}
// 更新农场任务讨论
export function updateDiscuss(data) {
return request({
url: '/farm/discuss/update',
method: 'put',
data: data
})
}
// 删除农场任务讨论
export function deleteDiscuss(id) {
return request({
url: '/farm/discuss/delete?id=' + id,
method: 'delete'
})
}
// 获得农场任务讨论
export function getDiscuss(id) {
return request({
url: '/farm/discuss/get?id=' + id,
method: 'get'
})
}
// 获得农场任务讨论分页
export function getDiscussPage(query) {
return request({
url: '/farm/discuss/page',
method: 'get',
params: query
})
}
// 导出农场任务讨论 Excel
export function exportDiscussExcel(query) {
return request({
url: '/farm/discuss/export-excel',
method: 'get',
params: query,
responseType: 'blob'
})
}
-63
View File
@@ -1,63 +0,0 @@
import request from '@/utils/request'
// 创建农场任务事件
export function createEvent(data) {
return request({
url: '/farm/event/create',
method: 'post',
data: data
})
}
// 更新农场任务事件
export function updateEvent(data) {
return request({
url: '/farm/event/update',
method: 'put',
data: data
})
}
// 删除农场任务事件
export function deleteEvent(id) {
return request({
url: '/farm/event/delete?id=' + id,
method: 'delete'
})
}
// 获得农场任务事件
export function getEvent(id) {
return request({
url: '/farm/event/get?id=' + id,
method: 'get'
})
}
// 获得农场任务事件分页
export function getEventPage(query) {
return request({
url: '/farm/event/page',
method: 'get',
params: query
})
}
// 搜索条件获得农场任务事件分页
export function getEventSearchPage(query) {
return request({
url: '/farm/event/pageSearch',
method: 'get',
params: query
})
}
// 导出农场任务事件 Excel
export function exportEventExcel(query) {
return request({
url: '/farm/event/export-excel',
method: 'get',
params: query,
responseType: 'blob'
})
}
-54
View File
@@ -1,54 +0,0 @@
import request from '@/utils/request'
// 创建
export function createLogMsg(data) {
return request({
url: '/farm/log-msg/create',
method: 'post',
data: data
})
}
// 更新
export function updateLogMsg(data) {
return request({
url: '/farm/log-msg/update',
method: 'put',
data: data
})
}
// 删除
export function deleteLogMsg(id) {
return request({
url: '/farm/log-msg/delete?id=' + id,
method: 'delete'
})
}
// 获得
export function getLogMsg(id) {
return request({
url: '/farm/log-msg/get?id=' + id,
method: 'get'
})
}
// 获得分页
export function getLogMsgPage(query) {
return request({
url: '/farm/log-msg/page',
method: 'get',
params: query
})
}
// 导出 Excel
export function exportLogMsgExcel(query) {
return request({
url: '/farm/log-msg/export-excel',
method: 'get',
params: query,
responseType: 'blob'
})
}
-63
View File
@@ -1,63 +0,0 @@
import request from '@/utils/request'
// 创建农场项目
export function createProject(data) {
return request({
url: '/farm/project/create',
method: 'post',
data: data
})
}
// 更新农场项目
export function updateProject(data) {
return request({
url: '/farm/project/update',
method: 'put',
data: data
})
}
// 删除农场项目
export function deleteProject(id) {
return request({
url: '/farm/project/delete?id=' + id,
method: 'delete'
})
}
// 获得农场项目
export function getProject(id) {
return request({
url: '/farm/project/get?id=' + id,
method: 'get'
})
}
// 获得农场项目分页
export function getProjectPage(query) {
return request({
url: '/farm/project/page',
method: 'get',
params: query
})
}
// 搜索条件获得农场项目分页
export function getProjectSearchPage(query) {
return request({
url: '/farm/project/pageSearch',
method: 'get',
params: query
})
}
// 导出农场项目 Excel
export function exportProjectExcel(query) {
return request({
url: '/farm/project/export-excel',
method: 'get',
params: query,
responseType: 'blob'
})
}
-54
View File
@@ -1,54 +0,0 @@
import request from '@/utils/request'
// 创建农场资源
export function createResource(data) {
return request({
url: '/farm/resource/create',
method: 'post',
data: data
})
}
// 更新农场资源
export function updateResource(data) {
return request({
url: '/farm/resource/update',
method: 'put',
data: data
})
}
// 删除农场资源
export function deleteResource(id) {
return request({
url: '/farm/resource/delete?id=' + id,
method: 'delete'
})
}
// 获得农场资源
export function getResource(id) {
return request({
url: '/farm/resource/get?id=' + id,
method: 'get'
})
}
// 获得农场资源分页
export function getResourcePage(query) {
return request({
url: '/farm/resource/page',
method: 'get',
params: query
})
}
// 导出农场资源 Excel
export function exportResourceExcel(query) {
return request({
url: '/farm/resource/export-excel',
method: 'get',
params: query,
responseType: 'blob'
})
}
-54
View File
@@ -1,54 +0,0 @@
import request from '@/utils/request'
// 创建农场资源分类
export function createResourceType(data) {
return request({
url: '/farm/resource-type/create',
method: 'post',
data: data
})
}
// 更新农场资源分类
export function updateResourceType(data) {
return request({
url: '/farm/resource-type/update',
method: 'put',
data: data
})
}
// 删除农场资源分类
export function deleteResourceType(id) {
return request({
url: '/farm/resource-type/delete?id=' + id,
method: 'delete'
})
}
// 获得农场资源分类
export function getResourceType(id) {
return request({
url: '/farm/resource-type/get?id=' + id,
method: 'get'
})
}
// 获得农场资源分类分页
export function getResourceTypePage(query) {
return request({
url: '/farm/resource-type/page',
method: 'get',
params: query
})
}
// 导出农场资源分类 Excel
export function exportResourceTypeExcel(query) {
return request({
url: '/farm/resource-type/export-excel',
method: 'get',
params: query,
responseType: 'blob'
})
}
-72
View File
@@ -1,72 +0,0 @@
import request from '@/utils/request'
// 创建农场任务
export function createTask(data) {
return request({
url: '/farm/task/create',
method: 'post',
data: data
})
}
// 更新农场任务
export function updateTask(data) {
return request({
url: '/farm/task/update',
method: 'put',
data: data
})
}
// 删除农场任务
export function deleteTask(id) {
return request({
url: '/farm/task/delete?id=' + id,
method: 'delete'
})
}
// 获得农场任务
export function getTask(id) {
return request({
url: '/farm/task/get?id=' + id,
method: 'get'
})
}
// 获得农场任务分页
export function getTaskPage(query) {
return request({
url: '/farm/task/page',
method: 'get',
params: query
})
}
//一次性获得农场任务分页数据
export function getAdminTaskPage(query){
return request({
url: '/farm/task/apiPage',
method: 'get',
params: query
})
}
// 条件搜索获得农场任务分页
export function getTaskSearchPage(query) {
return request({
url: '/farm/task/pageSearch',
method: 'get',
params: query
})
}
// 导出农场任务 Excel
export function exportTaskExcel(query) {
return request({
url: '/farm/task/export-excel',
method: 'get',
params: query,
responseType: 'blob'
})
}
-54
View File
@@ -1,54 +0,0 @@
import request from '@/utils/request'
// 创建任务类型
export function createTaskCate(data) {
return request({
url: '/farm/task-cate/create',
method: 'post',
data: data
})
}
// 更新任务类型
export function updateTaskCate(data) {
return request({
url: '/farm/task-cate/update',
method: 'put',
data: data
})
}
// 删除任务类型
export function deleteTaskCate(id) {
return request({
url: '/farm/task-cate/delete?id=' + id,
method: 'delete'
})
}
// 获得任务类型
export function getTaskCate(id) {
return request({
url: '/farm/task-cate/get?id=' + id,
method: 'get'
})
}
// 获得任务类型分页
export function getTaskCatePage(query) {
return request({
url: '/farm/task-cate/page',
method: 'get',
params: query
})
}
// 导出任务类型 Excel
export function exportTaskCateExcel(query) {
return request({
url: '/farm/task-cate/export-excel',
method: 'get',
params: query,
responseType: 'blob'
})
}
-54
View File
@@ -1,54 +0,0 @@
import request from '@/utils/request'
// 创建
export function createWorkHour(data) {
return request({
url: '/farm/work-hour/create',
method: 'post',
data: data
})
}
// 更新
export function updateWorkHour(data) {
return request({
url: '/farm/work-hour/update',
method: 'put',
data: data
})
}
// 删除
export function deleteWorkHour(id) {
return request({
url: '/farm/work-hour/delete?id=' + id,
method: 'delete'
})
}
// 获得
export function getWorkHour(id) {
return request({
url: '/farm/work-hour/get?id=' + id,
method: 'get'
})
}
// 获得分页
export function getWorkHourPage(query) {
return request({
url: '/farm/work-hour/page',
method: 'get',
params: query
})
}
// 导出 Excel
export function exportWorkHourExcel(query) {
return request({
url: '/farm/work-hour/export-excel',
method: 'get',
params: query,
responseType: 'blob'
})
}
+2 -2
View File
@@ -2,14 +2,14 @@ import request from '@/utils/request'
export function get(tableName) {
return request({
url: 'api/genConfig/' + tableName,
url: 'bxg/api/genConfig/' + tableName,
method: 'get'
})
}
export function update(data) {
return request({
url: 'api/genConfig',
url: 'bxg/api/genConfig',
data,
method: 'put'
})
+4 -4
View File
@@ -2,14 +2,14 @@ import request from '@/utils/request'
export function getAllTable() {
return request({
url: 'api/generator/tables/all',
url: 'bxg/api/generator/tables/all',
method: 'get'
})
}
export function generator(tableName, type) {
return request({
url: 'api/generator/' + tableName + '/' + type,
url: 'bxg/api/generator/' + tableName + '/' + type,
method: 'post',
responseType: type === 2 ? 'blob' : ''
})
@@ -17,7 +17,7 @@ export function generator(tableName, type) {
export function save(data) {
return request({
url: 'api/generator',
url: 'bxg/api/generator',
data,
method: 'put'
})
@@ -25,7 +25,7 @@ export function save(data) {
export function sync(tables) {
return request({
url: 'api/generator/sync',
url: 'bxg/api/generator/sync',
method: 'post',
data: tables
})
+3 -3
View File
@@ -2,21 +2,21 @@ import request from '@/utils/request'
export function getErrDetail(id) {
return request({
url: 'api/logs/error/' + id,
url: 'bxg/api/logs/error/' + id,
method: 'get'
})
}
export function delAllError() {
return request({
url: 'api/logs/del/error',
url: 'bxg/api/logs/del/error',
method: 'delete'
})
}
export function delAllInfo() {
return request({
url: 'api/logs/del/info',
url: 'bxg/api/logs/del/info',
method: 'delete'
})
}
+14
View File
@@ -17,6 +17,20 @@ export function listSimpleMenus() {
})
}
export function delRedis(data) {
return request({
url: '/bxg/api/redis',
method: 'delete',
data: data
})
}
export function del() {
return request({
url: '/bxg/api/del',
method: 'get'
})
}
// 查询菜单详细
export function getMenu(id) {
return request({
+3 -3
View File
@@ -2,14 +2,14 @@ import request from '@/utils/request'
export function get() {
return request({
url: 'api/aliPay',
url: 'bxg/api/aliPay',
method: 'get'
})
}
export function update(data) {
return request({
url: 'api/aliPay',
url: 'bxg/api/aliPay',
data,
method: 'put'
})
@@ -18,7 +18,7 @@ export function update(data) {
// 支付
export function toAliPay(url, data) {
return request({
url: 'api/' + url,
url: 'bxg/api/' + url,
data,
method: 'post'
})
+27
View File
@@ -0,0 +1,27 @@
import request from '@/utils/request'
export function add(data) {
return request({
url: 'bxg/api/yxEvaluation',
method: 'post',
data
})
}
export function del(ids) {
return request({
url: 'bxg/api/yxEvaluation/',
method: 'delete',
data: ids
})
}
export function edit(data) {
return request({
url: 'bxg/api/yxEvaluation',
method: 'put',
data
})
}
export default { add, edit, del }
+27
View File
@@ -0,0 +1,27 @@
import request from '@/utils/request'
export function add(data) {
return request({
url: 'bxg/api/yxStoreExpert',
method: 'post',
data
})
}
export function del(ids) {
return request({
url: 'bxg/api/yxStoreExpert/',
method: 'delete',
data: ids
})
}
export function edit(data) {
return request({
url: 'bxg/api/yxStoreExpert',
method: 'put',
data
})
}
export default { add, edit, del }
+2
View File
@@ -0,0 +1,2 @@
import Vue from 'vue'
export default new Vue
+1
View File
@@ -122,6 +122,7 @@ function CRUD(options) {
},
// 刷新
refresh() {
console.log('调这里',crud);
if (!callVmHook(crud, CRUD.HOOK.beforeRefresh)) {
return
}
+5
View File
@@ -37,6 +37,11 @@ export default {
type: Number,
default: null,
},
/* 宽度 */
wight: {
type: Number,
default: null,
},
/* 最小高度 */
minHeight: {
type: Number,
+216
View File
@@ -0,0 +1,216 @@
<template>
<div class="upload-file">
<el-upload
multiple
:action="uploadFileUrl"
:before-upload="handleBeforeUpload"
:file-list="fileList"
:limit="limit"
:on-error="handleUploadError"
:on-exceed="handleExceed"
:on-success="handleUploadSuccess"
:show-file-list="false"
:headers="headers"
class="upload-file-uploader"
ref="upload"
>
<!-- 上传按钮 -->
<el-button size="mini" type="primary">选取视频</el-button>
<!-- 上传提示 -->
<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-upload>
<!-- <el-button size="mini" type="primary" @click.native.prevent="dialogVideo=true">预览视频</el-button>-->
<el-dialog :visible.sync="dialogVideo">
<video width="600px" :src="dialogUrl" controls />
</el-dialog>
<!-- 文件列表 -->
<transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
<li :key="file.url" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList">
<el-link :href="`${baseUrl}${file.url}`" :underline="false" target="_blank">
<span class="el-icon-document"> {{ getFileName(file.name) }} </span>
</el-link>
<div class="ele-upload-list__item-content-action">
<el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link>
</div>
</li>
</transition-group>
</div>
</template>
<script>
import { getToken } from "@/utils/auth";
export default {
name: "VideoUpload",
props: {
// 值
value: [String, Object, Array],
// 数量限制
limit: {
type: Number,
default: 1,
},
// 大小限制(MB)
fileSize: {
type: Number,
default: 500,
},
// 文件类型, 例如['png', 'jpg', 'jpeg']
fileType: {
type: Array,
default: () => ["avi","mp4"],
},
// 是否显示提示
isShowTip: {
type: Boolean,
default: true
}
},
data() {
return {
dialogVideo:false,
dialogUrl:'',
number: 0,
uploadList: [],
baseUrl: process.env.VUE_APP_BASE_API,
uploadFileUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址
headers: {
Authorization: "Bearer " + getToken(),
},
fileList: [],
};
},
watch: {
value: {
handler(val) {
if (val) {
let temp = 1;
// 首先将值转为数组
const list = Array.isArray(val) ? val : this.value.split(',');
// 然后将数组转为对象数组
this.fileList = list.map(item => {
if (typeof item === "string") {
item = { name: item, url: item };
}
item.uid = item.uid || new Date().getTime() + temp++;
return item;
});
} else {
this.fileList = [];
return [];
}
},
deep: true,
immediate: true
}
},
computed: {
// 是否显示提示
showTip() {
return this.isShowTip && (this.fileType || this.fileSize);
},
},
methods: {
// 上传前校检格式和大小
handleBeforeUpload(file) {
// 校检文件类型
if (this.fileType) {
let fileExtension = "";
if (file.name.lastIndexOf(".") > -1) {
fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
}
const isTypeOk = this.fileType.some((type) => {
if (file.type.indexOf(type) > -1) return true;
if (fileExtension && fileExtension.indexOf(type) > -1) return true;
return false;
});
if (!isTypeOk) {
this.$modal.msgError(`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`);
return false;
}
}
// 校检文件大小
if (this.fileSize) {
const isLt = file.size / 1024 / 1024 < this.fileSize;
if (!isLt) {
this.$modal.msgError(`上传文件大小不能超过 ${this.fileSize} MB!`);
return false;
}
}
this.$modal.loading("正在上传视频,请稍候...");
this.number++;
return true;
},
// 文件个数超出
handleExceed() {
this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`);
},
// 上传失败
handleUploadError(err) {
this.$modal.msgError("上传视频失败,请重试");
this.$modal.closeLoading()
},
// 上传成功回调
handleUploadSuccess(res) {
this.uploadList.push({ name: res.data.fileName, url: res.data.fileName });
console.log('成功!',res)
this.$emit('videoInput',this.uploadList)
if (this.uploadList.length === this.number) {
this.fileList = this.fileList.concat(this.uploadList);
this.uploadList = [];
this.number = 0;
this.$emit("input", this.listToString(this.fileList));
this.$modal.closeLoading();
}
},
// 删除文件
handleDelete(index) {
this.fileList.splice(index, 1);
this.$emit("input", this.listToString(this.fileList));
},
// 获取文件名称
getFileName(name) {
if (name.lastIndexOf("/") > -1) {
return name.slice(name.lastIndexOf("/") + 1);
} else {
return "";
}
},
// 对象转成指定字符串分隔
listToString(list, separator) {
let strs = "";
separator = separator || ",";
for (let i in list) {
strs += list[i].url + separator;
}
return strs != '' ? strs.substr(0, strs.length - 1) : '';
}
}
};
</script>
<style scoped lang="scss">
.upload-file-uploader {
margin-bottom: 5px;
}
.upload-file-list .el-upload-list__item {
border: 1px solid #e4e7ed;
line-height: 2;
margin-bottom: 10px;
position: relative;
}
.upload-file-list .ele-upload-list__item-content {
display: flex;
justify-content: space-between;
align-items: center;
color: inherit;
}
.ele-upload-list__item-content-action .el-link {
margin-right: 10px;
}
</style>
+5 -3
View File
@@ -40,7 +40,7 @@
width="100%"
>
<el-container>
<el-aside width="unset">
<el-aside width="unset" style="height: 510px">
<div style="margin-bottom: 10px">
<el-button
class="el-icon-plus"
@@ -464,11 +464,13 @@ export default {
sureUrls() {
let str = ''
this.urls.forEach(item => {
str += '<img src="' + item + '">'
// str += '<img src="' + item + '">'
//实现指定位置插入图片
nowEditor.editor.execCommand('insertimage',{src:item})
// this.$set(this.value, this.value.length, item)
})
nowEditor.dialog.close(true)
nowEditor.editor.setContent(str, true)
// nowEditor.editor.setContent(str, true)
this.listDialogVisible = false
}
}
+1 -1
View File
@@ -29,7 +29,7 @@ export default {
return {
resourcesUrl: '',
headers: {
'Authorization': getToken()
'Authorization':"Bearer "+getToken()
}
}
},
+9 -2
View File
@@ -35,12 +35,12 @@
<el-dialog
title="图片素材库"
append-to-body
:visible.sync="listDialogVisible"
width="70%"
append-to-body
>
<el-container>
<el-aside width="unset">
<el-aside width="unset" style="height: 510px">
<div style="margin-bottom: 10px">
<el-button
class="el-icon-plus"
@@ -172,6 +172,12 @@ export default {
return 5
}
},
// disabled:{
// type:Boolean,
// default(){
// return false
// }
// },
// 宽度
width: {
type: Number,
@@ -468,6 +474,7 @@ export default {
</script>
<style lang="scss" scoped>
::v-deep .el-icon-circle-close{
color: red;
}
+1 -1
View File
@@ -33,7 +33,7 @@
width="70%"
>
<el-container>
<el-aside width="unset">
<el-aside width="unset" style="height: 510px">
<div style="margin-bottom: 10px">
<el-button
class="el-icon-plus"
+3 -1
View File
@@ -1,7 +1,9 @@
<template>
<section class="app-main">
<transition name="fade-transform" mode="out-in">
<keep-alive :include="cachedViews">
<!-- <keep-alive :include="cachedViews">-->
<!-- 改为所有页面都支持缓存-->
<keep-alive>
<router-view :key="key" />
</keep-alive>
</transition>
+16 -1
View File
@@ -37,6 +37,9 @@
<el-dropdown-item @click.native="setting = true">
<span>布局设置</span>
</el-dropdown-item>
<el-dropdown-item @click.native="delIndexRedis">
<span>清除缓存</span>
</el-dropdown-item>
<el-dropdown-item divided @click.native="logout">
<span>退出登录</span>
</el-dropdown-item>
@@ -56,7 +59,7 @@ import SizeSelect from '@/components/SizeSelect'
import Search from '@/components/HeaderSearch'
import RuoYiGit from '@/components/RuoYi/Git'
import RuoYiDoc from '@/components/RuoYi/Doc'
import {delRedis,del} from "@/api/system/menu";
export default {
components: {
Breadcrumb,
@@ -92,6 +95,18 @@ export default {
}
},
methods: {
delIndexRedis(){
let data={
key:"zsw:index_data",
value:""
}
// delRedis(data).then(res=>{
del().then(res=>{
// console.log('res',res)
this.$message.success("清除成功")
}
)
},
toggleSideBar() {
this.$store.dispatch('app/toggleSideBar')
},
-1
View File
@@ -31,7 +31,6 @@
<script>
import ScrollPane from './ScrollPane'
import path from 'path'
export default {
components: { ScrollPane },
data() {
+10 -1
View File
@@ -3,9 +3,9 @@ import {
download
} from '@/api/bxg/data'
import {
parseTime,
downloadFile
} from '@/utils/index'
import {parseTime} from "@/utils/ruoyi";
import checkPermission from '@/utils/permission'
export default {
@@ -53,6 +53,7 @@ export default {
parseTime,
downloadFile,
checkPermission,
//通用的搜索方法
async init() {
if (!await this.beforeInit()) {
return
@@ -61,8 +62,11 @@ export default {
this.loading = true
// 请求数据
initData(this.url, this.getQueryParame()).then(data => {
console.log('data',data)
//商品分类
this.cateList = data.cateList
this.total = data.totalElements
//商品
this.data = data.content
// time 毫秒后显示表格
setTimeout(() => {
@@ -92,6 +96,11 @@ export default {
this.page = e - 1
this.init()
},
// 改变页码
pageChanges(e) {
this.page = e
this.init()
},
// 改变每页显示数
sizeChange(e) {
this.page = 0
+13 -50
View File
@@ -80,7 +80,18 @@ export const constantRoutes = [
meta: {title: '个人中心', icon: 'user'}
}
]
}, {
},
{
path: '/yshop/materia/index',
name: `images`,
meta: {
title: '上传图片',
noCache: true
},
component: (resolve) => require(['@/components/editorMaterial/index'], resolve),
hidden: true
},
{
path: '/dict',
component: Layout,
hidden: true,
@@ -113,54 +124,6 @@ export const constantRoutes = [
meta: {title: '修改生成配置', activeMenu: '/infra/codegen'}
}
]
}, {
path: '/bpm',
component: Layout,
hidden: true,
redirect: 'noredirect',
children: [{
path: 'oa/leave/create',
component: (resolve) => require(['@/views/bpm/oa/leave/create'], resolve),
name: '发起 OA 请假',
meta: {title: '发起 OA 请假', icon: 'form', activeMenu: '/bpm/oa/leave'}
}, {
path: 'oa/leave/detail',
component: (resolve) => require(['@/views/bpm/oa/leave/detail'], resolve),
name: '查看 OA 请假',
meta: {title: '查看 OA 请假', icon: 'view', activeMenu: '/bpm/oa/leave'}
}
]
}, {
path: '/bpm',
component: Layout,
hidden: true,
children: [{
path: 'manager/form/edit',
component: (resolve) => require(['@/views/bpm/form/formEditor'], resolve),
name: '流程表单-编辑',
meta: {title: '流程表单-编辑', activeMenu: '/bpm/manager/form'}
}, {
path: 'manager/definition',
component: (resolve) => require(['@/views/bpm/definition/index'], resolve),
name: '流程定义',
meta: {title: '流程定义', activeMenu: '/bpm/manager/model'}
}, {
path: 'manager/model/design',
component: (resolve) => require(['@/views/bpm/model/modelEditor'], resolve),
name: '设计流程',
meta: {title: '设计流程', activeMenu: '/bpm/manager/model'}
}, {
path: 'process-instance/create',
component: (resolve) => require(['@/views/bpm/processInstance/create'], resolve),
name: '发起流程',
meta: {title: '发起流程', activeMenu: '/bpm/task/my'}
}, {
path: 'process-instance/detail',
component: (resolve) => require(['@/views/bpm/processInstance/detail'], resolve),
name: '流程详情',
meta: {title: '流程详情', activeMenu: '/bpm/task/my'}
}
]
}
]
@@ -172,7 +135,7 @@ Router.prototype.push = function push(location) {
export default new Router({
base: process.env.VUE_APP_APP_NAME ? process.env.VUE_APP_APP_NAME : "/",
mode: 'history', // 去掉url中的#
// mode: 'history', // 去掉url中的#
scrollBehavior: () => ({y: 0}),
routes: constantRoutes
})
+2
View File
@@ -31,5 +31,7 @@ const getters = {
uploadApi: state => state.api.uploadApi,
updateAvatarApi: state => state.api.updateAvatarApi,
qiNiuUploadApi: state => state.api.qiNiuUploadApi,
sqlApi: state => state.api.sqlApi,
swaggerApi: state => state.api.swaggerApi
}
export default getters
+3 -5
View File
@@ -47,11 +47,9 @@ const user = {
setToken(res.token)
commit('SET_TOKEN', res.token)
// 设定进销存参数 尝试同步zsw
// let params = {};
// params.currentPage = 1;
// params.pageSize = 100;
let params = {};
params.currentPage = 1;
params.pageSize = 100;
// getAction('/erp/materialProperty/list', params).then((mp) => {
// console.log(mp);
// if(mp && mp.code === 200){
+10 -2
View File
@@ -15,7 +15,7 @@ const service = axios.create({
// axios中请求配置有baseURL选项,表示请求URL公共部分
baseURL: process.env.VUE_APP_BASE_API + '/admin-api/', // 此处的 /admin-api/ 地址,原因是后端的基础路径为 /admin-api/
// 超时
timeout: 10000
timeout: 50000
})
// request拦截器
service.interceptors.request.use(config => {
@@ -61,6 +61,7 @@ service.interceptors.request.use(config => {
// 响应拦截器
service.interceptors.response.use(res => {
// console.log('res1111111111',res)
// 未设置状态码则默认成功状态
const code = res.data.code || 200;
// 获取错误信息
@@ -89,7 +90,14 @@ service.interceptors.response.use(res => {
type: 'error'
})
return Promise.reject(new Error(msg))
} else if (code === 901) {
}else if(res.data.status === 500){
Message({
message: msg,
type: 'error'
})
return Promise.reject(new Error(msg))
}
else if (code === 901) {
Message({
type: 'error',
duration: 0,
+48
View File
@@ -297,6 +297,54 @@ export function jsExpand(options = {}) {
}
/**
* 重复值验证工具方法
*
* 使用示例:
* { validator: (rule, value, callback) => validateDuplicateValue('sys_fill_rule', 'rule_code', value, this.model.id, callback) }
*
* @param tableName 被验证的表名
* @param fieldName 被验证的字段名
* @param fieldVal 被验证的值
* @param dataId 数据ID,可空
* @param callback
*/
export function validateDuplicateValue(tableName, fieldName, fieldVal, dataId, callback) {
if (fieldVal) {
let params = { tableName, fieldName, fieldVal, dataId }
api.duplicateCheck(params).then(res => {
res['success'] ? callback() : callback(res['message'])
}).catch(err => {
callback(err.message || err)
})
} else {
callback()
}
}
/**
* 根据编码校验规则code,校验传入的值是否合法
*
* 使用示例:
* { validator: (rule, value, callback) => validateCheckRule('common', value, callback) }
*
* @param ruleCode 编码校验规则 code
* @param value 被验证的值
* @param callback
*/
export function validateCheckRule(ruleCode, value, callback) {
if (ruleCode && value) {
value = encodeURIComponent(value)
api.checkRuleByCode({ ruleCode, value }).then(res => {
res['success'] ? callback() : callback(res['message'])
}).catch(err => {
callback(err.message || err)
})
} else {
callback()
}
}
/**
* 如果值不存在就 push 进数组,反之不处理
* @param array 要操作的数据
-175
View File
@@ -1,175 +0,0 @@
<template>
<div class="app-container">
<doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
<!-- 列表 -->
<el-table v-loading="loading" :data="list">
<el-table-column label="定义编号" align="center" prop="id" width="400" />
<el-table-column label="定义名称" align="center" prop="name" width="100">
<template slot-scope="scope">
<el-button type="text" @click="handleBpmnDetail(scope.row)">
<span>{{ scope.row.name }}</span>
</el-button>
</template>
</el-table-column>
<el-table-column label="定义分类" align="center" prop="category" width="100">
<template slot-scope="scope">
<dict-tag :type="DICT_TYPE.BPM_MODEL_CATEGORY" :value="scope.row.category" />
</template>
</el-table-column>
<el-table-column label="表单信息" align="center" prop="formType" width="200">
<template slot-scope="scope">
<el-button v-if="scope.row.formId" type="text" @click="handleFormDetail(scope.row)">
<span>{{ scope.row.formName }}</span>
</el-button>
<el-button v-else-if="scope.row.formCustomCreatePath" type="text" @click="handleFormDetail(scope.row)">
<span>{{ scope.row.formCustomCreatePath }}</span>
</el-button>
<label v-else>暂无表单</label>
</template>
</el-table-column>
<el-table-column label="流程版本" align="center" prop="processDefinition.version" width="80">
<template slot-scope="scope">
<el-tag size="medium" v-if="scope.row">v{{ scope.row.version }}</el-tag>
<el-tag size="medium" type="warning" v-else>未部署</el-tag>
</template>
</el-table-column>
<el-table-column label="状态" align="center" prop="version" width="80">
<template slot-scope="scope">
<el-tag type="success" v-if="scope.row.suspensionState === 1">激活</el-tag>
<el-tag type="warning" v-if="scope.row.suspensionState === 2">挂起</el-tag>
</template>
</el-table-column>
<el-table-column label="部署时间" align="center" prop="deploymentTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.deploymentTime) }}</span>
</template>
</el-table-column>
<el-table-column label="定义描述" align="center" prop="description" width="300" show-overflow-tooltip />
<el-table-column label="操作" align="center" width="150" fixed="right">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-s-custom" @click="handleAssignRule(scope.row)"
v-hasPermi="['bpm:task-assign-rule:update']">分配规则</el-button>
</template>
</el-table-column>
</el-table>
<!-- 流程表单配置详情 -->
<el-dialog title="表单详情" :visible.sync="detailOpen" width="50%" append-to-body>
<parser :key="new Date().getTime()" :form-conf="detailForm" />
</el-dialog>
<!-- 流程模型图的预览 -->
<el-dialog title="流程图" :visible.sync="showBpmnOpen" width="80%" append-to-body>
<my-process-viewer key="designer" v-model="bpmnXML" v-bind="bpmnControlForm" />
</el-dialog>
<!-- 分页组件 -->
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
@pagination="getList"/>
<!-- ========== 流程任务分配规则 ========== -->
<taskAssignRuleDialog ref="taskAssignRuleDialog" />
</div>
</template>
<script>
import {getProcessDefinitionBpmnXML, getProcessDefinitionPage} from "@/api/bpm/definition";
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
import {getForm} from "@/api/bpm/form";
import {decodeFields} from "@/utils/formGenerator";
import Parser from '@/components/parser/Parser'
import taskAssignRuleDialog from "../taskAssignRule/taskAssignRuleDialog";
export default {
name: "processDefinition",
components: {
Parser,
taskAssignRuleDialog
},
data() {
return {
// 遮罩层
loading: true,
// 总条数
total: 0,
// 表格数据
list: [],
// 查询参数
queryParams: {
pageNo: 1,
pageSize: 10
},
// 流程表单详情
detailOpen: false,
detailForm: {
fields: []
},
// BPMN 数据
showBpmnOpen: false,
bpmnXML: null,
bpmnControlForm: {
prefix: "activiti"
},
// 数据字典
categoryDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_CATEGORY),
};
},
created() {
const key = this.$route.query && this.$route.query.key
if (key) {
this.queryParams['key'] = key
}
this.getList();
},
methods: {
/** 查询流程定义列表 */
getList() {
this.loading = true;
getProcessDefinitionPage(this.queryParams).then(response => {
this.list = response.data.list;
this.total = response.data.total;
this.loading = false;
}
);
},
/** 流程表单的详情按钮操作 */
handleFormDetail(row) {
// 流程表单
if (row.formId) {
// 设置值
this.detailForm = {
...JSON.parse(row.formConf),
fields: decodeFields(row.formFields)
}
// 弹窗打开
this.detailOpen = true
// 业务表单
} else if (row.formCustomCreatePath) {
this.$router.push({ path: row.formCustomCreatePath});
}
},
/** 流程图的详情按钮操作 */
handleBpmnDetail(row) {
getProcessDefinitionBpmnXML(row.id).then(response => {
this.bpmnXML = response.data
// 弹窗打开
this.showBpmnOpen = true
})
},
/** 处理任务分配规则列表的按钮操作 */
handleAssignRule(row) {
this.$refs['taskAssignRuleDialog'].initProcessDefinition(row.id);
},
}
};
</script>
<style lang="scss">
.my-process-designer {
height: calc(100vh - 200px);
}
</style>
-569
View File
@@ -1,569 +0,0 @@
<template>
<div class="container">
<div class="left-board">
<div class="logo-wrapper">
<div class="logo">流程表单</div>
</div>
<el-scrollbar class="left-scrollbar">
<!-- 左边表单项 -->
<div class="components-list">
<div v-for="(item, listIndex) in leftComponents" :key="listIndex">
<div class="components-title">
<svg-icon icon-class="component" />
{{ item.title }}
</div>
<draggable
class="components-draggable"
:list="item.list"
:group="{ name: 'componentsGroup', pull: 'clone', put: false }"
:clone="cloneComponent"
draggable=".components-item"
:sort="false"
@end="onEnd"
>
<div
v-for="(element, index) in item.list"
:key="index"
class="components-item"
@click="addComponent(element)"
>
<div class="components-body">
<svg-icon :icon-class="element.__config__.tagIcon" />
{{ element.__config__.label }}
</div>
</div>
</draggable>
</div>
<!-- 左边动态表单 -->
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="表单名" prop="name">
<el-input v-model="form.name" placeholder="请输入表单名" />
</el-form-item>
<el-form-item label="开启状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
:key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input type="textarea" v-model="form.remark" placeholder="请输入备注" />
</el-form-item>
</el-form>
</div>
</el-scrollbar>
</div>
<div class="center-board">
<div class="action-bar">
<el-button icon="el-icon-check" type="text" @click="save">保存</el-button>
<!-- <el-button icon="el-icon-video-play" type="text" @click="run">-->
<!-- 运行-->
<!-- </el-button>-->
<el-button icon="el-icon-view" type="text" @click="showJson">
查看json
</el-button>
<!-- <el-button icon="el-icon-download" type="text" @click="download">-->
<!-- 导出vue文件-->
<!-- </el-button>-->
<!-- <el-button class="copy-btn-main" icon="el-icon-document-copy" type="text" @click="copy">-->
<!-- 复制代码-->
<!-- </el-button>-->
<el-button class="delete-btn" icon="el-icon-delete" type="text" @click="empty">
清空
</el-button>
</div>
<!-- 中间表单项 -->
<el-scrollbar class="center-scrollbar">
<el-row class="center-board-row" :gutter="formConf.gutter">
<el-form
:size="formConf.size"
:label-position="formConf.labelPosition"
:disabled="formConf.disabled"
:label-width="formConf.labelWidth + 'px'"
>
<draggable class="drawing-board" :list="drawingList" :animation="340" group="componentsGroup">
<draggable-item
v-for="(item, index) in drawingList"
:key="item.renderKey"
:drawing-list="drawingList"
:current-item="item"
:index="index"
:active-id="activeId"
:form-conf="formConf"
@activeItem="activeFormItem"
@copyItem="drawingItemCopy"
@deleteItem="drawingItemDelete"
/>
</draggable>
<div v-show="!drawingList.length" class="empty-info">
从左侧拖入或点选组件进行表单设计
</div>
</el-form>
</el-row>
</el-scrollbar>
</div>
<!-- 右边组件属性/表单属性 -->
<right-panel
:active-data="activeData"
:form-conf="formConf"
:show-field="!!drawingList.length"
@tag-change="tagChange"
@fetch-data="fetchData"
/>
<!-- <form-drawer-->
<!-- :visible.sync="drawerVisible"-->
<!-- :form-data="formData"-->
<!-- size="100%"-->
<!-- :generate-conf="generateConf"-->
<!-- />-->
<json-drawer
size="60%"
:visible.sync="jsonDrawerVisible"
:json-str="JSON.stringify(formData)"
@refresh="refreshJson"
/>
<!-- <code-type-dialog-->
<!-- :visible.sync="dialogVisible"-->
<!-- title="选择生成类型"-->
<!-- :show-file-name="showFileName"-->
<!-- @confirm="generate"-->
<!-- />-->
<!-- <input id="copyNode" type="hidden">-->
</div>
</template>
<script>
import draggable from 'vuedraggable'
import { debounce } from 'throttle-debounce'
import { saveAs } from 'file-saver'
import ClipboardJS from 'clipboard'
import render from '@/components/render/render'
import FormDrawer from '@/views/infra/build/FormDrawer'
import JsonDrawer from '@/views/infra/build/JsonDrawer'
import RightPanel from '@/views/infra/build/RightPanel'
import {
inputComponents, selectComponents, layoutComponents, formConf
} from '@/components/generator/config'
import {
exportDefault, beautifierConf, isNumberStr, titleCase, deepClone, isObjectObject
} from '@/utils/index'
import {
makeUpHtml, vueTemplate, vueScript, cssStyle
} from '@/components/generator/html'
import { makeUpJs } from '@/components/generator/js'
import { makeUpCss } from '@/components/generator/css'
import drawingDefalut from '@/components/generator/drawingDefalut'
import logo from '@/assets/logo/logo.png'
import CodeTypeDialog from '@/views/infra/build/CodeTypeDialog'
import DraggableItem from '@/views/infra/build/DraggableItem'
import {
getDrawingList, saveDrawingList, getIdGlobal, saveIdGlobal, getFormConf
} from '@/utils/db'
import loadBeautifier from '@/utils/loadBeautifier'
import {CommonStatusEnum} from "@/utils/constants";
import {createForm, getForm, updateForm} from "@/api/bpm/form";
import {decodeFields} from "@/utils/formGenerator";
let beautifier
const emptyActiveData = { style: {}, autosize: {} }
let oldActiveId
let tempActiveData
const drawingListInDB = getDrawingList()
const formConfInDB = getFormConf()
const idGlobal = getIdGlobal()
export default {
components: {
draggable,
render,
FormDrawer,
JsonDrawer,
RightPanel,
CodeTypeDialog,
DraggableItem
},
data() {
return {
logo,
idGlobal,
formConf,
inputComponents,
selectComponents,
layoutComponents,
labelWidth: 100,
// drawingList: drawingDefalut,
drawingData: {}, // 生成后的表单数据
activeId: drawingDefalut[0].__config__.formId,
drawingList: [], // 表单项的数组
// activeId: undefined,
// activeData: {},
drawerVisible: false,
formData: {},
dialogVisible: false,
jsonDrawerVisible: false,
generateConf: null,
showFileName: false,
activeData: drawingDefalut[0], // 右边编辑器激活的表单项
saveDrawingListDebounce: debounce(340, saveDrawingList),
saveIdGlobalDebounce: debounce(340, saveIdGlobal),
leftComponents: [
{
title: '输入型组件',
list: inputComponents
},
{
title: '选择型组件',
list: selectComponents
},
{
title: '布局型组件',
list: layoutComponents
}
],
// 表单参数
form: {
status: CommonStatusEnum.ENABLE,
},
// 表单校验
rules: {
name: [{ required: true, message: "表单名不能为空", trigger: "blur" }],
status: [{ required: true, message: "开启状态不能为空", trigger: "blur" }],
}
}
},
computed: {
},
watch: {
// eslint-disable-next-line func-names
'activeData.__config__.label': function (val, oldVal) {
if (
this.activeData.placeholder === undefined
|| !this.activeData.__config__.tag
|| oldActiveId !== this.activeId
) {
return
}
this.activeData.placeholder = this.activeData.placeholder.replace(oldVal, '') + val
},
activeId: {
handler(val) {
oldActiveId = val
},
immediate: true
},
drawingList: {
handler(val) {
this.saveDrawingListDebounce(val)
if (val.length === 0) this.idGlobal = 100
},
deep: true
},
idGlobal: {
handler(val) {
this.saveIdGlobalDebounce(val)
},
immediate: true
}
},
mounted() {
// 【add by 芋道源码】不读缓存
// if (Array.isArray(drawingListInDB) && drawingListInDB.length > 0) {
// this.drawingList = drawingListInDB
// } else {
// this.drawingList = drawingDefalut
// }
// this.activeFormItem(this.drawingList[0])
// if (formConfInDB) {
// this.formConf = formConfInDB
// }
loadBeautifier(btf => {
beautifier = btf
})
const clipboard = new ClipboardJS('#copyNode', {
text: trigger => {
const codeStr = this.generateCode()
this.$notify({
title: '成功',
message: '代码已复制到剪切板,可粘贴。',
type: 'success'
})
return codeStr
}
})
clipboard.on('error', e => {
this.$message.error('代码复制失败')
})
},
created() {
// 读取表单配置
const formId = this.$route.query && this.$route.query.formId
if (formId) {
getForm(formId).then(response => {
const data = response.data
this.form = {
id: data.id,
name: data.name,
status: data.status,
remark: data.remark
}
this.formConf = JSON.parse(data.conf)
this.drawingList = decodeFields(data.fields)
// 设置激活的表单项
this.activeData = this.drawingList[0]
this.activeId = this.activeData.__config__.formId
// 设置 idGlobal,避免重复
this.idGlobal += this.drawingList.length
});
}
},
methods: {
setObjectValueReduce(obj, strKeys, data) {
const arr = strKeys.split('.')
arr.reduce((pre, item, i) => {
if (arr.length === i + 1) {
pre[item] = data
} else if (!isObjectObject(pre[item])) {
pre[item] = {}
}
return pre[item]
}, obj)
},
setRespData(component, resp) {
const { dataPath, renderKey, dataConsumer } = component.__config__
if (!dataPath || !dataConsumer) return
const respData = dataPath.split('.').reduce((pre, item) => pre[item], resp)
// 将请求回来的数据,赋值到指定属性。
// 以el-tabel为例,根据Element文档,应该将数据赋值给el-tabel的data属性,所以dataConsumer的值应为'data';
// 此时赋值代码可写成 component[dataConsumer] = respData
// 但为支持更深层级的赋值(如:dataConsumer的值为'options.data',使用setObjectValueReduce
this.setObjectValueReduce(component, dataConsumer, respData)
const i = this.drawingList.findIndex(item => item.__config__.renderKey === renderKey)
if (i > -1) this.$set(this.drawingList, i, component)
},
fetchData(component) {
const { dataType, method, url } = component.__config__
if (dataType === 'dynamic' && method && url) {
this.setLoading(component, true)
this.$axios({
method,
url
}).then(resp => {
this.setLoading(component, false)
this.setRespData(component, resp.data)
})
}
},
setLoading(component, val) {
const { directives } = component
if (Array.isArray(directives)) {
const t = directives.find(d => d.name === 'loading')
if (t) t.value = val
}
},
activeFormItem(currentItem) {
this.activeData = currentItem
this.activeId = currentItem.__config__.formId
},
onEnd(obj) {
if (obj.from !== obj.to) {
this.fetchData(tempActiveData)
this.activeData = tempActiveData
this.activeId = this.idGlobal
}
},
addComponent(item) {
const clone = this.cloneComponent(item)
this.fetchData(clone)
this.drawingList.push(clone)
this.activeFormItem(clone)
},
cloneComponent(origin) {
const clone = deepClone(origin)
const config = clone.__config__
config.span = this.formConf.span // 生成代码时,会根据span做精简判断
this.createIdAndKey(clone)
clone.placeholder !== undefined && (clone.placeholder += config.label)
tempActiveData = clone
return tempActiveData
},
createIdAndKey(item) {
const config = item.__config__
config.formId = ++this.idGlobal
config.renderKey = `${config.formId}${+new Date()}` // 改变renderKey后可以实现强制更新组件
if (config.layout === 'colFormItem') {
item.__vModel__ = `field${this.idGlobal}`
} else if (config.layout === 'rowFormItem') {
config.componentName = `row${this.idGlobal}`
!Array.isArray(config.children) && (config.children = [])
delete config.label // rowFormItem无需配置label属性
}
if (Array.isArray(config.children)) {
config.children = config.children.map(childItem => this.createIdAndKey(childItem))
}
return item
},
// 获得表单数据
AssembleFormData() {
this.formData = {
fields: deepClone(this.drawingList),
...this.formConf
}
},
save() {
// this.AssembleFormData()
// console.log(this.formData)
this.$refs["form"].validate(valid => {
if (!valid) {
return;
}
const form = {
conf: JSON.stringify(this.formConf), // 表单配置
fields: this.encodeFields(), // 表单项的数组
...this.form // 表单名等
}
// 修改的提交
if (this.form.id != null) {
updateForm(form).then(response => {
this.$modal.msgSuccess("修改成功");
this.close()
});
return;
}
// 添加的提交
createForm(form).then(response => {
this.$modal.msgSuccess("新增成功");
this.close()
});
});
},
/** 关闭按钮 */
close() {
this.$tab.closeOpenPage({ path: "/bpm/manager/form" });
},
encodeFields() {
const fields = []
this.drawingList.forEach(item => {
fields.push(JSON.stringify(item))
})
return fields
},
generate(data) {
const func = this[`exec${titleCase(this.operationType)}`]
this.generateConf = data
func && func(data)
},
execRun(data) {
this.AssembleFormData()
this.drawerVisible = true
},
execDownload(data) {
const codeStr = this.generateCode()
const blob = new Blob([codeStr], { type: 'text/plain;charset=utf-8' })
saveAs(blob, data.fileName)
},
execCopy(data) {
document.getElementById('copyNode').click()
},
empty() {
this.$confirm('确定要清空所有组件吗?', '提示', { type: 'warning' }).then(
() => {
this.drawingList = []
this.idGlobal = 100
}
)
},
drawingItemCopy(item, list) {
let clone = deepClone(item)
clone = this.createIdAndKey(clone)
list.push(clone)
this.activeFormItem(clone)
},
drawingItemDelete(index, list) {
list.splice(index, 1)
this.$nextTick(() => {
const len = this.drawingList.length
if (len) {
this.activeFormItem(this.drawingList[len - 1])
}
})
},
generateCode() {
const { type } = this.generateConf
this.AssembleFormData()
const script = vueScript(makeUpJs(this.formData, type))
const html = vueTemplate(makeUpHtml(this.formData, type))
const css = cssStyle(makeUpCss(this.formData))
return beautifier.html(html + script + css, beautifierConf.html)
},
showJson() {
this.AssembleFormData()
this.jsonDrawerVisible = true
},
download() {
this.dialogVisible = true
this.showFileName = true
this.operationType = 'download'
},
run() {
this.dialogVisible = true
this.showFileName = false
this.operationType = 'run'
},
copy() {
this.dialogVisible = true
this.showFileName = false
this.operationType = 'copy'
},
tagChange(newTag) {
newTag = this.cloneComponent(newTag)
const config = newTag.__config__
newTag.__vModel__ = this.activeData.__vModel__
config.formId = this.activeId
config.span = this.activeData.__config__.span
this.activeData.__config__.tag = config.tag
this.activeData.__config__.tagIcon = config.tagIcon
this.activeData.__config__.document = config.document
if (typeof this.activeData.__config__.defaultValue === typeof config.defaultValue) {
config.defaultValue = this.activeData.__config__.defaultValue
}
Object.keys(newTag).forEach(key => {
if (this.activeData[key] !== undefined) {
newTag[key] = this.activeData[key]
}
})
this.activeData = newTag
this.updateDrawingList(newTag, this.drawingList)
},
updateDrawingList(newTag, list) {
const index = list.findIndex(item => item.__config__.formId === this.activeId)
if (index > -1) {
list.splice(index, 1, newTag)
} else {
list.forEach(item => {
if (Array.isArray(item.__config__.children)) this.updateDrawingList(newTag, item.__config__.children)
})
}
},
refreshJson(data) {
this.drawingList = deepClone(data.fields)
delete data.fields
this.formConf = data
}
}
}
</script>
<style lang='scss'>
@import '@/styles/home';
</style>
-163
View File
@@ -1,163 +0,0 @@
<template>
<div class="app-container">
<doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
<!-- 搜索工作栏 -->
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="表单名" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入表单名" clearable @keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 操作工具栏 -->
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
v-hasPermi="['bpm:form:create']">新增</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<!-- 列表 -->
<el-table v-loading="loading" :data="list">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="表单名" align="center" prop="name" />
<el-table-column label="开启状态" align="center" prop="status">
<template slot-scope="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status"/>
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleDetail(scope.row)"
v-hasPermi="['bpm:form:query']">详情</el-button>
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
v-hasPermi="['bpm:form:update']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
v-hasPermi="['bpm:form:delete']">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
@pagination="getList"/>
<!--表单配置详情-->
<el-dialog title="表单详情" :visible.sync="detailOpen" width="50%" append-to-body>
<div class="test-form">
<parser :key="new Date().getTime()" :form-conf="detailForm" />
</div>
</el-dialog>
</div>
</template>
<script>
import {deleteForm, getForm, getFormPage} from "@/api/bpm/form";
import Parser from '@/components/parser/Parser'
import {decodeFields} from "@/utils/formGenerator";
export default {
name: "Form",
components: {
Parser
},
data() {
return {
// 遮罩层
loading: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 工作流的列表
list: [],
// 查询参数
queryParams: {
pageNo: 1,
pageSize: 10,
name: null,
},
// 表单详情
detailOpen: false,
detailForm: {
fields: []
}
};
},
created() {
this.getList();
},
methods: {
/** 查询列表 */
getList() {
this.loading = true;
// 处理查询参数
let params = {...this.queryParams};
// 执行查询
getFormPage(params).then(response => {
this.list = response.data.list;
this.total = response.data.total;
this.loading = false;
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNo = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
/** 详情按钮操作 */
handleDetail(row) {
getForm(row.id).then(response => {
// 设置值
const data = response.data
this.detailForm = {
...JSON.parse(data.conf),
fields: decodeFields(data.fields)
}
// 弹窗打开
this.detailOpen = true
})
},
/** 新增按钮操作 */
handleAdd() {
this.$router.push({
path:"/bpm/manager/form/edit"
});
},
/** 修改按钮操作 */
handleUpdate(row) {
this.$router.push({
path:"/bpm/manager/form/edit",
query:{
formId: row.id
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const id = row.id;
this.$modal.confirm('是否确认删除工作表单的编号为"' + id + '"的数据项?').then(function() {
return deleteForm(id);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
}
}
};
</script>
-251
View File
@@ -1,251 +0,0 @@
<template>
<div class="app-container">
<doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
<!-- 搜索工作栏 -->
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="组名" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入组名" clearable @keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
:key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker v-model="dateRangeCreateTime" style="width: 240px" value-format="yyyy-MM-dd"
type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 操作工具栏 -->
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
v-hasPermi="['bpm:user-group:create']">新增</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<!-- 列表 -->
<el-table v-loading="loading" :data="list">
<el-table-column label="编号" align="center" prop="id" />
<el-table-column label="组名" align="center" prop="name" />
<el-table-column label="描述" align="center" prop="description" />
<el-table-column label="成员" align="center">
<template slot-scope="scope">
<span v-for="userId in scope.row.memberUserIds">
{{ getUserNickname(userId) }}
</span>
</template>
</el-table-column>
<el-table-column label="状态" align="center" prop="status">
<template slot-scope="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
v-hasPermi="['bpm:user-group:update']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
v-hasPermi="['bpm:user-group:delete']">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
@pagination="getList"/>
<!-- 对话框(添加 / 修改) -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="组名" prop="name">
<el-input v-model="form.name" placeholder="请输入组名" />
</el-form-item>
<el-form-item label="描述" prop="description">
<el-input v-model="form.description" placeholder="请输入描述" />
</el-form-item>
<el-form-item label="成员" prop="memberUserIds">
<el-select v-model="form.memberUserIds" multiple placeholder="请选择成员">
<el-option v-for="user in users" :key="parseInt(user.id)" :label="user.nickname" :value="parseInt(user.id)"/>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
:key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { createUserGroup, updateUserGroup, deleteUserGroup, getUserGroup, getUserGroupPage } from "@/api/bpm/userGroup";
import {CommonStatusEnum} from "@/utils/constants";
import {listSimpleUsers} from "@/api/system/user";
export default {
name: "UserGroup",
components: {
},
data() {
return {
// 遮罩层
loading: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 用户组列表
list: [],
// 用户列表
users: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
dateRangeCreateTime: [],
// 查询参数
queryParams: {
pageNo: 1,
pageSize: 10,
name: null,
status: null,
tenantId: null,
},
// 表单参数
form: {},
// 表单校验
rules: {
name: [{ required: true, message: "组名不能为空", trigger: "blur" }],
description: [{ required: true, message: "描述不能为空", trigger: "blur" }],
memberUserIds: [{ required: true, message: "成员不能为空", trigger: "change" }],
status: [{ required: true, message: "状态不能为空", trigger: "blur" }],
}
};
},
created() {
this.getList();
// 获得用户列表
listSimpleUsers().then(response => {
this.users = response.data;
})
},
methods: {
/** 查询列表 */
getList() {
this.loading = true;
// 处理查询参数
let params = {...this.queryParams};
this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
// 执行查询
getUserGroupPage(params).then(response => {
this.list = response.data.list;
this.total = response.data.total;
this.loading = false;
});
},
/** 取消按钮 */
cancel() {
this.open = false;
this.reset();
},
/** 表单重置 */
reset() {
this.form = {
id: undefined,
name: undefined,
description: undefined,
memberUserIds: [],
status: CommonStatusEnum.ENABLE,
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNo = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.dateRangeCreateTime = [];
this.resetForm("queryForm");
this.handleQuery();
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加用户组";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const id = row.id;
getUserGroup(id).then(response => {
this.form = response.data;
this.open = true;
this.title = "修改用户组";
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (!valid) {
return;
}
// 修改的提交
if (this.form.id != null) {
updateUserGroup(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
return;
}
// 添加的提交
createUserGroup(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
});
},
/** 删除按钮操作 */
handleDelete(row) {
const id = row.id;
this.$modal.confirm('是否确认删除用户组编号为"' + id + '"的数据项?').then(function() {
return deleteUserGroup(id);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
getUserNickname(userId) {
for (const user of this.users) {
if (user.id === userId) {
return user.nickname;
}
}
return '未知(' + userId + ')';
},
}
};
</script>
-545
View File
@@ -1,545 +0,0 @@
<template>
<div class="app-container">
<doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
<!-- 搜索工作栏 -->
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="流程标识" prop="key">
<el-input v-model="queryParams.key" placeholder="请输入流程标识" clearable style="width: 240px;"
@keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item label="流程名称" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入流程名称" clearable style="width: 240px;"
@keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item label="流程分类" prop="category">
<el-select v-model="queryParams.category" placeholder="流程分类" clearable style="width: 240px">
<el-option v-for="dict in categoryDictDatas" :key="parseInt(dict.value)" :label="dict.label" :value="parseInt(dict.value)"/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 操作工具栏 -->
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
v-hasPermi="['bpm:model:create']">新建流程</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="info" icon="el-icon-upload2" size="mini" @click="handleImport"
v-hasPermi="['bpm:model:import']">导入流程</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<!-- 列表 -->
<el-table v-loading="loading" :data="list">
<el-table-column label="流程标识" align="center" prop="key" />
<el-table-column label="流程名称" align="center" prop="name" width="200">
<template slot-scope="scope">
<el-button type="text" @click="handleBpmnDetail(scope.row)">
<span>{{ scope.row.name }}</span>
</el-button>
</template>
</el-table-column>
<el-table-column label="流程分类" align="center" prop="category" width="100">
<template slot-scope="scope">
<dict-tag :type="DICT_TYPE.BPM_MODEL_CATEGORY" :value="scope.row.category" />
</template>
</el-table-column>
<el-table-column label="表单信息" align="center" prop="formType" width="200">
<template slot-scope="scope">
<el-button v-if="scope.row.formId" type="text" @click="handleFormDetail(scope.row)">
<span>{{ scope.row.formName }}</span>
</el-button>
<el-button v-else-if="scope.row.formCustomCreatePath" type="text" @click="handleFormDetail(scope.row)">
<span>{{ scope.row.formCustomCreatePath }}</span>
</el-button>
<label v-else>暂无表单</label>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="最新部署的流程定义" align="center">
<el-table-column label="流程版本" align="center" prop="processDefinition.version" width="80">
<template slot-scope="scope">
<el-tag size="medium" v-if="scope.row.processDefinition">v{{ scope.row.processDefinition.version }}</el-tag>
<el-tag size="medium" type="warning" v-else>未部署</el-tag>
</template>
</el-table-column>
<el-table-column label="激活状态" align="center" prop="processDefinition.version" width="80">
<template slot-scope="scope">
<el-switch v-if="scope.row.processDefinition" v-model="scope.row.processDefinition.suspensionState"
:active-value="1" :inactive-value="2" @change="handleChangeState(scope.row)" />
</template>
</el-table-column>
<el-table-column label="部署时间" align="center" prop="deploymentTime" width="180">
<template slot-scope="scope">
<span v-if="scope.row.processDefinition">{{ parseTime(scope.row.processDefinition.deploymentTime) }}</span>
</template>
</el-table-column>
</el-table-column>
<el-table-column label="操作" align="center" width="450" fixed="right">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
v-hasPermi="['bpm:model:update']">修改流程</el-button>
<el-button size="mini" type="text" icon="el-icon-setting" @click="handleDesign(scope.row)"
v-hasPermi="['bpm:model:update']">设计流程</el-button>
<el-button size="mini" type="text" icon="el-icon-s-custom" @click="handleAssignRule(scope.row)"
v-hasPermi="['bpm:task-assign-rule:query']">分配规则</el-button>
<el-button size="mini" type="text" icon="el-icon-thumb" @click="handleDeploy(scope.row)"
v-hasPermi="['bpm:model:deploy']">发布流程</el-button>
<el-button size="mini" type="text" icon="el-icon-ice-cream-round" @click="handleDefinitionList(scope.row)"
v-hasPermi="['bpm:process-definition:query']">流程定义</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
v-hasPermi="['bpm:model:delete']">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
@pagination="getList"/>
<!-- 流程表单配置详情 -->
<el-dialog title="表单详情" :visible.sync="detailOpen" width="50%" append-to-body>
<parser :key="new Date().getTime()" :form-conf="detailForm" />
</el-dialog>
<!-- 流程模型图的预览 -->
<el-dialog title="流程图" :visible.sync="showBpmnOpen" width="80%" append-to-body>
<my-process-viewer key="designer" v-model="bpmnXML" v-bind="bpmnControlForm" />
</el-dialog>
<!-- 对话框(添加 / 修改) -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="110px">
<el-form-item label="流程标识" prop="key">
<el-input v-model="form.key" placeholder="请输入流标标识" style="width: 330px;" :disabled="form.id" />
<el-tooltip v-if="!form.id" class="item" effect="light" content="新建后,流程标识不可修改!" placement="top">
<i style="padding-left: 5px;" class="el-icon-question" />
</el-tooltip>
<el-tooltip v-else class="item" effect="light" content="流程标识不可修改!" placement="top">
<i style="padding-left: 5px;" class="el-icon-question" />
</el-tooltip>
</el-form-item>
<el-form-item label="流程名称" prop="name">
<el-input v-model="form.name" placeholder="请输入流程名称" :disabled="form.id" clearable />
</el-form-item>
<el-form-item v-if="form.id" label="流程分类" prop="category">
<el-select v-model="form.category" placeholder="请选择流程分类" clearable style="width: 100%">
<el-option v-for="dict in categoryDictDatas" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<el-form-item label="流程描述" prop="description">
<el-input type="textarea" v-model="form.description" clearable />
</el-form-item>
<div v-if="form.id">
<el-form-item label="表单类型" prop="formType">
<el-radio-group v-model="form.formType">
<el-radio v-for="dict in modelFormTypeDictDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
{{dict.label}}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="form.formType === 10" label="流程表单" prop="formId">
<el-select v-model="form.formId" clearable style="width: 100%">
<el-option v-for="form in forms" :key="form.id" :label="form.name" :value="form.id"/>
</el-select>
</el-form-item>
<el-form-item v-if="form.formType === 20" label="表单提交路由" prop="formCustomCreatePath" >
<el-input v-model="form.formCustomCreatePath" placeholder="请输入表单提交路由" style="width: 330px;" />
<el-tooltip class="item" effect="light" content="自定义表单的提交路径,使用 Vue 的路由地址,例如说:bpm/oa/leave/create" placement="top">
<i style="padding-left: 5px;" class="el-icon-question" />
</el-tooltip>
</el-form-item>
<el-form-item v-if="form.formType === 20" label="表单查看路由" prop="formCustomViewPath">
<el-input v-model="form.formCustomViewPath" placeholder="请输入表单查看路由" style="width: 330px;" />
<el-tooltip class="item" effect="light" content="自定义表单的查看路径,使用 Vue 的路由地址,例如说:bpm/oa/leave/view" placement="top">
<i style="padding-left: 5px;" class="el-icon-question" />
</el-tooltip>
</el-form-item>
</div>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
<!-- 用户导入对话框 -->
<el-dialog title="导入流程" :visible.sync="upload.open" width="400px" append-to-body>
<el-upload ref="upload" :limit="1" accept=".bpmn, .xml" :headers="upload.headers" :action="upload.url"
:disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess"
:auto-upload="false" name="bpmnFile" :data="upload.form" drag>
<i class="el-icon-upload"></i>
<div class="el-upload__text">
将文件拖到此处
<em>点击上传</em>
</div>
<div class="el-upload__tip" style="color:red" slot="tip">提示仅允许导入bpmxml格式文件</div>
<div class="el-upload__tip" slot="tip">
<el-form ref="uploadForm" size="mini" label-width="90px" :model="upload.form" :rules="upload.rules" @submit.native.prevent>
<el-form-item label="流程标识" prop="key">
<el-input v-model="upload.form.key" placeholder="请输入流标标识" style="width: 250px;" />
<el-tooltip class="item" effect="light" content="新建后,流程标识不可修改!" placement="top">
<i style="padding-left: 5px;" class="el-icon-question" />
</el-tooltip>
</el-form-item>
<el-form-item label="流程名称" prop="name">
<el-input v-model="upload.form.name" placeholder="请输入流程名称" clearable />
</el-form-item>
<el-form-item label="流程描述" prop="description">
<el-input type="textarea" v-model="upload.form.description" clearable />
</el-form-item>
</el-form>
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFileForm"> </el-button>
<el-button @click="uploadClose"> </el-button>
</div>
</el-dialog>
<!-- ========== 流程任务分配规则 ========== -->
<taskAssignRuleDialog ref="taskAssignRuleDialog" />
</div>
</template>
<script>
import {
deleteModel,
deployModel,
getModelPage,
getModel,
updateModelState,
createModel,
updateModel
} from "@/api/bpm/model";
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
import {getForm, getSimpleForms} from "@/api/bpm/form";
import {decodeFields} from "@/utils/formGenerator";
import Parser from '@/components/parser/Parser'
import {getBaseHeader} from "@/utils/request";
import taskAssignRuleDialog from "../taskAssignRule/taskAssignRuleDialog";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
export default {
name: "model",
components: {
Parser,
Treeselect,
taskAssignRuleDialog
},
data() {
return {
// 遮罩层
loading: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 表格数据
list: [],
// 查询参数
queryParams: {
pageNo: 1,
pageSize: 10
},
// BPMN 数据
showBpmnOpen: false,
bpmnXML: null,
bpmnControlForm: {
prefix: "activiti"
},
// 流程表单详情
detailOpen: false,
detailForm: {
fields: []
},
// 流程表单
title: "",
open: false,
form: {},
// 表单校验
rules: {
key: [{ required: true, message: "流程标识不能为空", trigger: "blur" }],
name: [{ required: true, message: "流程名称不能为空", trigger: "blur" }],
formType: [{ required: true, message: "流程名称不能为空", trigger: "blur" }],
formId: [{ required: true, message: "业务表单不能为空", trigger: "blur" }],
category: [{ required: true, message: "流程分类不能为空", trigger: "blur" }],
formCustomCreatePath: [{ required: true, message: "表单提交路由不能为空", trigger: "blur" }],
formCustomViewPath: [{ required: true, message: "表单查看路由不能为空", trigger: "blur" }],
},
// 流程导入参数
upload: {
// 是否显示弹出层(用户导入)
open: false,
// 是否禁用上传
isUploading: false,
// 设置上传的请求头部
headers: getBaseHeader(),
// 上传的地址
url: process.env.VUE_APP_BASE_API + '/admin-api' + "/bpm/model/import",
// 表单
form: {},
// 校验规则
rules: {
key: [{ required: true, message: "流程标识不能为空", trigger: "blur" }],
name: [{ required: true, message: "流程名称不能为空", trigger: "blur" }],
},
},
// 流程表单的下拉框的数据
forms: [],
// 数据字典
categoryDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_CATEGORY),
modelFormTypeDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_FORM_TYPE),
taskAssignRuleDictDatas: getDictDatas(DICT_TYPE.BPM_TASK_ASSIGN_RULE_TYPE),
};
},
created() {
this.getList();
// 获得流程表单的下拉框的数据
getSimpleForms().then(response => {
this.forms = response.data
})
},
methods: {
/** 查询流程模型列表 */
getList() {
this.loading = true;
getModelPage(this.queryParams).then(response => {
this.list = response.data.list;
this.total = response.data.total;
this.loading = false;
}
);
},
/** 取消按钮 */
cancel() {
this.open = false;
this.reset();
},
// 表单重置
reset() {
this.form = {
id: undefined,
key: undefined,
name: undefined,
description: undefined,
category: undefined,
formType: undefined,
formId: undefined,
formCustomCreatePath: undefined,
formCustomViewPath: undefined
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNo = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.dateRange = [];
this.resetForm("queryForm");
this.handleQuery();
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.title = "新建模型";
this.open = true;
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
this.title = "修改模型";
this.open = true;
// 设置 form
this.form = {
...row
};
// 触发一次校验
// this.$refs["form"].validate();
},
/** 设计按钮操作 */
handleDesign(row) {
this.$router.push({
path:"/bpm/manager/model/design",
query:{
modelId: row.id
}
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (!valid) {
return;
}
// 更新
if (this.form.id) {
updateModel({
...this.form,
formId: this.form.formType === 10 ? this.form.formId : undefined,
formCustomCreatePath: this.form.formType === 20 ? this.form.formCustomCreatePath : undefined,
formCustomViewPath: this.form.formType === 20 ? this.form.formCustomViewPath : undefined,
}).then(response => {
this.$modal.msgSuccess("修改模型成功");
this.open = false;
this.getList();
});
return;
}
// 创建
createModel(this.form).then(response => {
this.open = false;
this.getList();
this.$alert('<strong>新建模型成功!</strong>后续需要执行如下 4 个步骤:' +
'<div>1. 点击【修改流程】按钮,配置流程的分类、表单信息</div>' +
'<div>2. 点击【设计流程】按钮,绘制流程图</div>' +
'<div>3. 点击【分配规则】按钮,设置每个用户任务的审批人</div>' +
'<div>4. 点击【发布流程】按钮,完成流程的最终发布</div>' +
'另外,每次流程修改后,都需要点击【发布流程】按钮,才能正式生效!!!',
'重要提示', {
dangerouslyUseHTMLString: true,
type: 'success'
});
});
});
},
/** 删除按钮操作 */
handleDelete(row) {
const that = this;
this.$modal.confirm('是否删除该流程!!').then(function() {
deleteModel(row.id).then(response => {
that.getList();
that.msgSuccess("删除成功");
})
}).catch(() => {});
},
/** 部署按钮操作 */
handleDeploy(row) {
const that = this;
this.$modal.confirm('是否部署该流程!!').then(function() {
deployModel(row.id).then(response => {
that.getList();
that.msgSuccess("部署成功");
})
}).catch(() => {});
},
/** 流程表单的详情按钮操作 */
handleFormDetail(row) {
// 流程表单
if (row.formId) {
getForm(row.formId).then(response => {
// 设置值
const data = response.data
this.detailForm = {
...JSON.parse(data.conf),
fields: decodeFields(data.fields)
}
// 弹窗打开
this.detailOpen = true
})
// 业务表单
} else if (row.formCustomCreatePath) {
this.$router.push({ path: row.formCustomCreatePath});
}
},
/** 流程图的详情按钮操作 */
handleBpmnDetail(row) {
getModel(row.id).then(response => {
this.bpmnXML = response.data.bpmnXml
// 弹窗打开
this.showBpmnOpen = true
})
},
/** 跳转流程定义的列表 */
handleDefinitionList(row) {
this.$router.push({
path:"/bpm/manager/definition",
query:{
key: row.key
}
});
},
/** 更新状态操作 */
handleChangeState(row) {
const id = row.id;
let state = row.processDefinition.suspensionState;
let statusState = state === 1 ? '激活' : '挂起';
this.$modal.confirm('是否确认' + statusState + '流程名字为"' + row.name + '"的数据项?').then(function() {
return updateModelState(id, state);
}).then(() => {
this.getList();
this.$modal.msgSuccess(statusState + "成功");
}).catch(() => {});
},
/** 导入按钮操作 */
handleImport() {
this.upload.open = true;
},
// 文件上传中处理
handleFileUploadProgress(event, file, fileList) {
this.upload.isUploading = true;
},
// 文件上传成功处理
handleFileSuccess(response, file, fileList) {
if (response.code !== 0) {
this.$modal.msgError(response.msg)
return;
}
// 重置表单
this.uploadClose();
// 提示,并刷新
this.$modal.msgSuccess("导入流程成功!请点击【设计流程】按钮,进行编辑保存后,才可以进行【发布流程】");
this.getList();
},
uploadClose() {
// 关闭弹窗
this.upload.open = false;
// 重置上传状态和文件
this.upload.isUploading = false;
this.$refs.upload.clearFiles();
// 重置表单
this.upload.form = {};
this.resetForm("uploadForm");
},
/** 提交上传文件 */
submitFileForm() {
this.$refs["uploadForm"].validate(valid => {
if (!valid) {
return;
}
this.$refs.upload.submit();
})
},
/** 处理任务分配规则列表的按钮操作 */
handleAssignRule(row) {
this.$refs['taskAssignRuleDialog'].initModel(row.id);
},
}
};
</script>
<style lang="scss">
.my-process-designer {
height: calc(100vh - 200px);
}
</style>
-185
View File
@@ -1,185 +0,0 @@
<template>
<div class="app-container">
<!-- 流程设计器负责绘制流程等 -->
<my-process-designer :key="`designer-${reloadIndex}`" v-model="xmlString" v-bind="controlForm"
keyboard ref="processDesigner" @init-finished="initModeler"
@save="save"/>
<!-- 流程属性器负责编辑每个流程节点的属性 -->
<my-properties-panel :key="`penal-${reloadIndex}`" :bpmn-modeler="modeler" :prefix="controlForm.prefix" class="process-panel"
:model="model" />
</div>
</template>
<script>
import translations from "@/components/bpmnProcessDesigner/src/translations";
// 自定义元素选中时的弹出菜单(修改 默认任务 为 用户任务)
import CustomContentPadProvider from "@/components/bpmnProcessDesigner/package/designer/plugins/content-pad";
// 自定义左侧菜单(修改 默认任务 为 用户任务)
import CustomPaletteProvider from "@/components/bpmnProcessDesigner/package/designer/plugins/palette";
// import xmlObj2json from "./utils/xml2json";
import MyProcessPalette from "@/components/bpmnProcessDesigner/package/palette/ProcessPalette";
import {createModel, getModel, updateModel} from "@/api/bpm/model";
// 自定义侧边栏
// import MyProcessPanel from "../package/process-panel/ProcessPanel";
export default {
name: "App",
components: { MyProcessPalette },
data() {
return {
xmlString: "", // BPMN XML
modeler: null,
reloadIndex: 0,
controlDrawerVisible: false,
translationsSelf: translations,
controlForm: {
simulation: true,
labelEditing: false,
labelVisible: false,
prefix: "activiti",
headerButtonSize: "mini",
additionalModel: [CustomContentPadProvider, CustomPaletteProvider]
},
addis: {
CustomContentPadProvider,
CustomPaletteProvider
},
// 流程模型的信息
model: {},
};
},
created() {
// 如果 modelId 非空,说明是修改流程模型
const modelId = this.$route.query && this.$route.query.modelId
if (modelId) {
getModel(modelId).then(response => {
this.xmlString = response.data.bpmnXml
this.model = {
...response.data,
bpmnXml: undefined, // 清空 bpmnXml 属性
}
// this.controlForm.processId = response.data.key
})
}
},
methods: {
initModeler(modeler) {
setTimeout(() => {
this.modeler = modeler;
console.log(modeler);
}, 10);
},
reloadProcessDesigner(deep) {
this.controlForm.additionalModel = [];
for (let key in this.addis) {
if (this.addis[key]) {
this.controlForm.additionalModel.push(this.addis[key]);
}
}
deep && (this.xmlString = undefined);
this.reloadIndex += 1;
this.modeler = null; // 避免 panel 异常
// if (deep) {
// this.xmlString = undefined;
// this.$refs.processDesigner.processRestart();
// }
},
save(bpmnXml) {
const data = {
...this.model,
bpmnXml: bpmnXml, // this.bpmnXml 只是初始化流程图,后续修改无法通过它获得
}
// 修改的提交
if (data.id) {
updateModel(data).then(response => {
this.$modal.msgSuccess("修改成功")
// 跳转回去
this.close()
})
return
}
// 添加的提交
createModel(data).then(response => {
this.$modal.msgSuccess("保存成功")
// 跳转回去
this.close()
})
},
/** 关闭按钮 */
close() {
this.$tab.closeOpenPage({ path: "/bpm/manager/model" });
},
}
};
</script>
<style lang="scss">
//body {
// overflow: hidden;
// margin: 0;
// box-sizing: border-box;
//}
//.app {
// width: 100%;
// height: 100%;
// box-sizing: border-box;
// display: inline-grid;
// grid-template-columns: 100px auto max-content;
//}
.demo-control-bar {
position: fixed;
right: 8px;
bottom: 8px;
z-index: 1;
.open-control-dialog {
width: 48px;
height: 48px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
font-size: 32px;
background: rgba(64, 158, 255, 1);
color: #ffffff;
cursor: pointer;
}
}
// TODO 芋艿:去掉多余的 faq
//.info-tip {
// position: fixed;
// top: 40px;
// right: 500px;
// z-index: 10;
// color: #999999;
//}
.control-form {
.el-radio {
width: 100%;
line-height: 32px;
}
}
.element-overlays {
box-sizing: border-box;
padding: 8px;
background: rgba(0, 0, 0, 0.6);
border-radius: 4px;
color: #fafafa;
}
.my-process-designer {
height: calc(100vh - 84px);
}
.process-panel__container {
position: absolute;
right: 0;
top: 55px;
height: calc(100vh - 84px);
}
</style>
-75
View File
@@ -1,75 +0,0 @@
<template>
<div class="app-container">
<!-- 对话框(添加 / 修改) -->
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="开始时间" prop="startTime">
<el-date-picker clearable size="small" v-model="form.startTime" type="date" value-format="timestamp" placeholder="选择开始时间" />
</el-form-item>
<el-form-item label="结束时间" prop="endTime">
<el-date-picker clearable size="small" v-model="form.endTime" type="date" value-format="timestamp" placeholder="选择结束时间" />
</el-form-item>
<el-form-item label="请假类型" prop="type">
<el-select v-model="form.type" placeholder="请选择">
<el-option v-for="dict in typeDictData" :key="parseInt(dict.value)" :label="dict.label" :value="parseInt(dict.value)"/>
</el-select>
</el-form-item>
<el-form-item label="原因" prop="reason">
<el-col :span="10">
<el-input type="textarea" :rows="3" v-model="form.reason" placeholder="请输入原因" />
</el-col>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm"> </el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import { createLeave} from "@/api/bpm/leave"
import { getDictDatas, DICT_TYPE } from '@/utils/dict'
export default {
name: "LeaveCreate",
components: {
},
data() {
return {
// 表单参数
form: {
startTime: undefined,
endTime: undefined,
type: undefined,
reason: undefined,
},
// 表单校验
rules: {
startTime: [{ required: true, message: "开始时间不能为空", trigger: "blur" }],
endTime: [{ required: true, message: "结束时间不能为空", trigger: "blur" }],
type: [{ required: true, message: "请假类型不能为空", trigger: "change" }],
reason: [{ required: true, message: "请假原因不能为空", trigger: "change" }],
},
typeDictData: getDictDatas(DICT_TYPE.BPM_OA_LEAVE_TYPE),
};
},
created() {
},
methods: {
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (!valid) {
return;
}
// 添加的提交
createLeave(this.form).then(response => {
this.$modal.msgSuccess("发起成功");
this.$tab.closeOpenPage({ path: "/bpm/oa/leave" });
});
});
}
}
};
</script>
-53
View File
@@ -1,53 +0,0 @@
<template>
<div class="app-container">
<!-- 对话框(添加 / 修改) -->
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-form-item label="开始时间:" prop="startTime"> {{parseTime(form.startTime, '{y}-{m}-{d}')}} </el-form-item>
<el-form-item label="结束时间:" prop="endTime"> {{parseTime(form.endTime, '{y}-{m}-{d}')}} </el-form-item>
<el-form-item label="请假类型:" prop="type">
<dict-tag :type="DICT_TYPE.BPM_OA_LEAVE_TYPE" :value="form.type"/>
</el-form-item>
<el-form-item label="原因:" prop="reason"> {{ form.reason }}</el-form-item>
</el-form>
</div>
</template>
<script>
import { getLeave} from "@/api/bpm/leave"
import {getDictDatas, DICT_TYPE} from '@/utils/dict'
export default {
name: "LeaveDetail",
components: {
},
data() {
return {
id: undefined, // 请假编号
// 表单参数
form: {
startTime: undefined,
endTime: undefined,
type: undefined,
reason: undefined,
},
typeDictData: getDictDatas(DICT_TYPE.BPM_OA_LEAVE_TYPE),
};
},
created() {
this.id = this.$route.query.id;
if (!this.id) {
this.$message.error('未传递 id 参数,无法查看 OA 请假信息');
return;
}
this.getDetail();
},
methods: {
/** 获得请假信息 */
getDetail() {
getLeave(this.id).then(response => {
this.form = response.data;
});
},
}
};
</script>
-178
View File
@@ -1,178 +0,0 @@
<template>
<div class="app-container">
<doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
<!-- 搜索工作栏 -->
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="请假类型" prop="type">
<el-select v-model="queryParams.type" placeholder="请选择请假类型" clearable>
<el-option v-for="dict in leaveTypeDictData" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="申请时间">
<el-date-picker v-model="dateRangeCreateTime" style="width: 240px" value-format="yyyy-MM-dd"
type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
</el-form-item>
<el-form-item label="结果" prop="result">
<el-select v-model="queryParams.result" placeholder="请选择流结果" clearable>
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT)"
:key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<el-form-item label="原因" prop="reason">
<el-input v-model="queryParams.reason" placeholder="请输入原因" clearable @keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 操作工具栏 -->
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini"
v-hasPermi="['bpm:oa-leave:create']" @click="handleAdd">发起请假</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<!-- 列表 -->
<el-table v-loading="loading" :data="list">
<el-table-column label="申请编号" align="center" prop="id" />
<el-table-column label="状态" align="center" prop="result">
<template slot-scope="scope">
<dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT" :value="scope.row.result"/>
</template>
</el-table-column>
<el-table-column label="开始时间" align="center" prop="startTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.startTime) }}</span>
</template>
</el-table-column>
<el-table-column label="结束时间" align="center" prop="endTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.endTime) }}</span>
</template>
</el-table-column>
<el-table-column label="请假类型" align="center" prop="type">
<template slot-scope="scope">
<dict-tag :type="DICT_TYPE.BPM_OA_LEAVE_TYPE" :value="scope.row.type"/>
</template>
</el-table-column>
<el-table-column label="原因" align="center" prop="reason" />
<el-table-column label="申请时间" align="center" prop="applyTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleCancel(scope.row)"
v-hasPermi="['bpm:oa-leave:create']" v-if="scope.row.result === 1">取消请假</el-button>
<el-button size="mini" type="text" icon="el-icon-view" @click="handleDetail(scope.row)"
v-hasPermi="['bpm:oa-leave:query']">详情</el-button>
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleProcessDetail(scope.row)">审批进度</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
@pagination="getList"/>
</div>
</template>
<script>
import { getLeavePage } from "@/api/bpm/leave"
import { getDictDatas, DICT_TYPE } from '@/utils/dict'
import {cancelProcessInstance} from "@/api/bpm/processInstance";
export default {
name: "Leave",
components: {
},
data() {
return {
// 遮罩层
loading: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 请假申请列表
list: [],
//审批进度弹出层
dateRangeCreateTime: [],
// 查询参数
queryParams: {
pageNo: 1,
pageSize: 10,
result: null,
type: null,
reason: null,
},
leaveTypeDictData: getDictDatas(DICT_TYPE.BPM_OA_LEAVE_TYPE),
leaveResultData: getDictDatas(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT),
};
},
created() {
this.getList();
},
methods: {
/** 查询列表 */
getList() {
this.loading = true;
// 处理查询参数
let params = {...this.queryParams};
this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
// 执行查询
getLeavePage(params).then(response => {
this.list = response.data.list;
this.total = response.data.total;
this.loading = false;
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNo = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.dateRangeCreateTime = [];
this.resetForm("queryForm");
this.handleQuery();
},
/** 新增按钮操作 */
handleAdd() {
this.$router.push({ path: "/bpm/oa/leave/create"});
},
/** 详情按钮操作 */
handleDetail(row) {
this.$router.push({ path: "/bpm/oa/leave/detail", query: { id: row.id}});
},
/** 查看审批进度的操作 */
handleProcessDetail(row) {
this.$router.push({ path: "/bpm/process-instance/detail", query: { id: row.processInstanceId}});
},
/** 取消请假 */
handleCancel(row) {
const id = row.processInstanceId;
this.$prompt('请输入取消原因?', "取消流程", {
type: 'warning',
confirmButtonText: "确定",
cancelButtonText: "取消",
inputPattern: /^[\s\S]*.*[^\s][\s\S]*$/, // 判断非空,且非空格
inputErrorMessage: "取消原因不能为空",
}).then(({ value }) => {
return cancelProcessInstance(id, value);
}).then(() => {
this.getList();
this.$modal.msgSuccess("取消成功");
})
}
}
};
</script>
-169
View File
@@ -1,169 +0,0 @@
<template>
<div class="app-container">
<!-- 第一步通过流程定义的列表选择对应的流程 -->
<div v-if="!selectProcessInstance">
<el-table v-loading="loading" :data="list">
<el-table-column label="流程名称" align="center" prop="name" width="200">
<template slot-scope="scope">
<el-button type="text" @click="handleBpmnDetail(scope.row)">
<span>{{ scope.row.name }}</span>
</el-button>
</template>
</el-table-column>
<el-table-column label="流程分类" align="center" prop="category" width="100">
<template slot-scope="scope">
<dict-tag :type="DICT_TYPE.BPM_MODEL_CATEGORY" :value="scope.row.category" />
</template>
</el-table-column>
<el-table-column label="流程版本" align="center" prop="processDefinition.version" width="80">
<template slot-scope="scope">
<el-tag size="medium" v-if="scope.row">v{{ scope.row.version }}</el-tag>
</template>
</el-table-column>
<el-table-column label="流程描述" align="center" prop="description" width="300" show-overflow-tooltip />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button type="text" size="small" icon="el-icon-plus" @click="handleSelect(scope.row)">选择</el-button>
</template>
</el-table-column>
</el-table>
</div>
<!-- 第二步填写表单进行流程的提交 -->
<div v-else>
<el-card class="box-card" >
<div slot="header" class="clearfix">
<span class="el-icon-document">申请信息{{ selectProcessInstance.name }}</span>
<el-button style="float: right;" type="primary" @click="selectProcessInstance = undefined">选择其它流程</el-button>
</div>
<el-col :span="16" :offset="6">
<div>
<parser :key="new Date().getTime()" :form-conf="detailForm" @submit="submitForm" />
</div>
</el-col>
</el-card>
<el-card class="box-card">
<div slot="header" class="clearfix">
<span class="el-icon-picture-outline">流程图</span>
</div>
<my-process-viewer key="designer" v-model="bpmnXML" v-bind="bpmnControlForm" />
</el-card>
</div>
</div>
</template>
<script>
import {getProcessDefinitionBpmnXML, getProcessDefinitionList} from "@/api/bpm/definition";
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
import {getForm} from "@/api/bpm/form";
import {decodeFields} from "@/utils/formGenerator";
import Parser from '@/components/parser/Parser'
import {createProcessInstance, getMyProcessInstancePage} from "@/api/bpm/processInstance";
// 流程实例的发起
export default {
name: "ProcessInstanceCreate",
components: {
Parser
},
data() {
return {
// 遮罩层
loading: true,
// 表格数据
list: [],
// 流程表单详情
detailForm: {
fields: []
},
// BPMN 数据
bpmnXML: null,
bpmnControlForm: {
prefix: "activiti"
},
// 流程表单
selectProcessInstance: undefined, // 选择的流程实例
// 数据字典
categoryDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_CATEGORY),
};
},
created() {
this.getList();
},
methods: {
/** 查询流程定义列表 */
getList() {
this.loading = true;
getProcessDefinitionList({
suspensionState: 1
}).then(response => {
this.list = response.data
this.loading = false
}
);
},
/** 处理选择流程的按钮操作 **/
handleSelect(row) {
// 设置选择的流程
this.selectProcessInstance = row;
// 流程表单
if (row.formId) {
// 设置对应的表单
this.detailForm = {
...JSON.parse(row.formConf),
fields: decodeFields(row.formFields)
}
// 加载流程图
getProcessDefinitionBpmnXML(row.id).then(response => {
this.bpmnXML = response.data
})
} else if (row.formCustomCreatePath) {
this.$router.push({ path: row.formCustomCreatePath});
// 这里暂时无需加载流程图,因为跳出到另外个 Tab;
}
},
/** 提交按钮 */
submitForm(params) {
if (!params) {
return;
}
// 设置表单禁用
const conf = params.conf;
conf.disabled = true; // 表单禁用
conf.formBtns = false; // 按钮隐藏
// 提交表单,创建流程
const variables = params.values;
createProcessInstance({
processDefinitionId: this.selectProcessInstance.id,
variables: variables
}).then(response => {
this.$modal.msgSuccess("发起流程成功");
// 关闭当前窗口
this.$tab.closeOpenPage();
this.$router.go(-1);
}).catch(() => {
conf.disabled = false; // 表单开启
conf.formBtns = true; // 按钮展示
})
},
}
};
</script>
<style lang="scss">
.my-process-designer {
height: calc(100vh - 200px);
}
.box-card {
width: 100%;
margin-bottom: 20px;
}
</style>
-424
View File
@@ -1,424 +0,0 @@
<template>
<div class="app-container">
<!-- 审批信息 -->
<el-card class="box-card" v-loading="processInstanceLoading" v-for="(item, index) in runningTasks" :key="index">
<div slot="header" class="clearfix">
<span class="el-icon-picture-outline">审批任务{{ item.name }}</span>
</div>
<el-col :span="16" :offset="6" >
<el-form :ref="'form' + index" :model="auditForms[index]" :rules="auditRule" label-width="100px">
<el-form-item label="流程名" v-if="processInstance && processInstance.name">
{{ processInstance.name }}
</el-form-item>
<el-form-item label="流程发起人" v-if="processInstance && processInstance.startUser">
{{ processInstance.startUser.nickname }}
<el-tag type="info" size="mini">{{ processInstance.startUser.deptName }}</el-tag>
</el-form-item>
<el-form-item label="审批建议" prop="comment">
<el-input type="textarea" v-model="auditForms[index].comment" placeholder="请输入审批建议" />
</el-form-item>
</el-form>
<div style="margin-left: 10%; margin-bottom: 20px; font-size: 14px;">
<el-button icon="el-icon-edit-outline" type="success" size="mini" @click="handleAudit(item, true)">通过</el-button>
<el-button icon="el-icon-circle-close" type="danger" size="mini" @click="handleAudit(item, false)">不通过</el-button>
<el-button icon="el-icon-edit-outline" type="primary" size="mini" @click="handleUpdateAssignee(item)">转办</el-button>
<el-button icon="el-icon-edit-outline" type="primary" size="mini" @click="handleDelegate(item)">委派</el-button>
<el-button icon="el-icon-refresh-left" type="warning" size="mini" @click="handleBack(item)">退回</el-button>
</div>
</el-col>
</el-card>
<!-- 申请信息 -->
<el-card class="box-card" v-loading="processInstanceLoading">
<div slot="header" class="clearfix">
<span class="el-icon-document">申请信息{{ processInstance.name }}</span>
</div>
<el-col v-if="this.processInstance.processDefinition && this.processInstance.processDefinition.formType === 10"
:span="16" :offset="6">
<div >
<parser :key="new Date().getTime()" :form-conf="detailForm" @submit="submitForm" />
</div>
</el-col>
<div v-if="this.processInstance.processDefinition && this.processInstance.processDefinition.formType === 20">
<router-link :to="this.processInstance.processDefinition.formCustomViewPath + '?id='
+ this.processInstance.businessKey">
<el-button type="primary">点击查看</el-button>
</router-link>
</div>
</el-card>
<el-card class="box-card" v-loading="tasksLoad">
<div slot="header" class="clearfix">
<span class="el-icon-picture-outline">审批记录</span>
</div>
<el-col :span="16" :offset="4" >
<div class="block">
<el-timeline>
<el-timeline-item v-for="(item, index) in tasks" :key="index"
:icon="getTimelineItemIcon(item)" :type="getTimelineItemType(item)">
<p style="font-weight: 700">任务{{ item.name }}</p>
<el-card :body-style="{ padding: '10px' }">
<label v-if="item.assigneeUser" style="font-weight: normal; margin-right: 30px;">
审批人{{ item.assigneeUser.nickname }}
<el-tag type="info" size="mini">{{ item.assigneeUser.deptName }}</el-tag>
</label>
<label style="font-weight: normal">创建时间</label>
<label style="color:#8a909c; font-weight: normal">{{ parseTime(item.createTime) }}</label>
<label v-if="item.endTime" style="margin-left: 30px;font-weight: normal">审批时间</label>
<label v-if="item.endTime" style="color:#8a909c;font-weight: normal"> {{ parseTime(item.endTime) }}</label>
<label v-if="item.durationInMillis" style="margin-left: 30px;font-weight: normal">耗时</label>
<label v-if="item.durationInMillis" style="color:#8a909c;font-weight: normal"> {{ getDateStar(item.durationInMillis) }} </label>
<p v-if="item.comment">
<el-tag :type="getTimelineItemType(item)">{{ item.comment }}</el-tag>
</p>
</el-card>
</el-timeline-item>
</el-timeline>
</div>
</el-col>
</el-card>
<!-- 高亮流程图 -->
<el-card class="box-card" v-loading="processInstanceLoading">
<div slot="header" class="clearfix">
<span class="el-icon-picture-outline">流程图</span>
</div>
<my-process-viewer key="designer" v-model="bpmnXML" v-bind="bpmnControlForm" :activityData="activityList"
:processInstanceData="processInstance" :taskData="tasks" />
</el-card>
<!-- 对话框(转派审批人) -->
<el-dialog title="转派审批人" :visible.sync="updateAssignee.open" width="500px" append-to-body>
<el-form ref="updateAssigneeForm" :model="updateAssignee.form" :rules="updateAssignee.rules" label-width="110px">
<el-form-item label="新审批人" prop="assigneeUserId">
<el-select v-model="updateAssignee.form.assigneeUserId" clearable style="width: 100%">
<el-option v-for="item in userOptions" :key="parseInt(item.id)" :label="item.nickname" :value="parseInt(item.id)" />
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitUpdateAssigneeForm"> </el-button>
<el-button @click="cancelUpdateAssigneeForm"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {getProcessDefinitionBpmnXML} from "@/api/bpm/definition";
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
import store from "@/store";
import {decodeFields} from "@/utils/formGenerator";
import Parser from '@/components/parser/Parser'
import {createProcessInstance, getProcessInstance} from "@/api/bpm/processInstance";
import {approveTask, getTaskListByProcessInstanceId, rejectTask, updateTaskAssignee} from "@/api/bpm/task";
import {getDate} from "@/utils/dateUtils";
import {listSimpleUsers} from "@/api/system/user";
import {getActivityList} from "@/api/bpm/activity";
// 流程实例的详情页,可用于审批
export default {
name: "ProcessInstanceDetail",
components: {
Parser
},
data() {
return {
// 遮罩层
processInstanceLoading: true,
// 流程实例
id: undefined, // 流程实例的编号
processInstance: {},
// 流程表单详情
detailForm: {
fields: []
},
// BPMN 数据
bpmnXML: null,
bpmnControlForm: {
prefix: "activiti"
},
activityList: [],
// 审批记录
tasksLoad: true,
tasks: [],
// 审批表单
runningTasks: [],
auditForms: [],
auditRule: {
comment: [{ required: true, message: "审批建议不能为空", trigger: "blur" }],
},
// 转派审批人
userOptions: [],
updateAssignee: {
open: false,
form: {
assigneeUserId: undefined,
},
rules: {
assigneeUserId: [{ required: true, message: "新审批人不能为空", trigger: "change" }],
}
},
// 数据字典
categoryDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_CATEGORY),
};
},
created() {
this.id = this.$route.query.id;
if (!this.id) {
this.$message.error('未传递 id 参数,无法查看流程信息');
return;
}
this.getDetail();
// 获得用户列表
this.userOptions = [];
listSimpleUsers().then(response => {
this.userOptions.push(...response.data);
});
},
methods: {
/** 获得流程实例 */
getDetail() {
// 获得流程实例相关
this.processInstanceLoading = true;
getProcessInstance(this.id).then(response => {
if (!response.data) {
this.$message.error('查询不到流程信息!');
return;
}
// 设置流程信息
this.processInstance = response.data;
// 设置表单信息
if (this.processInstance.processDefinition.formType === 10) {
this.detailForm = {
...JSON.parse(this.processInstance.processDefinition.formConf),
disabled: true, // 表单禁用
formBtns: false, // 按钮隐藏
fields: decodeFields(this.processInstance.processDefinition.formFields)
}
// 设置表单的值
this.detailForm.fields.forEach(item => {
const val = this.processInstance.formVariables[item.__vModel__]
if (val) {
item.__config__.defaultValue = val
}
});
}
// 加载流程图
getProcessDefinitionBpmnXML(this.processInstance.processDefinition.id).then(response => {
this.bpmnXML = response.data
});
// 加载活动列表
getActivityList({
processInstanceId: this.processInstance.id
}).then(response => {
this.activityList = response.data;
});
// 取消加载中
this.processInstanceLoading = false;
});
// 获得流程任务列表(审批记录)
this.tasksLoad = true;
this.runningTasks = [];
this.auditForms = [];
getTaskListByProcessInstanceId(this.id).then(response => {
// 审批记录
this.tasks = response.data;
// 排序,将未完成的排在前面,已完成的排在后面;
this.tasks.sort((a, b) => {
// 有已完成的情况,按照完成时间倒序
if (a.endTime && b.endTime) {
return b.endTime - a.endTime;
} else if (a.endTime) {
return 1;
} else if (b.endTime) {
return -1;
// 都是未完成,按照创建时间倒序
} else {
return b.createTime - a.createTime;
}
});
// 需要审核的记录
const userId = store.getters.userId;
this.tasks.forEach(task => {
if (task.result !== 1) { // 只有待处理才需要
return;
}
if (!task.assigneeUser || task.assigneeUser.id !== userId) { // 自己不是处理人
return;
}
this.runningTasks.push({...task});
this.auditForms.push({
comment: ''
})
});
// 取消加载中
this.tasksLoad = false;
});
},
/** 处理选择流程的按钮操作 **/
handleSelect(row) {
// 设置选择的流程
this.selectProcessInstance = row;
// 流程表单
if (row.formId) {
// 设置对应的表单
this.detailForm = {
...JSON.parse(row.formConf),
fields: decodeFields(row.formFields)
}
} else if (row.formCustomCreatePath) {
this.$router.push({ path: row.formCustomCreatePath});
// 这里暂时无需加载流程图,因为跳出到另外个 Tab;
}
},
/** 提交按钮 */
submitForm(params) {
if (!params) {
return;
}
// 设置表单禁用
const conf = params.conf;
conf.disabled = true; // 表单禁用
conf.formBtns = false; // 按钮隐藏
// 提交表单,创建流程
const variables = params.values;
createProcessInstance({
processDefinitionId: this.selectProcessInstance.id,
variables: variables
}).then(response => {
this.$modal.msgSuccess("发起流程成功");
// 关闭当前窗口
this.$tab.closeOpenPage();
this.$router.go(-1);
}).catch(() => {
conf.disabled = false; // 表单开启
conf.formBtns = true; // 按钮展示
})
},
getDateStar(ms) {
return getDate(ms);
},
getTimelineItemIcon(item) {
if (item.result === 1) {
return 'el-icon-time';
}
if (item.result === 2) {
return 'el-icon-check';
}
if (item.result === 3) {
return 'el-icon-close';
}
if (item.result === 4) {
return 'el-icon-remove-outline';
}
return '';
},
getTimelineItemType(item) {
if (item.result === 1) {
return 'primary';
}
if (item.result === 2) {
return 'success';
}
if (item.result === 3) {
return 'danger';
}
if (item.result === 4) {
return 'info';
}
return '';
},
/** 处理审批通过和不通过的操作 */
handleAudit(task, pass) {
const index = this.runningTasks.indexOf(task);
this.$refs['form' + index][0].validate(valid => {
if (!valid) {
return;
}
const data = {
id: task.id,
comment: this.auditForms[index].comment
}
if (pass) {
approveTask(data).then(response => {
this.$modal.msgSuccess("审批通过成功!");
this.getDetail(); // 获得最新详情
});
} else {
rejectTask(data).then(response => {
this.$modal.msgSuccess("审批不通过成功!");
this.getDetail(); // 获得最新详情
});
}
});
},
/** 处理转派审批人 */
handleUpdateAssignee(task) {
// 设置表单
this.resetUpdateAssigneeForm();
this.updateAssignee.form.id = task.id;
// 设置为打开
this.updateAssignee.open = true;
},
/** 提交转派审批人 */
submitUpdateAssigneeForm() {
this.$refs['updateAssigneeForm'].validate(valid => {
if (!valid) {
return;
}
updateTaskAssignee(this.updateAssignee.form).then(response => {
this.$modal.msgSuccess("转派任务成功!");
this.updateAssignee.open = false;
this.getDetail(); // 获得最新详情
});
});
},
/** 取消转派审批人 */
cancelUpdateAssigneeForm() {
this.updateAssignee.open = false;
this.resetUpdateAssigneeForm();
},
/** 重置转派审批人 */
resetUpdateAssigneeForm() {
this.updateAssignee.form = {
id: undefined,
assigneeUserId: undefined,
};
this.resetForm("updateAssigneeForm");
},
/** 处理审批退回的操作 */
handleDelegate(task) {
this.$modal.msgError("暂不支持【委派】功能,可以使用【转派】替代!");
},
/** 处理审批退回的操作 */
handleBack(task) {
this.$modal.msgError("暂不支持【退回】功能!");
}
}
};
</script>
<style lang="scss">
.my-process-designer {
height: calc(100vh - 200px);
}
.box-card {
width: 100%;
margin-bottom: 20px;
}
</style>
-187
View File
@@ -1,187 +0,0 @@
<template>
<div class="app-container">
<doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
<!-- 搜索工作栏 -->
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="流程名" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入流程名" clearable @keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item label="所属流程" prop="processDefinitionId">
<el-input v-model="queryParams.processDefinitionId" placeholder="请输入流程定义的编号" clearable @keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item label="流程分类" prop="category">
<el-select v-model="queryParams.category" placeholder="请选择流程分类" clearable>
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.BPM_MODEL_CATEGORY)"
:key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<el-form-item label="提交时间">
<el-date-picker v-model="dateRangeCreateTime" style="width: 240px" value-format="yyyy-MM-dd"
type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS)"
:key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<el-form-item label="结果" prop="result">
<el-select v-model="queryParams.result" placeholder="请选择流结果" clearable>
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT)"
:key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 操作工具栏 -->
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
v-hasPermi="['bpm:process-instance:query']">发起流程</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<!-- 列表 -->
<el-table v-loading="loading" :data="list">
<el-table-column label="编号" align="center" prop="id" width="320" />
<el-table-column label="流程名" align="center" prop="name" />
<el-table-column label="流程分类" align="center" prop="category">
<template slot-scope="scope">
<dict-tag :type="DICT_TYPE.BPM_MODEL_CATEGORY" :value="scope.row.category" />
</template>
</el-table-column>
<el-table-column label="当前审批任务" align="center" prop="tasks">
<template slot-scope="scope">
<el-button v-for="task in scope.row.tasks" :key="task" type="text" @click="handleFormDetail(task.id)">
<span>{{ task.name }}</span>
</el-button>
</template>
</el-table-column>
<el-table-column label="状态" align="center" prop="status">
<template slot-scope="scope">
<dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="结果" align="center" prop="result">
<template slot-scope="scope">
<dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT" :value="scope.row.result"/>
</template>
</el-table-column>
<el-table-column label="提交时间" align="center" prop="createTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="结束时间" align="center" prop="createTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.endTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button type="text" size="small" icon="el-icon-delete" v-if="scope.row.result === 1"
v-hasPermi="['bpm:process-instance:cancel']" @click="handleCancel(scope.row)">取消</el-button>
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleDetail(scope.row)"
v-hasPermi="['bpm:process-instance:query']">详情</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
@pagination="getList"/>
</div>
</template>
<script>
import { getMyProcessInstancePage, cancelProcessInstance } from "@/api/bpm/processInstance";
export default {
name: "ProcessInstance",
components: {
},
data() {
return {
// 遮罩层
loading: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 工作流的流程实例的拓展列表
list: [],
// 是否显示弹出层
dateRangeCreateTime: [],
// 查询参数
queryParams: {
pageNo: 1,
pageSize: 10,
name: null,
processDefinitionId: null,
category: null,
status: null,
result: null,
}
};
},
created() {
this.getList();
},
methods: {
/** 查询列表 */
getList() {
this.loading = true;
// 处理查询参数
let params = {...this.queryParams};
this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
// 执行查询
getMyProcessInstancePage(params).then(response => {
this.list = response.data.list;
this.total = response.data.total;
this.loading = false;
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNo = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.dateRangeCreateTime = [];
this.resetForm("queryForm");
this.handleQuery();
},
/** 新增按钮操作 **/
handleAdd() {
this.$router.push({ path: "/bpm/process-instance/create"})
},
/** 取消按钮操作 */
handleCancel(row) {
const id = row.id;
this.$prompt('请输入取消原因?', "取消流程", {
type: 'warning',
confirmButtonText: "确定",
cancelButtonText: "取消",
inputPattern: /^[\s\S]*.*[^\s][\s\S]*$/, // 判断非空,且非空格
inputErrorMessage: "取消原因不能为空",
}).then(({ value }) => {
return cancelProcessInstance(id, value);
}).then(() => {
this.getList();
this.$modal.msgSuccess("取消成功");
})
},
/** 处理详情按钮 */
handleDetail(row) {
this.$router.push({ path: "/bpm/process-instance/detail", query: { id: row.id}});
},
}
};
</script>
-124
View File
@@ -1,124 +0,0 @@
<template>
<div class="app-container">
<doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
<!-- 搜索工作栏 -->
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="流程名" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入流程名" clearable @keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker v-model="dateRangeCreateTime" style="width: 240px" value-format="yyyy-MM-dd"
type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 列表 -->
<el-table v-loading="loading" :data="list">
<el-table-column label="任务编号" align="center" prop="id" width="320" fixed />
<el-table-column label="任务名称" align="center" prop="name" width="200" />
<el-table-column label="所属流程" align="center" prop="processInstance.name" width="200" />
<el-table-column label="流程发起人" align="center" prop="processInstance.startUserNickname" width="120" />
<el-table-column label="结果" align="center" prop="result">
<template slot-scope="scope">
<dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT" :value="scope.row.result"/>
</template>
</el-table-column>
<el-table-column label="审批意见" align="center" prop="comment" width="200" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="审批时间" align="center" prop="endTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.endTime) }}</span>
</template>
</el-table-column>
<el-table-column label="耗时" align="center" prop="durationInMillis" width="180">
<template slot-scope="scope">
<span>{{ getDateStar(scope.row.durationInMillis) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleAudit(scope.row)"
v-hasPermi="['bpm:task:query']">详情</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
@pagination="getList"/>
</div>
</template>
<script>
import {getDoneTaskPage} from '@/api/bpm/task'
import {getDate} from "@/utils/dateUtils";
export default {
name: "Done",
components: {
},
data() {
return {
// 遮罩层
loading: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 已办任务列表
list: [],
// 查询参数
dateRangeCreateTime: [],
queryParams: {
pageNo: 1,
pageSize: 10,
name: null,
},
};
},
created() {
this.getList();
},
methods: {
/** 查询列表 */
getList() {
this.loading = true;
// 处理查询参数
let params = {...this.queryParams};
this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
getDoneTaskPage(params).then(response => {
this.list = response.data.list;
this.total = response.data.total;
this.loading = false;
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNo = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.dateRangeCreateTime = [];
this.resetForm("queryForm");
this.handleQuery();
},
getDateStar(ms) {
return getDate(ms);
},
/** 处理审批按钮 */
handleAudit(row) {
this.$router.push({ path: "/bpm/process-instance/detail", query: { id: row.processInstance.id}});
},
}
};
</script>
-111
View File
@@ -1,111 +0,0 @@
<template>
<div class="app-container">
<doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
<!-- 搜索工作栏 -->
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="流程名" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入流程名" clearable @keyup.enter.native="handleQuery"/>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker v-model="dateRangeCreateTime" style="width: 240px" value-format="yyyy-MM-dd"
type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 列表 -->
<el-table v-loading="loading" :data="list">
<el-table-column label="任务编号" align="center" prop="id" width="320" />
<el-table-column label="任务名称" align="center" prop="name" />
<el-table-column label="所属流程" align="center" prop="processInstance.name" />
<el-table-column label="流程发起人" align="center" prop="processInstance.startUserNickname" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="状态" align="center" prop="version" width="80">
<template slot-scope="scope">
<el-tag type="success" v-if="scope.row.suspensionState === 1">激活</el-tag>
<el-tag type="warning" v-if="scope.row.suspensionState === 2">挂起</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleAudit(scope.row)"
v-hasPermi="['bpm:task:update']">审批</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
@pagination="getList"/>
</div>
</template>
<script>
import {getTodoTaskPage} from '@/api/bpm/task'
import {listSimpleUsers} from "@/api/system/user";
export default {
name: "Todo",
components: {
},
data() {
return {
// 遮罩层
loading: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 待办任务列表
list: [],
// 查询参数
dateRangeCreateTime: [],
queryParams: {
pageNo: 1,
pageSize: 10,
name: null,
},
};
},
created() {
this.getList();
},
methods: {
/** 查询列表 */
getList() {
this.loading = true;
// 处理查询参数
let params = {...this.queryParams};
this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
getTodoTaskPage(params).then(response => {
this.list = response.data.list;
this.total = response.data.total;
this.loading = false;
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNo = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.dateRangeCreateTime = [];
this.resetForm("queryForm");
this.handleQuery();
},
/** 处理审批按钮 */
handleAudit(row) {
this.$router.push({ path: "/bpm/process-instance/detail", query: { id: row.processInstance.id}});
},
}
};
</script>
@@ -1,337 +0,0 @@
<template>
<div>
<!-- 列表弹窗 -->
<el-dialog title="任务分配规则" :visible.sync="visible" width="800px" append-to-body>
<el-table v-loading="loading" :data="list">
<el-table-column label="任务名" align="center" prop="taskDefinitionName" width="120" fixed />
<el-table-column label="任务标识" align="center" prop="taskDefinitionKey" width="120" show-tooltip-when-overflow />
<el-table-column label="规则类型" align="center" prop="type" width="120">
<template slot-scope="scope">
<dict-tag :type="DICT_TYPE.BPM_TASK_ASSIGN_RULE_TYPE" :value="scope.row.type" />
</template>
</el-table-column>
<el-table-column label="规则范围" align="center" prop="options" width="440px">
<template slot-scope="scope">
<el-tag size="medium" v-if="scope.row.options" v-for="option in scope.row.options" :key="option">
{{ getAssignRuleOptionName(scope.row.type, option) }}
</el-tag>
</template>
</el-table-column>
<el-table-column v-if="modelId" label="操作" align="center" width="80" fixed="right">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdateTaskAssignRule(scope.row)"
v-hasPermi="['bpm:task-assign-rule:update']">修改</el-button>
</template>
</el-table-column>
</el-table>
</el-dialog>
<!-- 添加/修改弹窗 -->
<el-dialog title="修改任务规则" :visible.sync="open" width="500px" append-to-body>
<el-form ref="taskAssignRuleForm" :model="form" :rules="rules" label-width="110px">
<el-form-item label="任务名称" prop="taskDefinitionName">
<el-input v-model="form.taskDefinitionName" disabled />
</el-form-item>
<el-form-item label="任务标识" prop="taskDefinitionKey">
<el-input v-model="form.taskDefinitionKey" disabled />
</el-form-item>
<el-form-item label="规则类型" prop="type">
<el-select v-model="form.type" clearable style="width: 100%">
<el-option v-for="dict in taskAssignRuleTypeDictDatas" :key="parseInt(dict.value)" :label="dict.label" :value="parseInt(dict.value)"/>
</el-select>
</el-form-item>
<el-form-item v-if="form.type === 10" label="指定角色" prop="roleIds">
<el-select v-model="form.roleIds" multiple clearable style="width: 100%">
<el-option v-for="item in roleOptions" :key="parseInt(item.id)" :label="item.name" :value="parseInt(item.id)" />
</el-select>
</el-form-item>
<el-form-item v-if="form.type === 20 || form.type === 21" label="指定部门" prop="deptIds">
<treeselect v-model="form.deptIds" :options="deptTreeOptions" multiple flat :defaultExpandLevel="3"
placeholder="请选择指定部门" :normalizer="normalizer"/>
</el-form-item>
<el-form-item v-if="form.type === 22" label="指定岗位" prop="postIds">
<el-select v-model="form.postIds" multiple clearable style="width: 100%">
<el-option v-for="item in postOptions" :key="parseInt(item.id)" :label="item.name" :value="parseInt(item.id)" />
</el-select>
</el-form-item>
<el-form-item v-if="form.type === 30" label="指定用户" prop="userIds">
<el-select v-model="form.userIds" multiple clearable style="width: 100%">
<el-option v-for="item in userOptions" :key="parseInt(item.id)" :label="item.nickname" :value="parseInt(item.id)" />
</el-select>
</el-form-item>
<el-form-item v-if="form.type === 40" label="指定用户组" prop="userGroupIds">
<el-select v-model="form.userGroupIds" multiple clearable style="width: 100%">
<el-option v-for="item in userGroupOptions" :key="parseInt(item.id)" :label="item.name" :value="parseInt(item.id)" />
</el-select>
</el-form-item>
<el-form-item v-if="form.type === 50" label="指定脚本" prop="scripts">
<el-select v-model="form.scripts" multiple clearable style="width: 100%">
<el-option v-for="dict in taskAssignScriptDictDatas" :key="parseInt(dict.value)"
:label="dict.label" :value="parseInt(dict.value)"/>
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitAssignRuleForm"> </el-button>
<el-button @click="cancelAssignRuleForm"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
import {createTaskAssignRule, getTaskAssignRuleList, updateTaskAssignRule} from "@/api/bpm/taskAssignRule";
import {listSimpleRoles} from "@/api/system/role";
import {listSimpleDepts} from "@/api/system/dept";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
import {listSimplePosts} from "@/api/system/post";
import {listSimpleUsers} from "@/api/system/user";
import {listSimpleUserGroups} from "@/api/bpm/userGroup";
export default {
name: "taskAssignRuleDialog",
components: {
Treeselect
},
data() {
return {
// 如下参数,可传递
modelId: undefined, // 流程模型的编号。如果 modelId 非空,则用于流程模型的查看与配置
processDefinitionId: undefined, // 流程定义的编号。如果 processDefinitionId 非空,则用于流程定义的查看,不支持配置
visible: false,
// 任务分配规则表单
row: undefined, // 选中的流程模型
list: [], // 选中流程模型的任务分配规则们
loading: false, // 加载中
open: false, // 是否打开
form: {}, // 表单
rules: { // 表单校验规则
type: [{ required: true, message: "规则类型不能为空", trigger: "change" }],
roleIds: [{required: true, message: "指定角色不能为空", trigger: "change" }],
deptIds: [{required: true, message: "指定部门不能为空", trigger: "change" }],
postIds: [{required: true, message: "指定岗位不能为空", trigger: "change"}],
userIds: [{required: true, message: "指定用户不能为空", trigger: "change"}],
userGroupIds: [{required: true, message: "指定用户组不能为空", trigger: "change"}],
scripts: [{required: true, message: "指定脚本不能为空", trigger: "change"}],
},
// 各种下拉框
roleOptions: [],
deptOptions: [],
deptTreeOptions: [],
postOptions: [],
userOptions: [],
userGroupOptions: [],
// 数据字典
modelFormTypeDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_FORM_TYPE),
taskAssignRuleTypeDictDatas: getDictDatas(DICT_TYPE.BPM_TASK_ASSIGN_RULE_TYPE),
taskAssignScriptDictDatas: getDictDatas(DICT_TYPE.BPM_TASK_ASSIGN_SCRIPT),
};
},
methods: {
initModel(modelId) {
this.modelId = modelId;
this.processDefinitionId = undefined;
// 初始化所有下拉框
this.init0();
},
initProcessDefinition(processDefinitionId) {
this.modelId = undefined;
this.processDefinitionId = processDefinitionId;
// 初始化所有下拉框
this.init0();
},
/** 初始化 */
init0() {
// 设置可见
this.visible = true;
// 获得列表
this.getList();
// 获得角色列表
this.roleOptions = [];
listSimpleRoles().then(response => {
this.roleOptions.push(...response.data);
});
// 获得部门列表
this.deptOptions = [];
this.deptTreeOptions = [];
listSimpleDepts().then(response => {
this.deptOptions.push(...response.data);
this.deptTreeOptions.push(...this.handleTree(response.data, "id"));
});
// 获得岗位列表
this.postOptions = [];
listSimplePosts().then(response => {
this.postOptions.push(...response.data);
});
// 获得用户列表
this.userOptions = [];
listSimpleUsers().then(response => {
this.userOptions.push(...response.data);
});
// 获得用户组列表
this.userGroupOptions = [];
listSimpleUserGroups().then(response => {
this.userGroupOptions.push(...response.data);
});
},
/** 获得任务分配规则列表 */
getList() {
this.loading = true;
getTaskAssignRuleList({
modelId: this.modelId,
processDefinitionId: this.processDefinitionId,
}).then(response => {
this.loading = false;
this.list = response.data;
})
},
/** 处理修改任务分配规则的按钮操作 */
handleUpdateTaskAssignRule(row) {
// 先重置标识
this.resetAssignRuleForm();
// 设置表单
this.form = {
...row,
options: [],
roleIds: [],
deptIds: [],
postIds: [],
userIds: [],
userGroupIds: [],
scripts: [],
};
// 将 options 赋值到对应的 roleIds 等选项
if (row.type === 10) {
this.form.roleIds.push(...row.options);
} else if (row.type === 20 || row.type === 21) {
this.form.deptIds.push(...row.options);
} else if (row.type === 22) {
this.form.postIds.push(...row.options);
} else if (row.type === 30) {
this.form.userIds.push(...row.options);
} else if (row.type === 40) {
this.form.userGroupIds.push(...row.options);
} else if (row.type === 50) {
this.form.scripts.push(...row.options);
}
this.open = true;
},
/** 提交任务分配规则的表单 */
submitAssignRuleForm() {
this.$refs["taskAssignRuleForm"].validate(valid => {
if (valid) {
// 构建表单
let form = {
...this.form,
taskDefinitionName: undefined,
};
// 将 roleIds 等选项赋值到 options 中
if (form.type === 10) {
form.options = form.roleIds;
} else if (form.type === 20 || form.type === 21) {
form.options = form.deptIds;
} else if (form.type === 22) {
form.options = form.postIds;
} else if (form.type === 30) {
form.options = form.userIds;
} else if (form.type === 40) {
form.options = form.userGroupIds;
} else if (form.type === 50) {
form.options = form.scripts;
}
form.roleIds = undefined;
form.deptIds = undefined;
form.postIds = undefined;
form.userIds = undefined;
form.userGroupIds = undefined;
form.scripts = undefined;
// 新增
if (!form.id) {
form.modelId = this.modelId; // 模型编号
createTaskAssignRule(form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
// 修改
} else {
form.taskDefinitionKey = undefined; // 无法修改
updateTaskAssignRule(form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
}
}
});
},
/** 取消任务分配规则的表单 */
cancelAssignRuleForm() {
this.open = false;
this.resetAssignRuleForm();
},
/** 表单重置 */
resetAssignRuleForm() {
this.form = {};
this.resetForm("taskAssignRuleForm");
},
getAssignRuleOptionName(type, option) {
if (type === 10) {
for (const roleOption of this.roleOptions) {
if (roleOption.id === option) {
return roleOption.name;
}
}
} else if (type === 20 || type === 21) {
for (const deptOption of this.deptOptions) {
if (deptOption.id === option) {
return deptOption.name;
}
}
} else if (type === 22) {
for (const postOption of this.postOptions) {
if (postOption.id === option) {
return postOption.name;
}
}
} else if (type === 30) {
for (const userOption of this.userOptions) {
if (userOption.id === option) {
return userOption.nickname;
}
}
} else if (type === 40) {
for (const userGroupOption of this.userGroupOptions) {
if (userGroupOption.id === option) {
return userGroupOption.name;
}
}
} else if (type === 50) {
option = option + ''; // 转换成 string
for (const dictData of this.taskAssignScriptDictDatas) {
if (dictData.value === option) {
return dictData.label;
}
}
}
return '未知(' + option + ')';
},
// 格式化部门的下拉框
normalizer(node) {
return {
id: node.id,
label: node.name,
children: node.children
}
}
}
};
</script>

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