Commit 2eda2c1c45ac18e8d5fbddfc17c95b4ae00cc3f7

Authored by zhangdaihao
1 parent 6e738846

Jeecg-Boot 2.1.0 版本发布,Online表单开发&在线代码生成器(迟到的版本,感谢大家支持)

Showing 167 changed files with 13537 additions and 17623 deletions

Too many changes to show.

To preserve performance only 37 of 167 files are displayed.

README.md
... ... @@ -6,7 +6,7 @@
6 6 Jeecg-Boot 快速开发平台(前后端分离版本)
7 7 ===============
8 8  
9   -当前最新版本: 2.0.2(发布日期:20190708
  9 +当前最新版本: 2.1.0(发布日期:20190826
10 10  
11 11 [![AUR](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE)
12 12 [![](https://img.shields.io/badge/Author-JEECG团队-orange.svg)](http://www.jeecg.com)
... ... @@ -239,7 +239,7 @@ Jeecg-Boot快速开发平台,可以应用在任何J2EE项目的开发中,尤
239 239 │ └─异常页面
240 240 │ └─个人页面
241 241 ├─Online在线开发(暂未开源)
242   -│ ├─Online在线表单
  242 +│ ├─Online在线表单 - 已开放功能
243 243 │ ├─Online在线图表
244 244 │ ├─Online图表模板配置
245 245 │ ├─Online在线报表
... ...
ant-design-vue-jeecg/README.md
1 1 Ant Design Jeecg Vue
2 2 ====
3 3  
4   -当前最新版本: 2.0.2(发布日期:20190708
  4 +当前最新版本: 2.1.0(发布日期:20190826
5 5  
6 6 Overview
7 7 ----
... ...
ant-design-vue-jeecg/package.json
1 1 {
2   - "name": "ant-design-vue-jeecg",
3   - "version": "2.0.2",
4   - "private": true,
  2 + "name": "vue-antd-jeecg",
  3 + "version": "2.1.0",
  4 + "private": false,
5 5 "scripts": {
6   - "serve": "vue-cli-service serve --open",
  6 + "pre": "cnpm install || yarn --registry https://registry.npm.taobao.org || npm install --registry https://registry.npm.taobao.org ",
  7 + "serve": "vue-cli-service serve",
7 8 "build": "vue-cli-service build",
8   - "lint": "vue-cli-service lint",
9   - "test:unit": "vue-cli-service test:unit",
10   - "test:e2e": "vue-cli-service test:e2e"
  9 + "lint": "vue-cli-service lint"
11 10 },
12 11 "dependencies": {
13 12 "@antv/data-set": "^0.10.2",
  13 + "@jeecg/antd-onine": "^1.0.1",
14 14 "@tinymce/tinymce-vue": "^2.0.0",
15 15 "ant-design-vue": "^1.3.9",
16 16 "apexcharts": "^3.6.5",
... ...
ant-design-vue-jeecg/public/index.html
... ... @@ -242,9 +242,10 @@
242 242 <!-- 全局配置 -->
243 243 <script>
244 244 window._CONFIG = {};
245   - window._CONFIG['domianURL'] = 'http://localhost:8080/jeecg-boot';
246   - window._CONFIG['imgDomainURL'] = 'http://localhost:8080/jeecg-boot/sys/common/view';
247   - window._CONFIG['pdfDomainURL'] = 'http://localhost:8080/jeecg-boot/sys/common/pdf/pdfPreviewIframe';
  245 + window._CONFIG['domianURL'] = 'http://127.0.0.1:8080/jeecg-boot';
  246 + window._CONFIG['casPrefixUrl'] = 'http://cas.example.org:8443/cas';
  247 + window._CONFIG['imgDomainURL'] = window._CONFIG['domianURL'] + '/sys/common/view';
  248 + window._CONFIG['pdfDomainURL'] = window._CONFIG['domianURL'] + '/sys/common/pdf/pdfPreviewIframe';
248 249 </script>
249 250 </head>
250 251  
... ... @@ -261,15 +262,6 @@
261 262 </div>
262 263 </div>
263 264  
264   -<!-- update_begin author:sunjianlei date:20190524 for: 去指定页面的加载动画 -->
265   -<script>
266   - // 去指定页面的加载动画
267   - if (location.href.indexOf('online/desform/pureview') !== -1) {
268   - document.getElementById('loader-wrapper').style.display = 'none'
269   - }
270   -</script>
271   -<!-- update_end author:sunjianlei date:20190524 for: 去指定页面的加载动画 -->
272   -
273 265 </body>
274 266  
275 267 </html>
276 268 \ No newline at end of file
... ...
ant-design-vue-jeecg/src/api/api.js
... ... @@ -45,11 +45,11 @@ const getPermissionRuleList = (params)=&gt;getAction(&quot;/sys/permission/getPermRuleLi
45 45 const queryPermissionRule = (params)=>getAction("/sys/permission/queryPermissionRule",params);
46 46  
47 47 // 部门管理
48   -const queryDepartTreeList = (params)=>getAction("/sysdepart/sysDepart/queryTreeList",params);
49   -const queryIdTree = (params)=>getAction("/sysdepart/sysDepart/queryIdTree",params);
50   -const queryParentName = (params)=>getAction("/sysdepart/sysDepart/queryParentName",params);
51   -const searchByKeywords = (params)=>getAction("/sysdepart/sysDepart/searchBy",params);
52   -const deleteByDepartId = (params)=>deleteAction("/sysdepart/sysDepart/delete",params);
  48 +const queryDepartTreeList = (params)=>getAction("/sys/sysDepart/queryTreeList",params);
  49 +const queryIdTree = (params)=>getAction("/sys/sysDepart/queryIdTree",params);
  50 +const queryParentName = (params)=>getAction("/sys/sysDepart/queryParentName",params);
  51 +const searchByKeywords = (params)=>getAction("/sys/sysDepart/searchBy",params);
  52 +const deleteByDepartId = (params)=>deleteAction("/sys/sysDepart/delete",params);
53 53  
54 54 //日志管理
55 55 //const getLogList = (params)=>getAction("/sys/log/list",params);
... ...
ant-design-vue-jeecg/src/assets/logo-white.png 0 → 100644

20.2 KB

ant-design-vue-jeecg/src/cas/sso.js 0 → 100644
  1 +import Vue from 'vue'
  2 +import { ACCESS_TOKEN } from "@/store/mutation-types"
  3 +import store from '@/store'
  4 +/**
  5 + * 单点登录
  6 + */
  7 +const init = (callback) => {
  8 + console.log("-------单点登录开始-------");
  9 + let token = Vue.ls.get(ACCESS_TOKEN);
  10 + let st = getUrlParam("ticket");
  11 + var sevice = "http://"+window.location.host+"/";
  12 + if(token){
  13 + loginSuccess(callback);
  14 + }else{
  15 + if(st){
  16 + validateSt(st,sevice,callback);
  17 + }else{
  18 + var serviceUrl = encodeURIComponent(sevice);
  19 + window.location.href = window._CONFIG['casPrefixUrl']+"/login?service="+serviceUrl;
  20 + }
  21 + }
  22 + console.log("-------单点登录结束-------");
  23 +};
  24 +const SSO = {
  25 + init: init
  26 +};
  27 +
  28 +function getUrlParam(paraName) {
  29 + var url = document.location.toString();
  30 + var arrObj = url.split("?");
  31 +
  32 + if (arrObj.length > 1) {
  33 + var arrPara = arrObj[1].split("&");
  34 + var arr;
  35 +
  36 + for (var i = 0; i < arrPara.length; i++) {
  37 + arr = arrPara[i].split("=");
  38 +
  39 + if (arr != null && arr[0] == paraName) {
  40 + return arr[1];
  41 + }
  42 + }
  43 + return "";
  44 + }
  45 + else {
  46 + return "";
  47 + }
  48 +}
  49 +
  50 +function validateSt(ticket,service,callback){
  51 + let params = {
  52 + ticket: ticket,
  53 + service:service
  54 + };
  55 + store.dispatch('ValidateLogin',params).then(res => {
  56 + //this.departConfirm(res)
  57 + if(res.success){
  58 + loginSuccess(callback);
  59 + }else{
  60 + var sevice = "http://"+window.location.host+"/";
  61 + var serviceUrl = encodeURIComponent(sevice);
  62 + window.location.href = window._CONFIG['casPrefixUrl']+"/login?service="+serviceUrl;
  63 + }
  64 + }).catch((err) => {
  65 + console.log(err);
  66 + //that.requestFailed(err);
  67 + });
  68 +}
  69 +
  70 +function loginSuccess (callback) {
  71 + callback();
  72 +}
  73 +export default SSO;
0 74 \ No newline at end of file
... ...
ant-design-vue-jeecg/src/components/README.md
... ... @@ -39,3 +39,5 @@ UserMenu.vue:首页右上侧的内容
39 39 ![输入图片说明](https://static.oschina.net/uploads/img/201904/12201226_laQK.png "在这里输入图片标题")
40 40 ####16.trend包 趋势显示组件(如下图)
41 41 ![输入图片说明](https://static.oschina.net/uploads/img/201904/12201600_Wo8K.png "在这里输入图片标题")
  42 +![corn表达式](https://oscimg.oschina.net/oscnet/661f9ac09016395f9f49286143af3241623.jpg)
  43 +![corn控件添加清除按钮](https://oscimg.oschina.net/oscnet/15096e49f2e29bd829e304d56770025d03c.jpg)
42 44 \ No newline at end of file
... ...
ant-design-vue-jeecg/src/components/chart/DashChartDemo.vue
... ... @@ -32,7 +32,7 @@
32 32 type="arc"
33 33 :zIndex="1"
34 34 :start="arcGuide2Start"
35   - :end="getArcGuide2End"
  35 + :end="getArcGuide2End()"
36 36 :vStyle="arcGuide2Style"
37 37 ></v-guide>
38 38 <v-guide
... ... @@ -88,7 +88,7 @@
88 88 }];
89 89  
90 90 const data = [
91   - { value: 7.0 },
  91 + { value: 0},
92 92 ];
93 93  
94 94 export default {
... ... @@ -96,7 +96,7 @@
96 96 props:{
97 97 datasource:{
98 98 type: Number,
99   - default:7
  99 + default:0
100 100 },
101 101 title: {
102 102 type: String,
... ...
ant-design-vue-jeecg/src/components/jeecg/JCron.vue 0 → 100644
  1 +<template>
  2 + <div class="components-input-demo-presuffix">
  3 + <a-input @click="openModal" placeholder="corn表达式" v-model="cron" @change="handleOK">
  4 + <a-icon slot="prefix" type="schedule" title="corn控件"/>
  5 + <a-icon v-if="cron" slot="suffix" type="close-circle" @click="handleEmpty" title="清空"/>
  6 + </a-input>
  7 + <JCronModal ref="innerVueCron" :data="cron" @ok="handleOK"></JCronModal>
  8 + </div>
  9 +</template>
  10 +<script>
  11 + import JCronModal from "./modal/JCronModal";
  12 + export default {
  13 + name: 'JCron',
  14 + components: {
  15 + JCronModal
  16 + },
  17 + props: {
  18 + value: {
  19 + required: false,
  20 + type: String,
  21 + default:()=>{
  22 + return '* * * * * ? *'
  23 + }
  24 + }
  25 + },
  26 + data(){
  27 + return {
  28 + cron: this.value,
  29 + }
  30 + },
  31 + watch:{
  32 + value(val){
  33 + this.cron = val
  34 + }
  35 + },
  36 + methods:{
  37 + openModal(){
  38 + this.$refs.innerVueCron.show();
  39 + },
  40 + handleOK(val){
  41 + this.cron = val;
  42 + this.$emit("change", this.cron);
  43 + //this.$emit("change", Object.assign({}, this.cron));
  44 + },
  45 + handleEmpty(){
  46 + this.handleOK('')
  47 + }
  48 + },
  49 + model: {
  50 + prop: 'value',
  51 + event: 'change'
  52 + }
  53 + }
  54 +</script>
  55 +<style scoped>
  56 + .components-input-demo-presuffix .anticon-close-circle {
  57 + cursor: pointer;
  58 + color: #ccc;
  59 + transition: color 0.3s;
  60 + font-size: 12px;
  61 + }
  62 + .components-input-demo-presuffix .anticon-close-circle:hover {
  63 + color: #f5222d;
  64 + }
  65 + .components-input-demo-presuffix .anticon-close-circle:active {
  66 + color: #666;
  67 + }
  68 +</style>
... ...
ant-design-vue-jeecg/src/components/jeecg/JEditableTable.vue
1 1 <!-- JEditableTable -->
2   -<!-- @version 1.4.2 -->
  2 +<!-- @version 1.4.4 -->
3 3 <!-- @author sjlei -->
4 4 <template>
5 5 <a-spin :spinning="loading">
... ... @@ -26,6 +26,9 @@
26 26 <div class="thead" ref="thead">
27 27 <div class="tr" :style="{width: this.realTrWidth}">
28 28 <!-- 左侧固定td -->
  29 + <div v-if="dragSort" class="td td-ds" :style="style.tdLeftDs">
  30 + <span></span>
  31 + </div>
29 32 <div v-if="rowSelection" class="td td-cb" :style="style.tdLeft">
30 33 <!--:indeterminate="true"-->
31 34 <a-checkbox
... ... @@ -62,85 +65,95 @@
62 65 <div v-if="rows.length===0" class="tr-nodata">
63 66 <span>暂无数据</span>
64 67 </div>
65   - <!-- 动态生成tr -->
66   - <template v-for="(row,rowIndex) in rows">
67   - <!-- tr 只加载可见的和预加载的总共十条数据 -->
68   - <div
69   - v-if="
  68 + <draggable v-model="rows" handle=".td-ds-icons" @end="handleDragMoveEnd">
  69 +
  70 + <!-- 动态生成tr -->
  71 + <template v-for="(row,rowIndex) in rows">
  72 + <!-- tr 只加载可见的和预加载的总共十条数据 -->
  73 + <div
  74 + v-if="
70 75 rowIndex >= parseInt(`${(scrollTop-rowHeight) / rowHeight}`) &&
71 76 (parseInt(`${scrollTop / rowHeight}`) + 9) > rowIndex
72 77 "
73   - :id="`${caseId}tbody-tr-${rowIndex}`"
74   - :data-idx="rowIndex"
75   - class="tr"
76   - :class="selectedRowIds.indexOf(row.id) !== -1 ? 'tr-checked' : ''"
77   - :style="buildTrStyle(rowIndex)"
78   - :key="row.id">
79   - <!-- 左侧固定td -->
80   - <div v-if="rowSelection" class="td td-cb" :style="style.tdLeft">
81   - <!-- 此 v-for 只是为了拼接 id 字符串 -->
82   - <template v-for="(id,i) in [`${row.id}`]">
83   - <a-checkbox
84   - :id="id"
85   - :key="i"
86   - :checked="selectedRowIds.indexOf(id) !== -1"
87   - @change="handleChangeLeftCheckbox"/>
88   - </template>
89   - </div>
90   - <div v-if="rowNumber" class="td td-num" :style="style.tdLeft">
91   - <span>{{ rowIndex+1 }}</span>
92   - </div>
93   - <!-- 右侧动态生成td -->
94   - <div
95   - class="td"
96   - v-for="col in columns"
97   - v-show="col.type !== formTypes.hidden"
98   - :key="col.key"
99   - :style="buildTdStyle(col)">
100   -
101   - <!-- 此 v-for 只是为了拼接 id 字符串 -->
102   - <template v-for="(id,i) in [`${col.key}${row.id}`]">
103   -
104   - <!-- native input -->
105   - <label :key="i" v-if="col.type === formTypes.input || col.type === formTypes.inputNumber">
106   - <a-tooltip
107   - :id="id"
108   - placement="top"
109   - :title="(tooltips[id] || {}).title"
110   - :visible="(tooltips[id] || {}).visible || false"
111   - :autoAdjustOverflow="true">
112   -
113   - <input
114   - :id="id"
115   - v-bind="buildProps(row,col)"
116   - :data-input-number="col.type === formTypes.inputNumber"
117   - :placeholder="replaceProps(col, col.placeholder)"
118   - @input="(e)=>{handleInputCommono(e.target,rowIndex,row,col)}"
119   - @mouseover="()=>{handleMouseoverCommono(row,col)}"
120   - @mouseout="()=>{handleMouseoutCommono(row,col)}"/>
121   -
122   - </a-tooltip>
  78 + :id="`${caseId}tbody-tr-${rowIndex}`"
  79 + :data-idx="rowIndex"
  80 + class="tr"
  81 + :class="selectedRowIds.indexOf(row.id) !== -1 ? 'tr-checked' : ''"
  82 + :style="buildTrStyle(rowIndex)"
  83 + :key="row.id">
  84 + <!-- 左侧固定td -->
  85 +
  86 + <div v-if="dragSort" class="td td-ds" :style="style.tdLeftDs">
  87 + <div class="td-ds-icons">
  88 + <a-icon type="align-left"/>
  89 + <a-icon type="align-right"/>
  90 + </div>
  91 + </div>
123 92  
124   - </label>
125   - <!-- checkbox -->
126   - <template v-else-if="col.type === formTypes.checkbox">
  93 + <div v-if="rowSelection" class="td td-cb" :style="style.tdLeft">
  94 + <!-- 此 v-for 只是为了拼接 id 字符串 -->
  95 + <template v-for="(id,i) in [`${row.id}`]">
127 96 <a-checkbox
128   - :key="i"
129 97 :id="id"
130   - v-bind="buildProps(row,col)"
131   - :checked="checkboxValues[id]"
132   - @change="(e)=>handleChangeCheckboxCommon(e,row,col)"
133   - />
134   - </template>
135   - <!-- select -->
136   - <template v-else-if="col.type === formTypes.select">
137   - <a-tooltip
138 98 :key="i"
139   - :id="id"
140   - placement="top"
141   - :title="(tooltips[id] || {}).title"
142   - :visible="(tooltips[id] || {}).visible || false"
143   - :autoAdjustOverflow="true">
  99 + :checked="selectedRowIds.indexOf(id) !== -1"
  100 + @change="handleChangeLeftCheckbox"/>
  101 + </template>
  102 + </div>
  103 + <div v-if="rowNumber" class="td td-num" :style="style.tdLeft">
  104 + <span>{{ rowIndex+1 }}</span>
  105 + </div>
  106 + <!-- 右侧动态生成td -->
  107 + <div
  108 + class="td"
  109 + v-for="col in columns"
  110 + v-show="col.type !== formTypes.hidden"
  111 + :key="col.key"
  112 + :style="buildTdStyle(col)">
  113 +
  114 + <!-- 此 v-for 只是为了拼接 id 字符串 -->
  115 + <template v-for="(id,i) in [`${col.key}${row.id}`]">
  116 +
  117 + <!-- native input -->
  118 + <label :key="i" v-if="col.type === formTypes.input || col.type === formTypes.inputNumber">
  119 + <a-tooltip
  120 + :id="id"
  121 + placement="top"
  122 + :title="(tooltips[id] || {}).title"
  123 + :visible="(tooltips[id] || {}).visible || false"
  124 + :autoAdjustOverflow="true">
  125 +
  126 + <input
  127 + :id="id"
  128 + v-bind="buildProps(row,col)"
  129 + :data-input-number="col.type === formTypes.inputNumber"
  130 + :placeholder="replaceProps(col, col.placeholder)"
  131 + @input="(e)=>{handleInputCommono(e.target,rowIndex,row,col)}"
  132 + @mouseover="()=>{handleMouseoverCommono(row,col)}"
  133 + @mouseout="()=>{handleMouseoutCommono(row,col)}"/>
  134 +
  135 + </a-tooltip>
  136 +
  137 + </label>
  138 + <!-- checkbox -->
  139 + <template v-else-if="col.type === formTypes.checkbox">
  140 + <a-checkbox
  141 + :key="i"
  142 + :id="id"
  143 + v-bind="buildProps(row,col)"
  144 + :checked="checkboxValues[id]"
  145 + @change="(e)=>handleChangeCheckboxCommon(e,row,col)"
  146 + />
  147 + </template>
  148 + <!-- select -->
  149 + <template v-else-if="col.type === formTypes.select">
  150 + <a-tooltip
  151 + :key="i"
  152 + :id="id"
  153 + placement="top"
  154 + :title="(tooltips[id] || {}).title"
  155 + :visible="(tooltips[id] || {}).visible || false"
  156 + :autoAdjustOverflow="true">
144 157  
145 158 <span
146 159 @mouseover="()=>{handleMouseoverCommono(row,col)}"
... ... @@ -165,17 +178,17 @@
165 178 <!--</template>-->
166 179 </a-select>
167 180 </span>
168   - </a-tooltip>
169   - </template>
170   - <!-- date -->
171   - <template v-else-if="col.type === formTypes.date || col.type === formTypes.datetime">
172   - <a-tooltip
173   - :key="i"
174   - :id="id"
175   - placement="top"
176   - :title="(tooltips[id] || {}).title"
177   - :visible="(tooltips[id] || {}).visible || false"
178   - :autoAdjustOverflow="true">
  181 + </a-tooltip>
  182 + </template>
  183 + <!-- date -->
  184 + <template v-else-if="col.type === formTypes.date || col.type === formTypes.datetime">
  185 + <a-tooltip
  186 + :key="i"
  187 + :id="id"
  188 + placement="top"
  189 + :title="(tooltips[id] || {}).title"
  190 + :visible="(tooltips[id] || {}).visible || false"
  191 + :autoAdjustOverflow="true">
179 192  
180 193 <span
181 194 @mouseover="()=>{handleMouseoverCommono(row,col)}"
... ... @@ -195,80 +208,81 @@
195 208 @change="(v)=>handleChangeJDateCommon(v,id,row,col,col.type === formTypes.datetime)"/>
196 209  
197 210 </span>
198   - </a-tooltip>
199   - </template>
200   -
201   - <div v-else-if="col.type === formTypes.upload" :key="i">
202   - <template v-if="uploadValues[id] != null" v-for="(file,fileKey) of [(uploadValues[id]||{})]">
203   - <a-input
204   - :key="fileKey"
205   - :readOnly="true"
206   - :value="file.name"
207   - >
208   -
209   - <template slot="addonBefore" style="width: 30px">
210   - <a-tooltip v-if="file.status==='uploading'" :title="`上传中(${Math.floor(file.percent)}%)`">
211   - <a-icon type="loading"/>
212   - </a-tooltip>
213   - <a-tooltip v-else-if="file.status==='done'" title="上传完成">
214   - <a-icon type="check-circle" style="color:#00DB00;"/>
215   - </a-tooltip>
216   - <a-tooltip v-else title="上传失败">
217   - <a-icon type="exclamation-circle" style="color:red;"/>
218   - </a-tooltip>
219   - </template>
220   -
221   - <template slot="addonAfter" style="width: 30px">
222   - <a-tooltip title="删除并重新上传">
223   - <a-icon
224   - v-if="file.status!=='uploading'"
225   - type="close-circle"
226   - style="cursor: pointer;"
227   - @click="()=>handleClickDelFile(id)"/>
228   - </a-tooltip>
229   - </template>
230   -
231   - </a-input>
  211 + </a-tooltip>
232 212 </template>
233 213  
234   - <div :hidden="uploadValues[id] != null">
  214 + <div v-else-if="col.type === formTypes.upload" :key="i">
  215 + <template v-if="uploadValues[id] != null" v-for="(file,fileKey) of [(uploadValues[id]||{})]">
  216 + <a-input
  217 + :key="fileKey"
  218 + :readOnly="true"
  219 + :value="file.name"
  220 + >
235 221  
236   - <a-upload
237   - name="file"
238   - :data="{'isup':1}"
239   - :multiple="false"
240   - :action="col.action"
241   - :headers="uploadGetHeaders(row,col)"
242   - :showUploadList="false"
243   - v-bind="buildProps(row,col)"
244   - @change="(v)=>handleChangeUpload(v,id,row,col)"
245   - >
246   - <a-button icon="upload">{{ col.placeholder }}</a-button>
247   - </a-upload>
248   - </div>
  222 + <template slot="addonBefore" style="width: 30px">
  223 + <a-tooltip v-if="file.status==='uploading'" :title="`上传中(${Math.floor(file.percent)}%)`">
  224 + <a-icon type="loading"/>
  225 + </a-tooltip>
  226 + <a-tooltip v-else-if="file.status==='done'" title="上传完成">
  227 + <a-icon type="check-circle" style="color:#00DB00;"/>
  228 + </a-tooltip>
  229 + <a-tooltip v-else title="上传失败">
  230 + <a-icon type="exclamation-circle" style="color:red;"/>
  231 + </a-tooltip>
  232 + </template>
  233 +
  234 + <template slot="addonAfter" style="width: 30px">
  235 + <a-tooltip title="删除并重新上传">
  236 + <a-icon
  237 + v-if="file.status!=='uploading'"
  238 + type="close-circle"
  239 + style="cursor: pointer;"
  240 + @click="()=>handleClickDelFile(id)"/>
  241 + </a-tooltip>
  242 + </template>
  243 +
  244 + </a-input>
  245 + </template>
  246 +
  247 + <div :hidden="uploadValues[id] != null">
  248 +
  249 + <a-upload
  250 + name="file"
  251 + :data="{'isup':1}"
  252 + :multiple="false"
  253 + :action="col.action"
  254 + :headers="uploadGetHeaders(row,col)"
  255 + :showUploadList="false"
  256 + v-bind="buildProps(row,col)"
  257 + @change="(v)=>handleChangeUpload(v,id,row,col)"
  258 + >
  259 + <a-button icon="upload">{{ col.placeholder }}</a-button>
  260 + </a-upload>
  261 + </div>
249 262  
250   - </div>
  263 + </div>
251 264  
252   - <div v-else-if="col.type === formTypes.slot" :key="i">
253   - <slot
254   - :name="(col.slot || col.slotName) || col.key"
255   - :text="inputValues[rowIndex][col.key]"
256   - :column="col"
257   - :rowId="removeCaseId(row.id)"
258   - :getValue="()=>_getValueForSlot(row.id)"
259   - :target="getVM()"
260   - />
261   - </div>
  265 + <div v-else-if="col.type === formTypes.slot" :key="i">
  266 + <slot
  267 + :name="(col.slot || col.slotName) || col.key"
  268 + :index="rowIndex"
  269 + :text="inputValues[rowIndex][col.key]"
  270 + :column="col"
  271 + :rowId="removeCaseId(row.id)"
  272 + :getValue="()=>_getValueForSlot(row.id)"
  273 + :target="getVM()"
  274 + />
  275 + </div>
262 276  
263   - <!-- else (normal) -->
264   - <span v-else :key="i">{{ inputValues[rowIndex][col.key] }}</span>
265   - </template>
  277 + <!-- else (normal) -->
  278 + <span v-else :key="i">{{ inputValues[rowIndex][col.key] }}</span>
  279 + </template>
  280 + </div>
266 281 </div>
267   - </div>
268   - <!-- -- tr end -- -->
269   -
270   - </template>
  282 + <!-- -- tr end -- -->
271 283  
  284 + </template>
  285 + </draggable>
272 286  
273 287 </div>
274 288 </div>
... ... @@ -278,6 +292,7 @@
278 292  
279 293 <script>
280 294 import Vue from 'vue'
  295 + import Draggable from 'vuedraggable'
281 296 import { ACCESS_TOKEN } from '@/store/mutation-types'
282 297 import { FormTypes, VALIDATE_NO_PASSED } from '@/utils/JEditableTableUtil'
283 298 import { cloneObject, randomString } from '@/utils/util'
... ... @@ -289,7 +304,7 @@
289 304  
290 305 export default {
291 306 name: 'JEditableTable',
292   - components: { JDate },
  307 + components: { JDate, Draggable },
293 308 props: {
294 309 // 列信息
295 310 columns: {
... ... @@ -338,7 +353,16 @@
338 353 disabled: {
339 354 type: Boolean,
340 355 default: false
341   - }
  356 + },
  357 + // 是否可拖拽排序
  358 + dragSort: {
  359 + type: Boolean,
  360 + default: false
  361 + },
  362 + dragSortKey: {
  363 + type: String,
  364 + default: 'orderNum'
  365 + },
342 366 },
343 367 data() {
344 368 return {
... ... @@ -354,7 +378,8 @@
354 378 // 'max-height': '400px'
355 379 tbody: { left: '0px' },
356 380 // 左侧固定td的style
357   - tdLeft: { 'min-width': '4%', 'max-width': '45px' }
  381 + tdLeft: { 'min-width': '4%', 'max-width': '45px' },
  382 + tdLeftDs: { 'min-width': '30px', 'max-width': '35px' },
358 383 },
359 384 // 表单的类型
360 385 formTypes: FormTypes,
... ... @@ -455,89 +480,92 @@
455 480 },
456 481 // 侦听器
457 482 watch: {
458   - dataSource: function (newValue) {
459   - this.initialize()
460   -
461   - let rows = []
462   - let checkboxValues = {}
463   - let selectValues = {}
464   - let jdateValues = {}
465   - // 禁用行的id
466   - let disabledRowIds = (this.disabledRowIds || [])
467   - newValue.forEach((data, newValueIndex) => {
468   - // 判断源数据是否带有id
469   - if (data.id == null || data.id === '') {
470   - data.id = this.removeCaseId(this.generateId() + newValueIndex)
471   - }
  483 + dataSource: {
  484 + immediate: true,
  485 + handler: function (newValue) {
  486 + this.initialize()
  487 +
  488 + let rows = []
  489 + let checkboxValues = {}
  490 + let selectValues = {}
  491 + let jdateValues = {}
  492 + // 禁用行的id
  493 + let disabledRowIds = (this.disabledRowIds || [])
  494 + newValue.forEach((data, newValueIndex) => {
  495 + // 判断源数据是否带有id
  496 + if (data.id == null || data.id === '') {
  497 + data.id = this.removeCaseId(this.generateId() + newValueIndex)
  498 + }
472 499  
473   - let value = { id: this.caseId + data.id }
474   - let row = { id: value.id }
475   - let disabled = false
476   - this.columns.forEach(column => {
477   - let inputId = column.key + value.id
478   - let sourceValue = (data[column.key] == null ? '' : data[column.key]).toString()
479   - if (column.type === FormTypes.checkbox) {
  500 + let value = { id: this.caseId + data.id }
  501 + let row = { id: value.id }
  502 + let disabled = false
  503 + this.columns.forEach(column => {
  504 + let inputId = column.key + value.id
  505 + let sourceValue = (data[column.key] == null ? '' : data[column.key]).toString()
  506 + if (column.type === FormTypes.checkbox) {
  507 +
  508 + // 判断是否设定了customValue(自定义值)
  509 + if (column.customValue instanceof Array) {
  510 + let customValue = (column.customValue[0] || '').toString()
  511 + checkboxValues[inputId] = (sourceValue === customValue)
  512 + } else {
  513 + checkboxValues[inputId] = sourceValue
  514 + }
480 515  
481   - // 判断是否设定了customValue(自定义值)
482   - if (column.customValue instanceof Array) {
483   - let customValue = (column.customValue[0] || '').toString()
484   - checkboxValues[inputId] = (sourceValue === customValue)
485   - } else {
486   - checkboxValues[inputId] = sourceValue
487   - }
  516 + } else if (column.type === FormTypes.select) {
  517 + if (sourceValue) {
  518 + // 判断是否是多选
  519 + selectValues[inputId] = (column.props || {})['mode'] === 'multiple' ? sourceValue.split(',') : sourceValue
  520 + } else {
  521 + selectValues[inputId] = undefined
  522 + }
488 523  
489   - } else if (column.type === FormTypes.select) {
490   - if (sourceValue) {
491   - // 判断是否是多选
492   - selectValues[inputId] = (column.props || {})['mode'] === 'multiple' ? sourceValue.split(',') : sourceValue
493   - } else {
494   - selectValues[inputId] = undefined
495   - }
  524 + } else if (column.type === FormTypes.date || column.type === FormTypes.datetime) {
  525 + jdateValues[inputId] = sourceValue
496 526  
497   - } else if (column.type === FormTypes.date || column.type === FormTypes.datetime) {
498   - jdateValues[inputId] = sourceValue
  527 + } else if (column.type === FormTypes.slot) {
  528 + if (sourceValue !== 0 && !sourceValue) {
  529 + value[column.key] = column.defaultValue
  530 + } else {
  531 + value[column.key] = sourceValue
  532 + }
499 533  
500   - } else if (column.type === FormTypes.slot) {
501   - if (sourceValue !== 0 && !sourceValue) {
502   - value[column.key] = column.defaultValue
503 534 } else {
504 535 value[column.key] = sourceValue
505 536 }
506 537  
507   - } else {
508   - value[column.key] = sourceValue
509   - }
510   -
511   - // 解析disabledRows
512   - for (let columnKey in this.disabledRows) {
513   - // 判断是否有该属性
514   - if (this.disabledRows.hasOwnProperty(columnKey) && data.hasOwnProperty(columnKey)) {
515   - // row[columnKey] =
  538 + // 解析disabledRows
  539 + for (let columnKey in this.disabledRows) {
  540 + // 判断是否有该属性
  541 + if (this.disabledRows.hasOwnProperty(columnKey) && data.hasOwnProperty(columnKey)) {
  542 + // row[columnKey] =
516 543  
517   - if (disabled !== true) {
518   - disabled = this.disabledRows[columnKey] === data[columnKey]
519   - if (disabled) {
520   - disabledRowIds.push(row.id)
  544 + if (disabled !== true) {
  545 + disabled = this.disabledRows[columnKey] === data[columnKey]
  546 + if (disabled) {
  547 + disabledRowIds.push(row.id)
  548 + }
521 549 }
522   - }
523 550  
  551 + }
524 552 }
525   - }
  553 + })
  554 + this.inputValues.push(value)
  555 + rows.push(row)
526 556 })
527   - this.inputValues.push(value)
528   - rows.push(row)
529   - })
530   - this.disabledRowIds = disabledRowIds
531   - this.checkboxValues = checkboxValues
532   - this.selectValues = selectValues
533   - this.jdateValues = jdateValues
534   - this.rows = rows
  557 + this.disabledRowIds = disabledRowIds
  558 + this.checkboxValues = checkboxValues
  559 + this.selectValues = selectValues
  560 + this.jdateValues = jdateValues
  561 + this.rows = rows
535 562  
536   - // 更新form表单的值
537   - this.$nextTick(() => {
538   - this.updateFormValues()
539   - })
  563 + // 更新form表单的值
  564 + this.$nextTick(() => {
  565 + this.updateFormValues()
  566 + })
540 567  
  568 + }
541 569 },
542 570 columns: {
543 571 immediate: true,
... ... @@ -722,6 +750,12 @@
722 750 this.selectValues = selectValues
723 751 this.jdateValues = jdateValues
724 752  
  753 + if (this.dragSort) {
  754 + this.inputValues.forEach((item, index) => {
  755 + item[this.dragSortKey] = (index + 1)
  756 + })
  757 + }
  758 +
725 759 if (update) {
726 760 this.rows = rows
727 761 this.$nextTick(() => {
... ... @@ -751,6 +785,7 @@
751 785 },
752 786 /** 添加一行 */
753 787 add(num = 1, forceScrollToBottom = false) {
  788 + if (num < 1) return
754 789 // let timestamp = new Date().getTime()
755 790 let rows = this.rows
756 791 let row
... ... @@ -1230,6 +1265,31 @@
1230 1265 }
1231 1266 },
1232 1267  
  1268 + /** 拖动结束,交换inputValue中的值 */
  1269 + handleDragMoveEnd(event) {
  1270 + let { oldIndex, newIndex } = event
  1271 +
  1272 + let values = this.inputValues
  1273 + // 存储旧数据,并删除旧项目
  1274 + let temp = values[oldIndex]
  1275 + values.splice(oldIndex, 1)
  1276 + // 向新项目里添加旧数据
  1277 + values.splice(newIndex, 0, temp)
  1278 +
  1279 + values.forEach((item, index) => {
  1280 + item[this.dragSortKey] = (index + 1)
  1281 + })
  1282 +
  1283 + this.forceUpdateFormValues()
  1284 +
  1285 + // 触发已拖动事件
  1286 + this.$emit('dragged', {
  1287 + oldIndex,
  1288 + newIndex,
  1289 + target: this
  1290 + })
  1291 + },
  1292 +
1233 1293 /* --- common function begin --- */
1234 1294  
1235 1295 /** 鼠标移入 */
... ... @@ -1355,7 +1415,12 @@
1355 1415 _loadDictConcatToOptions(column) {
1356 1416 initDictOptions(column.dictCode).then((res) => {
1357 1417 if (res.success) {
1358   - column.options = (column.options || []).concat(res.result)
  1418 + let newOptions = (column.options || [])// .concat(res.result)
  1419 + res.result.forEach(item => {
  1420 + for (let option of newOptions) if (option.value === item.value) return
  1421 + newOptions.push(item)
  1422 + })
  1423 + column.options = newOptions
1359 1424 } else {
1360 1425 console.group(`JEditableTable 查询字典(${column.dictCode})发生异常`)
1361 1426 console.log(res.message)
... ... @@ -1377,14 +1442,46 @@
1377 1442  
1378 1443 /** 辅助方法:指定a-select 和 j-data 的父容器 */
1379 1444 getParentContainer(node) {
1380   - if (this.$el && this.$el.nodeType !== 8) {
1381   - return this.$el
1382   - }
1383   - let doc = document.getElementById(this.caseId + 'inputTable')
1384   - if (doc != null) {
1385   - return doc
  1445 + let element = (() => {
  1446 + // nodeType 8 : Comment : 注释
  1447 + if (this.$el && this.$el.nodeType !== 8) {
  1448 + return this.$el
  1449 + }
  1450 + let doc = document.getElementById(this.caseId + 'inputTable')
  1451 + if (doc != null) {
  1452 + return doc
  1453 + }
  1454 + return node.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode
  1455 + })()
  1456 +
  1457 + // 递归判断是否带有 overflow: hidden;的父元素
  1458 + const ifParent = (child) => {
  1459 + let currentOverflow = null
  1460 + if (child['currentStyle']) {
  1461 + currentOverflow = child['currentStyle']['overflow']
  1462 + } else if (window.getComputedStyle) {
  1463 + currentOverflow = window.getComputedStyle(child)['overflow']
  1464 + }
  1465 + if (currentOverflow != null) {
  1466 + if (currentOverflow === 'hidden') {
  1467 + // 找到了带有 hidden 的标签,判断它的父级是否还有 hidden,直到遇到完全没有 hidden 或 body 的时候才停止递归
  1468 + let temp = ifParent(child.parentNode)
  1469 + return temp != null ? temp : child.parentNode
  1470 + } else
  1471 + // 当前标签没有 hidden ,如果有父级并且父级不是 body 的话就继续递归判断父级
  1472 + if (child.parentNode && child.parentNode.tagName.toLocaleLowerCase() !== 'body') {
  1473 + return ifParent(child.parentNode)
  1474 + } else {
  1475 + // 直到 body 都没有遇到有 hidden 的标签
  1476 + return null
  1477 + }
  1478 + } else {
  1479 + return child
  1480 + }
1386 1481 }
1387   - return node.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode
  1482 +
  1483 + let temp = ifParent(element)
  1484 + return (temp != null) ? temp : element
1388 1485 },
1389 1486  
1390 1487 /** 辅助方法:替换${...}变量 */
... ... @@ -1440,6 +1537,9 @@
1440 1537 props['showSearch'] = true
1441 1538 }
1442 1539  
  1540 + // 判断是否是禁用的列
  1541 + props['disabled'] = !!col['disabled']
  1542 +
1443 1543 // 判断是否为禁用的行
1444 1544 if (props['disabled'] !== true) {
1445 1545 props['disabled'] = ((this.disabledRowIds || []).indexOf(row.id) !== -1)
... ... @@ -1515,6 +1615,38 @@
1515 1615 align-items: center;
1516 1616 }
1517 1617  
  1618 + &.td-ds {
  1619 + margin-right: 0;
  1620 + padding-left: 0;
  1621 + padding-right: 0;
  1622 + justify-content: center;
  1623 + align-items: center;
  1624 +
  1625 + .td-ds-icons {
  1626 + position: relative;
  1627 + cursor: move;
  1628 + width: 100%;
  1629 + /*padding: 25% 0;*/
  1630 + height: 100%;
  1631 +
  1632 + .anticon-align-left,
  1633 + .anticon-align-right {
  1634 + position: absolute;
  1635 + top: 30%;
  1636 + }
  1637 +
  1638 + .anticon-align-left {
  1639 + left: 25%;
  1640 + }
  1641 +
  1642 + .anticon-align-right {
  1643 + right: 25%;
  1644 + }
  1645 + }
  1646 +
  1647 +
  1648 + }
  1649 +
1518 1650 }
1519 1651  
1520 1652 }
... ...
ant-design-vue-jeecg/src/components/jeecg/JEditor.vue
... ... @@ -84,7 +84,7 @@
84 84 },
85 85 watch: {
86 86 value(newValue) {
87   - this.myValue = newValue
  87 + this.myValue = (newValue == null ? '' : newValue)
88 88 },
89 89 myValue(newValue) {
90 90 console.log(newValue)
... ...
ant-design-vue-jeecg/src/components/jeecg/README_JEditableTable.md
... ... @@ -2,30 +2,33 @@
2 2  
3 3 ## 参数配置
4 4  
5   -| 参数 | 类型 | 必填 | 说明 |
6   -|--------------|---------|------|----------------------------------------------------------------|
7   -| columns | array | ✔️ | 表格列的配置描述,具体项见下表 |
8   -| dataSource | array | ✔️ | 表格数据 |
9   -| loading | boolean | | 是否正在加载,加载中不会显示任何行,默认false |
10   -| actionButton | boolean | | 是否显示操作按钮,包括"新增"、"删除",默认false |
11   -| rowNumber | boolean | | 是否显示行号,默认false |
12   -| rowSelection | boolean | | 是否可选择行,默认false |
13   -| maxHeight | number | | 设定最大高度(px),默认400 |
14   -| disabledRows | object | | 设定禁用的行,被禁用的行无法被选择和编辑,配置方法可以查看示例 |
15   -| disabled | boolean | | 是否禁用所有行,默认false |
  5 +| 参数 | 类型 | 必填 | 说明 |
  6 +|--------------|---------|------|---------------------------------------------------------------------------------|
  7 +| columns | array | ✔️ | 表格列的配置描述,具体项见下表 |
  8 +| dataSource | array | ✔️ | 表格数据 |
  9 +| loading | boolean | | 是否正在加载,加载中不会显示任何行,默认false |
  10 +| actionButton | boolean | | 是否显示操作按钮,包括"新增"、"删除",默认false |
  11 +| rowNumber | boolean | | 是否显示行号,默认false |
  12 +| rowSelection | boolean | | 是否可选择行,默认false |
  13 +| dragSort | boolean | | 是否可拖动排序,默认false |
  14 +| dragSortKey | string | | 拖动排序存储的Key,无需定义在columns内也能在getValues()时获取到值,默认orderNum |
  15 +| maxHeight | number | | 设定最大高度(px),默认400 |
  16 +| disabledRows | object | | 设定禁用的行,被禁用的行无法被选择和编辑,配置方法可以查看示例 |
  17 +| disabled | boolean | | 是否禁用所有行,默认false |
16 18  
17 19 ### columns 参数详解
18 20  
19   -| 参数 | 类型 | 必填 | 说明 |
20   -|---------------|--------|------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
21   -| title | string | ✔️ | 表格列头显示的问题 |
22   -| key | string | ✔️ | 列数据在数据项中对应的 key,必须是唯一的 |
23   -| type | string | ✔️ | 表单的类型,可以通过`JEditableTableUtil.FormTypes`赋值 |
24   -| width | string | | 列的宽度,可以是百分比,也可以是`px`或其他单位,建议设置为百分比,且每一列的宽度加起来不应超过100%,否则可能会不能达到预期的效果。留空会自动计算百分比 |
25   -| placeholder | string | | 表单预期值的提示信息,可以使用`${...}`变量替换文本(详见`${...} 变量使用方式`) |
26   -| defaultValue | string | | 默认值,在新增一行时生效 |
27   -| validateRules | array | | 表单验证规则,配置方式见[validateRules 配置规则](#validaterules-配置规则) |
28   -| props | object | | 设置添加给表单元素的自定义属性,例如:`props:{title: 'show title'}` |
  21 +| 参数 | 类型 | 必填 | 说明 |
  22 +|---------------|---------|------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
  23 +| title | string | ✔️ | 表格列头显示的问题 |
  24 +| key | string | ✔️ | 列数据在数据项中对应的 key,必须是唯一的 |
  25 +| type | string | ✔️ | 表单的类型,可以通过`JEditableTableUtil.FormTypes`赋值 |
  26 +| width | string | | 列的宽度,可以是百分比,也可以是`px`或其他单位,建议设置为百分比,且每一列的宽度加起来不应超过100%,否则可能会不能达到预期的效果。留空会自动计算百分比 |
  27 +| placeholder | string | | 表单预期值的提示信息,可以使用`${...}`变量替换文本(详见`${...} 变量使用方式`) |
  28 +| defaultValue | string | | 默认值,在新增一行时生效 |
  29 +| validateRules | array | | 表单验证规则,配置方式见[validateRules 配置规则](#validaterules-配置规则) |
  30 +| props | object | | 设置添加给表单元素的自定义属性,例如:`props:{title: 'show title'}` |
  31 +| disabled | boolean | | 是否禁用当前列,默认false |
29 32  
30 33 #### 当 type=checkbox 时所需的参数
31 34  
... ... @@ -40,7 +43,7 @@
40 43 |------------|---------|------|----------------------------------------------------|
41 44 | options | array | ✔️ | 下拉选项列表,详见下表 |
42 45 | allowInput | boolean | | 是否允许用户输入内容,并创建新的内容 |
43   -| dictCode | String | | 数据字典Code,若options也有值,则拼接options后面 |
  46 +| dictCode | String | | 数据字典Code,若options也有值,则拼接options后面 |
44 47  
45 48 ##### options 所需参数
46 49  
... ... @@ -75,11 +78,12 @@
75 78  
76 79 ## 事件
77 80  
78   -| 事件名 | 触发时机 | 参数 |
79   -|-----------------|----------------------------------------------------|-------------------------------|
80   -| added | 当添加行操作完成后触发 | |
81   -| deleted | 当删除行操作完成后触发(批量删除操作只会触发一次) | `deleteIds` 被逻辑删除的id |
82   -| selectRowChange | 当行被选中或取消选中时触发 | `selectedRowIds` 被选中行的id |
  81 +| 事件名 | 触发时机 | 参数 |
  82 +|-----------------|----------------------------------------------------|--------------------------------------------------|
  83 +| added | 当添加行操作完成后触发 | |
  84 +| deleted | 当删除行操作完成后触发(批量删除操作只会触发一次) | `deleteIds` 被逻辑删除的id |
  85 +| selectRowChange | 当行被选中或取消选中时触发 | `selectedRowIds` 被选中行的id |
  86 +| valueChange | 当数据发生改变的时候触发的事件 | `{ type, row, column, value, target }` Event对象 |
83 87  
84 88 ## 方法
85 89  
... ... @@ -490,6 +494,7 @@ this.$refs.editableTable.getValues((error, values) =&gt; {
490 494 /* a 标签的点击事件,删除当前选中的行 */
491 495 handleDelete(props) {
492 496 // 参数解释
  497 + // props.index :当前行的下标
493 498 // props.text :当前值,可能是defaultValue定义的值,也可能是从dataSource中取出的值
494 499 // props.rowId :当前选中行的id,如果是新增行则是临时id
495 500 // props.column :当前操作的列
... ...
ant-design-vue-jeecg/src/components/jeecg/modal/JCronModal.vue 0 → 100644
  1 +<template>
  2 + <a-modal
  3 + title="corn表达式"
  4 + :width="modalWidth"
  5 + :visible="visible"
  6 + :confirmLoading="confirmLoading"
  7 + @ok="handleSubmit"
  8 + @cancel="close"
  9 + cancelText="关闭">
  10 + <div class="card-container">
  11 + <a-tabs type="card">
  12 + <a-tab-pane key="1" type="card">
  13 + <span slot="tab"><a-icon type="schedule" /> 秒</span>
  14 + <a-radio-group v-model="result.second.cronEvery">
  15 + <a-row>
  16 + <a-radio value="1">每一秒钟</a-radio>
  17 + </a-row>
  18 + <a-row>
  19 + <a-radio value="2">每隔
  20 + <a-input-number size="small" v-model="result.second.incrementIncrement" :min="1" :max="60"></a-input-number>
  21 + 秒执行 从
  22 + <a-input-number size="small" v-model="result.second.incrementStart" :min="0" :max="59"></a-input-number>
  23 + 秒开始
  24 + </a-radio>
  25 + </a-row>
  26 + <a-row>
  27 + <a-radio value="3">具体秒数(可多选)</a-radio>
  28 + <a-select style="width:354px;" size="small" mode="multiple" v-model="result.second.specificSpecific">
  29 + <a-select-option v-for="(val,index) in 60" :key="index" :value="index">{{ index }}</a-select-option>
  30 + </a-select>
  31 + </a-row>
  32 + <a-row>
  33 + <a-radio value="4">周期从
  34 + <a-input-number size="small" v-model="result.second.rangeStart" :min="1" :max="60"></a-input-number>
  35 + 到
  36 + <a-input-number size="small" v-model="result.second.rangeEnd" :min="0" :max="59"></a-input-number>
  37 + 秒
  38 + </a-radio>
  39 + </a-row>
  40 + </a-radio-group>
  41 + </a-tab-pane>
  42 + <a-tab-pane key="2">
  43 + <span slot="tab"><a-icon type="schedule" />分</span>
  44 + <div class="tabBody">
  45 + <a-radio-group v-model="result.minute.cronEvery">
  46 + <a-row>
  47 + <a-radio value="1">每一分钟</a-radio>
  48 + </a-row>
  49 + <a-row>
  50 + <a-radio value="2">每隔
  51 + <a-input-number size="small" v-model="result.minute.incrementIncrement" :min="1" :max="60"></a-input-number>
  52 + 分执行 从
  53 + <a-input-number size="small" v-model="result.minute.incrementStart" :min="0" :max="59"></a-input-number>
  54 + 分开始
  55 + </a-radio>
  56 + </a-row>
  57 + <a-row>
  58 + <a-radio value="3">具体分钟数(可多选)</a-radio>
  59 + <a-select style="width:340px;" size="small" mode="multiple" v-model="result.minute.specificSpecific">
  60 + <a-select-option v-for="(val,index) in Array(60)" :key="index" :value="index"> {{ index }}</a-select-option>
  61 + </a-select>
  62 + </a-row>
  63 + <a-row>
  64 + <a-radio value="4">周期从
  65 + <a-input-number size="small" v-model="result.minute.rangeStart" :min="1" :max="60"></a-input-number>
  66 + 到
  67 + <a-input-number size="small" v-model="result.minute.rangeEnd" :min="0" :max="59"></a-input-number>
  68 + 分
  69 + </a-radio>
  70 + </a-row>
  71 + </a-radio-group>
  72 + </div>
  73 + </a-tab-pane>
  74 + <a-tab-pane key="3">
  75 + <span slot="tab"><a-icon type="schedule" /> 时</span>
  76 + <div class="tabBody">
  77 + <a-radio-group v-model="result.hour.cronEvery">
  78 + <a-row>
  79 + <a-radio value="1">每一小时</a-radio>
  80 + </a-row>
  81 + <a-row>
  82 + <a-radio value="2">每隔
  83 + <a-input-number size="small" v-model="result.hour.incrementIncrement" :min="0" :max="23"></a-input-number>
  84 + 小时执行 从
  85 + <a-input-number size="small" v-model="result.hour.incrementStart" :min="0" :max="23"></a-input-number>
  86 + 小时开始
  87 + </a-radio>
  88 + </a-row>
  89 + <a-row>
  90 + <a-radio class="long" value="3">具体小时数(可多选)</a-radio>
  91 + <a-select style="width:340px;" size="small" mode="multiple" v-model="result.hour.specificSpecific">
  92 + <a-select-option v-for="(val,index) in Array(24)" :key="index" >{{ index }}</a-select-option>
  93 + </a-select>
  94 + </a-row>
  95 + <a-row>
  96 + <a-radio value="4">周期从
  97 + <a-input-number size="small" v-model="result.hour.rangeStart" :min="0" :max="23"></a-input-number>
  98 + 到
  99 + <a-input-number size="small" v-model="result.hour.rangeEnd" :min="0" :max="23"></a-input-number>
  100 + 小时
  101 + </a-radio>
  102 + </a-row>
  103 + </a-radio-group>
  104 + </div>
  105 + </a-tab-pane>
  106 + <a-tab-pane key="4">
  107 + <span slot="tab"><a-icon type="schedule" /> 天</span>
  108 + <div class="tabBody">
  109 + <a-radio-group v-model="result.day.cronEvery">
  110 + <a-row>
  111 + <a-radio value="1">每一天</a-radio>
  112 + </a-row>
  113 + <a-row>
  114 + <a-radio value="2">每隔
  115 + <a-input-number size="small" v-model="result.week.incrementIncrement" :min="1" :max="7"></a-input-number>
  116 + 周执行 从
  117 + <a-select size="small" v-model="result.week.incrementStart">
  118 + <a-select-option v-for="(val,index) in Array(7)" :key="index" :value="index+1">{{ weekDays[index] }}</a-select-option>
  119 + </a-select>
  120 + 开始
  121 + </a-radio>
  122 + </a-row>
  123 + <a-row>
  124 + <a-radio value="3">每隔
  125 + <a-input-number size="small" v-model="result.day.incrementIncrement" :min="1" :max="31"></a-input-number>
  126 + 天执行 从
  127 + <a-input-number size="small" v-model="result.day.incrementStart" :min="1" :max="31"></a-input-number>
  128 + 天开始
  129 + </a-radio>
  130 + </a-row>
  131 + <a-row>
  132 + <a-radio class="long" value="4">具体星期几(可多选)</a-radio>
  133 + <a-select style="width:340px;" size="small" mode="multiple" v-model="result.week.specificSpecific">
  134 + <a-select-option v-for="(val,index) in Array(7)" :key="index" :value="index+1">{{ weekDays[index] }}</a-select-option>
  135 + </a-select>
  136 + </a-row>
  137 + <a-row>
  138 + <a-radio class="long" value="5">具体天数(可多选)</a-radio>
  139 + <a-select style="width:354px;" size="small" mode="multiple" v-model="result.day.specificSpecific">
  140 + <a-select-option v-for="(val,index) in Array(31)" :key="index" :value="index+1">{{ index+1 }}</a-select-option>
  141 + </a-select>
  142 + </a-row>
  143 + <a-row>
  144 + <a-radio value="6">在这个月的最后一天</a-radio>
  145 + </a-row>
  146 + <a-row>
  147 + <a-radio value="7">在这个月的最后一个工作日</a-radio>
  148 + </a-row>
  149 + <a-row>
  150 + <a-radio value="8">在这个月的最后一个
  151 + <a-select size="small" v-model="result.day.cronLastSpecificDomDay">
  152 + <a-select-option v-for="(val,index) in Array(7)" :key="index" :value="index+1">{{ weekDays[index] }}</a-select-option>
  153 + </a-select>
  154 + </a-radio>
  155 + </a-row>
  156 + <a-row>
  157 + <a-radio value="9">
  158 + 在本月底前
  159 + <a-input-number size="small" v-model="result.day.cronDaysBeforeEomMinus" :min="1" :max="31"></a-input-number>
  160 + 天
  161 + </a-radio>
  162 + </a-row>
  163 + <a-row>
  164 + <a-radio value="10">最近的工作日(周一至周五)至本月
  165 + <a-input-number size="small" v-model="result.day.cronDaysNearestWeekday" :min="1" :max="31"></a-input-number>
  166 + 日
  167 + </a-radio>
  168 + </a-row>
  169 + <a-row>
  170 + <a-radio value="11">在这个月的第
  171 + <a-input-number size="small" v-model="result.week.cronNthDayNth" :min="1" :max="5"></a-input-number>
  172 + 个
  173 + <a-select size="small" v-model="result.week.cronNthDayDay">
  174 + <a-select-option v-for="(val,index) in Array(7)" :key="index" :value="index+1">{{ weekDays[index] }}</a-select-option>
  175 + </a-select>
  176 +
  177 + </a-radio>
  178 + </a-row>
  179 + </a-radio-group>
  180 + </div>
  181 + </a-tab-pane>
  182 + <a-tab-pane key="5">
  183 + <span slot="tab"><a-icon type="schedule" /> 月</span>
  184 + <div class="tabBody">
  185 + <a-radio-group v-model="result.month.cronEvery">
  186 + <a-row>
  187 + <a-radio value="1">每一月</a-radio>
  188 + </a-row>
  189 + <a-row>
  190 + <a-radio value="2">每隔
  191 + <a-input-number size="small" v-model="result.month.incrementIncrement" :min="0" :max="12"></a-input-number>
  192 + 月执行 从
  193 + <a-input-number size="small" v-model="result.month.incrementStart" :min="0" :max="12"></a-input-number>
  194 + 月开始
  195 + </a-radio>
  196 + </a-row>
  197 + <a-row>
  198 + <a-radio class="long" value="3">具体月数(可多选)</a-radio>
  199 + <a-select style="width:354px;" size="small" filterable mode="multiple" v-model="result.month.specificSpecific">
  200 + <a-select-option v-for="(val,index) in Array(12)" :key="index" :value="index+1">{{ index+1 }}</a-select-option>
  201 + </a-select>
  202 + </a-row>
  203 + <a-row>
  204 + <a-radio value="4">从
  205 + <a-input-number size="small" v-model="result.month.rangeStart" :min="1" :max="12"></a-input-number>
  206 + 到
  207 + <a-input-number size="small" v-model="result.month.rangeEnd" :min="1" :max="12"></a-input-number>
  208 + 月之间的每个月
  209 + </a-radio>
  210 + </a-row>
  211 + </a-radio-group>
  212 + </div>
  213 + </a-tab-pane>
  214 + <a-tab-pane key="6">
  215 + <span slot="tab"><a-icon type="schedule" /> 年</span>
  216 + <div class="tabBody">
  217 + <a-radio-group v-model="result.year.cronEvery">
  218 + <a-row>
  219 + <a-radio value="1">每一年</a-radio>
  220 + </a-row>
  221 + <a-row>
  222 + <a-radio value="2">每隔
  223 + <a-input-number size="small" v-model="result.year.incrementIncrement" :min="1" :max="99"></a-input-number>
  224 + 年执行 从
  225 + <a-input-number size="small" v-model="result.year.incrementStart" :min="2019" :max="2119"></a-input-number>
  226 + 年开始
  227 + </a-radio>
  228 + </a-row>
  229 + <a-row>
  230 + <a-radio class="long" value="3">具体年份(可多选)</a-radio>
  231 + <a-select style="width:354px;" size="small" filterable mode="multiple" v-model="result.year.specificSpecific">
  232 + <a-select-option v-for="(val,index) in Array(100)" :key="index" :value="2019+index">{{ 2019+index }}</a-select-option>
  233 + </a-select>
  234 + </a-row>
  235 + <a-row>
  236 + <a-radio value="4">从
  237 + <a-input-number size="small" v-model="result.year.rangeStart" :min="2019" :max="2119"></a-input-number>
  238 + 到
  239 + <a-input-number size="small" v-model="result.year.rangeEnd" :min="2019" :max="2119"></a-input-number>
  240 + 年之间的每一年
  241 + </a-radio>
  242 + </a-row>
  243 + </a-radio-group>
  244 + </div>
  245 + </a-tab-pane>
  246 + </a-tabs>
  247 + <div class="bottom">
  248 + <span class="value">{{this.cron }}</span>
  249 + </div>
  250 + </div>
  251 + </a-modal>
  252 +</template>
  253 +<script>
  254 + export default {
  255 + name:'VueCron',
  256 + props:['data'],
  257 + data(){
  258 + return {
  259 + visible: false,
  260 + confirmLoading:false,
  261 + size:'large',
  262 + weekDays:['天','一','二','三','四','五','六'].map(val=>'星期'+val),
  263 + result: {
  264 + second:{},
  265 + minute:{},
  266 + hour:{},
  267 + day:{},
  268 + week:{},
  269 + month:{},
  270 + year:{}
  271 + },
  272 + defaultValue: {
  273 + second:{
  274 + cronEvery:'',
  275 + incrementStart:3,
  276 + incrementIncrement:5,
  277 + rangeStart:1,
  278 + rangeEnd:0,
  279 + specificSpecific:[],
  280 + },
  281 + minute:{
  282 + cronEvery:'',
  283 + incrementStart:3,
  284 + incrementIncrement:5,
  285 + rangeStart:1,
  286 + rangeEnd:'0',
  287 + specificSpecific:[],
  288 + },
  289 + hour:{
  290 + cronEvery:'',
  291 + incrementStart:3,
  292 + incrementIncrement:5,
  293 + rangeStart:'0',
  294 + rangeEnd:'0',
  295 + specificSpecific:[],
  296 + },
  297 + day:{
  298 + cronEvery:'',
  299 + incrementStart:1,
  300 + incrementIncrement:'1',
  301 + rangeStart:'',
  302 + rangeEnd:'',
  303 + specificSpecific:[],
  304 + cronLastSpecificDomDay:1,
  305 + cronDaysBeforeEomMinus:1,
  306 + cronDaysNearestWeekday:1,
  307 + },
  308 + week:{
  309 + cronEvery:'',
  310 + incrementStart:1,
  311 + incrementIncrement:1,
  312 + specificSpecific:[],
  313 + cronNthDayDay:1,
  314 + cronNthDayNth:1,
  315 + },
  316 + month:{
  317 + cronEvery:'',
  318 + incrementStart:3,
  319 + incrementIncrement:5,
  320 + rangeStart:1,
  321 + rangeEnd:1,
  322 + specificSpecific:[],
  323 + },
  324 + year:{
  325 + cronEvery:'',
  326 + incrementStart:2017,
  327 + incrementIncrement:1,
  328 + rangeStart:2019,
  329 + rangeEnd: 2019,
  330 + specificSpecific:[],
  331 + },
  332 + label:''
  333 + }
  334 + }
  335 + },
  336 + computed: {
  337 + modalWidth(){
  338 + return 608;
  339 + },
  340 + secondsText() {
  341 + let seconds = '';
  342 + let cronEvery=this.result.second.cronEvery||'';
  343 + switch (cronEvery.toString()){
  344 + case '1':
  345 + seconds = '*';
  346 + break;
  347 + case '2':
  348 + seconds = this.result.second.incrementStart+'/'+this.result.second.incrementIncrement;
  349 + break;
  350 + case '3':
  351 + this.result.second.specificSpecific.map(val=> {seconds += val+','});
  352 + seconds = seconds.slice(0, -1);
  353 + break;
  354 + case '4':
  355 + seconds = this.result.second.rangeStart+'-'+this.result.second.rangeEnd;
  356 + break;
  357 + }
  358 + return seconds;
  359 + },
  360 + minutesText() {
  361 + let minutes = '';
  362 + let cronEvery=this.result.minute.cronEvery||'';
  363 + switch (cronEvery.toString()){
  364 + case '1':
  365 + minutes = '*';
  366 + break;
  367 + case '2':
  368 + minutes = this.result.minute.incrementStart+'/'+this.result.minute.incrementIncrement;
  369 + break;
  370 + case '3':
  371 + this.result.minute.specificSpecific.map(val=> {
  372 + minutes += val+','
  373 + });
  374 + minutes = minutes.slice(0, -1);
  375 + break;
  376 + case '4':
  377 + minutes = this.result.minute.rangeStart+'-'+this.result.minute.rangeEnd;
  378 + break;
  379 + }
  380 + return minutes;
  381 + },
  382 + hoursText() {
  383 + let hours = '';
  384 + let cronEvery=this.result.hour.cronEvery||'';
  385 + switch (cronEvery.toString()){
  386 + case '1':
  387 + hours = '*';
  388 + break;
  389 + case '2':
  390 + hours = this.result.hour.incrementStart+'/'+this.result.hour.incrementIncrement;
  391 + break;
  392 + case '3':
  393 + this.result.hour.specificSpecific.map(val=> {
  394 + hours += val+','
  395 + });
  396 + hours = hours.slice(0, -1);
  397 + break;
  398 + case '4':
  399 + hours = this.result.hour.rangeStart+'-'+this.result.hour.rangeEnd;
  400 + break;
  401 + }
  402 + return hours;
  403 + },
  404 + daysText() {
  405 + let days='';
  406 + let cronEvery=this.result.day.cronEvery||'';
  407 + switch (cronEvery.toString()){
  408 + case '1':
  409 + break;
  410 + case '2':
  411 + case '4':
  412 + case '11':
  413 + days = '?';
  414 + break;
  415 + case '3':
  416 + days = this.result.day.incrementStart+'/'+this.result.day.incrementIncrement;
  417 + break;
  418 + case '5':
  419 + this.result.day.specificSpecific.map(val=> {
  420 + days += val+','
  421 + });
  422 + days = days.slice(0, -1);
  423 + break;
  424 + case '6':
  425 + days = "L";
  426 + break;
  427 + case '7':
  428 + days = "LW";
  429 + break;
  430 + case '8':
  431 + days = this.result.day.cronLastSpecificDomDay + 'L';
  432 + break;
  433 + case '9':
  434 + days = 'L-' + this.result.day.cronDaysBeforeEomMinus;
  435 + break;
  436 + case '10':
  437 + days = this.result.day.cronDaysNearestWeekday+"W";
  438 + break
  439 + }
  440 + return days;
  441 + },
  442 + weeksText() {
  443 + let weeks = '';
  444 + let cronEvery=this.result.day.cronEvery||'';
  445 + switch (cronEvery.toString()){
  446 + case '1':
  447 + case '3':
  448 + case '5':
  449 + weeks = '?';
  450 + break;
  451 + case '2':
  452 + weeks = this.result.week.incrementStart+'/'+this.result.week.incrementIncrement;
  453 + break;
  454 + case '4':
  455 + this.result.week.specificSpecific.map(val=> {
  456 + weeks += val+','
  457 + });
  458 + weeks = weeks.slice(0, -1);
  459 + break;
  460 + case '6':
  461 + case '7':
  462 + case '8':
  463 + case '9':
  464 + case '10':
  465 + weeks = "?";
  466 + break;
  467 + case '11':
  468 + weeks = this.result.week.cronNthDayDay+"#"+this.result.week.cronNthDayNth;
  469 + break;
  470 + }
  471 + return weeks;
  472 + },
  473 + monthsText() {
  474 + let months = '';
  475 + let cronEvery=this.result.month.cronEvery||'';
  476 + switch (cronEvery.toString()){
  477 + case '1':
  478 + months = '*';
  479 + break;
  480 + case '2':
  481 + months = this.result.month.incrementStart+'/'+this.result.month.incrementIncrement;
  482 + break;
  483 + case '3':
  484 + this.result.month.specificSpecific.map(val=> {
  485 + months += val+','
  486 + });
  487 + months = months.slice(0, -1);
  488 + break;
  489 + case '4':
  490 + months = this.result.month.rangeStart+'-'+this.result.month.rangeEnd;
  491 + break;
  492 + }
  493 + return months;
  494 + },
  495 + yearsText() {
  496 + let years = '';
  497 + let cronEvery=this.result.year.cronEvery||'';
  498 + switch (cronEvery.toString()){
  499 + case '1':
  500 + years = '*';
  501 + break;
  502 + case '2':
  503 + years = this.result.year.incrementStart+'/'+this.result.year.incrementIncrement;
  504 + break;
  505 + case '3':
  506 + this.result.year.specificSpecific.map(val=> {
  507 + years += val+','
  508 + });
  509 + years = years.slice(0, -1);
  510 + break;
  511 + case '4':
  512 + years = this.result.year.rangeStart+'-'+this.result.year.rangeEnd;
  513 + break;
  514 + }
  515 + return years;
  516 + },
  517 + cron(){
  518 + return `${this.secondsText||'*'} ${this.minutesText||'*'} ${this.hoursText||'*'} ${this.daysText||'*'} ${this.monthsText||'*'} ${this.weeksText||'?'} ${this.yearsText||'*'}`
  519 + },
  520 + },
  521 + watch:{
  522 + visible:{
  523 + handler() {
  524 + // if(this.data){
  525 + // //this. result = Object.keys(this.data.value).length>0?this.deepCopy(this.data.value):this.deepCopy(this.defaultValue);
  526 + // //this.result = Object.keys(this.data.value).length>0?clone(this.data.value):clone(this.defaultValue);
  527 + // //this.result = Object.keys(this.data.value).length>0?clone(JSON.parse(this.data.value)):clone(this.defaultValue);
  528 + // this.result = Object.keys(this.data.value).length>0?JSON.parse(this.data.value):JSON.parse(JSON.stringify(this.defaultValue));
  529 + // }else{
  530 + // //this.result = this.deepCopy(this.defaultValue);
  531 + // //this.result = clone(this.defaultValue);
  532 + // this.result = JSON.parse(JSON.stringify(this.defaultValue));
  533 + // }
  534 + let label = this.data;
  535 + if(label){
  536 + this.secondsReverseExp(label)
  537 + this.minutesReverseExp(label);
  538 + this.hoursReverseExp(label);
  539 + this.daysReverseExp(label);
  540 + this.daysReverseExp(label);
  541 + this.monthsReverseExp(label);
  542 + this.yearReverseExp(label);
  543 + JSON.parse(JSON.stringify(label));
  544 + }else {
  545 + this.result = JSON.parse(JSON.stringify(this.defaultValue));
  546 + }
  547 + }
  548 + }
  549 + },
  550 + methods: {
  551 + show(){
  552 + this.visible = true;
  553 + // console.log('secondsReverseExp',this.secondsReverseExp(this.data));
  554 + // console.log('minutesReverseExp',this.minutesReverseExp(this.data));
  555 + // console.log('hoursReverseExp',this.hoursReverseExp(this.data));
  556 + // console.log('daysReverseExp',this.daysReverseExp(this.data));
  557 + // console.log('monthsReverseExp',this.monthsReverseExp(this.data));
  558 + // console.log('yearReverseExp',this.yearReverseExp(this.data));
  559 +
  560 + },
  561 + handleSubmit(){
  562 + this.$emit('ok',this.cron);
  563 + this.close();
  564 + this.visible = false;
  565 + },
  566 + close(){
  567 + this.visible = false;
  568 + },
  569 + secondsReverseExp(seconds) {
  570 + let val = seconds.split(" ")[0];
  571 + //alert(val);
  572 + let second = {
  573 + cronEvery:'',
  574 + incrementStart:3,
  575 + incrementIncrement:5,
  576 + rangeStart:1,
  577 + rangeEnd:0,
  578 + specificSpecific:[]
  579 + };
  580 + switch (true) {
  581 + case val.includes('*'):
  582 + second.cronEvery = '1';
  583 + break;
  584 + case val.includes('/'):
  585 + second.cronEvery = '2';
  586 + second.incrementStart = val.split('/')[0];
  587 + second.incrementIncrement = val.split('/')[1];
  588 + break;
  589 + case val.includes(','):
  590 + second.cronEvery = '3';
  591 + second.specificSpecific = val.split(',').map(Number).sort();
  592 + break;
  593 + case val.includes('-'):
  594 + second.cronEvery = '4';
  595 + second.rangeStart = val.split('-')[0];
  596 + second.rangeEnd = val.split('-')[1];
  597 + break;
  598 + default:
  599 + second.cronEvery = '1';
  600 + }
  601 + this.result.second = second;
  602 + },
  603 + minutesReverseExp(minutes) {
  604 + let val = minutes.split(" ")[1];
  605 + let minute = {
  606 + cronEvery:'',
  607 + incrementStart:3,
  608 + incrementIncrement:5,
  609 + rangeStart:1,
  610 + rangeEnd:0,
  611 + specificSpecific:[],
  612 + }
  613 + switch (true) {
  614 + case val.includes('*'):
  615 + minute.cronEvery = '1';
  616 + break;
  617 + case val.includes('/'):
  618 + minute.cronEvery = '2';
  619 + minute.incrementStart = val.split('/')[0];
  620 + minute.incrementIncrement = val.split('/')[1];
  621 + break;
  622 + case val.includes(','):
  623 + minute.cronEvery = '3';
  624 + minute.specificSpecific = val.split(',').map(Number).sort();
  625 + break;
  626 + case val.includes('-'):
  627 + minute.cronEvery = '4';
  628 + minute.rangeStart = val.split('-')[0];
  629 + minute.rangeEnd = val.split('-')[1];
  630 + break;
  631 + default:
  632 + minute.cronEvery = '1';
  633 + }
  634 + this.result.minute = minute;
  635 + },
  636 + hoursReverseExp(hours) {
  637 + let val = hours.split(" ")[2];
  638 + let hour ={
  639 + cronEvery:'',
  640 + incrementStart:3,
  641 + incrementIncrement:5,
  642 + rangeStart:1,
  643 + rangeEnd:'0',
  644 + specificSpecific:[],
  645 + };
  646 + switch (true) {
  647 + case val.includes('*'):
  648 + hour.cronEvery = '1';
  649 + break;
  650 + case val.includes('/'):
  651 + hour.cronEvery = '2';
  652 + hour.incrementStart = val.split('/')[0];
  653 + hour.incrementIncrement = val.split('/')[1];
  654 + break;
  655 + case val.includes(','):
  656 + hour.cronEvery = '3';
  657 + hour.specificSpecific = val.split(',').map(Number).sort();
  658 + break;
  659 + case val.includes('-'):
  660 + hour.cronEvery = '4';
  661 + hour.rangeStart = val.split('-')[0];
  662 + hour.rangeEnd = val.split('-')[1];
  663 + break;
  664 + default:
  665 + hour.cronEvery = '1';
  666 + }
  667 + this.result.hour = hour;
  668 + },
  669 + daysReverseExp(cron) {
  670 + let days = cron.split(" ")[3];
  671 + let weeks = cron.split(" ")[5];
  672 + let day ={
  673 + cronEvery:'',
  674 + incrementStart:1,
  675 + incrementIncrement:1,
  676 + rangeStart:1,
  677 + rangeEnd:1,
  678 + specificSpecific:[],
  679 + cronLastSpecificDomDay:1,
  680 + cronDaysBeforeEomMinus:1,
  681 + cronDaysNearestWeekday:1,
  682 + };
  683 + let week = {
  684 + cronEvery:'',
  685 + incrementStart:1,
  686 + incrementIncrement:1,
  687 + specificSpecific:[],
  688 + cronNthDayDay:1,
  689 + cronNthDayNth:'1',
  690 + };
  691 + if (!days.includes('?')) {
  692 + switch (true) {
  693 + case days.includes('*'):
  694 + day.cronEvery = '1';
  695 + break;
  696 + case days.includes('?'):
  697 + // 2、4、11
  698 + break;
  699 + case days.includes('/'):
  700 + day.cronEvery = '3';
  701 + day.incrementStart = days.split('/')[0];
  702 + day.incrementIncrement = days.split('/')[1];
  703 + break;
  704 + case days.includes(','):
  705 + day.cronEvery = '5';
  706 + day.specificSpecific = days.split(',').map(Number).sort();
  707 + // day.specificSpecific.forEach(function (value, index) {
  708 + // day.specificSpecific[index] = value -1;
  709 + // });
  710 + break;
  711 + case days.includes('LW'):
  712 + day.cronEvery = '7';
  713 + break;
  714 + case days.includes('L-'):
  715 + day.cronEvery = '9';
  716 + day.cronDaysBeforeEomMinus = days.split('L-')[1];
  717 + break;
  718 + case days.includes('L'):
  719 +
  720 + //alert(days);
  721 + if(days.len == 1){
  722 + day.cronEvery = '6';
  723 + day.cronLastSpecificDomDay = '1';
  724 + }
  725 + else
  726 + {
  727 + day.cronEvery = '8';
  728 + day.cronLastSpecificDomDay = Number(days.split('L')[0]);
  729 + }
  730 + break;
  731 + case days.includes('W'):
  732 + day.cronEvery = '10';
  733 + day.cronDaysNearestWeekday = days.split('W')[0];
  734 + break;
  735 + default:
  736 + day.cronEvery = '1';
  737 + }
  738 + }else {
  739 + switch (true){
  740 + case weeks.includes('/'):
  741 + day.cronEvery = '2';
  742 + week.incrementStart = weeks.split("/")[0];
  743 + week.incrementIncrement = weeks.split("/")[1];
  744 + break;
  745 + case weeks.includes(','):
  746 + day.cronEvery = '4';
  747 + week.specificSpecific = weeks.split(',').map(Number).sort();
  748 + break;
  749 + case '#':
  750 + day.cronEvery = '11';
  751 + week.cronNthDayDay = weeks.split("#")[0];
  752 + week.cronNthDayNth = weeks.split("#")[1];
  753 + break;
  754 + default:
  755 + day.cronEvery = '1';
  756 + week.cronEvery = '1';
  757 + }
  758 + }
  759 + this.result.day = day;
  760 + this.result.week = week;
  761 + },
  762 + monthsReverseExp(cron) {
  763 + let months = cron.split(" ")[4];
  764 + let month = {
  765 + cronEvery:'',
  766 + incrementStart:3,
  767 + incrementIncrement:5,
  768 + rangeStart:1,
  769 + rangeEnd:1,
  770 + specificSpecific:[],
  771 + };
  772 + switch (true){
  773 + case months.includes('*'):
  774 + month.cronEvery = '1';
  775 + break;
  776 + case months.includes('/'):
  777 + month.cronEvery = '2';
  778 + month.incrementStart = months.split('/')[0];
  779 + month.incrementIncrement = months.split('/')[1];
  780 + break;
  781 + case months.includes(','):
  782 + month.cronEvery = '3';
  783 + month.specificSpecific = months.split(',').map(Number).sort();
  784 + break;
  785 + case months.includes('-'):
  786 + month.cronEvery = '4';
  787 + month.rangeStart = months.split('-')[0];
  788 + month.rangeEnd = months.split('-')[1];
  789 + break;
  790 + default:
  791 + month.cronEvery = '1';
  792 + }
  793 + this.result.month = month;
  794 + },
  795 + yearReverseExp(cron) {
  796 + let years = cron.split(" ")[6];
  797 + let year = {
  798 + cronEvery:'',
  799 + incrementStart:3,
  800 + incrementIncrement:5,
  801 + rangeStart:2019,
  802 + rangeEnd:2019,
  803 + specificSpecific:[],
  804 + };
  805 + switch (true){
  806 + case years.includes('*'):
  807 + year.cronEvery = '1';
  808 + break;
  809 + case years.includes('/'):
  810 + year.cronEvery = '2';
  811 + year.incrementStart = years.split('/')[0];
  812 + year.incrementIncrement = years.split('/')[1];
  813 + break;
  814 + case years.includes(','):
  815 + year.cronEvery = '3';
  816 + year.specificSpecific = years.split(',').map(Number).sort();
  817 + break;
  818 + case years.includes('-'):
  819 + year.cronEvery = '4';
  820 + year.rangeStart = years.split('-')[0];
  821 + year.rangeEnd = years.split('-')[1];
  822 + break;
  823 + default:
  824 + year.cronEvery = '1';
  825 + }
  826 + this.result.year = year;
  827 + }
  828 + }
  829 + }
  830 +</script>
  831 +
  832 +<style lang="scss">
  833 + .card-container {
  834 + background: #fff;
  835 + overflow: hidden;
  836 + padding: 12px;
  837 + position: relative;
  838 + width: 100%;
  839 + .ant-tabs{
  840 + border:1px solid #e6ebf5;
  841 + padding: 0;
  842 + .ant-tabs-bar {
  843 + margin: 0;
  844 + outline: none;
  845 + border-bottom: none;
  846 + .ant-tabs-nav-container{
  847 + margin: 0;
  848 + .ant-tabs-tab {
  849 + padding: 0 24px!important;
  850 + background-color: #f5f7fa!important;
  851 + margin-right: 0px!important;
  852 + border-radius: 0;
  853 + line-height: 38px;
  854 + border: 1px solid transparent!important;
  855 + border-bottom: 1px solid #e6ebf5!important;
  856 + }
  857 + .ant-tabs-tab-active.ant-tabs-tab{
  858 + color: #409eff;
  859 + background-color: #fff!important;
  860 + border-right:1px solid #e6ebf5!important;
  861 + border-left:1px solid #e6ebf5!important;
  862 + border-bottom:1px solid #fff!important;
  863 + font-weight: normal;
  864 + transition:none!important;
  865 + }
  866 + }
  867 + }
  868 + .ant-tabs-tabpane{
  869 + padding: 15px;
  870 + .ant-row{
  871 + margin: 10px 0;
  872 + }
  873 + .ant-select,.ant-input-number{
  874 + width: 100px;
  875 + }
  876 + }
  877 + }
  878 + }
  879 +</style>
  880 +<style lang="scss" scoped>
  881 + .container-widthEn{
  882 + width: 755px;
  883 + }
  884 + .container-widthCn{
  885 + width: 608px;
  886 + }
  887 + .language{
  888 + text-align: center;
  889 + position: absolute;
  890 + right: 13px;
  891 + top: 13px;
  892 + border: 1px solid transparent;
  893 + height: 40px;
  894 + line-height: 38px;
  895 + font-size: 16px;
  896 + color: #409eff;
  897 + z-index: 1;
  898 + background: #f5f7fa;
  899 + outline: none;
  900 + width: 47px;
  901 + border-bottom: 1px solid #e6ebf5;
  902 + border-radius: 0;
  903 + }
  904 + .card-container{
  905 + .bottom{
  906 + display: flex;
  907 + justify-content: center;
  908 + padding: 10px 0 0 0;
  909 + .cronButton{
  910 + margin: 0 10px;
  911 + line-height: 40px;
  912 + }
  913 + }
  914 + }
  915 + .tabBody{
  916 + .a-row{
  917 + margin: 10px 0;
  918 + .long{
  919 + .a-select{
  920 + width:354px;
  921 + }
  922 + }
  923 + .a-input-number{
  924 + width: 110px;
  925 + }
  926 + }
  927 + }
  928 +</style>
... ...
ant-design-vue-jeecg/src/components/jeecgbiz/modal/JSelectDepartModal.vue
... ... @@ -58,6 +58,16 @@
58 58 watch:{
59 59 departId(){
60 60 this.initDepartComponent()
  61 + },
  62 + visible: {
  63 + handler() {
  64 + if (this.departId) {
  65 + this.checkedKeys = this.departId.split(",");
  66 + console.log('this.departId', this.departId)
  67 + } else {
  68 + this.checkedKeys = [];
  69 + }
  70 + }
61 71 }
62 72 },
63 73 methods:{
... ...
ant-design-vue-jeecg/src/components/menu/SideMenu.vue
... ... @@ -148,11 +148,28 @@
148 148 <style lang="scss">
149 149 .ant-menu.ant-menu-root {
150 150 & > .ant-menu-item:first-child {
151   - background-color: white;
  151 + background-color: transparent;
152 152  
153 153 & > a, & > a:hover {
154 154 color: rgba(0, 0, 0, 0.65);
  155 + }
  156 +
  157 + &.ant-menu-item-selected {
  158 + & > a, & > a:hover {
  159 + color: #1890ff;
  160 + }
  161 + }
  162 + }
155 163  
  164 + &.ant-menu-dark > .ant-menu-item:first-child {
  165 + & > a, & > a:hover {
  166 + color: rgba(255, 255, 255, 0.65);
  167 + }
  168 +
  169 + &.ant-menu-item-selected {
  170 + & > a, & > a:hover {
  171 + color: rgba(255, 255, 255, 1);
  172 + }
156 173 }
157 174 }
158 175 }
... ...
ant-design-vue-jeecg/src/components/setting/SettingDrawer.vue
... ... @@ -153,9 +153,10 @@
153 153 </a-alert>
154 154 </div>
155 155 </div>
156   - <div class="setting-drawer-index-handle" @click="toggle">
157   - <a-icon type="setting" v-if="!visible"/>
158   - <a-icon type="close" v-else/>
  156 + <div class="setting-drawer-index-handle" @click="toggle" v-if="visible">
  157 +<!-- <a-icon type="setting" v-if="!visible"/>-->
  158 +<!-- <a-icon type="close" v-else/>-->
  159 + <a-icon type="close" />
159 160 </div>
160 161 </a-drawer>
161 162 </div>
... ...
ant-design-vue-jeecg/src/components/tools/DepartSelect.vue
1 1 <template>
2 2 <a-modal
3   - :title="title"
  3 + :title="currTitle"
4 4 :width="450"
5 5 :visible="visible"
6 6 :closable="false"
... ... @@ -41,6 +41,9 @@
41 41  
42 42 <script>
43 43 import { getAction,putAction } from '@/api/manage'
  44 + import Vue from 'vue'
  45 + import store from '@/store/'
  46 + import { USER_INFO } from "@/store/mutation-types"
44 47  
45 48 export default {
46 49 name: 'DepartSelect',
... ... @@ -70,6 +73,7 @@
70 73 },
71 74 data(){
72 75 return {
  76 + currTitle:this.title,
73 77 visible:false,
74 78 departList:[],
75 79 departSelected:"",
... ... @@ -100,7 +104,7 @@
100 104 this.departSelected = orgCode
101 105 this.departList = departs
102 106 if(this.currDepartName){
103   - this.title ="部门切换(当前部门 : "+this.currDepartName+")"
  107 + this.currTitle ="部门切换(当前部门 : "+this.currDepartName+")"
104 108 }
105 109  
106 110 }
... ... @@ -122,6 +126,10 @@
122 126 }
123 127 putAction("/sys/selectDepart",obj).then(res=>{
124 128 if(res.success){
  129 + const userInfo = res.result.userInfo;
  130 + Vue.ls.set(USER_INFO, userInfo, 7 * 24 * 60 * 60 * 1000);
  131 + store.commit('SET_INFO', userInfo);
  132 + //console.log("---切换组织机构---userInfo-------",store.getters.userInfo.orgCode);
125 133 this.departClear()
126 134 }
127 135 })
... ...
ant-design-vue-jeecg/src/components/tools/HeaderNotice.vue
... ... @@ -78,6 +78,7 @@
78 78 <script>
79 79 import { getAction,putAction } from '@/api/manage'
80 80 import ShowAnnouncement from './ShowAnnouncement'
  81 + import store from '@/store/'
81 82  
82 83 export default {
83 84 name: "HeaderNotice",
... ... @@ -89,7 +90,8 @@
89 90 loadding: false,
90 91 url:{
91 92 listCementByUser:"/sys/annountCement/listByUser",
92   - editCementSend:"/system/sysAnnouncementSend/editByAnntIdAndUserId",
  93 + editCementSend:"/sys/sysAnnouncementSend/editByAnntIdAndUserId",
  94 + queryById:"/sys/annountCement/queryById",
93 95 },
94 96 hovered: false,
95 97 announcement1:[],
... ... @@ -98,6 +100,7 @@
98 100 msg2Count:"0",
99 101 msg1Title:"通知(3)",
100 102 msg2Title:"",
  103 + stopTimer:false,
101 104 }
102 105 },
103 106 computed:{
... ... @@ -105,15 +108,25 @@
105 108 return parseInt(this.msg1Count)+parseInt(this.msg2Count);
106 109 }
107 110 },
108   - created() {
  111 + mounted() {
109 112 this.loadData();
110   - this.timer();
  113 + //this.timerFun();
  114 + this.initWebSocket();
  115 + },
  116 + destroyed: function () { // 离开页面生命周期函数
  117 + this.websocketclose();
111 118 },
112 119 methods: {
113   - timer() {
114   - return setInterval(()=>{
  120 + timerFun() {
  121 + this.stopTimer = false;
  122 + let myTimer = setInterval(()=>{
  123 + // 停止定时器
  124 + if (this.stopTimer == true) {
  125 + clearInterval(myTimer);
  126 + return;
  127 + }
115 128 this.loadData()
116   - },60000)
  129 + },6000)
117 130 },
118 131 loadData (){
119 132 try {
... ... @@ -127,8 +140,14 @@
127 140 this.msg2Count = res.result.sysMsgTotal;
128 141 this.msg2Title = "系统消息(" + res.result.sysMsgTotal + ")";
129 142 }
  143 + }).catch(error => {
  144 + console.log("系统消息通知异常",error);//这行打印permissionName is undefined
  145 + this.stopTimer = true;
  146 + console.log("清理timer");
130 147 });
131 148 } catch (err) {
  149 + this.stopTimer = true;
  150 + console.log("通知异常",err);
132 151 }
133 152 },
134 153 fetchNotice () {
... ... @@ -163,6 +182,74 @@
163 182 this.hovered = visible;
164 183 },
165 184  
  185 + initWebSocket: function () {
  186 + // WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
  187 + var userId = store.getters.userInfo.id;
  188 + var url = window._CONFIG['domianURL'].replace("https://","wss://").replace("http://","ws://")+"/websocket/"+userId;
  189 + //console.log(url);
  190 + this.websock = new WebSocket(url);
  191 + this.websock.onopen = this.websocketonopen;
  192 + this.websock.onerror = this.websocketonerror;
  193 + this.websock.onmessage = this.websocketonmessage;
  194 + this.websock.onclose = this.websocketclose;
  195 + },
  196 + websocketonopen: function () {
  197 + console.log("WebSocket连接成功");
  198 + },
  199 + websocketonerror: function (e) {
  200 + console.log("WebSocket连接发生错误");
  201 + },
  202 + websocketonmessage: function (e) {
  203 + console.log("-----接收消息-------",e.data);
  204 + var data = eval("(" + e.data + ")"); //解析对象
  205 + this.loadData();
  206 + //if(data.cmd == "topic"){
  207 + //系统通知
  208 + this.openNotification(data);
  209 + //}else if(data.cmd == "user"){
  210 + //用户消息
  211 + // this.openNotification(data);
  212 + //}
  213 +
  214 +
  215 + },
  216 + websocketclose: function (e) {
  217 + console.log("connection closed (" + e.code + ")");
  218 + },
  219 +
  220 + openNotification (data) {
  221 + var text = data.msgTxt;
  222 + const key = `open${Date.now()}`;
  223 + this.$notification.open({
  224 + message: '消息提醒',
  225 + placement:'bottomRight',
  226 + description: text,
  227 + key,
  228 + btn: (h)=>{
  229 + return h('a-button', {
  230 + props: {
  231 + type: 'primary',
  232 + size: 'small',
  233 + },
  234 + on: {
  235 + click: () => this.showDetail(key,data)
  236 + }
  237 + }, '查看详情')
  238 + },
  239 + });
  240 + },
  241 +
  242 + showDetail(key,data){
  243 + this.$notification.close(key);
  244 + var id = data.msgId;
  245 + getAction(this.url.queryById,{id:id}).then((res) => {
  246 + if (res.success) {
  247 + var record = res.result;
  248 + this.showAnnouncement(record);
  249 + }
  250 + })
  251 +
  252 + },
166 253 }
167 254 }
168 255 </script>
... ...
ant-design-vue-jeecg/src/components/tools/Logo.vue
1 1 <template>
2 2 <div class="logo">
3 3 <router-link :to="{name:'dashboard'}">
4   - <img src="~@/assets/logo.svg" alt="logo">
  4 +
  5 + <!-- update-begin- author:sunjianlei --- date:20190814 --- for: logo颜色根据主题颜色变化 -->
  6 + <img v-if="navTheme === 'dark'" src="~@/assets/logo-white.png" alt="logo">
  7 + <img v-else src="~@/assets/logo.svg" alt="logo">
  8 + <!-- update-begin- author:sunjianlei --- date:20190814 --- for: logo颜色根据主题颜色变化 -->
  9 +
5 10 <h1 v-if="showTitle">{{ title }}</h1>
6 11 </router-link>
7 12 </div>
8 13 </template>
9 14  
10 15 <script>
  16 + import { mixin } from '@/utils/mixin.js'
  17 +
11 18 export default {
12 19 name: 'Logo',
  20 + mixins: [mixin],
13 21 props: {
14 22 title: {
15 23 type: String,
... ...
ant-design-vue-jeecg/src/components/tools/ShowAnnouncement.vue
1 1 <template>
2 2 <a-modal
3   - width="60%"
  3 + class="announcementCustomModal"
  4 + :width="modelStyle.width"
4 5 :visible="visible"
5 6 :bodyStyle ="bodyStyle"
6 7 @cancel="handleCancel"
7 8 destroyOnClose
8 9 :footer="null">
9   -
10   - <a-card style="width: 100%;height: 100%" class="daily-article" :loading="loading">
  10 + <template slot="title">
  11 + <a-button icon="fullscreen" class="custom-btn" @click="handleClickToggleFullScreen"/>
  12 + </template>
  13 + <a-card class="daily-article" :loading="loading">
11 14 <a-card-meta
12 15 :title="record.titile"
13   - :description="'发布人:'+record.sender + ' 发布时间: ' + record.sendTime"/>
  16 + :description="'发布人:'+record.sender + ' 发布时间: ' + record.sendTime">
  17 + </a-card-meta>
14 18 <a-divider />
15 19 <span v-html="record.msgContent" class="article-content"></span>
16 20 </a-card>
17   -
18 21 </a-modal>
19 22 </template>
20 23  
... ... @@ -40,8 +43,14 @@
40 43 bodyStyle:{
41 44 padding: "0",
42 45 height:(window.innerHeight*0.8)+"px",
43   - "overflow-y":"auto"
  46 + "overflow-y":"auto",
  47 +
44 48 },
  49 + modelStyle:{
  50 + width: '60%',
  51 + style: { top: '20px' },
  52 + fullScreen: false
  53 + }
45 54 }
46 55 },
47 56 created () {
... ... @@ -54,33 +63,68 @@
54 63 handleCancel () {
55 64 this.visible = false;
56 65 },
  66 + /** 切换全屏显示 */
  67 + handleClickToggleFullScreen() {
  68 + let mode = !this.modelStyle.fullScreen
  69 + if (mode) {
  70 + this.modelStyle.width = '100%'
  71 + this.modelStyle.style.top = '20px'
  72 + } else {
  73 + this.modelStyle.width = '60%'
  74 + this.modelStyle.style.top = '50px'
  75 + }
  76 + this.modelStyle.fullScreen = mode
  77 + }
57 78 }
58 79 }
59 80 </script>
60 81  
  82 +<style lang="less">
  83 + .announcementCustomModal{
  84 + .ant-modal-header {
  85 + border: none;
  86 + display: inline-block;
  87 + position: absolute;
  88 + z-index: 1;
  89 + right: 56px;
  90 + padding: 0;
  91 + .ant-modal-title{
  92 + .custom-btn{
  93 + width: 56px;
  94 + height: 56px;
  95 + border: none;
  96 + box-shadow: none;
  97 + }
  98 + }
  99 + }
  100 + .daily-article{
  101 + border-bottom: 0;
  102 + }
  103 + }
  104 +</style>
61 105 <style scoped lang="less">
62 106 .daily-article {
63   - .article-button {
64   - font-size: 1.2rem !important;
65   - }
66   - .ant-card-body {
67   - padding: 18px !important;
68   - }
69   - .ant-card-head {
70   - padding: 0 1rem;
71   - }
72   - .ant-card-meta {
73   - margin-bottom: 1rem;
74   - }
75   - .article-content {
76   - p {
77   - word-wrap: break-word;
78   - word-break: break-all;
79   - text-overflow: initial;
80   - white-space: normal;
81   - font-size: .9rem !important;
82   - margin-bottom: .8rem;
83   - }
84   - }
  107 + .article-button {
  108 + font-size: 1.2rem !important;
  109 + }
  110 + .ant-card-body {
  111 + padding: 18px !important;
  112 + }
  113 + .ant-card-head {
  114 + padding: 0 1rem;
  115 + }
  116 + .ant-card-meta {
  117 + margin-bottom: 1rem;
  118 + }
  119 + .article-content {
  120 + p {
  121 + word-wrap: break-word;
  122 + word-break: break-all;
  123 + text-overflow: initial;
  124 + white-space: normal;
  125 + font-size: .9rem !important;
  126 + margin-bottom: .8rem;
  127 + }
  128 + }
85 129 }
86   -</style>
87 130 \ No newline at end of file
  131 +</style>
... ...
ant-design-vue-jeecg/src/components/tools/UserMenu.vue
... ... @@ -24,11 +24,15 @@
24 24 <span>账户设置</span>
25 25 </router-link>
26 26 </a-menu-item>
27   - <a-menu-item key="2" @click="updatePassword">
  27 + <a-menu-item key="3" @click="systemSetting">
  28 + <a-icon type="tool"/>
  29 + <span>系统设置</span>
  30 + </a-menu-item>
  31 + <a-menu-item key="4" @click="updatePassword">
28 32 <a-icon type="setting"/>
29 33 <span>密码修改</span>
30 34 </a-menu-item>
31   - <a-menu-item key="3" @click="updateCurrentDepart">
  35 + <a-menu-item key="5" @click="updateCurrentDepart">
32 36 <a-icon type="cluster"/>
33 37 <span>切换部门</span>
34 38 </a-menu-item>
... ... @@ -53,12 +57,14 @@
53 57 </span>
54 58 <user-password ref="userPassword"></user-password>
55 59 <depart-select ref="departSelect" :closable="true" title="部门切换"></depart-select>
  60 + <setting-drawer ref="settingDrawer" :closable="true" title="系统设置"></setting-drawer>
56 61 </div>
57 62 </template>
58 63  
59 64 <script>
60 65 import HeaderNotice from './HeaderNotice'
61 66 import UserPassword from './UserPassword'
  67 + import SettingDrawer from "@/components/setting/SettingDrawer";
62 68 import DepartSelect from './DepartSelect'
63 69 import { mapActions, mapGetters } from 'vuex'
64 70 import { mixinDevice } from '@/utils/mixin.js'
... ... @@ -69,7 +75,8 @@
69 75 components: {
70 76 HeaderNotice,
71 77 UserPassword,
72   - DepartSelect
  78 + DepartSelect,
  79 + SettingDrawer
73 80 },
74 81 props: {
75 82 theme: {
... ... @@ -112,6 +119,9 @@
112 119 },
113 120 updateCurrentDepart(){
114 121 this.$refs.departSelect.show()
  122 + },
  123 + systemSetting(){
  124 + this.$refs.settingDrawer.showDrawer()
115 125 }
116 126 }
117 127 }
... ...
ant-design-vue-jeecg/src/config/router.config.js
... ... @@ -323,30 +323,6 @@ export const constantRouterMap = [
323 323 ]
324 324 },
325 325  
326   - // {
327   - // path: '/',
328   - // name: 'index',
329   - // component: TabLayout,
330   - // meta: {title: '首页'},
331   - // redirect: '/dashboard/workplace',
332   - // children: [
333   - // {
334   - // path: '/online',
335   - // name: 'online',
336   - // redirect: '/online',
337   - // component: RouteView,
338   - // meta: {title: '在线开发', icon: 'dashboard', permission: ['dashboard']},
339   - // children: [
340   - // {
341   - // path: '/online/auto/:code',
342   - // name: 'report',
343   - // component: () => import('@/views/modules/online/cgreport/OnlCgreportAutoList')
344   - // },
345   - // ]
346   - // },
347   - // ]
348   - // },
349   -
350 326 {
351 327 path: '/test',
352 328 component: BlankLayout,
... ...
ant-design-vue-jeecg/src/main.js
... ... @@ -18,6 +18,9 @@ import VueApexCharts from &#39;vue-apexcharts&#39;
18 18  
19 19 import preview from 'vue-photo-preview'
20 20 import 'vue-photo-preview/dist/skin.css'
  21 +import "@jeecg/antd-onine"
  22 +import '@jeecg/antd-onine/dist/OnlineForm.css'
  23 +
21 24  
22 25 import {
23 26 ACCESS_TOKEN,
... ...
ant-design-vue-jeecg/src/store/modules/user.js
... ... @@ -3,6 +3,7 @@ import { login, logout, phoneLogin } from &quot;@/api/login&quot;
3 3 import { ACCESS_TOKEN, USER_NAME,USER_INFO,USER_AUTH,SYS_BUTTON_AUTH } from "@/store/mutation-types"
4 4 import { welcome } from "@/utils/util"
5 5 import { queryPermissionsByUser } from '@/api/api'
  6 +import { getAction } from '@/api/manage'
6 7  
7 8 const user = {
8 9 state: {
... ... @@ -36,6 +37,30 @@ const user = {
36 37 },
37 38  
38 39 actions: {
  40 + // CAS验证登录
  41 + ValidateLogin({ commit }, userInfo) {
  42 + return new Promise((resolve, reject) => {
  43 + getAction("/cas/client/validateLogin",userInfo).then(response => {
  44 + console.log("----cas 登录--------",response);
  45 + if(response.success){
  46 + const result = response.result
  47 + const userInfo = result.userInfo
  48 + Vue.ls.set(ACCESS_TOKEN, result.token, 7 * 24 * 60 * 60 * 1000)
  49 + Vue.ls.set(USER_NAME, userInfo.username, 7 * 24 * 60 * 60 * 1000)
  50 + Vue.ls.set(USER_INFO, userInfo, 7 * 24 * 60 * 60 * 1000)
  51 + commit('SET_TOKEN', result.token)
  52 + commit('SET_INFO', userInfo)
  53 + commit('SET_NAME', { username: userInfo.username,realname: userInfo.realname, welcome: welcome() })
  54 + commit('SET_AVATAR', userInfo.avatar)
  55 + resolve(response)
  56 + }else{
  57 + resolve(response)
  58 + }
  59 + }).catch(error => {
  60 + reject(error)
  61 + })
  62 + })
  63 + },
39 64 // 登录
40 65 Login({ commit }, userInfo) {
41 66 return new Promise((resolve, reject) => {
... ... @@ -115,6 +140,9 @@ const user = {
115 140 Vue.ls.remove(ACCESS_TOKEN)
116 141 //console.log('logoutToken: '+ logoutToken)
117 142 logout(logoutToken).then(() => {
  143 + //var sevice = "http://"+window.location.host+"/";
  144 + //var serviceUrl = encodeURIComponent(sevice);
  145 + //window.location.href = window._CONFIG['casPrefixUrl']+"/logout?service="+serviceUrl;
118 146 resolve()
119 147 }).catch(() => {
120 148 resolve()
... ...
ant-design-vue-jeecg/src/utils/request.js
... ... @@ -78,9 +78,11 @@ service.interceptors.request.use(config =&gt; {
78 78 config.headers[ 'X-Access-Token' ] = token // 让每个请求携带自定义 token 请根据实际情况自行修改
79 79 }
80 80 if(config.method=='get'){
81   - config.params = {
82   - _t: Date.parse(new Date())/1000,
83   - ...config.params
  81 + if(config.url.indexOf("sys/dict/getDictItems")<0){
  82 + config.params = {
  83 + _t: Date.parse(new Date())/1000,
  84 + ...config.params
  85 + }
84 86 }
85 87 }
86 88 return config
... ...
ant-design-vue-jeecg/src/utils/util.js
... ... @@ -232,4 +232,23 @@ export function showDealBtn(bpmStatus){
232 232 return true;
233 233 }
234 234 return false;
  235 +}
  236 +
  237 +/**
  238 + * 增强CSS,可以在页面上输出全局css
  239 + * @param css 要增强的css
  240 + * @param id style标签的id,可以用来清除旧样式
  241 + */
  242 +export function cssExpand(css, id) {
  243 + let style = document.createElement('style')
  244 + style.type = "text/css"
  245 + style.innerHTML = `@charset "UTF-8"; ${css}`
  246 + // 清除旧样式
  247 + if (id) {
  248 + let $style = document.getElementById(id)
  249 + if ($style != null) $style.outerHTML = ''
  250 + style.id = id
  251 + }
  252 + // 应用新样式
  253 + document.head.appendChild(style)
235 254 }
236 255 \ No newline at end of file
... ...
ant-design-vue-jeecg/src/views/dashboard/Analysis.vue
... ... @@ -209,10 +209,10 @@
209 209 })
210 210 getVisitInfo().then(res=>{
211 211 if(res.success){
212   - console.log("aaaaaa",res.result)
213   - this.visitInfo = res.result;
214   - }
215   - })
  212 + console.log("aaaaaa",res.result)
  213 + this.visitInfo = res.result;
  214 + }
  215 + })
216 216 },
217 217 }
218 218 }
... ...
ant-design-vue-jeecg/src/views/jeecg/JeecgEditableTableExample.vue
1 1 <template>
2   - <div>
3   - <a-card :borderd="false">
  2 + <a-card :bordered="false">
4 3  
  4 + <a-tabs>
5 5  
6   - <a-button @click="handleTableCheck" type="primary">表单验证</a-button>
7   - <span style="padding-left:8px;"></span>
8   - <a-tooltip placement="top" title="获取值,忽略表单验证" :autoAdjustOverflow="true">
9   - <a-button @click="handleTableGet" type="primary">获取值</a-button>
10   - </a-tooltip>
11   - <span style="padding-left:8px;"></span>
12   - <a-tooltip placement="top" title="模拟加载1000条数据" :autoAdjustOverflow="true">
13   - <a-button @click="handleTableSet" type="primary">设置值</a-button>
14   - </a-tooltip>
  6 + <a-tab-pane tab="普通列表" key="1">
  7 + <default-table/>
  8 + </a-tab-pane>
15 9  
  10 + <a-tab-pane tab="只读列表" key="2">
  11 + <read-only-table/>
  12 + </a-tab-pane>
16 13  
17   - <j-editable-table
18   - ref="editableTable"
19   - :loading="loading"
20   - :columns="columns"
21   - :dataSource="dataSource"
22   - :rowNumber="true"
23   - :rowSelection="true"
24   - :actionButton="true"
25   - style="margin-top: 8px;"
26   - @selectRowChange="handleSelectRowChange">
  14 + <a-tab-pane tab="三级联动" key="3">
  15 + <three-linkage/>
  16 + </a-tab-pane>
27 17  
28   - <template v-slot:action="props">
29   - <a @click="handleDelete(props)">{{ props.text }}</a>
30   - </template>
  18 + </a-tabs>
31 19  
32   - </j-editable-table>
33   -
34   -
35   - </a-card>
36   - <br>
37   - <a-card title="只读列表">
38   - <j-editable-table
39   - :columns="columns1"
40   - :dataSource="dataSource1"
41   - :rowNumber="true"
42   - :rowSelection="true"
43   - :maxHeight="200"
44   - :disabled="true"
45   - />
46   - </a-card>
47   - </div>
  20 + </a-card>
48 21 </template>
49 22  
50 23 <script>
51   - import moment from 'moment'
52   - import JEditableTable from '@/components/jeecg/JEditableTable'
53   - import { FormTypes } from '@/utils/JEditableTableUtil'
54   - import { randomUUID, randomNumber } from '@/utils/util'
  24 + import DefaultTable from './modules/JEditableTable/DefaultTable'
  25 + import ReadOnlyTable from './modules/JEditableTable/ReadOnlyTable'
  26 + import ThreeLinkage from './modules/JEditableTable/ThreeLinkage'
55 27  
56 28 export default {
57 29 name: 'JeecgEditableTableExample',
58   - components: {
59   - JEditableTable
60   - },
  30 + components: { DefaultTable, ReadOnlyTable, ThreeLinkage },
61 31 data() {
62   - return {
63   - loading: false,
64   - columns: [
65   - {
66   - title: '字段名称',
67   - key: 'dbFieldName',
68   - // width: '19%',
69   - width: '300px',
70   - type: FormTypes.input,
71   - defaultValue: '',
72   - placeholder: '请输入${title}',
73   - validateRules: [
74   - {
75   - required: true, // 必填
76   - message: '请输入${title}' // 显示的文本
77   - },
78   - {
79   - pattern: /^[a-z|A-Z][a-z|A-Z\d_-]{0,}$/, // 正则
80   - message: '${title}必须以字母开头,可包含数字、下划线、横杠'
81   - }
82   - ]
83   - },
84   - {
85   - title: '文件域',
86   - key: 'upload',
87   - type: FormTypes.upload,
88   - // width: '19%',
89   - width: '300px',
90   - placeholder: '点击上传',
91   - token: true,
92   - responseName: 'message',
93   - action: window._CONFIG['domianURL'] + '/sys/common/upload'
94   - },
95   - {
96   - title: '字段类型',
97   - key: 'dbFieldType',
98   - // width: '18%',
99   - width: '300px',
100   - type: FormTypes.select,
101   - options: [ // 下拉选项
102   - { title: 'String', value: 'string' },
103   - { title: 'Integer', value: 'int' },
104   - { title: 'Double', value: 'double' },
105   - { title: 'Boolean', value: 'boolean' }
106   - ],
107   - allowInput: true,
108   - defaultValue: '',
109   - placeholder: '请选择${title}',
110   - validateRules: [{ required: true, message: '请选择${title}' }]
111   - },
112   - {
113   - title: '性别(字典)',
114   - key: 'sex_dict',
115   - width: '300px',
116   - type: FormTypes.select,
117   - options: [],
118   - dictCode: 'sex',
119   - placeholder: '请选择${title}',
120   - validateRules: [{ required: true, message: '请选择${title}' }]
121   - },
122   - {
123   - title: '多选测试',
124   - key: 'multipleSelect',
125   - // width: '18%',
126   - width: '300px',
127   - type: FormTypes.select,
128   - props: { 'mode': 'multiple' }, // 支持多选
129   - options: [
130   - { title: 'String', value: 'string' },
131   - { title: 'Integer', value: 'int' },
132   - { title: 'Double', value: 'double' },
133   - { title: 'Boolean', value: 'boolean' }
134   - ],
135   - defaultValue: ['int', 'boolean'], // 多个默认项
136   - // defaultValue: 'string,double,int', // 也可使用这种方式
137   - placeholder: '这里可以多选',
138   - validateRules: [{ required: true, message: '请选择${title}' }]
139   - },
140   - {
141   - title: '字段长度',
142   - key: 'dbLength',
143   - // width: '8%',
144   - width: '100px',
145   - type: FormTypes.inputNumber,
146   - defaultValue: 32,
147   - placeholder: '${title}',
148   - validateRules: [{ required: true, message: '请输入${title}' }]
149   - },
150   - {
151   - title: '日期',
152   - key: 'datetime',
153   - // width: '22%',
154   - width: '320px',
155   - type: FormTypes.datetime,
156   - defaultValue: '2019-4-30 14:52:22',
157   - placeholder: '请选择${title}',
158   - validateRules: [{ required: true, message: '请选择${title}' }]
159   - },
160   - {
161   - title: '可以为空',
162   - key: 'isNull',
163   - // width: '8%',
164   - width: '100px',
165   - type: FormTypes.checkbox,
166   - customValue: ['Y', 'N'], // true ,false
167   - defaultChecked: false
168   - },
169   - {
170   - title: '操作',
171   - key: 'action',
172   - // width: '8%',
173   - width: '100px',
174   - type: FormTypes.slot,
175   - slotName: 'action',
176   - defaultValue: '删除'
177   - }
178   -
179   - ],
180   - dataSource: [],
181   - selectedRowIds: [],
182   - // table2
183   - columns1: [
184   - {
185   - title: '输入框',
186   - key: 'input',
187   - type: FormTypes.input,
188   - placeholder: '清输入'
189   - },
190   - {
191   - title: '下拉框',
192   - key: 'select',
193   - type: FormTypes.select,
194   - options: [
195   - { title: 'String', value: 'string' },
196   - { title: 'Integer', value: 'int' },
197   - { title: 'Double', value: 'double' },
198   - { title: 'Boolean', value: 'boolean' }
199   - ],
200   - placeholder: '请选择'
201   - },
202   - {
203   - title: '多选框',
204   - key: 'checkbox',
205   - type: FormTypes.checkbox,
206   - customValue: [true, false]
207   - },
208   - {
209   - title: '日期',
210   - key: 'datetime',
211   - type: FormTypes.datetime
212   - }
213   - ],
214   - dataSource1: []
215   - }
216   - },
217   - created() {
218   -
219   - },
220   - mounted() {
221   - this.randomData(23, false)
222   - this.dataSource1 = [
223   - { input: 'hello', select: 'int', checkbox: true, datetime: '2019-6-17 14:50:48' },
224   - { input: 'world', select: 'string', checkbox: false, datetime: '2019-6-16 14:50:48' },
225   - { input: 'one', select: 'double', checkbox: true, datetime: '2019-6-17 15:50:48' },
226   - { input: 'two', select: 'boolean', checkbox: false, datetime: '2019-6-14 14:50:48' },
227   - { input: 'three', select: '', checkbox: false, datetime: '2019-6-13 14:50:48' }
228   - ]
  32 + return {}
229 33 },
230   - methods: {
231   -
232   - /** 表单验证 */
233   - handleTableCheck() {
234   - this.$refs.editableTable.getValues((error) => {
235   - if (error === 0) {
236   - this.$message.success('验证通过')
237   - } else {
238   - this.$message.error('验证未通过')
239   - }
240   - })
241   - },
242   - /** 获取值,忽略表单验证 */
243   - handleTableGet() {
244   - this.$refs.editableTable.getValues((error, values) => {
245   - console.log('values:', values)
246   - }, false)
247   - console.log('deleteIds:', this.$refs.editableTable.getDeleteIds())
248   -
249   - this.$message.info('获取值成功,请看控制台输出')
250   -
251   - },
252   - /** 模拟加载1000条数据 */
253   - handleTableSet() {
254   - this.randomData(1000, true)
255   - },
256   -
257   - handleSelectRowChange(selectedRowIds) {
258   - this.selectedRowIds = selectedRowIds
259   - },
260   -
261   - /* 随机生成数据 */
262   - randomData(size, loading = false) {
263   - if (loading) {
264   - this.loading = true
265   - }
266   -
267   - let randomDatetime = () => {
268   - let time = parseInt(randomNumber(1000, 9999999999999))
269   - return moment(new Date(time)).format('YYYY-MM-DD HH:mm:ss')
270   - }
271   -
272   - let begin = Date.now()
273   - let values = []
274   - for (let i = 0; i < size; i++) {
275   - values.push({
276   - id: randomUUID(),
277   - dbFieldName: `name_${i + 1}`,
278   - // dbFieldTxt: randomString(10),
279   - multipleSelect: ['string', ['int', 'double', 'boolean'][randomNumber(0, 2)]],
280   - dbFieldType: ['string', 'int', 'double', 'boolean'][randomNumber(0, 3)],
281   - dbLength: randomNumber(0, 233),
282   - datetime: randomDatetime(),
283   - isNull: ['Y', 'N'][randomNumber(0, 1)]
284   - })
285   - }
286   -
287   - this.dataSource = values
288   - let end = Date.now()
289   - let diff = end - begin
290   -
291   - if (loading && diff < size) {
292   - setTimeout(() => {
293   - this.loading = false
294   - }, size - diff)
295   - }
296   -
297   - },
298   -
299   - handleDelete(props) {
300   - let { rowId, target } = props
301   - target.removeRows(rowId)
302   - }
303   -
304   - }
  34 + methods: {}
305 35 }
306 36 </script>
307 37  
... ...
ant-design-vue-jeecg/src/views/jeecg/SelectDemo.vue
... ... @@ -49,7 +49,7 @@
49 49 <a-row :gutter="24">
50 50 <a-col :span="12">
51 51 <a-form-item label="选择部门">
52   - <j-select-depart v-model="departId"></j-select-depart>
  52 + <j-select-depart v-model="departId" :multi="true"></j-select-depart>
53 53 </a-form-item>
54 54 </a-col>
55 55 <a-col :span="12">选中的部门ID(v-model):{{ departId }}</a-col>
... ... @@ -217,10 +217,8 @@
217 217 <a-row :gutter="24">
218 218 <a-col :span="12">
219 219 <a-form-item label="cron表达式">
220   - <a-input @click="openModal" placeholder="corn表达式" v-model="cron.label" readOnly >
221   - <a-icon slot="prefix" type="schedule" title="corn控件"/>
222   - </a-input>
223   - <VueCron ref="innerVueCron" :data="cron" @change="changeCron" ></VueCron>
  220 + <j-cron ref="innerVueCron" v-decorator="['cronExpression', {'initialValue':'0/1 * * * * ?'}]" @change="setCorn"></j-cron>
  221 + <!-- <j-cron ref="innerVueCron" v-model="cron" @change="setCorn"></j-cron>-->
224 222 </a-form-item>
225 223 </a-col>
226 224 </a-row>
... ... @@ -245,7 +243,7 @@
245 243 import JSlider from '@/components/jeecg/JSlider'
246 244 import JSelectMultiple from '@/components/jeecg/JSelectMultiple'
247 245 import JTreeDict from "../../components/jeecg/JTreeDict.vue";
248   - import VueCron from "./modules/VueCronModal.vue";
  246 + import JCron from "@/components/jeecg/JCron.vue";
249 247 export default {
250 248 name: 'SelectDemo',
251 249 components: {
... ... @@ -257,7 +255,7 @@
257 255 JCheckbox,
258 256 JCodeEditor,
259 257 JDate, JEditor, JEllipsis, JGraphicCode, JSlider, JSelectMultiple,
260   - VueCron
  258 + JCron
261 259 },
262 260 data() {
263 261 return {
... ... @@ -314,10 +312,7 @@ sayHi(&#39;hello, world!&#39;)`
314 312 style: { top: '20px' },
315 313 fullScreen: true
316 314 },
317   - cron: {
318   - label: '',
319   - value: {}
320   - }
  315 + cron: '',
321 316 }
322 317 },
323 318 computed: {
... ... @@ -372,14 +367,12 @@ sayHi(&#39;hello, world!&#39;)`
372 367 }
373 368 this.modal.fullScreen = mode
374 369 },
375   - openModal(){
376   - this.$refs.innerVueCron.show()
377   - },
378   - changeCron(val){
379   - this.cron=val;
380   - console.log(val);
381   - }
  370 + setCorn(data){
382 371  
  372 + this.$nextTick(() => {
  373 + this.form.cronExpression = data;
  374 + })
  375 + }
383 376 }
384 377 }
385 378 </script>
... ...
ant-design-vue-jeecg/src/views/jeecg/TableTotal.vue 0 → 100644
  1 +<template>
  2 + <a-card :bordered="false">
  3 + <a-table
  4 + rowKey="id"
  5 + bordered
  6 + :columns="columns"
  7 + :dataSource="dataSource"
  8 + :pagination="false"
  9 + >
  10 + </a-table>
  11 + </a-card>
  12 +</template>
  13 +
  14 +<script>
  15 + export default {
  16 + name: 'TableTotal',
  17 + data() {
  18 + return {
  19 + columns: [
  20 + {
  21 + title: '#',
  22 + width: '180px',
  23 + align: 'center',
  24 + dataIndex: 'rowIndex',
  25 + customRender: function (text, r, index) {
  26 + return (text !== '合计') ? (parseInt(index) + 1) : text
  27 + }
  28 + },
  29 + {
  30 + title: '姓名',
  31 + dataIndex: 'name',
  32 + },
  33 + {
  34 + title: '贡献点',
  35 + dataIndex: 'point',
  36 + },
  37 + {
  38 + title: '等级',
  39 + dataIndex: 'level',
  40 + },
  41 + {
  42 + title: '更新时间',
  43 + dataIndex: 'updateTime',
  44 + },
  45 + ],
  46 + dataSource: [
  47 + { name: '张三', point: 23, level: 3, updateTime: '2019-8-14' },
  48 + { name: '小王', point: 6, level: 1, updateTime: '2019-8-13' },
  49 + { name: '李四', point: 53, level: 8, updateTime: '2019-8-12' },
  50 + { name: '小红', point: 44, level: 5, updateTime: '2019-8-11' },
  51 + { name: '王五', point: 97, level: 10, updateTime: '2019-8-10' },
  52 + { name: '小明', point: 33, level: 2, updateTime: '2019-8-10' },
  53 + ]
  54 + }
  55 + },
  56 + mounted() {
  57 + this.tableAddTotalRow(this.columns, this.dataSource)
  58 + },
  59 + methods: {
  60 +
  61 + /** 表格增加合计行 */
  62 + tableAddTotalRow(columns, dataSource) {
  63 + let numKey = 'rowIndex'
  64 + let totalRow = { [numKey]: '合计' }
  65 + columns.forEach(column => {
  66 + let { key, dataIndex } = column
  67 + if (![key, dataIndex].includes(numKey)) {
  68 +
  69 + let total = 0
  70 + dataSource.forEach(data => {
  71 + total += /^\d+\.?\d?$/.test(data[dataIndex]) ? Number.parseInt(data[dataIndex]) : Number.NaN
  72 + console.log(data[dataIndex], ':', (/^\d+\.?\d?$/.test(data[dataIndex]) ? Number.parseInt(data[dataIndex]) : Number.NaN))
  73 + })
  74 +
  75 + if (Number.isNaN(total)) {
  76 + total = '-'
  77 + }
  78 + totalRow[dataIndex] = total
  79 + }
  80 + })
  81 +
  82 + dataSource.push(totalRow)
  83 + }
  84 +
  85 + }
  86 + }
  87 +</script>
  88 +
  89 +<style scoped>
  90 +
  91 +</style>
0 92 \ No newline at end of file
... ...
ant-design-vue-jeecg/src/views/jeecg/modules/JEditableTable/DefaultTable.vue 0 → 100644
  1 +<template>
  2 +
  3 + <div>
  4 + <a-button @click="handleTableCheck" type="primary">表单验证</a-button>
  5 + <span style="padding-left:8px;"></span>
  6 + <a-tooltip placement="top" title="获取值,忽略表单验证" :autoAdjustOverflow="true">
  7 + <a-button @click="handleTableGet" type="primary">获取值</a-button>
  8 + </a-tooltip>
  9 + <span style="padding-left:8px;"></span>
  10 + <a-tooltip placement="top" title="模拟加载1000条数据" :autoAdjustOverflow="true">
  11 + <a-button @click="handleTableSet" type="primary">设置值</a-button>
  12 + </a-tooltip>
  13 +
  14 +
  15 + <j-editable-table
  16 + ref="editableTable"
  17 + :loading="loading"
  18 + :columns="columns"
  19 + :dataSource="dataSource"
  20 + :rowNumber="true"
  21 + :rowSelection="true"
  22 + :actionButton="true"
  23 + :dragSort="true"
  24 + style="margin-top: 8px;"
  25 + @selectRowChange="handleSelectRowChange">
  26 +
  27 + <template v-slot:action="props">
  28 + <a @click="handleDelete(props)">{{ props.text }}</a>
  29 + </template>
  30 +
  31 + </j-editable-table>
  32 + </div>
  33 +
  34 +</template>
  35 +
  36 +<script>
  37 + import moment from 'moment'
  38 + import { FormTypes } from '@/utils/JEditableTableUtil'
  39 + import { randomUUID, randomNumber } from '@/utils/util'
  40 + import JEditableTable from '@/components/jeecg/JEditableTable'
  41 +
  42 + export default {
  43 + name: 'DefaultTable',
  44 + components: { JEditableTable },
  45 + data() {
  46 + return {
  47 + loading: false,
  48 + columns: [
  49 + {
  50 + title: '字段名称',
  51 + key: 'dbFieldName',
  52 + // width: '19%',
  53 + width: '300px',
  54 + type: FormTypes.input,
  55 + defaultValue: '',
  56 + placeholder: '请输入${title}',
  57 + validateRules: [
  58 + {
  59 + required: true, // 必填
  60 + message: '请输入${title}' // 显示的文本
  61 + },
  62 + {
  63 + pattern: /^[a-z|A-Z][a-z|A-Z\d_-]{0,}$/, // 正则
  64 + message: '${title}必须以字母开头,可包含数字、下划线、横杠'
  65 + }
  66 + ]
  67 + },
  68 + {
  69 + title: '文件域',
  70 + key: 'upload',
  71 + type: FormTypes.upload,
  72 + // width: '19%',
  73 + width: '300px',
  74 + placeholder: '点击上传',
  75 + token: true,
  76 + responseName: 'message',
  77 + action: window._CONFIG['domianURL'] + '/sys/common/upload'
  78 + },
  79 + {
  80 + title: '字段类型',
  81 + key: 'dbFieldType',
  82 + // width: '18%',
  83 + width: '300px',
  84 + type: FormTypes.select,
  85 + options: [ // 下拉选项
  86 + { title: 'String', value: 'string' },
  87 + { title: 'Integer', value: 'int' },
  88 + { title: 'Double', value: 'double' },
  89 + { title: 'Boolean', value: 'boolean' }
  90 + ],
  91 + allowInput: true,
  92 + defaultValue: '',
  93 + placeholder: '请选择${title}',
  94 + validateRules: [{ required: true, message: '请选择${title}' }]
  95 + },
  96 + {
  97 + title: '性别(字典)',
  98 + key: 'sex_dict',
  99 + width: '300px',
  100 + type: FormTypes.select,
  101 + options: [],
  102 + dictCode: 'sex',
  103 + placeholder: '请选择${title}',
  104 + validateRules: [{ required: true, message: '请选择${title}' }]
  105 + },
  106 + {
  107 + title: '多选测试',
  108 + key: 'multipleSelect',
  109 + // width: '18%',
  110 + width: '300px',
  111 + type: FormTypes.select,
  112 + props: { 'mode': 'multiple' }, // 支持多选
  113 + options: [
  114 + { title: 'String', value: 'string' },
  115 + { title: 'Integer', value: 'int' },
  116 + { title: 'Double', value: 'double' },
  117 + { title: 'Boolean', value: 'boolean' }
  118 + ],
  119 + defaultValue: ['int', 'boolean'], // 多个默认项
  120 + // defaultValue: 'string,double,int', // 也可使用这种方式
  121 + placeholder: '这里可以多选',
  122 + validateRules: [{ required: true, message: '请选择${title}' }]
  123 + },
  124 + {
  125 + title: '字段长度',
  126 + key: 'dbLength',
  127 + // width: '8%',
  128 + width: '100px',
  129 + type: FormTypes.inputNumber,
  130 + defaultValue: 32,
  131 + placeholder: '${title}',
  132 + validateRules: [{ required: true, message: '请输入${title}' }]
  133 + },
  134 + {
  135 + title: '日期',
  136 + key: 'datetime',
  137 + // width: '22%',
  138 + width: '320px',
  139 + type: FormTypes.datetime,
  140 + defaultValue: '2019-4-30 14:52:22',
  141 + placeholder: '请选择${title}',
  142 + validateRules: [{ required: true, message: '请选择${title}' }]
  143 + },
  144 + {
  145 + title: '可以为空',
  146 + key: 'isNull',
  147 + // width: '8%',
  148 + width: '100px',
  149 + type: FormTypes.checkbox,
  150 + customValue: ['Y', 'N'], // true ,false
  151 + defaultChecked: false
  152 + },
  153 + {
  154 + title: '操作',
  155 + key: 'action',
  156 + // width: '8%',
  157 + width: '100px',
  158 + type: FormTypes.slot,
  159 + slotName: 'action',
  160 + defaultValue: '删除'
  161 + }
  162 +
  163 + ],
  164 + dataSource: [],
  165 + selectedRowIds: []
  166 + }
  167 + },
  168 + mounted() {
  169 + this.randomData(23, false)
  170 + },
  171 + methods: {
  172 +
  173 + /** 表单验证 */
  174 + handleTableCheck() {
  175 + this.$refs.editableTable.getValues((error) => {
  176 + if (error === 0) {
  177 + this.$message.success('验证通过')
  178 + } else {
  179 + this.$message.error('验证未通过')
  180 + }
  181 + })
  182 + },
  183 + /** 获取值,忽略表单验证 */
  184 + handleTableGet() {
  185 + this.$refs.editableTable.getValues((error, values) => {
  186 + console.log('values:', values)
  187 + }, false)
  188 + console.log('deleteIds:', this.$refs.editableTable.getDeleteIds())
  189 +
  190 + this.$message.info('获取值成功,请看控制台输出')
  191 +
  192 + },
  193 + /** 模拟加载1000条数据 */
  194 + handleTableSet() {
  195 + this.randomData(1000, true)
  196 + },
  197 +
  198 + handleSelectRowChange(selectedRowIds) {
  199 + this.selectedRowIds = selectedRowIds
  200 + },
  201 +
  202 + /* 随机生成数据 */
  203 + randomData(size, loading = false) {
  204 + if (loading) {
  205 + this.loading = true
  206 + }
  207 +
  208 + let randomDatetime = () => {
  209 + let time = parseInt(randomNumber(1000, 9999999999999))
  210 + return moment(new Date(time)).format('YYYY-MM-DD HH:mm:ss')
  211 + }
  212 +
  213 + let begin = Date.now()
  214 + let values = []
  215 + for (let i = 0; i < size; i++) {
  216 + values.push({
  217 + id: randomUUID(),
  218 + dbFieldName: `name_${i + 1}`,
  219 + // dbFieldTxt: randomString(10),
  220 + multipleSelect: ['string', ['int', 'double', 'boolean'][randomNumber(0, 2)]],
  221 + dbFieldType: ['string', 'int', 'double', 'boolean'][randomNumber(0, 3)],
  222 + dbLength: randomNumber(0, 233),
  223 + datetime: randomDatetime(),
  224 + isNull: ['Y', 'N'][randomNumber(0, 1)]
  225 + })
  226 + }
  227 +
  228 + this.dataSource = values
  229 + let end = Date.now()
  230 + let diff = end - begin
  231 +
  232 + if (loading && diff < size) {
  233 + setTimeout(() => {
  234 + this.loading = false
  235 + }, size - diff)
  236 + }
  237 +
  238 + },
  239 +
  240 + handleDelete(props) {
  241 + let { rowId, target } = props
  242 + target.removeRows(rowId)
  243 + }
  244 + }
  245 + }
  246 +</script>
  247 +
  248 +<style scoped>
  249 +
  250 +</style>
0 251 \ No newline at end of file
... ...
ant-design-vue-jeecg/src/views/jeecg/modules/JEditableTable/ReadOnlyTable.vue 0 → 100644
  1 +<template>
  2 + <j-editable-table
  3 + :columns="columns"
  4 + :dataSource="dataSource"
  5 + :rowNumber="true"
  6 + :rowSelection="true"
  7 + :maxHeight="400"
  8 + :disabled="true"
  9 + />
  10 +</template>
  11 +
  12 +<script>
  13 + import { FormTypes } from '@/utils/JEditableTableUtil'
  14 + import JEditableTable from '@/components/jeecg/JEditableTable'
  15 +
  16 + export default {
  17 + name: 'ReadOnlyTable',
  18 + components: { JEditableTable },
  19 + data() {
  20 + return {
  21 +
  22 + columns: [
  23 + {
  24 + title: '输入框',
  25 + key: 'input',
  26 + type: FormTypes.input,
  27 + placeholder: '清输入'
  28 + },
  29 + {
  30 + title: '下拉框',
  31 + key: 'select',
  32 + type: FormTypes.select,
  33 + options: [
  34 + { title: 'String', value: 'string' },
  35 + { title: 'Integer', value: 'int' },
  36 + { title: 'Double', value: 'double' },
  37 + { title: 'Boolean', value: 'boolean' }
  38 + ],
  39 + placeholder: '请选择'
  40 + },
  41 + {
  42 + title: '多选框',
  43 + key: 'checkbox',
  44 + type: FormTypes.checkbox,
  45 + customValue: [true, false]
  46 + },
  47 + {
  48 + title: '日期',
  49 + key: 'datetime',
  50 + type: FormTypes.datetime
  51 + }
  52 + ],
  53 + dataSource: [
  54 + { input: 'hello', select: 'int', checkbox: true, datetime: '2019-6-17 14:50:48' },
  55 + { input: 'world', select: 'string', checkbox: false, datetime: '2019-6-16 14:50:48' },
  56 + { input: 'one', select: 'double', checkbox: true, datetime: '2019-6-17 15:50:48' },
  57 + { input: 'two', select: 'boolean', checkbox: false, datetime: '2019-6-14 14:50:48' },
  58 + { input: 'three', select: '', checkbox: false, datetime: '2019-6-13 14:50:48' }
  59 + ]
  60 + }
  61 + },
  62 + mounted() {
  63 +
  64 + }
  65 + }
  66 +</script>
  67 +
  68 +<style scoped>
  69 +
  70 +</style>
0 71 \ No newline at end of file
... ...
ant-design-vue-jeecg/src/views/jeecg/modules/JEditableTable/ThreeLinkage.vue 0 → 100644
  1 +<template>
  2 + <j-editable-table
  3 + :columns="columns"
  4 + :dataSource="dataSource"
  5 + :rowNumber="true"
  6 + :actionButton="true"
  7 + :rowSelection="true"
  8 + :maxHeight="400"
  9 + @valueChange="handleValueChange"
  10 + />
  11 +</template>
  12 +
  13 +<script>
  14 + import { FormTypes } from '@/utils/JEditableTableUtil'
  15 + import JEditableTable from '@/components/jeecg/JEditableTable'
  16 +
  17 + export default {
  18 + name: 'ThreeLinkage',
  19 + components: { JEditableTable },
  20 + data() {
  21 + return {
  22 + columns: [
  23 + {
  24 + title: '省/直辖市/自治区',
  25 + key: 's1',
  26 + type: FormTypes.select,
  27 + width: '240px',
  28 + options: [],
  29 + placeholder: '请选择${title}'
  30 + },
  31 + {
  32 + title: '市',
  33 + key: 's2',
  34 + type: FormTypes.select,
  35 + width: '240px',
  36 + options: [],
  37 + placeholder: '请选择${title}'
  38 + },
  39 + {
  40 + title: '县/区',
  41 + key: 's3',
  42 + type: FormTypes.select,
  43 + width: '240px',
  44 + options: [],
  45 + placeholder: '请选择${title}'
  46 + }
  47 + ],
  48 + dataSource: [],
  49 +
  50 + mockData: [
  51 + { label: '北京市', value: '110000', parent: null },
  52 + { label: '天津市', value: '120000', parent: null },
  53 + { label: '河北省', value: '130000', parent: null },
  54 + { label: '上海市', value: '310000', parent: null },
  55 +
  56 + { label: '北京市', value: '110100', parent: '110000' },
  57 + { label: '天津市市', value: '120100', parent: '120000' },
  58 + { label: '石家庄市', value: '130100', parent: '130000' },
  59 + { label: '唐山市', value: '130200', parent: '130000' },
  60 + { label: '秦皇岛市', value: '130300', parent: '130000' },
  61 + { label: '上海市', value: '310100', parent: '310000' },
  62 +
  63 + { label: '东城区', value: '110101', parent: '110100' },
  64 + { label: '西城区', value: '110102', parent: '110100' },
  65 + { label: '朝阳区', value: '110105', parent: '110100' },
  66 + { label: '和平区', value: '120101', parent: '120000' },
  67 + { label: '河东区', value: '120102', parent: '120000' },
  68 + { label: '河西区', value: '120103', parent: '120000' },
  69 + { label: '黄浦区', value: '310101', parent: '310100' },
  70 + { label: '徐汇区', value: '310104', parent: '310100' },
  71 + { label: '长宁区', value: '310105', parent: '310100' },
  72 + { label: '长安区', value: '130102', parent: '130100' },
  73 + { label: '桥西区', value: '130104', parent: '130100' },
  74 + { label: '新华区', value: '130105', parent: '130100' },
  75 + { label: '路南区', value: '130202', parent: '130200' },
  76 + { label: '路北区', value: '130203', parent: '130200' },
  77 + { label: '古冶区', value: '130204', parent: '130200' },
  78 + { label: '海港区', value: '130302', parent: '130300' },
  79 + { label: '山海关区', value: '130303', parent: '130300' },
  80 + { label: '北戴河区', value: '130304', parent: '130300' },
  81 + ]
  82 + }
  83 + },
  84 + mounted() {
  85 + // 初始化数据
  86 + this.columns[0].options = this.request(null)
  87 + },
  88 + methods: {
  89 +
  90 + request(parentId) {
  91 + return this.mockData.filter(i => i.parent === parentId)
  92 + },
  93 +
  94 + /** 当选项被改变时,联动其他组件 */
  95 + handleValueChange(event) {
  96 + const { type, row, column, value, target } = event
  97 +
  98 + if (type === FormTypes.select) {
  99 +
  100 + // 第一列
  101 + if (column.key === 's1') {
  102 + // 设置第二列的 options
  103 + this.columns[1].options = this.request(value)
  104 + // 清空后两列的数据
  105 + target.setValues([{
  106 + rowKey: row.id,
  107 + values: { s2: '', s3: '' }
  108 + }])
  109 + this.columns[2].options = []
  110 + } else
  111 + // 第二列
  112 + if (column.key === 's2') {
  113 + this.columns[2].options = this.request(value)
  114 + target.setValues([{
  115 + rowKey: row.id,
  116 + values: { s3: '' }
  117 + }])
  118 + }
  119 + }
  120 +
  121 + }
  122 +
  123 + }
  124 + }
  125 +</script>
  126 +
  127 +<style scoped>
  128 +
  129 +</style>
0 130 \ No newline at end of file
... ...
ant-design-vue-jeecg/src/views/jeecg/modules/VueCronModal.vue
... ... @@ -486,7 +486,7 @@
486 486 days = this.result.day.cronLastSpecificDomDay + 'L';
487 487 break;
488 488 case '9':
489   - days = 'L-' + this.day.cronDaysBeforeEomMinus;
  489 + days = 'L-' + this.result.day.cronDaysBeforeEomMinus;
490 490 break;
491 491 case '10':
492 492 days = this.result.day.cronDaysNearestWeekday+"W";
... ...
ant-design-vue-jeecg/src/views/modules/online/cgform/OnlCgformHeadList.vue 0 → 100644
  1 +<template>
  2 + <a-card :bordered="false">
  3 +
  4 + <!-- 查询区域 -->
  5 + <div class="table-page-search-wrapper">
  6 + <a-form layout="inline">
  7 + <a-row :gutter="24">
  8 +
  9 + <a-col :md="6" :sm="24">
  10 + <a-form-item label="表名">
  11 + <a-input placeholder="请输入表名" v-model="queryParam.tableName"></a-input>
  12 + </a-form-item>
  13 + </a-col>
  14 + <a-col :md="6" :sm="24">
  15 + <a-form-item label="表类型">
  16 + <j-dict-select-tag dictCode="cgform_table_type" v-model="queryParam.tableType"/>
  17 + </a-form-item>
  18 + </a-col>
  19 +
  20 + <a-col :md="6" :sm="24">
  21 + <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
  22 + <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
  23 + <a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
  24 + </span>
  25 + </a-col>
  26 +
  27 + </a-row>
  28 + </a-form>
  29 + </div>
  30 +
  31 + <!-- 操作按钮区域 -->
  32 + <div class="table-operator">
  33 + <a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
  34 + <a-button @click="doCgformButton" type="primary" icon="highlight" style="margin-left:8px">自定义按钮</a-button>
  35 + <a-button @click="doEnhanceJs" type="primary" icon="strikethrough" style="margin-left:8px">JS增强</a-button>
  36 + <a-button @click="doEnhanceSql" type="primary" icon="filter" v-has="'online:sql'" style="margin-left:8px">SQL增强</a-button>
  37 + <a-button @click="doEnhanceJava" type="primary" icon="tool" style="margin-left:8px">Java增强</a-button>
  38 + <a-button @click="importOnlineForm" type="primary" icon="database" style="margin-left:8px">从数据库导入表单</a-button>
  39 + <a-button @click="goGenerateCode" v-has="'online:goGenerateCode'" type="primary" icon="database" style="margin-left:8px">代码生成</a-button>
  40 +
  41 + <a-dropdown v-if="selectedRowKeys.length > 0">
  42 + <a-menu slot="overlay">
  43 + <a-menu-item key="1" @click="batchDel">
  44 + <a-icon type="delete"/>
  45 + 删除
  46 + </a-menu-item>
  47 + </a-menu>
  48 + <a-button style="margin-left: 8px"> 批量操作
  49 + <a-icon type="down"/>
  50 + </a-button>
  51 + </a-dropdown>
  52 + </div>
  53 +
  54 + <!-- table区域-begin -->
  55 + <div>
  56 + <div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
  57 + <i class="anticon anticon-info-circle ant-alert-icon"></i>
  58 + 已选择
  59 + <a style="font-weight: 600">{{ selectedRowKeys.length }}</a>
  60 + 项
  61 + <a style="margin-left: 24px" @click="onClearSelected">清空</a>
  62 + </div>
  63 +
  64 + <a-table
  65 + ref="table"
  66 + size="middle"
  67 + bordered
  68 + rowKey="id"
  69 + :columns="columns"
  70 + :dataSource="dataSource"
  71 + :pagination="ipagination"
  72 + :loading="loading"
  73 + :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
  74 + @change="handleTableChange">
  75 +
  76 + <template slot="action" slot-scope="text, record">
  77 + <a @click="handleEdit(record)">编辑</a>
  78 +
  79 + <a-divider type="vertical"/>
  80 + <a-dropdown>
  81 + <a class="ant-dropdown-link">更多
  82 + <a-icon type="down"/>
  83 + </a>
  84 + <a-menu slot="overlay">
  85 + <a-menu-item v-if="record.isDbSynch!='Y'">
  86 + <a @click="openSyncModal(record.id)">同步数据库</a>
  87 + </a-menu-item>
  88 +
  89 + <template v-if="record.isDbSynch=='Y' && record.tableType !== 3">
  90 + <a-menu-item>
  91 + <a @click="goPageOnline(record)">功能测试</a>
  92 + </a-menu-item>
  93 + <a-menu-item>
  94 + <a @click="handleOnlineUrlShow(record)">配置地址</a>
  95 + </a-menu-item>
  96 + </template>
  97 +
  98 + <a-menu-item>
  99 + <a @click="handleRemoveRecord(record.id)">移除</a>
  100 + </a-menu-item>
  101 +
  102 + <a-menu-item>
  103 + <a @click="handleDelete(record.id)">删除</a>
  104 + </a-menu-item>
  105 +
  106 + </a-menu>
  107 + </a-dropdown>
  108 + </template>
  109 +
  110 + <template slot="dbsync" slot-scope="text">
  111 + <span v-if="text==='Y'" style="color:limegreen">已同步</span>
  112 + <span v-if="text==='N'" style="color:red">未同步</span>
  113 + </template>
  114 +
  115 + </a-table>
  116 + </div>
  117 + <!-- table区域-end -->
  118 +
  119 + <!-- 表单区域 -->
  120 + <onl-cgform-head-modal ref="modalForm" @ok="modalFormOk"></onl-cgform-head-modal>
  121 +
  122 + <!-- 同步数据库提示框 -->
  123 + <a-modal
  124 + :width="500"
  125 + :height="300"
  126 + title="同步数据库"
  127 + :visible="syncModalVisible"
  128 + @cancel="handleCancleDbSync"
  129 + style="top:5%;height: 95%;">
  130 + <template slot="footer">
  131 + <a-button @click="handleCancleDbSync">关闭</a-button>
  132 + <a-button type="primary" :loading="syncLoading" @click="handleDbSync">
  133 + 确定
  134 + </a-button>
  135 + </template>
  136 + <a-radio-group v-model="synMethod">
  137 + <a-radio style="display: block;width: 30px;height: 30px" value="normal">普通同步(保留表数据)</a-radio>
  138 + <a-radio style="display: block;width: 30px;height: 30px" value="force">强制同步(删除表,重新生成)</a-radio>
  139 + </a-radio-group>
  140 + </a-modal>
  141 +
  142 + <!-- 提示online报表链接 -->
  143 + <a-modal
  144 + :title="onlineUrlTitle"
  145 + :visible="onlineUrlVisible"
  146 + @cancel="handleOnlineUrlClose">
  147 + <template slot="footer">
  148 + <a-button @click="handleOnlineUrlClose">关闭</a-button>
  149 + <a-button type="primary" class="copy-this-text" :data-clipboard-text="onlineUrl" @click="onCopyUrl">复制</a-button>
  150 + </template>
  151 + <p>{{ onlineUrl }}</p>
  152 + </a-modal>
  153 +
  154 + <enhance-js ref="ehjs"></enhance-js>
  155 + <enhance-sql ref="ehsql"></enhance-sql>
  156 + <enhance-java ref="ehjava"></enhance-java>
  157 + <trans-db2-online ref="transd2o" @ok="transOk"></trans-db2-online>
  158 + <code-generator ref="cg"></code-generator>
  159 +
  160 + <onl-cgform-button-list ref="btnList"></onl-cgform-button-list>
  161 + </a-card>
  162 +</template>
  163 +
  164 +<script>
  165 + import { initDictOptions, filterDictText } from '@/components/dict/JDictSelectUtil'
  166 + import { deleteAction, postAction } from '@/api/manage'
  167 + import JDictSelectTag from '../../../../components/dict/JDictSelectTag.vue'
  168 + import { JeecgListMixin } from '@/mixins/JeecgListMixin'
  169 + import Clipboard from 'clipboard'
  170 +
  171 + export default {
  172 + name: 'OnlCgformHeadList',
  173 + mixins: [JeecgListMixin],
  174 + components: {
  175 + JDictSelectTag,
  176 + },
  177 + data() {
  178 + return {
  179 + description: 'Online表单开发管理页面',
  180 + // 表头
  181 + columns: [
  182 + {
  183 + title: '#',
  184 + dataIndex: '',
  185 + key: 'rowIndex',
  186 + width: 60,
  187 + align: 'center',
  188 + customRender: function(t, r, index) {
  189 + return parseInt(index) + 1
  190 + }
  191 + },
  192 + {
  193 + title: '表类型',
  194 + align: 'center',
  195 + dataIndex: 'tableType',
  196 + customRender: (text) => {
  197 + return filterDictText(this.tableTypeDictOptions, `${text}`)
  198 + }
  199 + },
  200 + {
  201 + title: '表名',
  202 + align: 'center',
  203 + dataIndex: 'tableName'
  204 + },
  205 + {
  206 + title: '表描述',
  207 + align: 'center',
  208 + dataIndex: 'tableTxt'
  209 + },
  210 + {
  211 + title: '版本',
  212 + align: 'center',
  213 + dataIndex: 'tableVersion'
  214 + },
  215 +
  216 + {
  217 + title: '同步数据库状态',
  218 + align: 'center',
  219 + dataIndex: 'isDbSynch',
  220 + scopedSlots: { customRender: 'dbsync' }
  221 + },
  222 + {
  223 + title: '操作',
  224 + dataIndex: 'action',
  225 + align: 'center',
  226 + scopedSlots: { customRender: 'action' }
  227 + }
  228 + ],
  229 + url: {
  230 + list: '/online/cgform/head/list',
  231 + delete: '/online/cgform/head/delete',
  232 + deleteBatch: '/online/cgform/head/deleteBatch',
  233 + doDbSynch: '/online/cgform/api/doDbSynch/',
  234 + removeRecord: '/online/cgform/head/removeRecord'
  235 + },
  236 + tableTypeDictOptions: [],
  237 + sexDictOptions: [],
  238 + syncModalVisible: false,
  239 + syncFormId: '',
  240 + synMethod: 'normal',
  241 + syncLoading: false,
  242 + onlineUrlTitle: '',
  243 + onlineUrlVisible: false,
  244 + onlineUrl: '',
  245 + selectedRowKeys: [],
  246 + selectedRows: []
  247 + }
  248 + },
  249 + created() {
  250 + //初始化字典 - 表类型
  251 + initDictOptions('cgform_table_type').then((res) => {
  252 + if (res.success) {
  253 + this.tableTypeDictOptions = res.result
  254 + }
  255 + })
  256 + this.loadData()
  257 + },
  258 + methods: {
  259 + doDbSynch(id) {
  260 + postAction(this.url.doDbSynch + id, { synMethod: '1' }).then((res) => {
  261 + if (res.success) {
  262 + this.$message.success(res.message)
  263 + this.loadData()
  264 + } else {
  265 + this.$message.warning(res.message)
  266 + }
  267 + })
  268 + },
  269 + handleCancleDbSync() {
  270 + this.syncModalVisible = false
  271 + },
  272 + handleDbSync() {
  273 + this.syncLoading = true
  274 + postAction(this.url.doDbSynch + this.syncFormId + '/' + this.synMethod).then((res) => {
  275 + this.syncModalVisible = false
  276 + this.syncLoading = false
  277 + if (res.success) {
  278 + this.$message.success(res.message)
  279 + this.loadData()
  280 + } else {
  281 + this.$message.warning(res.message)
  282 + }
  283 + })
  284 + },
  285 + openSyncModal(id) {
  286 + this.syncModalVisible = true
  287 + this.syncFormId = id
  288 + },
  289 + goPageOnline(rd) {
  290 + if(rd.isTree=='Y'){
  291 + this.$router.push({ path: '/online/cgformTreeList/' + rd.id })
  292 + }else{
  293 + this.$router.push({ path: '/online/cgformList/' + rd.id })
  294 + }
  295 + },
  296 + handleOnlineUrlClose() {
  297 + this.onlineUrlTitle = ''
  298 + this.onlineUrlVisible = false
  299 + },
  300 + handleOnlineUrlShow(record) {
  301 + if(record.isTree=='Y'){
  302 + this.onlineUrl = `/online/cgformTreeList/${record.id}`
  303 + }else{
  304 + this.onlineUrl = `/online/cgformList/${record.id}`
  305 + }
  306 + this.onlineUrlVisible = true
  307 + this.onlineUrlTitle = '菜单链接[' + record.tableTxt + ']'
  308 + },
  309 + handleRemoveRecord(id) {
  310 + let that = this
  311 + this.$confirm({
  312 + title: '确认要移除此记录?',
  313 + onOk() {
  314 + deleteAction(that.url.removeRecord, { id: id }).then((res) => {
  315 + if (res.success) {
  316 + that.$message.success('移除成功')
  317 + that.loadData()
  318 + } else {
  319 + that.$message.warning(res.message)
  320 + }
  321 + })
  322 + },
  323 + onCancel() {
  324 + }
  325 + })
  326 + },
  327 + doEnhanceJs() {
  328 + if (!this.selectedRowKeys || this.selectedRowKeys.length != 1) {
  329 + this.$message.warning('请先选中一条记录')
  330 + return
  331 + }
  332 + this.$refs.ehjs.show(this.selectedRowKeys[0])
  333 + },
  334 + doEnhanceSql() {
  335 + if (!this.selectedRowKeys || this.selectedRowKeys.length != 1) {
  336 + this.$message.warning('请先选中一条记录')
  337 + return
  338 + }
  339 + this.$refs.ehsql.show(this.selectedRowKeys[0])
  340 + },
  341 + doEnhanceJava() {
  342 + if (!this.selectedRowKeys || this.selectedRowKeys.length != 1) {
  343 + this.$message.warning('请先选中一条记录')
  344 + return
  345 + }
  346 + this.$refs.ehjava.show(this.selectedRowKeys[0])
  347 + },
  348 + doCgformButton() {
  349 + if (!this.selectedRowKeys || this.selectedRowKeys.length != 1) {
  350 + this.$message.warning('请先选中一条记录')
  351 + return
  352 + }
  353 + this.$refs.btnList.show(this.selectedRowKeys[0])
  354 +
  355 + //this.$router.push({ path: '/online/cgformButton/' + this.selectedRowKeys[0] })
  356 + },
  357 + importOnlineForm() {
  358 + this.$refs.transd2o.show()
  359 + },
  360 + transOk() {
  361 + this.loadData()
  362 + },
  363 + goGenerateCode() {
  364 + if (!this.selectedRowKeys || this.selectedRowKeys.length != 1) {
  365 + this.$message.warning('请先选中一条记录')
  366 + return
  367 + }
  368 + let row = this.selectedRows[0]
  369 + if (!row.isDbSynch || row.isDbSynch == 'N') {
  370 + this.$message.warning('请先同步数据库!')
  371 + return
  372 + }
  373 + if (row.tableType == 3) {
  374 + this.$message.warning('请选中该表对应的主表生成代码')
  375 + return
  376 + }
  377 + this.$refs.cg.show(this.selectedRowKeys[0])
  378 + },
  379 + onSelectChange(keys, rows) {
  380 + this.selectedRowKeys = keys
  381 + this.selectedRows = rows
  382 + },
  383 + onCopyUrl(){
  384 + var clipboard = new Clipboard('.copy-this-text')
  385 + clipboard.on('success', () => {
  386 + clipboard.destroy()
  387 + this.$message.success('复制成功')
  388 + this.handleOnlineUrlClose()
  389 + })
  390 + clipboard.on('error', () => {
  391 + this.$message.error('该浏览器不支持自动复制')
  392 + clipboard.destroy()
  393 + })
  394 + }
  395 + }
  396 + }
  397 +</script>
  398 +<style lang="less">
  399 + .ant-card-body .table-operator {
  400 + margin-bottom: 18px;
  401 + }
  402 +
  403 + .ant-table-tbody .ant-table-row td {
  404 + padding-top: 15px;
  405 + padding-bottom: 15px;
  406 + }
  407 +
  408 + .anty-row-operator button {
  409 + margin: 0 5px
  410 + }
  411 +
  412 + .ant-btn-danger {
  413 + background-color: #ffffff
  414 + }
  415 +
  416 + .ant-modal-cust-warp {
  417 + height: 100%
  418 + }
  419 +
  420 + .ant-modal-cust-warp .ant-modal-body {
  421 + height: calc(100% - 110px) !important;
  422 + overflow-y: auto
  423 + }
  424 +
  425 + .ant-modal-cust-warp .ant-modal-content {
  426 + height: 90% !important;
  427 + overflow-y: hidden
  428 + }
  429 +
  430 + .valid-error-cust{
  431 + .ant-select-selection{
  432 + border:2px solid #f5222d;
  433 + }
  434 + }
  435 +</style>
0 436 \ No newline at end of file
... ...
ant-design-vue-jeecg/src/views/modules/online/cgform/auto/OnlCgformAutoList.vue 0 → 100644
  1 +<template>
  2 + <a-card :bordered="false" style="height: 100%">
  3 + <div class="table-page-search-wrapper">
  4 + <a-form layout="inline">
  5 + <a-row :gutter="24" v-if="queryInfo && queryInfo.length>0">
  6 + <template v-for="(item,index) in queryInfo">
  7 + <template v-if=" item.hidden==='1' ">
  8 + <a-col v-if="item.view=='datetime'" :md="12" :sm="16" :key=" 'query'+index " v-show="toggleSearchStatus">
  9 + <online-query-form-item :queryParam="queryParam" :item="item" :dictOptions="dictOptions"></online-query-form-item>
  10 + </a-col>
  11 + <a-col v-else :md="6" :sm="8" :key=" 'query'+index " v-show="toggleSearchStatus">
  12 + <online-query-form-item :queryParam="queryParam" :item="item" :dictOptions="dictOptions"></online-query-form-item>
  13 + </a-col>
  14 + </template>
  15 + <template v-else>
  16 + <a-col v-if="item.view=='datetime'" :md="12" :sm="16" :key=" 'query'+index ">
  17 + <online-query-form-item :queryParam="queryParam" :item="item" :dictOptions="dictOptions"></online-query-form-item>
  18 + </a-col>
  19 + <a-col v-else :md="6" :sm="8" :key=" 'query'+index ">
  20 + <online-query-form-item :queryParam="queryParam" :item="item" :dictOptions="dictOptions"></online-query-form-item>
  21 + </a-col>
  22 + </template>
  23 + </template>
  24 +
  25 + <a-col :md="6" :sm="8">
  26 + <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
  27 + <a-button type="primary" @click="searchByquery" icon="search">查询</a-button>
  28 + <a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
  29 + <a @click="handleToggleSearch" style="margin-left: 8px">
  30 + {{ toggleSearchStatus ? '收起' : '展开' }}
  31 + <a-icon :type="toggleSearchStatus ? 'up' : 'down'"/>
  32 + </a>
  33 + </span>
  34 + </a-col>
  35 +
  36 + </a-row>
  37 + </a-form>
  38 + </div>
  39 +
  40 + <!-- 操作按钮区域 -->
  41 + <div class="table-operator">
  42 + <a-button v-if="buttonSwitch.add" @click="handleAdd" type="primary" icon="plus">新增</a-button>
  43 + <a-button v-if="buttonSwitch.import" @click="handleImportXls" type="primary" icon="upload" style="margin-left:8px">导入</a-button>
  44 + <a-button v-if="buttonSwitch.export" @click="handleExportXls" type="primary" icon="download" style="margin-left:8px">导出</a-button>
  45 + <template v-if="cgButtonList && cgButtonList.length>0" v-for="(item,index) in cgButtonList">
  46 + <a-button
  47 + v-if=" item.optType=='js' "
  48 + :key=" 'cgbtn'+index "
  49 + @click="cgButtonJsHandler(item.buttonCode)"
  50 + type="primary"
  51 + :icon="item.buttonIcon"
  52 + style="margin-left:8px">
  53 + {{ item.buttonName }}
  54 + </a-button>
  55 + <a-button
  56 + v-else-if=" item.optType=='action' "
  57 + :key=" 'cgbtn'+index "
  58 + @click="cgButtonActionHandler(item.buttonCode)"
  59 + type="primary"
  60 + :icon="item.buttonIcon"
  61 + style="margin-left:8px">
  62 + {{ item.buttonName }}
  63 + </a-button>
  64 + </template>
  65 +
  66 + <a-button
  67 + v-if="buttonSwitch.batch_delete"
  68 + @click="handleDelBatch"
  69 + style="margin-left:8px"
  70 + v-show="table.selectedRowKeys.length > 0"
  71 + ghost
  72 + type="primary"
  73 + icon="delete">批量删除</a-button>
  74 + </div>
  75 +
  76 + <div>
  77 + <div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
  78 + <i class="anticon anticon-info-circle ant-alert-icon"></i>
  79 + 已选择&nbsp;<a style="font-weight: 600">{{ table.selectedRowKeys.length }}</a>项&nbsp;&nbsp;
  80 + <a style="margin-left: 24px" @click="onClearSelected">清空</a>
  81 + </div>
  82 +
  83 + <a-table
  84 + ref="cgformAutoList"
  85 + bordered
  86 + size="middle"
  87 + rowKey="id"
  88 + :columns="table.columns"
  89 + :dataSource="table.dataSource"
  90 + :pagination="table.pagination"
  91 + :loading="table.loading"
  92 + :rowSelection="{selectedRowKeys:table.selectedRowKeys, onChange: handleChangeInTableSelect}"
  93 + @change="handleTableChange"
  94 + style="min-height: 300px">
  95 +
  96 + <template slot="dateSlot" slot-scope="text">
  97 + <span>{{ getFormatDate(text) }}</span>
  98 + </template>
  99 +
  100 + <template slot="htmlSlot" slot-scope="text">
  101 + <div v-html="text"></div>
  102 + </template>
  103 +
  104 + <template slot="imgSlot" slot-scope="text">
  105 + <span v-if="!text" style="font-size: 12px;font-style: italic;">无此图片</span>
  106 + <img v-else :src="getImgView(text)" height="25px" alt="图片不存在" style="max-width:80px;font-size: 12px;font-style: italic;"/>
  107 + </template>
  108 +
  109 + <template slot="fileSlot" slot-scope="text">
  110 + <span v-if="!text" style="font-size: 12px;font-style: italic;">无此文件</span>
  111 + <a-button
  112 + v-else
  113 + :ghost="true"
  114 + type="primary"
  115 + icon="download"
  116 + size="small"
  117 + @click="uploadFile(text)">
  118 + 下载
  119 + </a-button>
  120 + </template>
  121 +
  122 + <span slot="action" slot-scope="text, record">
  123 + <template v-if="hasBpmStatus">
  124 + <template v-if="record.bpm_status == '1'||record.bpm_status == ''|| record.bpm_status == null">
  125 + <template v-if="buttonSwitch.update">
  126 + <a @click="handleEdit(record)">编辑</a>
  127 + <a-divider type="vertical"/>
  128 + </template>
  129 + </template>
  130 + </template>
  131 + <template v-else>
  132 + <template v-if="buttonSwitch.update">
  133 + <a @click="handleEdit(record)">编辑</a>
  134 + <a-divider type="vertical"/>
  135 + </template>
  136 + </template>
  137 + <a-dropdown>
  138 + <a class="ant-dropdown-link">
  139 + 更多 <a-icon type="down" />
  140 + </a>
  141 + <a-menu slot="overlay">
  142 + <a-menu-item >
  143 + <a href="javascript:;" @click="handleDetail(record)">详情</a>
  144 + </a-menu-item>
  145 + <template v-if="hasBpmStatus">
  146 + </template>
  147 + <template v-else>
  148 + <a-menu-item v-if="buttonSwitch.delete">
  149 + <a-popconfirm title="确定删除吗?" @confirm="() => handleDeleteOne(record)">
  150 + <a>删除</a>
  151 + </a-popconfirm>
  152 + </a-menu-item>
  153 + </template>
  154 + <template v-if="cgButtonLinkList && cgButtonLinkList.length>0" v-for="(btnItem,btnIndex) in cgButtonLinkList">
  155 + <a-menu-item :key=" 'cgbtnLink'+btnIndex ">
  156 + <a href="javascript:void(0);" @click="cgButtonLinkHandler(record,btnItem.buttonCode,btnItem.optType)">
  157 + <a-icon v-if="btnItem.buttonIcon" :type="btnItem.buttonIcon" />
  158 + {{ btnItem.buttonName }}
  159 + </a>
  160 + </a-menu-item>
  161 + </template>
  162 +
  163 + </a-menu>
  164 + </a-dropdown>
  165 + </span>
  166 + </a-table>
  167 +
  168 + <OnlCgformAutoModal @success="handleFormSuccess" ref="modal" :code="code"></OnlCgformAutoModal>
  169 +
  170 + <j-import-modal ref="importModal" :url="getImportUrl()" @ok="importOk"></j-import-modal>
  171 +
  172 + </div>
  173 + </a-card>
  174 +</template>
  175 +
  176 +<script>
  177 +
  178 + import { postAction,getAction,deleteAction,downFile } from '@/api/manage'
  179 + import { filterMultiDictText } from '@/components/dict/JDictSelectUtil'
  180 + import { filterObj } from '@/utils/util';
  181 + import JImportModal from '@/components/jeecg/JImportModal'
  182 +
  183 + export default {
  184 + name: 'OnlCgFormAutoList',
  185 + components: {
  186 + JImportModal
  187 + },
  188 + data() {
  189 + return {
  190 + code: '',
  191 + description: '在线报表功能测试页面',
  192 + currentTableName:"",
  193 + url: {
  194 + getQueryInfo:'/online/cgform/api/getQueryInfo/',
  195 + getColumns: '/online/cgform/api/getColumns/',
  196 + getData: '/online/cgform/api/getData/',
  197 + optPre:"/online/cgform/api/form/",
  198 + exportXls:'/online/cgform/api/exportXls/',
  199 + buttonAction:'/online/cgform/api/doButton',
  200 + },
  201 + flowCodePre:"onl_",
  202 + isorter:{
  203 + column: 'createTime',
  204 + order: 'desc',
  205 + },
  206 + //dictOptions:{fieldName:[]}
  207 + dictOptions:{
  208 +
  209 + },
  210 + cgButtonLinkList:[],
  211 + cgButtonList:[],
  212 + queryInfo:[],
  213 + queryParam:{
  214 +
  215 + },
  216 + toggleSearchStatus:false,
  217 + table: {
  218 + loading: true,
  219 + // 表头
  220 + columns: [],
  221 + //数据集
  222 + dataSource: [],
  223 + // 选择器
  224 + selectedRowKeys: [],
  225 + selectionRows: [],
  226 + // 分页参数
  227 + pagination: {
  228 + current: 1,
  229 + pageSize: 10,
  230 + pageSizeOptions: ['10', '20', '30'],
  231 + showTotal: (total, range) => {
  232 + return range[0] + '-' + range[1] + ' 共' + total + '条'
  233 + },
  234 + showQuickJumper: true,
  235 + showSizeChanger: true,
  236 + total: 0
  237 + }
  238 + },
  239 + actionColumn:{
  240 + title: '操作',
  241 + dataIndex: 'action',
  242 + scopedSlots: { customRender: 'action' },
  243 + fixed:"right",
  244 + align:"center",
  245 + width:150
  246 + },
  247 + formTemplate:"99",
  248 + EnhanceJS:'',
  249 + hideColumns:[],
  250 + buttonSwitch:{
  251 + add:true,
  252 + update:true,
  253 + delete:true,
  254 + batch_delete:true,
  255 + import:true,
  256 + export:true
  257 + },
  258 + hasBpmStatus:false,
  259 + }
  260 + },
  261 + created() {
  262 + this.initAutoList();
  263 + },
  264 + mounted(){
  265 + this.cgButtonJsHandler('mounted')
  266 + },
  267 + watch: {
  268 + '$route'() {
  269 + // 刷新参数放到这里去触发,就可以刷新相同界面了
  270 + this.initAutoList()
  271 + }
  272 + },
  273 + methods: {
  274 + hasBpmStatusFilter(){
  275 + var columnObjs = this.table.columns;
  276 + let columns = [];
  277 + for (var item of columnObjs) {
  278 + columns.push(item.dataIndex);
  279 + }
  280 + if(columns.includes('bpm_status')||columns.includes('BPM_STATUS')){
  281 + this.hasBpmStatus = true;
  282 + }else{
  283 + this.hasBpmStatus = false;
  284 + }
  285 + },
  286 + initQueryInfo(){
  287 + getAction(`${this.url.getQueryInfo}${this.code}`).then((res)=>{
  288 + console.log("--onlineList-获取查询条件配置",res);
  289 + if(res.success){
  290 + this.queryInfo = res.result
  291 + }else{
  292 + this.$message.warning(res.message)
  293 + }
  294 + })
  295 + },
  296 + initAutoList(){
  297 + if(!this.$route.params.code){
  298 + return false
  299 + }
  300 + this.table.loading = true
  301 + this.code = this.$route.params.code
  302 + getAction(`${this.url.getColumns}${this.code}`).then((res)=>{
  303 + console.log("--onlineList-加载动态列>>",res);
  304 + if(res.success){
  305 + this.dictOptions = res.result.dictOptions
  306 + this.formTemplate = res.result.formTemplate
  307 + this.description = res.result.description
  308 + this.currentTableName = res.result.currentTableName
  309 + this.initCgButtonList(res.result.cgButtonList)
  310 + this.initCgEnhanceJs(res.result.enhanceJs)
  311 + this.initButtonSwitch(res.result.hideColumns)
  312 + let currColumns = res.result.columns
  313 + for(let a=0;a<currColumns.length;a++){
  314 + if(currColumns[a].customRender){
  315 + let dictCode = currColumns[a].customRender;
  316 + currColumns[a].customRender=(text)=>{
  317 + return filterMultiDictText(this.dictOptions[dictCode], text);
  318 + }
  319 + }
  320 + }
  321 + currColumns.push(this.actionColumn);
  322 + this.table.columns = [...currColumns]
  323 + this.hasBpmStatusFilter();
  324 + this.loadData();
  325 + this.initQueryInfo();
  326 + }else{
  327 + this.$message.warning(res.message)
  328 + }
  329 + })
  330 + },
  331 + loadData(arg){
  332 + if(arg==1){
  333 + this.table.pagination.current=1
  334 + }
  335 + let params = this.getQueryParams();//查询条件
  336 + console.log("--onlineList-查询条件-->",params)
  337 + getAction(`${this.url.getData}${this.code}`,params).then((res)=>{
  338 + console.log("--onlineList-列表数据",res)
  339 + if(res.success){
  340 + let result = res.result;
  341 + if(Number(result.total)>0){
  342 + this.table.pagination.total = Number(result.total)
  343 + this.table.dataSource = result.records
  344 + }else{
  345 + this.table.pagination.total=0;
  346 + this.table.dataSource=[]
  347 + //this.$message.warning("查无数据")
  348 + }
  349 + }else{
  350 + this.$message.warning(res.message)
  351 + }
  352 + this.table.loading = false
  353 + })
  354 + },
  355 + getQueryParams() {
  356 + let param = Object.assign({}, this.queryParam,this.isorter);
  357 + param.pageNo = this.table.pagination.current;
  358 + param.pageSize = this.table.pagination.pageSize;
  359 + return filterObj(param);
  360 + },
  361 + handleChangeInTableSelect(selectedRowKeys, selectionRows) {
  362 + this.table.selectedRowKeys = selectedRowKeys
  363 + this.table.selectionRows = selectionRows
  364 + },
  365 + handleTableChange(pagination, filters, sorter){
  366 + //TODO 筛选
  367 + if (Object.keys(sorter).length>0){
  368 + this.isorter.column = sorter.field;
  369 + this.isorter.order = "ascend"==sorter.order?"asc":"desc"
  370 + }
  371 + this.table.pagination = pagination;
  372 + this.loadData();
  373 + },
  374 + handleAdd(){
  375 + this.cgButtonJsHandler('beforeAdd')
  376 + this.$refs.modal.add(this.formTemplate);
  377 + },
  378 + handleImportXls(){
  379 + this.$refs.importModal.show()
  380 + },
  381 + importOk(){
  382 + this.loadData(1)
  383 + },
  384 + handleExportXls2(){
  385 + let param = this.queryParam;
  386 + if(this.table.selectedRowKeys && this.table.selectedRowKeys.length>0){
  387 + param['selections'] = this.table.selectedRowKeys.join(",")
  388 + }
  389 + let paramsStr = encodeURI(JSON.stringify(param));
  390 + console.log('paramsStr: ' + paramsStr)
  391 + let url = window._CONFIG['domianURL']+this.url.exportXls+this.code+"?paramsStr="+paramsStr
  392 + window.location.href = url;
  393 + },
  394 + handleExportXls(){
  395 + let param = this.queryParam;
  396 + if(this.table.selectedRowKeys && this.table.selectedRowKeys.length>0){
  397 + param['selections'] = this.table.selectedRowKeys.join(",")
  398 + }
  399 + console.log("导出参数",param)
  400 + let paramsStr = JSON.stringify(filterObj(param));
  401 + downFile(this.url.exportXls+this.code,{paramsStr:paramsStr}).then((data)=>{
  402 + if (!data) {
  403 + this.$message.warning("文件下载失败")
  404 + return
  405 + }
  406 + if (typeof window.navigator.msSaveBlob !== 'undefined') {
  407 + window.navigator.msSaveBlob(new Blob([data]), this.description+'.xls')
  408 + }else{
  409 + let url = window.URL.createObjectURL(new Blob([data]))
  410 + let link = document.createElement('a')
  411 + link.style.display = 'none'
  412 + link.href = url
  413 + link.setAttribute('download', this.description+'.xls')
  414 + document.body.appendChild(link)
  415 + link.click()
  416 + document.body.removeChild(link); //下载完成移除元素
  417 + window.URL.revokeObjectURL(url); //释放掉blob对象
  418 + }
  419 + })
  420 + },
  421 + handleEdit(record){
  422 + this.cgButtonLinkHandler(record,"beforeEdit","js")
  423 + this.$refs.modal.edit(this.formTemplate,record.id);
  424 + },
  425 + handleDetail(record){
  426 + this.$refs.modal.detail(this.formTemplate,record.id);
  427 + },
  428 + handleDeleteOne(record){
  429 + this.cgButtonLinkHandler(record,"beforeDelete","js")
  430 + this.handleDelete(record.id)
  431 + },
  432 + handleDelete(id){
  433 + deleteAction(this.url.optPre+this.code+"/"+id).then((res)=>{
  434 + if(res.success){
  435 + this.$message.success(res.message)
  436 + this.loadData()
  437 + }else{
  438 + this.$message.warning(res.message)
  439 + }
  440 + })
  441 + },
  442 +
  443 + handleFormSuccess(){
  444 + this.loadData()
  445 + },
  446 + onClearSelected(){
  447 + this.table.selectedRowKeys = []
  448 + this.table.selectionRows = []
  449 + },
  450 + getImgView(text){
  451 + if(text && text.indexOf(",")>0){
  452 + text = text.substring(0,text.indexOf(","))
  453 + }
  454 + return window._CONFIG['imgDomainURL']+"/"+text
  455 + },
  456 + uploadFile(text){
  457 + if(!text){
  458 + this.$message.warning("未知的文件")
  459 + return;
  460 + }
  461 + if(text.indexOf(",")>0){
  462 + text = text.substring(0,text.indexOf(","))
  463 + }
  464 + window.open(window._CONFIG['imgDomainURL']+"/"+text);//TODO 下载的方法
  465 + },
  466 + handleDelBatch(){
  467 + if(this.table.selectedRowKeys.length<=0){
  468 + this.$message.warning('请选择一条记录!');
  469 + return false;
  470 + }else{
  471 + let ids = "";
  472 + let that = this;
  473 + that.table.selectedRowKeys.forEach(function(val) {
  474 + ids+=val+",";
  475 + });
  476 + that.$confirm({
  477 + title:"确认删除",
  478 + content:"是否删除选中数据?",
  479 + onOk: function(){
  480 + that.handleDelete(ids)
  481 + that.onClearSelected();
  482 + }
  483 + });
  484 + }
  485 + },
  486 +
  487 + searchByquery(){
  488 + this.loadData(1);
  489 + },
  490 + searchReset(){
  491 + this.queryParam = {}
  492 + this.loadData(1);
  493 + },
  494 + handleToggleSearch(){
  495 + this.toggleSearchStatus = !this.toggleSearchStatus;
  496 + },
  497 + getFormatDate(text){
  498 + if(!text){
  499 + return ''
  500 + }
  501 + let a = text;
  502 + if(a.length>10){
  503 + a = a.substring(0,10);
  504 + }
  505 + return a;
  506 + },
  507 + getImportUrl(){
  508 + return '/online/cgform/api/importXls/'+this.code
  509 + },
  510 + initCgEnhanceJs(enhanceJs){
  511 + //console.log("--onlineList-js增强",enhanceJs)
  512 + if(enhanceJs){
  513 + let Obj = eval ("(" + enhanceJs + ")");
  514 + this.EnhanceJS = new Obj(getAction,postAction,deleteAction);
  515 + this.cgButtonJsHandler('created')
  516 + }else{
  517 + this.EnhanceJS = ''
  518 + }
  519 + },
  520 + initCgButtonList(btnList){
  521 + let linkArr = []
  522 + let buttonArr = []
  523 + if(btnList && btnList.length>0){
  524 + for(let i=0;i<btnList.length;i++){
  525 + let temp = btnList[i]
  526 + if(temp.buttonStyle=='button'){
  527 + buttonArr.push(temp)
  528 + }else if(temp.buttonStyle=='link'){
  529 + linkArr.push(temp)
  530 + }
  531 + }
  532 + }
  533 + this.cgButtonLinkList = [...linkArr]
  534 + this.cgButtonList=[...buttonArr]
  535 + },
  536 + cgButtonJsHandler(buttonCode){
  537 + if(this.EnhanceJS[buttonCode]){
  538 + this.EnhanceJS[buttonCode](this)
  539 + }
  540 + },
  541 + cgButtonActionHandler(buttonCode){
  542 + //处理自定义button的 需要配置该button自定义sql
  543 + if(!this.table.selectedRowKeys || this.table.selectedRowKeys.length==0){
  544 + this.$message.warning("请先选中一条记录")
  545 + return false
  546 + }
  547 + if(this.table.selectedRowKeys.length>1){
  548 + this.$message.warning("请只选中一条记录")
  549 + return false
  550 + }
  551 + let params = {
  552 + formId:this.code,
  553 + buttonCode:buttonCode,
  554 + dataId:this.table.selectedRowKeys[0]
  555 + }
  556 + console.log("自定义按钮请求后台参数:",params)
  557 + postAction(this.url.buttonAction,params).then(res=>{
  558 + if(res.success){
  559 + this.loadData()
  560 + this.$message.success("处理完成!")
  561 + }else{
  562 + this.$message.warning("处理失败!")
  563 + }
  564 + })
  565 +
  566 + },
  567 + cgButtonLinkHandler(record,buttonCode,optType){
  568 + if(optType=="js"){
  569 + if(this.EnhanceJS[buttonCode]){
  570 + this.EnhanceJS[buttonCode](this,record)
  571 + }
  572 + }else if(optType=="action"){
  573 + let params = {
  574 + formId:this.code,
  575 + buttonCode:buttonCode,
  576 + dataId:record.id
  577 + }
  578 + console.log("自定义按钮link请求后台参数:",params)
  579 + postAction(this.url.buttonAction,params).then(res=>{
  580 + if(res.success){
  581 + this.loadData()
  582 + this.$message.success("处理完成!")
  583 + }else{
  584 + this.$message.warning("处理失败!")
  585 + }
  586 + })
  587 + }
  588 + },
  589 + initButtonSwitch(hideColumns){
  590 + if(hideColumns && hideColumns.length>0){
  591 + Object.keys(this.buttonSwitch).forEach(key=>{
  592 + if(hideColumns.indexOf(key)>=0){
  593 + this.buttonSwitch[key]=false
  594 + }
  595 + })
  596 +
  597 + }
  598 + }
  599 +
  600 + }
  601 + }
  602 +</script>
  603 +<style>
  604 + .ant-card-body .table-operator{
  605 + margin-bottom: 18px;
  606 + }
  607 + .ant-table-tbody .ant-table-row td{
  608 + padding-top:15px;
  609 + padding-bottom:15px;
  610 + }
  611 + .anty-row-operator button{margin: 0 5px}
  612 + .ant-btn-danger{background-color: #ffffff}
  613 +
  614 + .anty-img-wrap{height:25px;position: relative;}
  615 + .anty-img-wrap > img{max-height:100%;}
  616 + .ant-modal-cust-warp{height: 100%}
  617 + .ant-modal-cust-warp .ant-modal-body{height:calc(100% - 110px) !important;overflow-y: auto}
  618 + .ant-modal-cust-warp .ant-modal-content{height:90% !important;overflow-y: hidden}
  619 +</style>
0 620 \ No newline at end of file
... ...