Jeecg-Boot 2.1.4 版本发布 | 重构较大,较多新功能

pull/1067/merge
zhangdaiscott 2020-02-24 02:44:53 +08:00
parent 06847cd801
commit 4a4f236772
269 changed files with 15734 additions and 24855 deletions

View File

@ -1,13 +1,13 @@
Ant Design Jeecg Vue
====
当前最新版本: 2.1.3发布日期20191226
当前最新版本: 2.0.4发布日期20200224
Overview
----
基于 [Ant Design of Vue](https://vuecomponent.github.io/ant-design-vue/docs/vue/introduce-cn/) 实现的 Ant Design Pro Vue 版
Jeecg-boot 的前端UI框架采用前后端分离框架,提供强大代码生成器的快速开发平台。
Jeecg-boot 的前段UI框架采用前后端分离方案,提供强大代码生成器的快速开发平台。
前端页面代码和后端功能代码一键生成不需要写任何代码保持jeecg一贯的强大

View File

@ -1,6 +1,6 @@
{
"name": "vue-antd-jeecg",
"version": "2.1.3",
"version": "2.1.4",
"private": true,
"scripts": {
"pre": "cnpm install || yarn --registry https://registry.npm.taobao.org || npm install --registry https://registry.npm.taobao.org ",
@ -10,7 +10,7 @@
},
"dependencies": {
"@antv/data-set": "^0.10.2",
"@jeecg/antd-online-re": "2.1.3",
"@jeecg/antd-online-214": "^2.1.4",
"@tinymce/tinymce-vue": "^2.0.0",
"ant-design-vue": "^1.4.0",
"apexcharts": "^3.6.5",
@ -24,7 +24,7 @@
"lodash.pick": "^4.4.0",
"md5": "^2.2.1",
"nprogress": "^0.2.0",
"tinymce": "^5.0.2",
"tinymce": "^5.1.4",
"viser-vue": "^2.4.4",
"vue": "^2.6.10",
"vue-apexcharts": "^1.3.2",
@ -51,12 +51,12 @@
"babel-eslint": "^10.0.1",
"eslint": "^5.16.0",
"eslint-plugin-vue": "^5.1.0",
"html-webpack-plugin": "^4.0.0-beta.11",
"less": "^3.9.0",
"less-loader": "^4.1.0",
"node-sass": "^4.11.0",
"sass-loader": "^7.0.1",
"vue-template-compiler": "^2.6.10",
"html-webpack-plugin": "^4.0.0-beta.11"
"vue-template-compiler": "^2.6.10"
},
"eslintConfig": {
"root": true,

View File

@ -5,9 +5,9 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Jeecg-Boot </title>
<title>Jeecg-Boot </title>
<link rel="icon" href="<%= BASE_URL %>logo.png">
<script src="https://cdn.bootcss.com/babel-polyfill/7.6.0/polyfill.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.2.5/polyfill.js"></script>
<style>
html,
body,
@ -244,8 +244,8 @@
window._CONFIG = {};
window._CONFIG['domianURL'] = 'http://127.0.0.1:8080/jeecg-boot';
window._CONFIG['casPrefixUrl'] = 'http://cas.example.org:8443/cas';
window._CONFIG['imgDomainURL'] = window._CONFIG['domianURL'] + '/sys/common/view';
window._CONFIG['downloadUrl'] = window._CONFIG['domianURL'] + '/sys/common/download';
window._CONFIG['onlinePreviewDomainURL'] = 'http://fileview.jeecg.com/onlinePreview'
window._CONFIG['staticDomainURL'] = window._CONFIG['domianURL'] + '/sys/common/static';
window._CONFIG['pdfDomainURL'] = window._CONFIG['domianURL'] + '/sys/common/pdf/pdfPreviewIframe';
</script>
</head>

View File

@ -25,7 +25,7 @@ const frozenBatch = (params)=>putAction("/sys/user/frozenBatch",params);
//验证用户是否存在
const checkOnlyUser = (params)=>getAction("/sys/user/checkOnlyUser",params);
//改变密码
const changPassword = (params)=>putAction("/sys/user/changPassword",params);
const changePassword = (params)=>putAction("/sys/user/changePassword",params);
//权限管理
const addPermission= (params)=>postAction("/sys/permission/add",params);
@ -34,6 +34,7 @@ const getPermissionList = (params)=>getAction("/sys/permission/list",params);
/*update_begin author:wuxianquan date:20190908 for:添加查询一级菜单和子菜单查询api */
const getSystemMenuList = (params)=>getAction("/sys/permission/getSystemMenuList",params);
const getSystemSubmenu = (params)=>getAction("/sys/permission/getSystemSubmenu",params);
const getSystemSubmenuBatch = (params) => getAction('/sys/permission/getSystemSubmenuBatch', params)
/*update_end author:wuxianquan date:20190908 for:添加查询一级菜单和子菜单查询api */
// const deletePermission = (params)=>deleteAction("/sys/permission/delete",params);
@ -56,6 +57,14 @@ const queryParentName = (params)=>getAction("/sys/sysDepart/queryParentName",p
const searchByKeywords = (params)=>getAction("/sys/sysDepart/searchBy",params);
const deleteByDepartId = (params)=>deleteAction("/sys/sysDepart/delete",params);
//二级部门管理
const queryDepartPermission = (params)=>getAction("/sys/permission/queryDepartPermission",params);
const saveDepartPermission = (params)=>postAction("/sys/permission/saveDepartPermission",params);
const queryTreeListForDeptRole = (params)=>getAction("/sys/sysDepartPermission/queryTreeListForDeptRole",params);
const queryDeptRolePermission = (params)=>getAction("/sys/sysDepartPermission/queryDeptRolePermission",params);
const saveDeptRolePermission = (params)=>postAction("/sys/sysDepartPermission/saveDeptRolePermission",params);
const queryMyDepartTreeList = (params)=>getAction("/sys/sysDepart/queryMyDeptTreeList",params);
//日志管理
//const getLogList = (params)=>getAction("/sys/log/list",params);
const deleteLog = (params)=>deleteAction("/sys/log/delete",params);
@ -94,6 +103,7 @@ const queryUserRoleMap = (params)=>getAction("/sys/user/queryUserRoleMap",params
const duplicateCheck = (params)=>getAction("/sys/duplicate/check",params);
// 加载分类字典
const loadCategoryData = (params)=>getAction("/sys/category/loadAllData",params);
const checkRuleByCode = (params) => getAction('/sys/checkRule/checkByCode', params)
export {
// imgView,
@ -108,7 +118,7 @@ export {
queryall,
frozenBatch,
checkOnlyUser,
changPassword,
changePassword,
getPermissionList,
addPermission,
editPermission,
@ -142,7 +152,15 @@ export {
queryTreeListForRole,
getSystemMenuList,
getSystemSubmenu,
loadCategoryData
getSystemSubmenuBatch,
loadCategoryData,
checkRuleByCode,
queryDepartPermission,
saveDepartPermission,
queryTreeListForDeptRole,
queryDeptRolePermission,
saveDeptRolePermission,
queryMyDepartTreeList
}

View File

@ -112,3 +112,17 @@ export function downFile(url,parameter){
})
}
/**
* 访
* @param avatar
* @param imgerver
* @param str
* @returns {*}
*/
export function getFileAccessHttpUrl(avatar,imgerver,subStr) {
if(avatar && avatar.indexOf(subStr) != -1 ){
return avatar;
}else{
return imgerver + "/" + avatar;
}
}

View File

@ -5,7 +5,7 @@
}
/** Button按钮间距 */
.table-operator .ant-btn {
margin-right: 6px
margin: 8px 8px 0 0;
}
/*列表td的padding设置 可以控制列表大小*/
.ant-table-tbody .ant-table-row td {

View File

@ -1,7 +1,7 @@
<template>
<div :style="{ padding: '0 50px 32px 0' }">
<h4 :style="{ marginBottom: '20px' }">{{ title }}</h4>
<v-chart :forceFit="true" :height="height" :data="data" :scale="scale" :padding=" padding">
<v-chart :forceFit="true" :height="height" :data="data" :scale="scale" :padding=" padding" :onClick="handleClick">
<v-tooltip/>
<v-legend/>
<v-axis/>
@ -12,9 +12,11 @@
</template>
<script>
import { ChartEventMixins } from './mixins/ChartMixins'
export default {
name: 'BarMultid',
name: 'BarAndLine',
mixins: [ChartEventMixins],
props: {
title: {
type: String,

View File

@ -1,71 +1,83 @@
<template>
<div :style="{ padding: '0 0 32px 32px' }">
<h4 :style="{ marginBottom: '20px' }">{{ title }}</h4>
<v-chart :forceFit="true" :height="254" :data="chartData" :padding="['auto', 'auto', '40', '50']">
<v-tooltip />
<v-axis />
<v-legend />
<v-bar position="x*y" color="type" :adjust="adjust" />
<v-chart :data="data" :height="height" :force-fit="true" :onClick="handleClick">
<v-tooltip/>
<v-axis/>
<v-legend/>
<v-bar position="x*y" color="type" :adjust="adjust"/>
</v-chart>
</div>
</template>
<script>
import { DataSet } from '@antv/data-set'
import { ChartEventMixins } from './mixins/ChartMixins'
const sourceDataConst = [
{ type: 'Jeecg', 'Jan.': 18.9, 'Feb.': 28.8, 'Mar.': 39.3, 'Apr.': 81.4, 'May': 47, 'Jun.': 20.3, 'Jul.': 24, 'Aug.': 35.6 },
{ type: 'Jeebt', 'Jan.': 12.4, 'Feb.': 23.2, 'Mar.': 34.5, 'Apr.': 99.7, 'May': 52.6, 'Jun.': 35.5, 'Jul.': 37.4, 'Aug.': 42.4 },
];
const fieldsConst = ['Jan.', 'Feb.', 'Mar.', 'Apr.', 'May', 'Jun.', 'Jul.', 'Aug.'];
export default {
name: 'BarMultid',
mixins: [ChartEventMixins],
props: {
title: {
type: String,
default: ''
},
sourceData:{
type:Array,
default:()=>[]
dataSource: {
type: Array,
default: () => [
{ type: 'Jeecg', 'Jan.': 18.9, 'Feb.': 28.8, 'Mar.': 39.3, 'Apr.': 81.4, 'May': 47, 'Jun.': 20.3, 'Jul.': 24, 'Aug.': 35.6 },
{ type: 'Jeebt', 'Jan.': 12.4, 'Feb.': 23.2, 'Mar.': 34.5, 'Apr.': 99.7, 'May': 52.6, 'Jun.': 35.5, 'Jul.': 37.4, 'Aug.': 42.4 }
]
},
fields:{
type:Array,
default:()=>[]
fields: {
type: Array,
default: () => ['Jan.', 'Feb.', 'Mar.', 'Apr.', 'May', 'Jun.', 'Jul.', 'Aug.']
},
// 别名,需要的格式:[{field:'name',alias:'姓名'}, {field:'sex',alias:'性别'}]
aliases: {
type: Array,
default: () => []
},
height: {
type: Number,
default: 254
}
},
data() {
return {
chartData:"",
height: 400,
adjust: [{
type: 'dodge',
marginRatio: 1 / 32,
}],
};
},
watch: {
'sourceData': function () {
this.drawChart();
marginRatio: 1 / 32
}]
}
},
mounted(){
this.drawChart()
},
methods:{
drawChart(){
let temp = sourceDataConst;
if(this.sourceData && this.sourceData.length>0){
temp = this.sourceData
}
const dv = new DataSet.View().source(temp);
computed: {
data() {
const dv = new DataSet.View().source(this.dataSource)
dv.transform({
type: 'fold',
fields:(!this.fields||this.fields.length==0)?fieldsConst:this.fields,
fields: this.fields,
key: 'x',
value: 'y',
});
this.chartData=dv.rows;
value: 'y'
})
// bar 使用不了 - 和 / 所以替换下
let rows = dv.rows.map(row => {
if (typeof row.x === 'string') {
row.x = row.x.replace(/[-/]/g, '_')
}
return row
})
// 替换别名
rows.forEach(row => {
for (let item of this.aliases) {
if (item.field === row.type) {
row.type = item.alias
break
}
}
})
return rows
}
}
}

View File

@ -1,7 +1,7 @@
<template>
<div :style="{ padding: '0 0 32px 32px' }">
<h4 :style="{ marginBottom: '20px' }">{{ title }}</h4>
<v-chart :force-fit="true" :height="height" :data="data" :scale="scale">
<v-chart :force-fit="true" :height="height" :data="data" :scale="scale" :onClick="handleClick">
<v-tooltip/>
<v-axis/>
<v-legend/>
@ -13,9 +13,11 @@
<script>
import { DataSet } from '@antv/data-set'
import { ChartEventMixins } from './mixins/ChartMixins'
export default {
name: 'LineChartMultid',
mixins: [ChartEventMixins],
props: {
title: {
type: String,

View File

@ -1,5 +1,5 @@
<template>
<v-chart :forceFit="true" :height="height" :data="data" :scale="scale">
<v-chart :forceFit="true" :height="height" :data="data" :scale="scale" :onClick="handleClick">
<v-tooltip :showTitle="false" dataKey="item*percent"/>
<v-axis/>
<v-legend dataKey="item"/>
@ -10,8 +10,11 @@
<script>
const DataSet = require('@antv/data-set')
import { ChartEventMixins } from './mixins/ChartMixins'
export default {
name: 'Pie',
mixins: [ChartEventMixins],
props: {
title: {
type: String,

View File

@ -0,0 +1,10 @@
export const ChartEventMixins = {
methods: {
handleClick(event, chart) {
this.handleEvent('click', event, chart)
},
handleEvent(eventName, event, chart) {
this.$emit(eventName, event, chart)
},
}
}

View File

@ -1,10 +1,10 @@
<template>
<a-radio-group v-if="tagType=='radio'" @change="handleInput" :value="value" :disabled="disabled">
<a-radio-group v-if="tagType=='radio'" @change="handleInput" :value="getValueSting" :disabled="disabled">
<a-radio v-for="(item, key) in dictOptions" :key="key" :value="item.value">{{ item.text }}</a-radio>
</a-radio-group>
<a-select v-else-if="tagType=='select'" :getPopupContainer = "(target) => target.parentNode" :placeholder="placeholder" :disabled="disabled" :value="value" @change="handleInput">
<a-select-option value=""></a-select-option>
<a-select v-else-if="tagType=='select'" :getPopupContainer = "(target) => target.parentNode" :placeholder="placeholder" :disabled="disabled" :value="getValueSting" @change="handleInput">
<a-select-option :value="undefined"></a-select-option>
<a-select-option v-for="(item, key) in dictOptions" :key="key" :value="item.value">
<span style="display: inline-block;width: 100%" :title=" item.text || item.label ">
{{ item.text || item.label }}
@ -23,7 +23,7 @@
placeholder: String,
triggerChange: Boolean,
disabled: Boolean,
value: String,
value: [String, Number],
type: String
},
data() {
@ -50,6 +50,11 @@
//获取字典数据
// this.initDictData();
},
computed: {
getValueSting(){
return this.value ? this.value.toString() : null;
},
},
methods: {
initDictData() {
//根据字典Code, 初始化字典数组

View File

@ -47,10 +47,20 @@ export function filterDictText(dictOptions, text) {
* @return String
*/
export function filterMultiDictText(dictOptions, text) {
//js “!text” 认为0为空所以做提前处理
if(text === 0 || text === '0'){
for (let dictItem of dictOptions) {
if (text == dictItem.value) {
return dictItem.text
}
}
}
if(!text || !dictOptions || dictOptions.length==0){
return ""
}
let re = "";
text = text.toString()
let arr = text.split(",")
dictOptions.forEach(function (option) {
for(let i=0;i<arr.length;i++){

View File

@ -32,6 +32,8 @@
</a-col>
</a-row>
<slot name="actionButtonAfter" :target="getVM()"/>
<div :id="`${caseId}inputTable`" class="input-table">
<!-- -->
<div class="thead" ref="thead">
@ -142,7 +144,9 @@
placement="top"
:title="(tooltips[id] || {}).title"
:visible="(tooltips[id] || {}).visible || false"
:autoAdjustOverflow="true">
:autoAdjustOverflow="true"
:getPopupContainer="getParentContainer"
>
<input
:id="id"
@ -175,7 +179,9 @@
placement="top"
:title="(tooltips[id] || {}).title"
:visible="(tooltips[id] || {}).visible || false"
:autoAdjustOverflow="true">
:autoAdjustOverflow="true"
:getPopupContainer="getParentContainer"
>
<span
@mouseover="()=>{handleMouseoverCommono(row,col)}"
@ -211,7 +217,9 @@
placement="top"
:title="(tooltips[id] || {}).title"
:visible="(tooltips[id] || {}).visible || false"
:autoAdjustOverflow="true">
:autoAdjustOverflow="true"
:getPopupContainer="getParentContainer"
>
<span
@mouseover="()=>{handleMouseoverCommono(row,col)}"
@ -278,19 +286,33 @@
</template>
<div :hidden="uploadValues[id] != null">
<a-upload
name="file"
:data="{'isup':1}"
:multiple="false"
:action="col.action"
:headers="uploadGetHeaders(row,col)"
:showUploadList="false"
v-bind="buildProps(row,col)"
@change="(v)=>handleChangeUpload(v,id,row,col)"
<a-tooltip
:key="i"
:id="id"
placement="top"
:title="(tooltips[id] || {}).title"
:visible="(tooltips[id] || {}).visible || false"
:autoAdjustOverflow="true"
:getPopupContainer="getParentContainer"
>
<a-button icon="upload">{{ col.placeholder }}</a-button>
</a-upload>
<span
@mouseover="()=>{handleMouseoverCommono(row,col)}"
@mouseout="()=>{handleMouseoutCommono(row,col)}">
<a-upload
name="file"
:data="{'isup':1}"
:multiple="false"
:action="col.action"
:headers="uploadGetHeaders(row,col)"
:showUploadList="false"
v-bind="buildProps(row,col)"
@change="(v)=>handleChangeUpload(v,id,row,col)"
>
<a-button icon="upload">{{ col.placeholder }}</a-button>
</a-upload>
</span>
</a-tooltip>
</div>
</div>
@ -303,7 +325,10 @@
placement="top"
:title="(tooltips[id] || {}).title"
:visible="(tooltips[id] || {}).visible || false"
:autoAdjustOverflow="true">
:autoAdjustOverflow="true"
:getPopupContainer="getParentContainer"
>
<span
@mouseover="()=>{handleMouseoverCommono(row,col)}"
@mouseout="()=>{handleMouseoutCommono(row,col)}">
@ -359,19 +384,33 @@
</template>
<div :hidden="uploadValues[id] != null">
<a-upload
name="file"
:data="{'isup':1}"
:multiple="false"
:action="getUploadAction(col.action)"
:headers="uploadGetHeaders(row,col)"
:showUploadList="false"
v-bind="buildProps(row,col)"
@change="(v)=>handleChangeUpload(v,id,row,col)"
<a-tooltip
:key="i"
:id="id"
placement="top"
:title="(tooltips[id] || {}).title"
:visible="(tooltips[id] || {}).visible || false"
:autoAdjustOverflow="true"
:getPopupContainer="getParentContainer"
>
<a-button icon="upload">{{ col.placeholder }}</a-button>
</a-upload>
<span
@mouseover="()=>{handleMouseoverCommono(row,col)}"
@mouseout="()=>{handleMouseoutCommono(row,col)}">
<a-upload
name="file"
:data="{'isup':1}"
:multiple="false"
:action="getUploadAction(col.action)"
:headers="uploadGetHeaders(row,col)"
:showUploadList="false"
v-bind="buildProps(row,col)"
@change="(v)=>handleChangeUpload(v,id,row,col)"
>
<a-button icon="upload">{{ col.placeholder }}</a-button>
</a-upload>
</span>
</a-tooltip>
</div>
</div>
@ -406,19 +445,33 @@
</template>
<div :hidden="uploadValues[id] != null">
<a-upload
name="file"
:data="{'isup':1}"
:multiple="false"
:action="getUploadAction(col.action)"
:headers="uploadGetHeaders(row,col)"
:showUploadList="false"
v-bind="buildProps(row,col)"
@change="(v)=>handleChangeUpload(v,id,row,col)"
<a-tooltip
:key="i"
:id="id"
placement="top"
:title="(tooltips[id] || {}).title"
:visible="(tooltips[id] || {}).visible || false"
:autoAdjustOverflow="true"
:getPopupContainer="getParentContainer"
>
<a-button icon="upload"></a-button>
</a-upload>
<span
@mouseover="()=>{handleMouseoverCommono(row,col)}"
@mouseout="()=>{handleMouseoutCommono(row,col)}">
<a-upload
name="file"
:data="{'isup':1}"
:multiple="false"
:action="getUploadAction(col.action)"
:headers="uploadGetHeaders(row,col)"
:showUploadList="false"
v-bind="buildProps(row,col)"
@change="(v)=>handleChangeUpload(v,id,row,col)"
>
<a-button icon="upload"></a-button>
</a-upload>
</span>
</a-tooltip>
</div>
</div>
@ -433,7 +486,10 @@
placement="top"
:title="(tooltips[id] || {}).title"
:visible="(tooltips[id] || {}).visible || false"
:autoAdjustOverflow="true">
:autoAdjustOverflow="true"
:getPopupContainer="getParentContainer"
>
<span
@mouseover="()=>{handleMouseoverCommono(row,col)}"
@mouseout="()=>{handleMouseoutCommono(row,col)}">
@ -459,7 +515,9 @@
placement="top"
:title="(tooltips[id] || {}).title"
:visible="(tooltips[id] || {}).visible || false"
:autoAdjustOverflow="true">
:autoAdjustOverflow="true"
:getPopupContainer="getParentContainer"
>
<span
@mouseover="()=>{handleMouseoverCommono(row,col)}"
@ -492,7 +550,9 @@
placement="top"
:title="(tooltips[id] || {}).title"
:visible="(tooltips[id] || {}).visible || false"
:autoAdjustOverflow="true">
:autoAdjustOverflow="true"
:getPopupContainer="getParentContainer"
>
<span
@mouseover="()=>{handleMouseoverCommono(row,col)}"
@ -526,7 +586,9 @@
placement="top"
:title="(tooltips[id] || {}).title"
:visible="(tooltips[id] || {}).visible || false"
:autoAdjustOverflow="true">
:autoAdjustOverflow="true"
:getPopupContainer="getParentContainer"
>
<span
@mouseover="()=>{handleMouseoverCommono(row,col)}"
@ -693,6 +755,7 @@
}
},
created() {
this.inputValues = []
// 当前显示的tr
this.visibleTrEls = []
this.disabledRowIds = (this.disabledRowIds || [])
@ -771,149 +834,155 @@
dataSource: {
immediate: true,
handler: function (newValue) {
this.initialize()
// 兼容IE
this.getElementPromise('tbody').then(() => {
let rows = []
let checkboxValues = {}
let selectValues = {}
let jdateValues = {}
let slotValues = {}
let uploadValues = {}
let popupValues = {}
let radioValues = {}
let multiSelectValues = {}
let searchSelectValues = {}
this.initialize()
// 禁用行的id
let disabledRowIds = (this.disabledRowIds || [])
newValue.forEach((data, newValueIndex) => {
// 判断源数据是否带有id
if (data.id == null || data.id === '') {
data.id = this.removeCaseId(this.generateId() + newValueIndex)
}
let rows = []
let checkboxValues = {}
let selectValues = {}
let jdateValues = {}
let slotValues = {}
let uploadValues = {}
let popupValues = {}
let radioValues = {}
let multiSelectValues = {}
let searchSelectValues = {}
let value = { id: this.caseId + data.id }
let row = { id: value.id }
let disabled = false
this.columns.forEach(column => {
let inputId = column.key + value.id
let sourceValue = (data[column.key] == null ? '' : data[column.key]).toString()
if (column.type === FormTypes.checkbox) {
// 判断是否设定了customValue自定义值
if (column.customValue instanceof Array) {
let customValue = (column.customValue[0] || '').toString()
checkboxValues[inputId] = (sourceValue === customValue)
} else {
checkboxValues[inputId] = sourceValue
}
} else if (column.type === FormTypes.select) {
if (sourceValue) {
// 判断是否是多选
selectValues[inputId] = (column.props || {})['mode'] === 'multiple' ? sourceValue.split(',') : sourceValue
} else {
selectValues[inputId] = undefined
}
} else if (column.type === FormTypes.date || column.type === FormTypes.datetime) {
jdateValues[inputId] = sourceValue
} else if (column.type === FormTypes.slot) {
if (sourceValue !== 0 && !sourceValue) {
slotValues[inputId] = column.defaultValue
} else {
slotValues[inputId] = sourceValue
}
} else if (column.type === FormTypes.popup) {
popupValues[inputId] = sourceValue
} else if (column.type === FormTypes.radio) {
radioValues[inputId] = sourceValue
} else if (column.type === FormTypes.sel_search) {
searchSelectValues[inputId] = sourceValue
} else if (column.type === FormTypes.list_multi) {
if (sourceValue.length > 0) {
multiSelectValues[inputId] = sourceValue.split(',')
} else {
multiSelectValues[inputId] = []
}
} else if (column.type === FormTypes.upload || column.type === FormTypes.file || column.type === FormTypes.image) {
if (sourceValue) {
let fileName = sourceValue.substring(sourceValue.lastIndexOf('/') + 1)
uploadValues[inputId] = {
name: fileName,
status: 'done',
path: sourceValue
}
}
} else {
value[column.key] = sourceValue
// 禁用行的id
let disabledRowIds = (this.disabledRowIds || [])
newValue.forEach((data, newValueIndex) => {
// 判断源数据是否带有id
if (data.id == null || data.id === '') {
data.id = this.removeCaseId(this.generateId() + newValueIndex)
}
// 解析disabledRows
for (let columnKey in this.disabledRows) {
// 判断是否有该属性
if (this.disabledRows.hasOwnProperty(columnKey) && data.hasOwnProperty(columnKey)) {
if (disabled !== true) {
let temp = this.disabledRows[columnKey]
// 禁用规则可以是一个数组
if (temp instanceof Array) {
disabled = temp.includes(data[columnKey])
} else {
disabled = (temp === data[columnKey])
let value = { id: this.caseId + data.id }
let row = { id: value.id }
let disabled = false
this.columns.forEach(column => {
let inputId = column.key + value.id
let sourceValue = (data[column.key] == null ? '' : data[column.key]).toString()
if (column.type === FormTypes.checkbox) {
// 判断是否设定了customValue自定义值
if (column.customValue instanceof Array) {
let customValue = (column.customValue[0] || '').toString()
checkboxValues[inputId] = (sourceValue === customValue)
} else {
checkboxValues[inputId] = sourceValue
}
} else if (column.type === FormTypes.select) {
if (sourceValue) {
// 判断是否是多选
selectValues[inputId] = (column.props || {})['mode'] === 'multiple' ? sourceValue.split(',') : sourceValue
} else {
selectValues[inputId] = undefined
}
} else if (column.type === FormTypes.date || column.type === FormTypes.datetime) {
jdateValues[inputId] = sourceValue
} else if (column.type === FormTypes.slot) {
if (sourceValue !== 0 && !sourceValue) {
slotValues[inputId] = column.defaultValue
} else {
slotValues[inputId] = sourceValue
}
} else if (column.type === FormTypes.popup) {
popupValues[inputId] = sourceValue
} else if (column.type === FormTypes.radio) {
radioValues[inputId] = sourceValue
} else if (column.type === FormTypes.sel_search) {
searchSelectValues[inputId] = sourceValue
} else if (column.type === FormTypes.list_multi) {
if (sourceValue.length > 0) {
multiSelectValues[inputId] = sourceValue.split(',')
} else {
multiSelectValues[inputId] = []
}
} else if (column.type === FormTypes.upload || column.type === FormTypes.file || column.type === FormTypes.image) {
if (sourceValue) {
let fileName = sourceValue.substring(sourceValue.lastIndexOf('/') + 1)
uploadValues[inputId] = {
name: fileName,
status: 'done',
path: sourceValue
}
if (disabled) {
disabledRowIds.push(row.id)
}
} else {
value[column.key] = sourceValue
}
// 解析disabledRows
for (let columnKey in this.disabledRows) {
// 判断是否有该属性
if (this.disabledRows.hasOwnProperty(columnKey) && data.hasOwnProperty(columnKey)) {
if (disabled !== true) {
let temp = this.disabledRows[columnKey]
// 禁用规则可以是一个数组
if (temp instanceof Array) {
disabled = temp.includes(data[columnKey])
} else {
disabled = (temp === data[columnKey])
}
if (disabled) {
disabledRowIds.push(row.id)
}
}
}
}
}
})
this.inputValues.push(value)
rows.push(row)
})
this.inputValues.push(value)
rows.push(row)
})
this.disabledRowIds = disabledRowIds
this.checkboxValues = checkboxValues
this.selectValues = selectValues
this.jdateValues = jdateValues
this.slotValues = slotValues
this.rows = rows
this.uploadValues = uploadValues
this.popupValues = popupValues
this.radioValues = radioValues
this.multiSelectValues = multiSelectValues
this.searchSelectValues = searchSelectValues
this.disabledRowIds = disabledRowIds
this.checkboxValues = checkboxValues
this.selectValues = selectValues
this.jdateValues = jdateValues
this.slotValues = slotValues
this.rows = rows
this.uploadValues = uploadValues
this.popupValues = popupValues
this.radioValues = radioValues
this.multiSelectValues = multiSelectValues
this.searchSelectValues = searchSelectValues
// 更新form表单的值
this.$nextTick(() => {
this.updateFormValues()
// 更新form表单的值
this.$nextTick(() => {
this.updateFormValues()
})
})
}
},
columns: {
immediate: true,
handler(columns) {
columns.forEach(column => {
if (column.type === FormTypes.select || column.type === FormTypes.list_multi || column.type === FormTypes.sel_search) {
// 兼容 旧版本 options
if (column.options instanceof Array) {
column.options = column.options.map(item => {
if (item) {
return {
...item,
text: item.text || item.title,
title: item.text || item.title
// 兼容IE
this.getElementPromise('tbody').then(() => {
columns.forEach(column => {
if (column.type === FormTypes.select || column.type === FormTypes.list_multi || column.type === FormTypes.sel_search) {
// 兼容 旧版本 options
if (column.options instanceof Array) {
column.options = column.options.map(item => {
if (item) {
return {
...item,
text: item.text || item.title,
title: item.text || item.title
}
}
}
return {}
})
return {}
})
}
if (column.dictCode) {
this._loadDictConcatToOptions(column)
}
}
if (column.dictCode) {
this._loadDictConcatToOptions(column)
}
}
})
})
}
},
@ -923,19 +992,12 @@
}
},
mounted() {
// 获取document element对象
let elements = {};
['inputTable', 'tbody'].forEach(id => {
elements[id] = document.getElementById(this.caseId + id)
})
this.el = elements
let vm = this
/** 监听滚动条事件 */
this.el.inputTable.onscroll = function (event) {
this.getElement('inputTable').onscroll = function (event) {
vm.syncScrollBar(event.target.scrollLeft)
}
this.el.tbody.onscroll = function (event) {
this.getElement('tbody').onscroll = function (event) {
// vm.recalcTrHiddenItem(event.target.scrollTop)
}
@ -955,6 +1017,25 @@
},
methods: {
getElement(id, noCaseId = false) {
if (!this.el[id]) {
this.el[id] = document.getElementById((noCaseId ? '' : this.caseId) + id)
}
return this.el[id]
},
getElementPromise(id, noCaseId = false) {
return new Promise((resolve) => {
let timer = setInterval(() => {
let element = this.getElement(id, noCaseId)
if (element) {
clearInterval(timer)
resolve(element)
}
}, 10)
})
},
/** 初始化列表 */
initialize() {
// inputValues用来存储input表单的值
@ -985,14 +1066,14 @@
this.searchSelectValues = []
this.scrollTop = 0
this.$nextTick(() => {
this.el.tbody.scrollTop = 0
this.getElement('tbody').scrollTop = 0
})
},
/** 同步滚动条状态 */
syncScrollBar(scrollLeft) {
// this.style.tbody.left = `${scrollLeft}px`
// this.el.tbody.scrollLeft = scrollLeft
// this.getElement('tbody').scrollLeft = scrollLeft
},
/** 重置滚动条位置,参数留空则滚动到上次记录的位置 */
resetScrollTop(top) {
@ -1157,7 +1238,7 @@
target: this
})
// 设置滚动条位置
let tbody = this.el.tbody
let tbody = this.getElement('tbody')
let offsetHeight = tbody.offsetHeight
let realScrollTop = tbody.scrollTop + offsetHeight
if (forceScrollToBottom === false) {
@ -1245,13 +1326,14 @@
return true
},
/** 获取表格表单里的值(步版) */
getValuesSync(options = {}) {
/** 获取表格表单里的值(步版) */
getValuesAsync(options = {}, callback) {
let { validate, rowIds } = options
if (typeof validate !== 'boolean') validate = true
if (!(rowIds instanceof Array)) rowIds = null
// console.log('options:', { validate, rowIds })
let asyncCount = 0
let error = 0
let inputValues = cloneObject(this.inputValues)
let tooltips = Object.assign({}, this.tooltips)
@ -1314,7 +1396,7 @@
} else if (column.type === FormTypes.sel_search) {
value[column.key] = this.searchSelectValues[inputId]
} else if (column.type === FormTypes.list_multi) {
if (!this.multiSelectValues[inputId] || this.multiSelectValues[inputId].length == 0) {
if (!this.multiSelectValues[inputId] || this.multiSelectValues[inputId].length === 0) {
value[column.key] = ''
} else {
value[column.key] = this.multiSelectValues[inputId].join(',')
@ -1326,20 +1408,27 @@
// 检查表单验证
if (validate === true) {
let results = this.validateOneInput(value[column.key], value, column, notPassedIds, false, 'getValues')
tooltips[inputId] = results[0]
if (tooltips[inputId].passed === false) {
error++
// if (error++ === 0) {
// let element = document.getElementById(inputId)
// while (element.className !== 'tr') {
// element = element.parentElement
// }
// this.jumpToId(inputId, element)
// }
const handleValidateOneInput = (results) => {
tooltips[inputId] = results[0]
if (tooltips[inputId].passed === false) {
error++
// if (error++ === 0) {
// let element = document.getElementById(inputId)
// while (element.className !== 'tr') {
// element = element.parentElement
// }
// this.jumpToId(inputId, element)
// }
}
tooltips[inputId].visible = false
notPassedIds = results[1]
}
tooltips[inputId].visible = false
notPassedIds = results[1]
asyncCount++
let results = this.validateOneInputAsync(value[column.key], value, column, notPassedIds, false, 'getValues', (results) => {
handleValidateOneInput(results)
asyncCount--
})
handleValidateOneInput(results)
}
})
// 将caseId去除
@ -1352,25 +1441,42 @@
this.tooltips = tooltips
this.notPassedIds = notPassedIds
}
const timer = setInterval(() => {
if (asyncCount === 0) {
clearInterval(timer)
if (typeof callback === 'function') {
callback({ error, values })
}
}
}, 50)
return { error, values }
},
/** 获取表格表单里的值(同步版) */
getValuesSync(options = {}) {
return this.getValuesAsync(options)
},
/** 获取表格表单里的值 */
getValues(callback, validate = true, rowIds) {
let result = this.getValuesSync({ validate, rowIds })
if (typeof callback === 'function') {
callback(result.error, result.values)
}
this.getValuesAsync({ validate, rowIds }, ({ error, values }) => {
if (typeof callback === 'function') {
callback(error, values)
}
})
},
/** getValues的Promise版 */
getValuesPromise(validate = true, rowIds) {
return new Promise((resolve, reject) => {
let { error, values } = this.getValuesSync({ validate, rowIds })
if (error === 0) {
resolve(values)
} else {
reject(VALIDATE_NO_PASSED)
}
this.getValuesAsync({ validate, rowIds }, ({ error, values }) => {
if (error === 0) {
resolve(values)
} else {
reject(VALIDATE_NO_PASSED)
}
})
})
},
/** 获取被删除项的id */
@ -1468,14 +1574,24 @@
// element = document.getElementById(id)
// }
// if (element != null) {
// console.log(this.el.tbody.scrollTop, element.offsetTop)
// this.el.tbody.scrollTop = element.offsetTop
// console.log(this.el.tbody.scrollTop, element.offsetTop)
// console.log(this.getElement('tbody').scrollTop, element.offsetTop)
// this.getElement('tbody').scrollTop = element.offsetTop
// console.log(this.getElement('tbody').scrollTop, element.offsetTop)
// }
// },
/** 验证单个表单 */
validateOneInput(value, row, column, notPassedIds, update = false, validType = 'input') {
/**
*
*
* @param value
* @param row
* @param column
* @param notPassedIds id
* @param update vue
* @param validType inputblur
* @param callback
*/
validateOneInputAsync(value, row, column, notPassedIds, update = false, validType = 'input', callback) {
let tooltips = Object.assign({}, this.tooltips)
// let notPassedIds = cloneObject(this.notPassedIds)
let inputId = column.key + row.id
@ -1515,6 +1631,10 @@
if (column.type === FormTypes.date || column.type === FormTypes.datetime) {
element = element.getElementsByTagName('input')[0]
}
// upload 在 .ant-upload .ant-btn 上设置 border-color
if (column.type === FormTypes.upload || column.type === FormTypes.file || column.type === FormTypes.image) {
element = element.getElementsByClassName('ant-upload')[0].getElementsByClassName('ant-btn')[0]
}
element.style.borderColor = borderColor
element.style.boxShadow = boxShadow
if (element.tagName === 'SPAN') {
@ -1527,6 +1647,10 @@
this.notPassedIds = notPassedIds
}
if (typeof callback === 'function') {
callback([tooltips[inputId], notPassedIds])
}
}
if (typeof passed === 'function') {
@ -1547,9 +1671,13 @@
nextThen([passed, message])
}
return [tooltips[inputId], notPassedIds]
},
/** 验证单个表单 */
validateOneInput(value, row, column, notPassedIds, update = false, validType = 'input') {
return this.validateOneInputAsync(value, row, column, notPassedIds, update, validType)
},
/** 通过规则验证值是否正确 */
validateValue(column, value) {
let rules = column.validateRules
@ -1620,7 +1748,7 @@
/** 动态更新表单的值 */
updateFormValues() {
let trs = this.el.tbody.getElementsByClassName('tr')
let trs = this.getElement('tbody').getElementsByClassName('tr')
let trEls = []
for (let tr of trs) {
trEls.push(tr)
@ -1959,7 +2087,7 @@
handleClickDownloadFile(id) {
let { path } = this.uploadValues[id] || {}
if (path) {
let url = window._CONFIG['downloadUrl'] + '/' + path
let url = window._CONFIG['staticDomainURL'] + '/' + path
window.open(url)
}
},
@ -2130,7 +2258,7 @@
getCellImageView(id) {
let currUploadObj = this.uploadValues[id] || null
if (currUploadObj && currUploadObj['path']) {
return window._CONFIG['domianURL'] + '/sys/common/view/' + currUploadObj['path']
return window._CONFIG['staticDomainURL'] + '/' + currUploadObj['path']
} else {
return ''
}
@ -2340,7 +2468,7 @@
.td {
/*flex: 1;*/
padding: 14px 0 14px @spacing;
padding: 14px @spacing 14px 0;
justify-content: center;
&:last-child {

View File

@ -150,7 +150,7 @@
console.log("aaaaa",res)
if(res.success){
this.checkKey = res.result.key
this.code = res.result.code
this.code = window.atob(res.result.code)
resolve();
}else{
this.$message.error("生成验证码错误,请联系系统管理员")

View File

@ -0,0 +1,202 @@
<template>
<a-upload
name="file"
listType="picture-card"
:multiple="isMultiple"
:action="uploadAction"
:headers="headers"
:data="{biz:bizPath}"
:fileList="fileList"
:beforeUpload="beforeUpload"
:disabled="disabled"
:isMultiple="isMultiple"
:showUploadList="isMultiple"
@change="handleChange"
@preview="handlePreview">
<img v-if="!isMultiple && picUrl" :src="getAvatarView()" style="height:104px;max-width:300px"/>
<div v-else >
<a-icon :type="uploadLoading ? 'loading' : 'plus'" />
<div class="ant-upload-text">{{ text }}</div>
</div>
<a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel()">
<img alt="example" style="width: 100%" :src="previewImage"/>
</a-modal>
</a-upload>
</template>
<script>
import Vue from 'vue'
import { ACCESS_TOKEN } from "@/store/mutation-types"
import { getFileAccessHttpUrl } from '@/api/manage'
const uidGenerator=()=>{
return '-'+parseInt(Math.random()*10000+1,10);
}
const getFileName=(path)=>{
if(path.lastIndexOf("\\")>=0){
let reg=new RegExp("\\\\","g");
path = path.replace(reg,"/");
}
return path.substring(path.lastIndexOf("/")+1);
}
export default {
name: 'JImageUpload',
data(){
return {
uploadAction:window._CONFIG['domianURL']+"/sys/common/upload",
urlView:window._CONFIG['staticDomainURL'],
uploadLoading:false,
picUrl:false,
headers:{},
fileList: [],
previewImage:"",
previewVisible: false,
}
},
props:{
text:{
type:String,
required:false,
default:"上传"
},
/*这个属性用于控制文件上传的业务路径*/
bizPath:{
type:String,
required:false,
default:"temp"
},
value:{
type:[String,Array],
required:false
},
disabled:{
type:Boolean,
required:false,
default: false
},
isMultiple:{
type:Boolean,
required:false,
default: false
}
},
watch:{
value(val){
if (val instanceof Array) {
this.initFileList(val.join(','))
} else {
this.initFileList(val)
}
}
},
created(){
const token = Vue.ls.get(ACCESS_TOKEN);
this.headers = {"X-Access-Token":token}
},
methods:{
initFileList(paths){
if(!paths || paths.length==0){
this.fileList = [];
return;
}
this.picUrl = true;
let fileList = [];
let arr = paths.split(",")
for(var a=0;a<arr.length;a++){
let url = getFileAccessHttpUrl(arr[a],this.urlView,"http");
fileList.push({
uid: uidGenerator(),
name: getFileName(arr[a]),
status: 'done',
url: url,
response:{
status:"history",
message:arr[a]
}
})
}
this.fileList = fileList
},
beforeUpload: function(file){
var fileType = file.type;
if(fileType.indexOf('image')<0){
this.$message.warning('');
return false;
}
},
handleChange(info) {
this.picUrl = false;
let fileList = info.fileList
if(info.file.status==='done'){
if(info.file.response.success){
this.picUrl = true;
fileList = fileList.map((file) => {
if (file.response) {
file.url = file.response.message;
}
return file;
});
}
//this.$message.success(`${info.file.name} 上传成功!`);
}else if (info.file.status === 'error') {
this.$message.error(`${info.file.name} .`);
}else if(info.file.status === 'removed'){
this.handleDelete(info.file)
}
this.fileList = fileList
if(info.file.status==='done' || info.file.status === 'removed'){
this.handlePathChange()
}
},
// 预览
handlePreview (file) {
this.previewImage = file.url || file.thumbUrl
this.previewVisible = true
},
getAvatarView(){
if(this.fileList.length>0){
let url = this.fileList[0].url
return getFileAccessHttpUrl(url,this.urlView,"http")
}
},
handlePathChange(){
let uploadFiles = this.fileList
let path = ''
if(!uploadFiles || uploadFiles.length==0){
path = ''
}
let arr = [];
if(!this.isMultiple){
arr.push(uploadFiles[uploadFiles.length-1].response.message)
}else{
for(var a=0;a<uploadFiles.length;a++){
arr.push(uploadFiles[a].response.message)
}
}
if(arr.length>0){
path = arr.join(",")
}
this.$emit('change', path);
},
handleDelete(file){
//如有需要新增 删除逻辑
console.log(file)
},
handleCancel() {
this.close();
this.previewVisible = false;
},
close () {
},
},
model: {
prop: 'value',
event: 'change'
}
}
</script>
<style scoped>
</style>

View File

@ -42,6 +42,11 @@
type: String,
default: '',
required: false
},
biz:{
type: String,
default: '',
required: false
}
},
data(){
@ -49,7 +54,8 @@
visible:false,
uploading:false,
fileList:[],
uploadAction:''
uploadAction:'',
foreignKeys:''
}
},
watch: {
@ -67,10 +73,11 @@
handleClose(){
this.visible=false
},
show(){
show(arg){
this.fileList = []
this.uploading = false
this.visible = true
this.foreignKeys = arg;
},
handleRemove(file) {
const index = this.fileList.indexOf(file);
@ -85,6 +92,12 @@
handleImport() {
const { fileList } = this;
const formData = new FormData();
if(this.biz){
formData.append('isSingleTableImport',this.biz);
}
if(this.foreignKeys && this.foreignKeys.length>0){
formData.append('foreignKeys',this.foreignKeys);
}
fileList.forEach((file) => {
formData.append('files[]', file);
});

View File

@ -0,0 +1,209 @@
<template>
<a-modal
ref="modal"
class="j-modal-box"
:class="{'fullscreen':innerFullscreen,'no-title':isNoTitle,'no-footer':isNoFooter,}"
:visible="visible"
v-bind="_attrs"
v-on="$listeners"
@ok="handleOk"
@cancel="handleCancel"
>
<slot></slot>
<template v-if="!isNoTitle" slot="title">
<a-row class="j-modal-title-row" type="flex">
<a-col class="left">
<slot name="title">{{ title }}</slot>
</a-col>
<a-col v-if="switchFullscreen" class="right" @click="toggleFullscreen">
<a-button class="ant-modal-close ant-modal-close-x" ghost type="link" :icon="fullscreenButtonIcon"/>
</a-col>
</a-row>
</template>
<!-- scopedSlots -->
<template v-for="slotName of scopedSlotsKeys" :slot="slotName">
<slot :name="slotName"></slot>
</template>
<!-- slots -->
<template v-for="slotName of slotsKeys" v-slot:[slotName]>
<slot :name="slotName"></slot>
</template>
</a-modal>
</template>
<script>
import ACol from 'ant-design-vue/es/grid/Col'
export default {
name: 'JModal',
components: { ACol },
props: {
title: String,
// 可使用 .sync 修饰符
visible: Boolean,
// 是否在弹出时禁止 body 滚动
lockScroll: {
type: Boolean,
default: true
},
// 是否全屏弹窗,当全屏时无论如何都会禁止 body 滚动。可使用 .sync 修饰符
fullscreen: {
type: Boolean,
default: true
},
// 是否允许切换全屏(允许后右上角会出现一个按钮)
switchFullscreen: {
type: Boolean,
default: false
},
},
data() {
return {
// 内部使用的 slots ,不再处理
usedSlots: ['title'],
// 缓存 body 的 overflow
bodyOverflowCache: '',
innerFullscreen: this.fullscreen,
fullscreenButtonIcon: 'fullscreen-exit',
}
},
computed: {
// 一些未处理的参数或特殊处理的参数绑定到 a-modal 上
_attrs() {
let attrs = { ...this.$attrs }
// 如果全屏就将宽度设为 100%
if (this.innerFullscreen) {
attrs['width'] = '100%'
}
return attrs
},
isNoTitle() {
return !this.title && !this.allSlotsKeys.includes('title')
},
isNoFooter() {
return this._attrs['footer'] === null
},
slotsKeys() {
return Object.keys(this.$slots).filter(key => !this.usedSlots.includes(key))
},
scopedSlotsKeys() {
return Object.keys(this.$scopedSlots).filter(key => !this.usedSlots.includes(key))
},
allSlotsKeys() {
return this.slotsKeys.concat(this.scopedSlotsKeys)
},
// 是否锁定body滚动
lockBodyScroll() {
return this.lockScroll || this.innerFullscreen
}
},
watch: {
visible() {
if (this.visible) {
this.innerFullscreen = this.fullscreen
}
if (this.lockBodyScroll) {
if (this.visible) {
this.bodyOverflowCache = document.body.style.overflow
document.body.style.overflow = 'hidden'
} else {
document.body.style.overflow = this.bodyOverflowCache
}
}
},
innerFullscreen(val) {
this.$emit('update:fullscreen', val)
},
},
methods: {
close() {
this.$emit('update:visible', false)
},
handleOk() {
this.close()
},
handleCancel() {
this.close()
},
toggleFullscreen() {
if (this.innerFullscreen) {
this.fullscreenButtonIcon = 'fullscreen'
} else {
this.fullscreenButtonIcon = 'fullscreen-exit'
}
this.innerFullscreen = !this.innerFullscreen
},
}
}
</script>
<style lang="scss">
.j-modal-box {
&.fullscreen {
top: 0;
left: 0;
padding: 0;
height: 100vh;
& .ant-modal-content {
height: 100vh;
border-radius: 0;
& .ant-modal-body {
/* title 和 footer 各占 55px */
height: calc(100% - 55px - 55px);
overflow: auto;
}
}
&.no-title, &.no-footer {
.ant-modal-body {
height: calc(100% - 55px);
}
}
&.no-title.no-footer {
.ant-modal-body {
height: 100%;
}
}
}
.j-modal-title-row {
.left {
width: calc(100% - 56px - 56px);
}
.right {
width: 56px;
.ant-modal-close {
right: 56px;
color: rgba(0, 0, 0, 0.45);
&:hover {
color: rgba(0, 0, 0, 0.75);
}
}
}
}
/deep/ {
}
}
</style>

View File

@ -1,15 +1,22 @@
<template>
<div class="j-super-query-box">
<slot>
<a-tooltip v-if="superQueryFlag" title="已有高级查询条件生效">
<a-button type="primary" @click="visible=true">
<a-icon type="appstore" theme="twoTone" :spin="true"></a-icon>
<span></span>
</a-button>
</a-tooltip>
<a-button v-else type="primary" icon="filter" @click="visible=true"></a-button>
</slot>
<div @click="visible=true">
<slot>
<a-tooltip v-if="superQueryFlag" :mouseLeaveDelay="0.2">
<template slot="title">
<span></span>
<a-divider type="vertical"/>
<a @click="handleReset"></a>
</template>
<a-button type="primary">
<a-icon type="appstore" theme="twoTone" :spin="true"></a-icon>
<span></span>
</a-button>
</a-tooltip>
<a-button v-else type="primary" icon="filter" @click="visible=true"></a-button>
</slot>
</div>
<a-modal
title="高级查询构造器"

View File

@ -4,11 +4,12 @@
:multiple="true"
:action="uploadAction"
:headers="headers"
:data="{'isup':1,'bizPath':bizPath}"
:data="{'biz':bizPath}"
:fileList="fileList"
:beforeUpload="beforeUpload"
@change="handleChange"
:disabled="disabled">
:disabled="disabled"
:returnUrl="returnUrl">
<a-button>
<a-icon type="upload" />{{ text }}
</a-button>
@ -19,6 +20,7 @@
import Vue from 'vue'
import { ACCESS_TOKEN } from "@/store/mutation-types"
import { getFileAccessHttpUrl } from '@/api/manage';
const FILE_TYPE_ALL = "all"
const FILE_TYPE_IMG = "image"
@ -38,9 +40,10 @@
data(){
return {
uploadAction:window._CONFIG['domianURL']+"/sys/common/upload",
urlDownload:window._CONFIG['domianURL'] + "/sys/common/download/",
urlDownload:window._CONFIG['staticDomainURL'],
headers:{},
fileList: []
fileList: [],
newFileList: [],
}
},
props:{
@ -77,11 +80,25 @@
required: false,
default: false
},
/**
* update -- author:lvdandan -- date:20190219 -- for:Juploadurl
* trueurl
* falsefileName filePath fileSize
*/
returnUrl:{
type:Boolean,
required:false,
default: true
},
},
watch:{
value(val){
if (val instanceof Array) {
this.initFileList(val.join(','))
if(this.returnUrl){
this.initFileList(val.join(','))
}else{
this.initFileListArr(val);
}
} else {
this.initFileList(val)
}
@ -93,6 +110,26 @@
},
methods:{
initFileListArr(val){
if(!val || val.length==0){
this.fileList = [];
return;
}
let fileList = [];
for(var a=0;a<val.length;a++){
fileList.push({
uid:uidGenerator(),
name:val[a].fileName,
status: 'done',
url: val[a].filePath,
response:{
status:"history",
message:val[a].filePath
}
})
}
this.fileList = fileList
},
initFileList(paths){
if(!paths || paths.length==0){
//return [];
@ -104,11 +141,12 @@
let fileList = [];
let arr = paths.split(",")
for(var a=0;a<arr.length;a++){
let url = getFileAccessHttpUrl(arr[a],this.urlDownload,"http");
fileList.push({
uid:uidGenerator(),
name:getFileName(arr[a]),
status: 'done',
url: this.urlDownload+arr[a],
url: url,
response:{
status:"history",
message:arr[a]
@ -156,12 +194,13 @@
if(info.file.response.success){
fileList = fileList.map((file) => {
if (file.response) {
file.url = this.urlDownload+file.response.message;
let reUrl = file.response.message;
file.url = getFileAccessHttpUrl(reUrl,this.urlDownload,"http");
}
return file;
});
}
this.$message.success(`${info.file.name} !`);
//this.$message.success(`${info.file.name} 上传成功!`);
}else if (info.file.status === 'error') {
this.$message.error(`${info.file.name} .`);
}else if(info.file.status === 'removed'){
@ -169,7 +208,26 @@
}
this.fileList = fileList
if(info.file.status==='done' || info.file.status === 'removed'){
this.handlePathChange()
//returnUrl为true时仅返回文件路径
if(this.returnUrl){
this.handlePathChange()
}else{
//returnUrl为false时返回文件名称、文件路径及文件大小
fileList = fileList.filter((file) => {
if (file.response) {
return file.response.success === true;
}
return false;
}).map((file) => {
var fileJson = {
fileName:file.name,
filePath:file.url,
fileSize:file.size
};
this.newFileList.push(fileJson);
this.$emit('change', this.newFileList);
});
}
}
},
handleDelete(file){

View File

@ -1,5 +1,9 @@
import T from './JFormContainer.vue'
let install = function (Vue) {
Vue.component('JFormContainer',T);
}
export default { install };
import JModal from './JModal'
import JFormContainer from './JFormContainer.vue'
export default {
install(Vue) {
Vue.component('JFormContainer', JFormContainer)
Vue.component(JModal.name, JModal)
}
}

View File

@ -17,9 +17,11 @@
selectable
:selectedKeys="selectedDepIds"
:checkStrictly="true"
@select="onDepSelect"
:dropdownStyle="{maxHeight:'200px',overflow:'auto'}"
:treeData="departTree"
:expandAction="false"
:expandedKeys.sync="expandedKeys"
@select="onDepSelect"
/>
</a-card>
</a-col>
@ -28,7 +30,7 @@
:
<a-input-search
:style="{width:'150px',marginBottom:'15px'}"
placeholder="请输入用户账号"
placeholder="请输入账号"
v-model="queryParam.username"
@search="onSearch"
></a-input-search>
@ -43,6 +45,7 @@
:dataSource="dataSource"
:pagination="ipagination"
:rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange,type: getType}"
:loading="loading"
@change="handleTableChange">
</a-table>
</a-card>
@ -71,7 +74,7 @@
dataIndex: 'username'
},
{
title: '',
title: '',
align: 'center',
dataIndex: 'realname'
},
@ -90,14 +93,14 @@
}
},
{
title: '',
title: '',
align: 'center',
dataIndex: 'phone'
},
{
title: '',
title: '',
align: 'center',
dataIndex: 'email'
dataIndex: 'orgCode'
}
],
scrollTrigger: {},
@ -124,60 +127,74 @@
selectedDepIds: [],
departTree: [],
visible: false,
form: this.$form.createForm(this)
form: this.$form.createForm(this),
loading: false,
expandedKeys: [],
}
},
computed: {
// 计算属性的 getter
getType: function () {
console.log("multi: ", this.multi);
return this.multi == true ? 'checkbox' : 'radio';
}
},
watch: {
userIds() {
this.initUserNames()
}
userIds: {
immediate: true,
handler() {
this.initUserNames()
}
},
},
created() {
// 该方法触发屏幕自适应
this.resetScreenSize();
this.loadData().then((res) => {
this.initUserNames();
})
this.loadData()
},
methods: {
initUserNames() {
let names = ''
console.log("props userIds: ", this.userIds)
if (this.userIds) {
let currUserIds = this.userIds
let userIdsArr = currUserIds.split(',');
for (let item of this.dataSource) {
if (userIdsArr.includes(item.username)) {
names += "," + item.realname
// 这里最后加一个 , 的原因是因为无论如何都要使用 in 查询,防止后台进行了模糊匹配,导致查询结果不准确
let values = this.userIds.split(',') + ','
getUserList({
username: values,
pageNo: 1,
pageSize: values.length
}).then((res) => {
if (res.success) {
let selectedRowKeys = []
let realNames = []
res.result.records.forEach(user => {
realNames.push(user['realname'])
selectedRowKeys.push(user['id'])
})
this.selectedRowKeys = selectedRowKeys
this.$emit('initComp', realNames.join(','))
}
}
if (names) {
names = names.substring(1)
}
this.$emit("initComp", names)
}else{
})
} else {
// JSelectUserByDep组件bug issues/I16634
this.$emit("initComp", "")
this.$emit('initComp', '')
}
},
async loadData(arg) {
if (arg === 1) {
this.ipagination.current = 1;
}
let params = this.getQueryParams();//查询条件
await getUserList(params).then((res) => {
if (res.success) {
this.dataSource = res.result.records;
this.ipagination.total = res.result.total;
}
})
if (this.selectedDepIds && this.selectedDepIds.length > 0) {
await this.initQueryUserByDepId(this.selectedDepIds)
} else {
this.loading = true
let params = this.getQueryParams()//查询条件
await getUserList(params).then((res) => {
if (res.success) {
this.dataSource = res.result.records
this.ipagination.total = res.result.total
}
}).finally(() => {
this.loading = false
})
}
},
// 触发屏幕自适应
resetScreenSize() {
@ -191,6 +208,7 @@
showModal() {
this.visible = true;
this.queryDepartTree();
this.initUserNames()
this.loadData();
this.form.resetFields();
},
@ -234,7 +252,6 @@
handleSubmit() {
let that = this;
this.getSelectUserRows();
console.log(that.selectUserRows)
that.$emit('ok', that.selectUserRows, that.selectUserIds);
that.searchReset(0)
that.close();
@ -270,17 +287,22 @@
},
// 根据选择的id来查询用户信息
initQueryUserByDepId(selectedDepIds) {
queryUserByDepId({id: selectedDepIds.toString()}).then((res) => {
this.loading = true
return queryUserByDepId({id: selectedDepIds.toString()}).then((res) => {
if (res.success) {
this.dataSource = res.result;
this.ipagination.total = res.result.length;
}
}).finally(() => {
this.loading = false
})
},
queryDepartTree() {
queryDepartTreeList().then((res) => {
if (res.success) {
this.departTree = res.result;
// 默认展开父节点
this.expandedKeys = this.departTree.map(item => item.id)
}
})
},

View File

@ -46,7 +46,7 @@
width: 200
},
{
title: '',
title: '',
align: "center",
dataIndex: 'realname',
},

View File

@ -5,6 +5,8 @@
</template>
<script>
import Vue from 'vue'
import { ACCESS_TOKEN } from "@/store/mutation-types"
import PageLayout from '../page/PageLayout'
import RouteView from './RouteView'
@ -40,6 +42,12 @@
/*update_begin author:wuxianquan date:20190908 for:判断打开方式新窗口打开时this.$route.meta.internalOrExternal==true */
if(this.$route.meta.internalOrExternal != undefined && this.$route.meta.internalOrExternal==true){
this.closeCurrent();
//外部url加入token
let tokenStr = "${token}";
if(url.indexOf(tokenStr)!=-1){
let token = Vue.ls.get(ACCESS_TOKEN);
this.url = url.replace(tokenStr,token);
}
window.open(this.url);
}
/*update_end author:wuxianquan date:20190908 for:判断打开方式新窗口打开时this.$route.meta.internalOrExternal==true */

View File

@ -80,30 +80,41 @@
},
created() {
if (this.$route.path != indexKey) {
this.pageList.push({
name: 'dashboard-analysis',
path: indexKey,
fullPath: indexKey,
meta: {
icon: 'dashboard',
title: ''
}
})
this.linkList.push(indexKey)
this.addIndexToFirst()
}
// update-begin-author:sunjianlei date:20191223 for: 修复刷新后菜单Tab名字显示异常
let storeKey = 'route:title:' + this.$route.fullPath
let routeTitle = this.$ls.get(storeKey)
if (routeTitle) {
this.$route.meta.title = routeTitle
}
// update-end-author:sunjianlei date:20191223 for: 修复刷新后菜单Tab名字显示异常
this.pageList.push(this.$route)
this.linkList.push(this.$route.fullPath)
this.activePage = this.$route.fullPath
},
watch: {
'$route': function(newRoute) {
//console.log("新的路由",newRoute)
this.activePage = newRoute.fullPath
if (!this.multipage) {
this.linkList = [newRoute.fullPath]
this.pageList = [Object.assign({},newRoute)]
} else if (this.linkList.indexOf(newRoute.fullPath) < 0) {
// update-begin-author:taoyan date:20200211 for: TASK #3368 【路由缓存】首页的缓存设置有问题,需要根据后台的路由配置来实现是否缓存
} else if(indexKey==newRoute.fullPath) {
//首页时 判断是否缓存 没有缓存 刷新之
if (newRoute.meta.keepAlive === false) {
this.routeReload()
}
// update-end-author:taoyan date:20200211 for: TASK #3368 【路由缓存】首页的缓存设置有问题,需要根据后台的路由配置来实现是否缓存
}else if (this.linkList.indexOf(newRoute.fullPath) < 0) {
this.linkList.push(newRoute.fullPath)
this.pageList.push(Object.assign({},newRoute))
// update-begin-author:sunjianlei date:20200103 for: 如果新增的页面配置了缓存路由,那么就强制刷新一遍
if (newRoute.meta.keepAlive) {
this.routeReload()
}
// update-end-author:sunjianlei date:20200103 for: 如果新增的页面配置了缓存路由,那么就强制刷新一遍
} else if (this.linkList.indexOf(newRoute.fullPath) >= 0) {
let oldIndex = this.linkList.indexOf(newRoute.fullPath)
let oldPositionRoute = this.pageList[oldIndex]
@ -114,6 +125,7 @@
let index = this.linkList.lastIndexOf(key)
let waitRouter = this.pageList[index]
this.$router.push(Object.assign({},waitRouter));
this.changeTitle(waitRouter.meta.title)
},
'multipage': function(newVal) {
if(this.reloadFlag){
@ -122,9 +134,44 @@
this.pageList = [this.$route]
}
}
}
},
// update-begin-author:sunjianlei date:20191223 for: 修复从单页模式切换回多页模式后首页不居第一位的 BUG
device() {
if (this.multipage && this.linkList.indexOf(indexKey) === -1) {
this.addIndexToFirst()
}
},
// update-end-author:sunjianlei date:20191223 for: 修复从单页模式切换回多页模式后首页不居第一位的 BUG
},
methods: {
// update-begin-author:sunjianlei date:20191223 for: 修复从单页模式切换回多页模式后首页不居第一位的 BUG
// 将首页添加到第一位
addIndexToFirst() {
this.pageList.splice(0, 0, {
name: 'dashboard-analysis',
path: indexKey,
fullPath: indexKey,
meta: {
icon: 'dashboard',
title: ''
}
})
this.linkList.splice(0, 0, indexKey)
},
// update-end-author:sunjianlei date:20191223 for: 修复从单页模式切换回多页模式后首页不居第一位的 BUG
// update-begin-author:sunjianlei date:20200120 for: 动态更改页面标题
changeTitle(title) {
let projectTitle = "Jeecg-Boot 企业级快速开发平台"
// 首页特殊处理
if (this.$route.path === indexKey) {
document.title = projectTitle
} else {
document.title = title + ' · ' + projectTitle
}
},
// update-end-author:sunjianlei date:20200120 for: 动态更改页面标题
changePage(key) {
this.activePage = key
},
@ -236,6 +283,9 @@
let currRouter = this.pageList[keyIndex]
let meta = Object.assign({},currRouter.meta,{title:title})
this.pageList.splice(keyIndex, 1, Object.assign({},currRouter,{meta:meta}))
if (key === this.activePage) {
this.changeTitle(title)
}
}
},
//update-end-author:taoyan date:20190430 for:动态路由title显示配置的菜单title而不是其对应路由的title

View File

@ -17,12 +17,12 @@
<div class="footer">
<div class="links">
<a href="http://jeecg-boot.mydoc.io" target="_blank"></a>
<a href="http://doc.jeecg.com" target="_blank"></a>
<a href="https://github.com/zhangdaiscott/jeecg-boot" target="_blank"></a>
<a href="https://github.com/zhangdaiscott/jeecg-boot" target="_blank"></a>
<a href="https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE" target="_blank"></a>
</div>
<div class="copyright">
Copyright &copy; 2019 <a href="http://www.jeecg.org" target="_blank">JEECG</a>
Copyright &copy; 2019 <a href="http://www.jeecg.com" target="_blank">JEECG</a>
</div>
</div>
</div>

View File

@ -1,7 +1,7 @@
<template>
<div class="footer">
<div class="links">
<a href="http://www.jeecg.org" target="_blank">JEECG </a>
<a href="http://www.jeecg.com" target="_blank">JEECG </a>
<a href="https://github.com/zhangdaiscott/jeecg-boot" target="_blank">
<a-icon type="github"/>
</a>

View File

@ -197,7 +197,7 @@
&.dark {
color: #000000;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.2);
background-color: @primary-color;
background-color: white !important;
}
}

View File

@ -154,6 +154,10 @@
//此处触发动态路由被点击事件
this.findMenuBykey(this.menus,value.key)
this.$emit("dynamicRouterShow",value.key,this.activeMenu.meta.title)
// update-begin-author:sunjianlei date:20191223 for: 修复刷新后菜单Tab名字显示异常
let storeKey = 'route:title:' + this.activeMenu.path
this.$ls.set(storeKey, this.activeMenu.meta.title)
// update-end-author:sunjianlei date:20191223 for: 修复刷新后菜单Tab名字显示异常
},
findMenuBykey(menus,key){
for(let i of menus){
@ -337,6 +341,10 @@
font-size: 16px;
padding: 4px;
}
.anticon {
color: white;
}
}
}
@ -349,6 +357,10 @@
&:hover {
background: rgba(0, 0, 0, 0.05);
}
.anticon {
color: black;
}
}
}
}

View File

@ -0,0 +1,36 @@
<template>
<component
:is="comp"
:formData="formData"
ref="compModel"
v-if="comp">
</component>
</template>
<script>
export default {
name: 'DynamicNotice',
data () {
return {
compName: this.path
}
},
computed: {
comp: function () {
if(!this.path){
return null;
}
return () => import(`@/views/${this.path}.vue`)
}
},
props: ['path','formData'],
methods: {
detail () {
setTimeout(() => {
if(this.path){
this.$refs.compModel.view(this.formData);
}
}, 200)
},
}
}
</script>

View File

@ -72,6 +72,7 @@
</a-badge>
</span>
<show-announcement ref="ShowAnnouncement" @ok="modalFormOk"></show-announcement>
<dynamic-notice ref="showDynamNotice" :path="openPath" :formData="formData"/>
</a-popover>
</template>
@ -79,11 +80,13 @@
import { getAction,putAction } from '@/api/manage'
import ShowAnnouncement from './ShowAnnouncement'
import store from '@/store/'
import DynamicNotice from './DynamicNotice'
export default {
name: "HeaderNotice",
components: {
DynamicNotice,
ShowAnnouncement,
},
data () {
@ -105,6 +108,8 @@
websock: null,
lockReconnect:false,
heartCheck:null,
formData:{},
openPath:''
}
},
computed:{
@ -172,7 +177,13 @@
}
});
this.hovered = false;
this.$refs.ShowAnnouncement.detail(record);
if(record.openType==='component'){
this.openPath = record.openPage;
this.formData = {id:record.busId};
this.$refs.showDynamNotice.detail(record.openPage);
}else{
this.$refs.ShowAnnouncement.detail(record);
}
},
toMyAnnouncement(){

View File

@ -5,11 +5,14 @@
:visible="visible"
:bodyStyle ="bodyStyle"
@cancel="handleCancel"
destroyOnClose
:footer="null">
destroyOnClose>
<template slot="title">
<a-button icon="fullscreen" class="custom-btn" @click="handleClickToggleFullScreen"/>
</template>
<template slot="footer">
<a-button key="back" @click="handleCancel"></a-button>
<a-button v-if="record.openType==='url'&&record.readFlag!=='1'" type="primary" @click="toHandle"></a-button>
</template>
<a-card class="daily-article" :loading="loading">
<a-card-meta
:title="record.titile"
@ -74,7 +77,14 @@
this.modelStyle.style.top = '50px'
}
this.modelStyle.fullScreen = mode
}
},
toHandle(){
if(this.record.openType==='url'&&this.record.readFlag!== '1'){
this.visible = false;
//链接跳转
this.$router.push({path: this.record.openPage})
}
},
}
}
</script>

View File

@ -5,7 +5,8 @@
<span class="action" @click="showClick">
<a-icon type="search"></a-icon>
</span>
<span v-show="shows" class="borders">
<!-- update-begin author:sunjianlei date:20200219 for: -->
<component :is="searchMenuComp" v-show="searchMenuVisible || isMobile()" class="borders" :visible="searchMenuVisible" title="搜索菜单" :footer="null" @cancel="searchMenuVisible=false">
<a-select
class="search-input"
showSearch
@ -13,16 +14,20 @@
placeholder="搜索菜单"
optionFilterProp="children"
:filterOption="filterOption"
:open="isMobile()?true:null"
:getPopupContainer="(node) => node.parentNode"
:style="isMobile()?{width: '100%',marginBottom:'50px'}:{}"
@change="searchMethods"
@blur="hiddenClick"
>
<a-select-option v-for="site in search " :value="site.id">{{site.meta.title}}</a-select-option>
<a-select-option v-for="site in searchMenuOptions" :value="site.id">{{site.meta.title}}</a-select-option>
</a-select>
</span>
<!-- update-end author:sunjianlei date:20191@20 for: -->
</component>
<!-- update-end author:sunjianlei date:20200219 for: -->
<!-- update-end author:sunjianlei date:20191220 for: -->
<!-- update_end author:zhaoxin date:20191129 for: -->
<span class="action">
<a class="logout_title" target="_blank" href="http://jeecg-boot.mydoc.io">
<a class="logout_title" target="_blank" href="http://doc.jeecg.com">
<a-icon type="question-circle-o"></a-icon>
</a>
</span>
@ -95,9 +100,11 @@
mixins: [mixinDevice],
data(){
return{
//菜单搜索
search:[],
shows:false
// update-begin author:sunjianlei date:20200219 for: 头部菜单搜索规范命名 --------------
searchMenuOptions:[],
searchMenuComp: 'span',
searchMenuVisible: false,
// update-begin author:sunjianlei date:20200219 for: 头部菜单搜索规范命名 --------------
}
},
components: {
@ -116,10 +123,8 @@
/* update_begin author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
created() {
let lists = []
console.log("permissionMenuList: ",this.permissionMenuList)
this.searchMenus(lists,this.permissionMenuList)
this.search=[...lists]
console.log(this.search)
this.searchMenuOptions=[...lists]
},
computed: {
...mapState({
@ -129,10 +134,21 @@
})
},
/* update_end author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
watch: {
// update-begin author:sunjianlei date:20200219 for: 菜单搜索改为动态组件,在手机端呈现出弹出框
device: {
immediate: true,
handler() {
this.searchMenuVisible = false
this.searchMenuComp = this.isMobile() ? 'a-modal' : 'span'
},
},
// update-end author:sunjianlei date:20200219 for: 菜单搜索改为动态组件,在手机端呈现出弹出框
},
methods: {
/* update_begin author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
showClick(){
this.shows = !this.shows
showClick() {
this.searchMenuVisible = true
},
hiddenClick(){
this.shows = false
@ -141,8 +157,8 @@
...mapActions(["Logout"]),
...mapGetters(["nickname", "avatar","userInfo"]),
getAvatar(){
console.log('url = '+ window._CONFIG['imgDomainURL']+"/"+this.avatar())
return window._CONFIG['imgDomainURL']+"/"+this.avatar()
console.log('url = '+ window._CONFIG['staticDomainURL']+"/"+this.avatar())
return window._CONFIG['staticDomainURL']+"/"+this.avatar()
},
handleLogout() {
const that = this
@ -189,10 +205,17 @@
filterOption(input, option) {
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
},
searchMethods(value){
let jump = this.search.filter(item=>item.id==value)
this.$router.push({ path:jump[0].path})
// update_begin author:sunjianlei date:20191230 for: 解决外部链接打开失败的问题
searchMethods(value) {
let route = this.searchMenuOptions.filter(item => item.id === value)[0]
if (route.meta.internalOrExternal === true || route.component.includes('layouts/IframePageView')) {
window.open(route.meta.url, '_blank')
} else {
this.$router.push({ path: route.path })
}
this.searchMenuVisible = false
}
// update_end author:sunjianlei date:20191230 for: 解决外部链接打开失败的问题
/*update_end author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
}
}
@ -203,7 +226,7 @@
/* update-begin author:sunjianlei date:20191220 for: 解决全局样式冲突问题 */
.user-wrapper .search-input {
width: 180px;
color: white;
color: inherit;
/deep/ {
.ant-select-selection {

View File

@ -18,8 +18,8 @@ import VueApexCharts from 'vue-apexcharts'
import preview from 'vue-photo-preview'
import 'vue-photo-preview/dist/skin.css'
import "@jeecg/antd-online-re"
import '@jeecg/antd-online-re/dist/OnlineForm.css'
import "@jeecg/antd-online-214"
import '@jeecg/antd-online-214/dist/OnlineForm.css'
import {
ACCESS_TOKEN,

View File

@ -236,9 +236,9 @@ export const JeecgListMixin = {
return
}
if (typeof window.navigator.msSaveBlob !== 'undefined') {
window.navigator.msSaveBlob(new Blob([data]), fileName+'.xls')
window.navigator.msSaveBlob(new Blob([data],{type: 'application/vnd.ms-excel'}), fileName+'.xls')
}else{
let url = window.URL.createObjectURL(new Blob([data]))
let url = window.URL.createObjectURL(new Blob([data],{type: 'application/vnd.ms-excel'}))
let link = document.createElement('a')
link.style.display = 'none'
link.href = url
@ -286,7 +286,7 @@ export const JeecgListMixin = {
if(text && text.indexOf(",")>0){
text = text.substring(0,text.indexOf(","))
}
return window._CONFIG['imgDomainURL']+"/"+text
return window._CONFIG['staticDomainURL']+"/"+text
},
/* 文件下载 */
uploadFile(text){
@ -297,7 +297,7 @@ export const JeecgListMixin = {
if(text.indexOf(",")>0){
text = text.substring(0,text.indexOf(","))
}
window.open(window._CONFIG['domianURL'] + "/sys/common/download/"+text);
window.open(window._CONFIG['staticDomainURL']+ "/"+text);
},
}

View File

@ -0,0 +1,78 @@
export const HrefJump = {
data() {
return {
fieldHrefSlots: [],
hrefComponent: {
model: {
title: '',
width: '100%',
visible: false,
destroyOnClose: true,
style: {
top: 0,
left: 0,
height: '100%',
margin: 0,
padding: 0
},
bodyStyle: { padding: '8px', height: 'calc(100vh - 108px)', overflow: 'auto', overflowX: 'hidden' },
// 隐藏掉取消按钮
cancelButtonProps: { style: { display: 'none' } },
afterClose: () => {
// 恢复body的滚动
document.body.style.overflow = null
}
},
on: {
ok: () => this.hrefComponent.model.visible = false,
cancel: () => this.hrefComponent.model.visible = false
},
is: null,
params: {},
}
}
},
methods: {
//支持链接href跳转
handleClickFieldHref(field, record) {
let href = field.href
let urlPattern = /(ht|f)tp(s?)\:\/\/[0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*(:(0-9)*)*(\/?)([a-zA-Z0-9\-\.\?\,\'\/\\\+&amp;%\$#_]*)?/
let compPattern = /\.vue(\?.*)?$/
if (typeof href === 'string') {
href = href.trim().replace(/\${([^}]+)?}/g, (s1, s2) => record[s2])
if (urlPattern.test(href)) {
window.open(href, '_blank')
} else if (compPattern.test(href)) {
this.openHrefCompModal(href)
} else {
this.$router.push(href)
}
}
},
openHrefCompModal(href) {
// 解析 href 参数
let index = href.indexOf('?')
let path = href
if (index !== -1) {
path = href.substring(0, index)
let paramString = href.substring(index + 1, href.length)
let paramArray = paramString.split('&')
let params = {}
paramArray.forEach(paramObject => {
let paramItem = paramObject.split('=')
params[paramItem[0]] = paramItem[1]
})
this.hrefComponent.params = params
} else {
this.hrefComponent.params = {}
}
this.hrefComponent.model.visible = true
this.hrefComponent.model.title = '@/views/' + path
this.hrefComponent.is = () => import('@/views/' + (path.startsWith('/')?path.slice(1):path))
// 禁止body滚动防止滚动穿透
setTimeout(() => {
document.body.style.overflow = 'hidden'
}, 300)
},
}
}

View File

@ -120,6 +120,19 @@ const user = {
sessionStorage.setItem(USER_AUTH,JSON.stringify(authData));
sessionStorage.setItem(SYS_BUTTON_AUTH,JSON.stringify(allAuthData));
if (menuData && menuData.length > 0) {
//update--begin--autor:qinfeng-----date:20200109------forJEECG-63 一级菜单的子菜单全部是隐藏路由,则一级菜单不显示------
menuData.forEach((item, index) => {
if (item["children"]) {
let hasChildrenMenu = item["children"].filter((i) => {
return !i.hidden || i.hidden == false
})
if (hasChildrenMenu == null || hasChildrenMenu.length == 0) {
item["hidden"] = true
}
}
})
console.log(" menu show json ", menuData)
//update--end--autor:qinfeng-----date:20200109------forJEECG-63 一级菜单的子菜单全部是隐藏路由,则一级菜单不显示------
commit('SET_PERMISSIONLIST', menuData)
} else {
reject('getPermissionList: permissions must be a non-null array !')

View File

@ -1,4 +1,3 @@
import { USER_AUTH,SYS_BUTTON_AUTH } from "@/store/mutation-types"
export function disabledAuthFilter(code,formData) {
@ -10,27 +9,30 @@ export function disabledAuthFilter(code,formData) {
}
function nodeDisabledAuth(code,formData){
console.log("页面权限禁用--NODE--开始");
var permissionList = [];
let permissionList = [];
try {
var obj = formData;
//console.log("页面权限禁用--NODE--开始",obj);
if (obj) {
let bpmList = obj.permissionList;
for (var bpm of bpmList) {
if(bpm.type == '2') {
permissionList.push(bpm);
}
}
if (formData) {
let bpmList = formData.permissionList;
permissionList = bpmList.filter(item=>item.type=='2')
// for (let bpm of bpmList) {
// if(bpm.type == '2') {
// permissionList.push(bpm);
// }
// }
}else{
return false;
}
} catch (e) {
//console.log("页面权限异常----", e);
}
if (permissionList === null || permissionList === "" || permissionList === undefined||permissionList.length<=0) {
if (permissionList.length == 0) {
return false;
}
console.log("流程节点页面权限禁用--NODE--开始");
let permissions = [];
for (var item of permissionList) {
for (let item of permissionList) {
if(item.type == '2') {
permissions.push(item.action);
}
@ -39,9 +41,9 @@ function nodeDisabledAuth(code,formData){
if (!permissions.includes(code)) {
return false;
}else{
for (var item2 of permissionList) {
for (let item2 of permissionList) {
if(code === item2.action){
console.log("页面权限禁用--NODE--生效");
console.log("流程节点页面权限禁用--NODE--生效");
return true;
}
}
@ -50,21 +52,21 @@ function nodeDisabledAuth(code,formData){
}
function globalDisabledAuth(code){
console.log("页面禁用权限--Global--开始");
//console.log("全局页面禁用权限--Global--开始");
var permissionList = [];
var allPermissionList = [];
//let authList = Vue.ls.get(USER_AUTH);
let authList = JSON.parse(sessionStorage.getItem(USER_AUTH) || "[]");
for (var auth of authList) {
for (let auth of authList) {
if(auth.type == '2') {
permissionList.push(auth);
}
}
//console.log("页面禁用权限--Global--",sessionStorage.getItem(SYS_BUTTON_AUTH));
let allAuthList = JSON.parse(sessionStorage.getItem(SYS_BUTTON_AUTH) || "[]");
for (var gauth of allAuthList) {
for (let gauth of allAuthList) {
if(gauth.type == '2') {
allPermissionList.push(gauth);
}
@ -73,7 +75,7 @@ function globalDisabledAuth(code){
var gFlag = false;//禁用命中
var invalidFlag = false;//无效命中
if(allPermissionList != null && allPermissionList != "" && allPermissionList != undefined && allPermissionList.length > 0){
for (var itemG of allPermissionList) {
for (let itemG of allPermissionList) {
if(code === itemG.action){
if(itemG.status == '0'){
invalidFlag = true;
@ -92,7 +94,7 @@ function globalDisabledAuth(code){
return gFlag;
}
let permissions = [];
for (var item of permissionList) {
for (let item of permissionList) {
if(item.type == '2') {
permissions.push(item.action);
}
@ -101,9 +103,9 @@ function globalDisabledAuth(code){
if (!permissions.includes(code)) {
return gFlag;
}else{
for (var item2 of permissionList) {
for (let item2 of permissionList) {
if(code === item2.action){
console.log("页面权限解除禁用--Global--生效");
console.log("全局页面权限解除禁用--Global--生效");
gFlag = false;
}
}
@ -134,12 +136,12 @@ function hasColoum(item,authList){
//权限无效时不做控制,有效时控制,只能控制 显示不显示
//根据授权码前缀获取未授权的列信息
function getNoAuthCols(pre){
var permissionList = [];
var allPermissionList = [];
let permissionList = [];
let allPermissionList = [];
//let authList = Vue.ls.get(USER_AUTH);
let authList = JSON.parse(sessionStorage.getItem(USER_AUTH) || "[]");
for (var auth of authList) {
for (let auth of authList) {
//显示策略,有效状态
if(auth.type == '1'&&startWith(auth.action,pre)) {
permissionList.push(substrPre(auth.action,pre));
@ -147,7 +149,7 @@ function getNoAuthCols(pre){
}
//console.log("页面禁用权限--Global--",sessionStorage.getItem(SYS_BUTTON_AUTH));
let allAuthList = JSON.parse(sessionStorage.getItem(SYS_BUTTON_AUTH) || "[]");
for (var gauth of allAuthList) {
for (let gauth of allAuthList) {
//显示策略,有效状态
if(gauth.type == '1'&&gauth.status == '1'&&startWith(gauth.action,pre)) {
allPermissionList.push(substrPre(gauth.action,pre));

View File

@ -38,7 +38,7 @@ const getUploadFileList=(paths)=>{
uid:uidGenerator(),
name:getFileName(arr[a]),
status: 'done',
url: window._CONFIG['domianURL']+"/sys/common/view/"+arr[a],
url: window._CONFIG['staticDomainURL']+"/"+arr[a],
response:{
status:"history",
message:arr[a]

View File

@ -2,35 +2,37 @@ import { USER_AUTH,SYS_BUTTON_AUTH } from "@/store/mutation-types"
const hasPermission = {
install (Vue, options) {
console.log(options);
//console.log(options);
Vue.directive('has', {
inserted: (el, binding, vnode)=>{
console.log("页面权限控制----");
//console.log("页面权限控制----");
console.time()
//节点权限处理,如果命中则不进行全局权限处理
if(!filterNodePermission(el, binding, vnode)){
filterGlobalPermission(el, binding, vnode);
}
console.timeEnd() //计时结束并输出时长
}
});
}
};
/**
*
*
*/
export function filterNodePermission(el, binding, vnode) {
console.log("页面权限--NODE--");
var permissionList = [];
let permissionList = [];
try {
var obj = vnode.context.$props.formData;
let obj = vnode.context.$props.formData;
if (obj) {
let bpmList = obj.permissionList;
for (var bpm of bpmList) {
for (let bpm of bpmList) {
if(bpm.type != '2') {
permissionList.push(bpm);
}
}
}else{
return false;
}
} catch (e) {
//console.log("页面权限异常----", e);
@ -39,8 +41,10 @@ export function filterNodePermission(el, binding, vnode) {
//el.parentNode.removeChild(el)
return false;
}
console.log("流程节点页面权限--NODE--");
let permissions = [];
for (var item of permissionList) {
for (let item of permissionList) {
if(item.type != '2') {
permissions.push(item.action);
}
@ -51,7 +55,7 @@ export function filterNodePermission(el, binding, vnode) {
//el.parentNode.removeChild(el)
return false;
}else{
for (var item2 of permissionList) {
for (let item2 of permissionList) {
if(binding.value === item2.action){
return true;
}
@ -64,29 +68,29 @@ export function filterNodePermission(el, binding, vnode) {
*
*/
export function filterGlobalPermission(el, binding, vnode) {
console.log("页面权限--Global--");
console.log("全局页面权限--Global--");
var permissionList = [];
var allPermissionList = [];
let permissionList = [];
let allPermissionList = [];
//let authList = Vue.ls.get(USER_AUTH);
let authList = JSON.parse(sessionStorage.getItem(USER_AUTH) || "[]");
for (var auth of authList) {
for (let auth of authList) {
if(auth.type != '2') {
permissionList.push(auth);
}
}
//console.log("页面权限--Global--",sessionStorage.getItem(SYS_BUTTON_AUTH));
let allAuthList = JSON.parse(sessionStorage.getItem(SYS_BUTTON_AUTH) || "[]");
for (var gauth of allAuthList) {
for (let gauth of allAuthList) {
if(gauth.type != '2') {
allPermissionList.push(gauth);
}
}
//设置全局配置是否有命中
var invalidFlag = false;//无效命中
let invalidFlag = false;//无效命中
if(allPermissionList != null && allPermissionList != "" && allPermissionList != undefined && allPermissionList.length > 0){
for (var itemG of allPermissionList) {
for (let itemG of allPermissionList) {
if(binding.value === itemG.action){
if(itemG.status == '0'){
invalidFlag = true;
@ -103,7 +107,7 @@ export function filterGlobalPermission(el, binding, vnode) {
return;
}
let permissions = [];
for (var item of permissionList) {
for (let item of permissionList) {
if(item.type != '2'){
permissions.push(item.action);
}

View File

@ -5,9 +5,16 @@ import { VueAxios } from './axios'
import {Modal, notification} from 'ant-design-vue'
import { ACCESS_TOKEN } from "@/store/mutation-types"
//自动设置后台服务 baseURL (也可以手工指定写死项目名字)
let baseDomain = window._CONFIG['domianURL'];
let baseProject = baseDomain.substring(baseDomain.lastIndexOf("/"));
console.log("baseDomain= ",baseDomain)
console.log("baseProject= ",baseProject)
// 创建 axios 实例
const service = axios.create({
baseURL: '/jeecg-boot', // api base_url
//baseURL: '/jeecg-boot',
baseURL: baseProject, // api base_url
timeout: 9000 // 请求超时时间
})

View File

@ -257,6 +257,62 @@ export function cssExpand(css, id) {
document.head.appendChild(style)
}
/** 用于js增强事件运行JS代码可以传参 */
// options 所需参数:
// 参数名 类型 说明
// vm VueComponent vue实例
// event Object event对象
// jsCode String 待执行的js代码
// errorMessage String 执行出错后的提示(控制台)
export function jsExpand(options = {}) {
// 绑定到window上的keyName
let windowKeyName = 'J_CLICK_EVENT_OPTIONS'
if (typeof window[windowKeyName] != 'object') {
window[windowKeyName] = {}
}
// 随机生成JS增强的执行id防止冲突
let id = randomString(16, 'qwertyuioplkjhgfdsazxcvbnm'.toUpperCase())
// 封装按钮点击事件
let code = `
(function (o_${id}) {
try {
(function (globalEvent, vm) {
${options.jsCode}
})(o_${id}.event, o_${id}.vm)
} catch (e) {
o_${id}.error(e)
}
o_${id}.done()
})(window['${windowKeyName}']['EVENT_${id}'])
`
// 创建script标签
const script = document.createElement('script')
// 将需要传递的参数挂载到window对象上
window[windowKeyName]['EVENT_' + id] = {
vm: options.vm,
event: options.event,
// 当执行完成时,无论如何都会调用的回调事件
done() {
// 执行完后删除新增的 script 标签不会撤销执行结果(已产生的结果不会被撤销)
script.outerHTML = ''
delete window[windowKeyName]['EVENT_' + id]
},
// 当js运行出错的时候调用的事件
error(e) {
console.group(`${options.errorMessage || 'JS'}${new Date()}`)
console.error(e)
console.groupEnd()
}
}
// 将事件挂载到document中
script.innerHTML = code
document.body.appendChild(script)
}
/**
*
*
@ -270,12 +326,39 @@ export function cssExpand(css, id) {
* @param callback
*/
export function validateDuplicateValue(tableName, fieldName, fieldVal, dataId, callback) {
let params = { tableName, fieldName, fieldVal, dataId }
api.duplicateCheck(params).then(res => {
res['success'] ? callback() : callback(res['message'])
}).catch(err => {
callback(err.message || err)
})
if (fieldVal) {
let params = { tableName, fieldName, fieldVal, dataId }
api.duplicateCheck(params).then(res => {
res['success'] ? callback() : callback(res['message'])
}).catch(err => {
callback(err.message || err)
})
} else {
callback()
}
}
/**
* code
*
* 使
* { validator: (rule, value, callback) => validateCheckRule('common', value, callback) }
*
* @param ruleCode code
* @param value
* @param callback
*/
export function validateCheckRule(ruleCode, value, callback) {
if (ruleCode && value) {
value = encodeURIComponent(value)
api.checkRuleByCode({ ruleCode, value }).then(res => {
res['success'] ? callback() : callback(res['message'])
}).catch(err => {
callback(err.message || err)
})
} else {
callback()
}
}
/**
@ -295,4 +378,40 @@ export function pushIfNotExist(array, value, key) {
}
array.push(value)
return true
}
/**
*
* @type {symbol}
*/
export const succeedSymbol = Symbol()
/**
*
* @type {symbol}
*/
export const failedSymbol = Symbol()
/**
* 使 promise resolvePromisePromise
* Promise.all
*
* @param promise PromisePromise
* @returns {Promise<any>}
*/
export function alwaysResolve(promise) {
return new Promise((resolve, reject) => {
let p = promise
if (typeof promise === 'function') {
p = promise()
}
if (p instanceof Promise) {
p.then(data => {
resolve({ type: succeedSymbol, data })
}).catch(error => {
resolve({ type: failedSymbol, error })
})
} else {
reject('alwaysResolve: PromisePromise')
}
})
}

View File

@ -133,7 +133,7 @@
methods: {
...mapGetters(["nickname", "avatar"]),
getAvatar(){
return window._CONFIG['imgDomainURL']+"/"+this.avatar();
return window._CONFIG['staticDomainURL']+"/"+this.avatar();
},
getTeams() {
this.$http.get('/api/workplace/teams')

View File

@ -20,14 +20,14 @@
</chart-card>
</a-col>
<a-col :sm="24" :md="12" :xl="6" :style="{ marginBottom: '24px' }">
<chart-card :loading="loading" title="访问量" :total="8846 | NumberFormat">
<chart-card :loading="loading" title="订单量" :total="8846 | NumberFormat">
<a-tooltip title="指标说明" slot="action">
<a-icon type="info-circle-o" />
</a-tooltip>
<div>
<mini-area />
</div>
<template slot="footer">访<span> {{ '1234' | NumberFormat }}</span></template>
<template slot="footer"><span> {{ '1234' | NumberFormat }}</span></template>
</chart-card>
</a-col>
<a-col :sm="24" :md="12" :xl="6" :style="{ marginBottom: '24px' }">
@ -85,7 +85,7 @@
</a-col>
</a-row>
</a-tab-pane>
<a-tab-pane tab="访问量" key="2">
<a-tab-pane tab="销售趋势" key="2">
<a-row>
<a-col :xl="16" :lg="12" :md="12" :sm="24" :xs="24">
<bar title="销售额趋势" :dataSource="barData"/>
@ -101,10 +101,10 @@
<a-row>
<a-col :span="24">
<a-card :loading="loading" :bordered="false" title="最近一周访问次数统计" :style="{ marginTop: '24px' }">
<a-card :loading="loading" :bordered="false" title="最近一周访问统计" :style="{ marginTop: '24px' }">
<a-row>
<a-col :span="6">
<head-info title="今日访问IP" :content="loginfo.todayIp"></head-info>
<head-info title="今日IP" :content="loginfo.todayIp"></head-info>
</a-col>
<a-col :span="2">
<a-spin class='circle-cust'>
@ -112,7 +112,7 @@
</a-spin>
</a-col>
<a-col :span="6">
<head-info title="今日访问次数" :content="loginfo.todayVisitCount"></head-info>
<head-info title="今日访问" :content="loginfo.todayVisitCount"></head-info>
</a-col>
<a-col :span="2">
<a-spin class='circle-cust'>
@ -120,7 +120,7 @@
</a-spin>
</a-col>
<a-col :span="6">
<head-info title="访问总次数" :content="loginfo.totalVisitCount"></head-info>
<head-info title="总访问量" :content="loginfo.totalVisitCount"></head-info>
</a-col>
<a-col :span="2">
<a-spin class='circle-cust'>

View File

@ -185,7 +185,7 @@
},
created() {
this.user = this.userInfo
this.avatar = window._CONFIG['imgDomainURL'] +"/"+ this.userInfo.avatar
this.avatar = window._CONFIG['staticDomainURL'] +"/"+ this.userInfo.avatar
console.log('this.avatar :'+ this.avatar)
getRoleList().then(res => {

View File

@ -9,7 +9,7 @@
<a-row :gutter="24">
<a-col :span="12">
<a-form-item label="性别">
<j-dict-select-tag v-model="formData.sex" title="性别" dictCode="sex"/>
<j-dict-select-tag v-model="formData.sex" title="性别" dictCode="sex" placeholder="请选择性别"/>
<!-- <j-dict-select-tag title="性别" dictCode="sex" disabled/>-->
</a-form-item>
</a-col>
@ -176,34 +176,28 @@
<a-row :gutter="24">
<a-col>
<a-form-item label="最大化弹窗">
<a-button @click="()=>modal.visible=true"></a-button>
<a-form-item label="JModal弹窗">
<a-button style="margin-right: 8px;" @click="()=>modal.visible=true">JModal</a-button>
<span style="margin-right: 8px;"><a-switch v-model="modal.fullscreen"/></span>
<span style="margin-right: 8px;"><a-switch v-model="modal.switchFullscreen"/></span>
<span>Body<a-switch v-model="modal.lockScroll"/></span>
</a-form-item>
<a-modal
:visible="modal.visible"
:width="modal.width"
:style="modal.style"
@ok="()=>modal.visible=false"
@cancel="()=>modal.visible=false">
<template slot="title">
<div style="width: 100%;height:20px;padding-right:32px;">
<div style="float: left;">{{ modal.title }}</div>
<div style="float: right;">
<a-button
icon="fullscreen"
style="width:56px;height:100%;border:0"
@click="handleClickToggleFullScreen"/>
</div>
</div>
</template>
<j-modal
:visible.sync="modal.visible"
:width="1200"
:title="modal.title"
:lockScroll="modal.lockScroll"
:fullscreen.sync="modal.fullscreen"
:switchFullscreen="modal.switchFullscreen"
>
<template v-for="(i,k) of 30">
<p :key="k"></p>
</template>
</a-modal>
</j-modal>
</a-col>
</a-row>
@ -217,10 +211,10 @@
<a-row :gutter="24">
<a-col :span="12">
<a-form-item label="树字典">
<j-tree-dict parentCode="B01" />
<j-tree-dict v-model="formData.treeDict" placeholder="请选择树字典" parentCode="A01" />
</a-form-item>
</a-col>
<a-col :span="12"></a-col>
<a-col :span="12">(v-model){{ formData.treeDict }}</a-col>
</a-row>
<a-row :gutter="24">
@ -262,6 +256,45 @@
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="24">
<a-col :span="12">
<a-form-item label="高级查询">
<j-super-query :fieldList="superQuery.fieldList" />
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="24">
<a-col :span="12">
<a-form-item label="高级查询(自定义按钮)">
<j-super-query :fieldList="superQuery.fieldList">
<!-- -->
<a-button type="primary" ghost icon="clock-circle"></a-button>
</j-super-query>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="24">
<a-col :span="12">
<a-form-item label="图片上传">
<j-image-upload v-model="imgList"></j-image-upload>
</a-form-item>
</a-col>
<a-col :spapn="12">(v-model){{ imgList }}</a-col>
</a-row>
<a-row :gutter="24" style="margin-top: 65px;margin-bottom:50px;">
<a-col :span="12">
<a-form-item label="文件上传">
<j-upload v-model="fileList"></j-upload>
</a-form-item>
</a-col>
<a-col :spapn="12">
(v-model)
<j-ellipsis :value="fileList" :length="30" v-if="fileList.length>0"/>
</a-col>
</a-row>
</a-form>
</div>
@ -286,10 +319,15 @@
import JTreeDict from "../../components/jeecg/JTreeDict.vue";
import JCron from "@/components/jeecg/JCron.vue";
import JTreeSelect from '@/components/jeecg/JTreeSelect'
import JSuperQuery from '@/components/jeecg/JSuperQuery'
import JUpload from '@/components/jeecg/JUpload'
import JImageUpload from '@/components/jeecg/JImageUpload'
export default {
name: 'SelectDemo',
components: {
JImageUpload,
JUpload,
JTreeDict,
JDictSelectTag,
JSelectDepart,
@ -299,7 +337,7 @@
JCheckbox,
JCodeEditor,
JDate, JEditor, JEllipsis, JGraphicCode, JSlider, JSelectMultiple,
JCron, JTreeSelect
JCron, JTreeSelect, JSuperQuery
},
data() {
return {
@ -352,11 +390,20 @@ sayHi('hello, world!')`
modal: {
title: '',
visible: false,
width: '100%',
style: { top: '20px' },
fullScreen: true
lockScroll: true,
fullscreen: true,
switchFullscreen: true,
},
cron: '',
superQuery: {
fieldList: [
{ type: 'input', value: 'name', text: '', },
{ type: 'select', value: 'sex', text: '', dictCode: 'sex' },
{ type: 'number', value: 'age', text: '', }
]
},
fileList:[],
imgList:[],
}
},
computed: {
@ -399,18 +446,6 @@ sayHi('hello, world!')`
handleJSliderSuccess(value) {
this.jslider.value = value
},
/** 切换全屏显示 */
handleClickToggleFullScreen() {
let mode = !this.modal.fullScreen
if (mode) {
this.modal.width = '100%'
this.modal.style.top = '20px'
} else {
this.modal.width = '1200px'
this.modal.style.top = '50px'
}
this.modal.fullScreen = mode
},
setCorn(data){
this.$nextTick(() => {
this.form.cronExpression = data;

View File

@ -19,11 +19,13 @@
<a-cascader :options="areaOptions" @change="onChange" :showSearch="{filter}" placeholder="Please select" />
</a-form-item>
</a-col>
<a-col :md="24" :sm="24">
<a-form-item :wrapperCol="{ span: 12, offset: 5 }">
<a-button type="primary" htmlType="submit">Submit</a-button>
</a-form-item>
</a-col>
<a-form-item :wrapperCol="{ span: 12, offset: 5 }">
<a-col :md="24" :sm="24">
<a-form-item :wrapperCol="{ span: 12, offset: 5 }">
<a-button type="primary" htmlType="submit">Submit</a-button>
</a-form-item>
</a-col>
</a-form-item>
</a-form>
</a-card>
</template>
@ -68,4 +70,4 @@
})
}
}
</script>
</script>

View File

@ -35,12 +35,13 @@
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="sex">
<a-select v-decorator="['sex', {}]" placeholder="请选择性别">
<a-select-option value=""></a-select-option>
<a-select-option value="1"></a-select-option>
<a-select-option value="2"></a-select-option>
</a-select>
label="性别">
<!-- <a-select v-decorator="['sex', {}]" placeholder="请选择性别">
<a-select-option value=""></a-select-option>
<a-select-option value="1"></a-select-option>
<a-select-option value="2"></a-select-option>
</a-select>-->
<j-dict-select-tag type="radio" v-decorator="['sex', {}]" :trigger-change="true" dictCode="sex"/>
</a-form-item>
<a-form-item
:labelCol="labelCol"

View File

@ -2,7 +2,7 @@
<a-card :bordered="false">
<a-tabs defaultActiveKey="1" @change="callback">
<a-tab-pane tab="柱状图" key="1">
<a-row :gutter="24">
<a-row>
<a-col :span="10">
<a-radio-group :value="barType" @change="statisticst">
<a-radio-button value="year"></a-radio-button>

View File

@ -43,24 +43,7 @@
:wrapperCol="wrapperCol"
label="身份证扫描件"
hasFeedback>
<a-upload
:action="uploadAction"
listType="picture-card"
:headers="headers"
:fileList="fileList"
@change="handleChange"
@preview="handlePreview"
>
<a-button>
<a-icon type="upload"/>
upload
</a-button>
</a-upload>
<a-modal :visible="previewVisible" :footer="null" @cancel="handlePicCancel">
<img alt="example" style="width: 100%" :src="previewImage"/>
</a-modal>
<br/>
<j-image-upload text="上传" v-model="fileList" :isMultiple="true"></j-image-upload>
</a-form-item>
<a-form-item
:labelCol="labelCol"
@ -88,11 +71,11 @@
import pick from 'lodash.pick'
import Vue from 'vue'
import {ACCESS_TOKEN} from "@/store/mutation-types"
import { getUploadFileList,getFilePaths } from '@/utils/commonUploadFile.js'
import JImageUpload from '../../../../components/jeecg/JImageUpload'
export default {
name: "JeecgOrderCustomerModal",
components: { JImageUpload },
data() {
return {
title: "操作",
@ -177,7 +160,7 @@
add: "/test/order/addCustomer",
edit: "/test/order/editCustomer",
fileUpload: window._CONFIG['domianURL'] + "/sys/common/upload",
imgerver: window._CONFIG['domianURL'] + "/sys/common/view",
imgerver: window._CONFIG['staticDomainURL'],
getOrderCustomerList: "/test/order/listOrderCustomerByMainId",
},
validatorRules: {
@ -222,8 +205,6 @@
this.form.resetFields();
this.orderId = record.orderId;
let currFileList = getUploadFileList(record.idcardPic)
this.fileList = [...currFileList]
this.model = Object.assign({}, record);
if (record.id) {
this.hiding = false;
@ -232,6 +213,9 @@
this.$nextTick(() => {
this.form.setFieldsValue(pick(this.model, 'id', 'name', 'sex', 'idcard','telphone', 'orderId', 'createBy', 'createTime', 'updateBy', 'updateTime'))
});
setTimeout(() => {
this.fileList = record.idcardPic
}, 5)
} else {
this.addStatus = false;
this.editStatus = true;
@ -262,7 +246,7 @@
let formData = Object.assign(this.model, values);
console.log(formData);
formData.orderId = this.orderId;
formData.idcardPic = getFilePaths(this.fileList)
formData.idcardPic = this.fileList;
httpAction(httpurl, formData, method).then((res) => {
if (res.success) {
that.$message.success(res.message);

View File

@ -6,13 +6,13 @@
<a-form layout="inline">
<a-row :gutter="24">
<a-col :md="6" :sm="24">
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<a-form-item label="表名">
<a-input placeholder="请输入表名" v-model="queryParam.tableName"></a-input>
</a-form-item>
</a-col>
<a-col :md="6" :sm="24">
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
<a-button type="primary" @click="searchQuery" icon="search"></a-button>
<a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px"></a-button>
@ -25,10 +25,10 @@
<!-- -->
<div class="table-operator">
<a-button @click="doCgformButton" type="primary" icon="highlight" style="margin-left:8px"></a-button>
<a-button @click="doEnhanceJs" type="primary" icon="strikethrough" style="margin-left:8px">JS</a-button>
<a-button @click="doEnhanceSql" type="primary" icon="filter" style="margin-left:8px">SQL</a-button>
<a-button @click="doEnhanceJava" type="primary" icon="tool" style="margin-left:8px">Java</a-button>
<a-button @click="doCgformButton" type="primary" icon="highlight"></a-button>
<a-button @click="doEnhanceJs" type="primary" icon="strikethrough">JS</a-button>
<a-button @click="doEnhanceSql" type="primary" icon="filter">SQL</a-button>
<a-button @click="doEnhanceJava" type="primary" icon="tool">Java</a-button>
<a-dropdown v-if="selectedRowKeys.length > 0">
<a-menu slot="overlay">
@ -37,7 +37,7 @@
</a-menu-item>
</a-menu>
<a-button style="margin-left: 8px">
<a-button>
<a-icon type="down"/>
</a-button>
</a-dropdown>
@ -348,6 +348,9 @@
}
}
</script>
<style scoped>
@import '~@assets/less/common.less';
</style>
<style lang="less">
.ant-card-body .table-operator {
margin-bottom: 18px;

View File

@ -6,18 +6,22 @@
<a-form layout="inline">
<a-row :gutter="24">
<a-col :md="6" :sm="24">
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<a-form-item label="表名">
<a-input placeholder="请输入表名" v-model="queryParam.tableName"></a-input>
</a-form-item>
</a-col>
<a-col :md="6" :sm="24">
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<a-form-item label="表类型">
<j-dict-select-tag dictCode="cgform_table_type" v-model="queryParam.tableType"/>
</a-form-item>
</a-col>
<a-col :md="6" :sm="24">
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<a-form-item label="表描述">
<a-input placeholder="请输入表描述" v-model="queryParam.tableTxt"></a-input>
</a-form-item>
</a-col>
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
<a-button type="primary" @click="searchQuery" icon="search"></a-button>
<a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px"></a-button>
@ -31,12 +35,12 @@
<!-- -->
<div class="table-operator">
<a-button @click="handleAdd" type="primary" icon="plus"></a-button>
<a-button @click="doCgformButton" type="primary" icon="highlight" style="margin-left:8px"></a-button>
<a-button @click="doEnhanceJs" type="primary" icon="strikethrough" style="margin-left:8px">JS</a-button>
<a-button @click="doEnhanceSql" type="primary" icon="filter" v-has="'online:sql'" style="margin-left:8px">SQL</a-button>
<a-button @click="doEnhanceJava" type="primary" icon="tool" style="margin-left:8px">Java</a-button>
<a-button @click="importOnlineForm" type="primary" icon="database" style="margin-left:8px"></a-button>
<a-button @click="goGenerateCode" v-has="'online:goGenerateCode'" type="primary" icon="database" style="margin-left:8px"></a-button>
<a-button @click="doCgformButton" type="primary" icon="highlight"></a-button>
<a-button @click="doEnhanceJs" type="primary" icon="strikethrough">JS</a-button>
<a-button @click="doEnhanceSql" type="primary" icon="filter">SQL</a-button>
<a-button @click="doEnhanceJava" type="primary" icon="tool">Java</a-button>
<a-button @click="importOnlineForm" type="primary" icon="database"></a-button>
<a-button @click="goGenerateCode" type="primary" icon="database"></a-button>
<a-dropdown v-if="selectedRowKeys.length > 0">
<a-menu slot="overlay">
@ -45,7 +49,7 @@
</a-menu-item>
</a-menu>
<a-button style="margin-left: 8px">
<a-button>
<a-icon type="down"/>
</a-button>
</a-dropdown>
@ -204,8 +208,12 @@
title: '',
align: 'center',
dataIndex: 'tableType',
customRender: (text) => {
return filterDictText(this.tableTypeDictOptions, `${text}`)
customRender: (text, record) => {
let tbTypeText = filterDictText(this.tableTypeDictOptions, `${text}`)
if(record.isTree === 'Y'){
tbTypeText+='()'
}
return tbTypeText;
}
},
{
@ -316,10 +324,14 @@
this.syncFormId = id
},
goPageOnline(rd) {
if(rd.isTree=='Y'){
this.$router.push({ path: '/online/cgformTreeList/' + rd.id })
if(rd.themeTemplate === 'erp'){
this.$router.push({ path: '/online/cgformErpList/' + rd.id })
}else{
this.$router.push({ path: '/online/cgformList/' + rd.id })
if(rd.isTree=='Y'){
this.$router.push({ path: '/online/cgformTreeList/' + rd.id })
}else{
this.$router.push({ path: '/online/cgformList/' + rd.id })
}
}
},
handleOnlineUrlClose() {
@ -438,6 +450,9 @@
}
}
</script>
<style scoped>
@import '~@assets/less/common.less';
</style>
<style lang="less">
.ant-card-body .table-operator {
margin-bottom: 18px;

View File

@ -40,16 +40,15 @@
<!-- -->
<div class="table-operator">
<a-button v-if="buttonSwitch.add" @click="handleAdd" type="primary" icon="plus"></a-button>
<a-button v-if="buttonSwitch.import" @click="handleImportXls" type="primary" icon="upload" style="margin-left:8px"></a-button>
<a-button v-if="buttonSwitch.export" @click="handleExportXls" type="primary" icon="download" style="margin-left:8px"></a-button>
<a-button v-if="buttonSwitch.import" @click="handleImportXls" type="primary" icon="upload"></a-button>
<a-button v-if="buttonSwitch.export" @click="handleExportXls" type="primary" icon="download"></a-button>
<template v-if="cgButtonList && cgButtonList.length>0" v-for="(item,index) in cgButtonList">
<a-button
v-if=" item.optType=='js' "
:key=" 'cgbtn'+index "
@click="cgButtonJsHandler(item.buttonCode)"
type="primary"
:icon="item.buttonIcon"
style="margin-left:8px">
:icon="item.buttonIcon">
{{ item.buttonName }}
</a-button>
<a-button
@ -57,8 +56,7 @@
:key=" 'cgbtn'+index "
@click="cgButtonActionHandler(item.buttonCode)"
type="primary"
:icon="item.buttonIcon"
style="margin-left:8px">
:icon="item.buttonIcon">
{{ item.buttonName }}
</a-button>
</template>
@ -69,13 +67,11 @@
:fieldList="superQuery.fieldList"
:saveCode="$route.fullPath"
:loading="table.loading"
style="margin-left: 8px;"
@handleSuperQuery="handleSuperQuery"/>
<a-button
v-if="buttonSwitch.batch_delete"
@click="handleDelBatch"
style="margin-left:8px"
v-show="table.selectedRowKeys.length > 0"
ghost
type="primary"
@ -103,6 +99,16 @@
:scroll="table.scroll"
style="min-height: 300px">
<!-- href -->
<template
v-for="field of fieldHrefSlots"
:slot="field.slotName"
slot-scope="text, record"
>
<a @click="handleClickFieldHref(field,record)">{{ text }}</a>
</template>
<template slot="dateSlot" slot-scope="text">
<span>{{ getFormatDate(text) }}</span>
</template>
@ -149,23 +155,17 @@
<a-icon type="down" />
</a>
<a-menu slot="overlay">
<a-menu-item >
<a-menu-item v-if="buttonSwitch.detail">
<a href="javascript:;" @click="handleDetail(record)"></a>
</a-menu-item>
<template v-if="hasBpmStatus">
<template v-if="record.bpm_status == '1'||record.bpm_status == ''|| record.bpm_status == null">
<a-menu-item>
<a href="javascript:;" @click="startProcess(record)"></a>
</a-menu-item>
<a-menu-item v-if="buttonSwitch.delete">
<a-popconfirm title="确定删除吗?" @confirm="() => handleDeleteOne(record)">
<a></a>
</a-popconfirm>
</a-menu-item>
</template>
<template v-else>
<a-menu-item @click="handlePreviewPic(record)"></a-menu-item>
</template>
</template>
<template v-else>
<a-menu-item v-if="buttonSwitch.delete">
@ -175,7 +175,7 @@
</a-menu-item>
</template>
<template v-if="cgButtonLinkList && cgButtonLinkList.length>0" v-for="(btnItem,btnIndex) in cgButtonLinkList">
<a-menu-item :key=" 'cgbtnLink'+btnIndex ">
<a-menu-item :key=" 'cgbtnLink'+btnIndex " v-if="showLinkButton(btnItem,record)">
<a href="javascript:void(0);" @click="cgButtonLinkHandler(record,btnItem.buttonCode,btnItem.optType)">
<a-icon v-if="btnItem.buttonIcon" :type="btnItem.buttonIcon" />
{{ btnItem.buttonName }}
@ -192,20 +192,27 @@
<j-import-modal ref="importModal" :url="getImportUrl()" @ok="importOk"></j-import-modal>
<!-- Href -->
<a-modal v-bind="hrefComponent.model" v-on="hrefComponent.on">
<component :is="hrefComponent.is" v-bind="hrefComponent.params"/>
</a-modal>
</div>
</a-card>
</template>
<script>
import { HrefJump } from '@/mixins/OnlAutoListMixin'
import { postAction,getAction,deleteAction,downFile } from '@/api/manage'
import { filterMultiDictText } from '@/components/dict/JDictSelectUtil'
import { filterObj } from '@/utils/util';
import { cloneObject, filterObj } from '@/utils/util'
import JImportModal from '@/components/jeecg/JImportModal'
import JSuperQuery from '@comp/jeecg/JSuperQuery'
export default {
name: 'OnlCgFormAutoList',
mixins: [HrefJump],
components: {
JSuperQuery,
JImportModal,
@ -222,7 +229,6 @@
optPre:"/online/cgform/api/form/",
exportXls:'/online/cgform/api/exportXls/',
buttonAction:'/online/cgform/api/doButton',
startProcess: "/process/extActProcess/startMutilProcess",
},
flowCodePre:"onl_",
isorter:{
@ -282,7 +288,8 @@
delete:true,
batch_delete:true,
import:true,
export:true
export:true,
detail:true
},
hasBpmStatus:false,
checkboxFlag:false,
@ -304,8 +311,7 @@
this.cgButtonJsHandler('mounted')
},
watch: {
'$route.path'(newVal,oldVal) {
console.log('$route.path ',oldVal)
'$route'() {
// 刷新参数放到这里去触发,就可以刷新相同界面了
this.initAutoList()
}
@ -343,30 +349,6 @@
this.hasBpmStatus = false;
}
},
startProcess: function(record){
var that = this;
this.$confirm({
title:"提示",
content:"确认提交流程吗?",
onOk: function(){
var param = {
flowCode:that.flowCodePre+that.currentTableName,
id:record.id,
formUrl:"modules/bpm/task/form/OnlineFormDetail",
formUrlMobile:"modules/bpm/task/form/OnlineFormDetail"
}
postAction(that.url.startProcess,param).then((res)=>{
if(res.success){
that.$message.success(res.message);
that.loadData();
that.onClearSelected();
}else{
that.$message.warning(res.message);
}
});
}
});
},
initQueryInfo(){
getAction(`${this.url.getQueryInfo}${this.code}`).then((res)=>{
console.log("--onlineList-获取查询条件配置",res);
@ -407,6 +389,7 @@
this.table.pagination = false
}
this.fieldHrefSlots = res.result.fieldHrefSlots
this.dictOptions = res.result.dictOptions
this.formTemplate = res.result.formTemplate
this.description = res.result.description
@ -441,6 +424,8 @@
this.hasBpmStatusFilter();
this.loadData();
this.initQueryInfo();
//加载新路由清空checkbox选中
this.table.selectedRowKeys = [];
}else{
this.$message.warning(res.message)
}
@ -569,6 +554,10 @@
this.cgButtonLinkHandler(record,"beforeEdit","js")
this.$refs.modal.edit(this.formTemplate,record.id);
},
showLinkButton(item,record){
let btn = new ButtonExpHandler(item.exp,record);
return btn.show;
},
handleDetail(record){
this.$refs.modal.detail(this.formTemplate,record.id);
},
@ -604,7 +593,8 @@
dictCode: field.dictCode,
dictTable: field.dictTable,
dictText: field.dictText,
options: field.enum || field.options
options: field.enum || field.options,
order: field.order,
})
}
let fieldList = []
@ -630,6 +620,17 @@
setField(fieldList, field)
}
}
// 冒泡排序
for (let i = 0; i < fieldList.length; i++) {
for (let j = i + 1; j < fieldList.length; j++) {
let temp1 = fieldList[i]
let temp2 = fieldList[j]
if (temp1.order > temp2.order) {
fieldList[i] = temp2
fieldList[j] = temp1
}
}
}
this.superQuery.fieldList = fieldList
}
},
@ -641,7 +642,7 @@
if(text && text.indexOf(",")>0){
text = text.substring(0,text.indexOf(","))
}
return window._CONFIG['imgDomainURL']+"/"+text
return window._CONFIG['staticDomainURL']+"/"+text
},
downloadRowFile(text){
if(!text){
@ -651,7 +652,7 @@
if(text.indexOf(",")>0){
text = text.substring(0,text.indexOf(","))
}
window.open(window._CONFIG['downloadUrl']+"/"+text);//TODO 下载的方法
window.open(window._CONFIG['staticDomainURL']+"/"+text);//TODO 下载的方法
},
handleDelBatch(){
if(this.table.selectedRowKeys.length<=0){
@ -777,13 +778,15 @@
}
},
initButtonSwitch(hideColumns){
Object.keys(this.buttonSwitch).forEach(key=>{
this.buttonSwitch[key]=true
})
if(hideColumns && hideColumns.length>0){
Object.keys(this.buttonSwitch).forEach(key=>{
if(hideColumns.indexOf(key)>=0){
this.buttonSwitch[key]=false
}
})
}
},
@ -801,6 +804,9 @@
}
}
</script>
<style scoped>
@import '~@assets/less/common.less';
</style>
<style>
.ant-card-body .table-operator{
margin-bottom: 18px;

View File

@ -98,15 +98,6 @@
<a-menu-item >
<a @click="handleDetail(record)"></a>
</a-menu-item>
<a-menu-item v-if="showSubmitFlowButton(record)">
<a @click="startProcess(record)"></a>
</a-menu-item>
<template v-if="showViewFlowButton(record)">
<a-menu-item @click="handlePreviewPic(record)"></a-menu-item>
</template>
<a-menu-item v-if="showOptButton('delete',record)">
<a-popconfirm title="确定删除吗?" @confirm="() => handleDeleteOne(record)">
<a></a>
@ -146,7 +137,7 @@
export default {
name: 'OnlCgformTreeList',
components: {
JImportModal
JImportModal,
},
data() {
return {
@ -183,7 +174,6 @@
optPre:"/online/cgform/api/form/",
exportXls:'/online/cgform/api/exportXls/',
buttonAction:'/online/cgform/api/doButton',
startProcess: "/process/extActProcess/startMutilProcess"
},
isorter:{
column: 'create_time',
@ -482,7 +472,7 @@
if(text && text.indexOf(",")>0){
text = text.substring(0,text.indexOf(","))
}
return window._CONFIG['imgDomainURL']+"/"+text
return window._CONFIG['staticDomainURL']+"/"+text
},
downloadRowFile(text){
if(!text){
@ -492,7 +482,7 @@
if(text.indexOf(",")>0){
text = text.substring(0,text.indexOf(","))
}
window.open(window._CONFIG['downloadUrl']+"/"+text);
window.open(window._CONFIG['staticDomainURL']+"/"+text);
},
/*-------数据格式化-end----------*/
@ -651,14 +641,6 @@
}
return true
},
showSubmitFlowButton(record){
if(this.hasBpmStatus){
if(record.bpm_status ==null || record.bpm_status =='' || record.bpm_status == '1'){
return true
}
}
return false
},
showViewFlowButton(record){
if(this.hasBpmStatus){
if(record.bpm_status !=null && record.bpm_status !='' && record.bpm_status != '1'){
@ -691,6 +673,7 @@
}
});
},
}
}
</script>

View File

@ -0,0 +1,111 @@
<template>
<a-card :bordered="false" style="height: 100%">
<online-common-list
:ref="'onl_'+mainModel.currentTableName"
:code="code"
:model="mainModel"
@seleted="onSelected">
</online-common-list>
<a-tabs defaultActiveKey="0">
<a-tab-pane v-for="(item,index) in subList" :tab="item.description" :key="index+''" :forceRender="true" >
<online-common-list
:ref="item.currentTableName"
:code="item.code"
:model="item"
:main="selectedRow">
</online-common-list>
</a-tab-pane>
</a-tabs>
</a-card>
</template>
<script>
import { getAction } from '@/api/manage'
export default {
name: 'OnlCgformErpList',
components:{
},
data(){
return {
code:'',
url: {
getColumns: '/online/cgform/api/getErpColumns/',
},
mainModel:{},
subList:[],
mainId:'',
selectedRow:{}
}
},
watch: {
'$route'() {
// 刷新参数放到这里去触发,就可以刷新相同界面了
this.initColumnConfig()
}
},
created() {
this.initColumnConfig();
},
methods:{
getSubIndex(index){
return index+1 + ''
},
getSubRef(item){
let ref = item.currentTableName
console.log("ref string",ref)
return ref;
},
initColumnConfig(){
if(!this.$route.params.code){
return false
}
this.code = this.$route.params.code
getAction(`${this.url.getColumns}${this.code}`).then((res)=>{
console.log("erp表单配置",res)
if(res.success){
this.mainModel = res.result.main
this.subList = res.result.subList
this.$nextTick(()=>{
this.$refs['onl_'+this.mainModel.currentTableName].initListByModel();
if(this.subList && this.subList.length>0){
for(let item of this.subList){
this.$refs[item.currentTableName][0].initListByModel();
}
}
});
}
})
},
onSelected(row){
console.log("onSelected",row)
this.selectedRow = row;
}
}
}
</script>
<style>
.ant-card-body .table-operator{
margin-bottom: 18px;
}
.ant-table-tbody .ant-table-row td{
padding-top:15px;
padding-bottom:15px;
}
.anty-row-operator button{margin: 0 5px}
.ant-btn-danger{background-color: #ffffff}
.anty-img-wrap{height:25px;position: relative;}
.anty-img-wrap > img{max-height:100%;}
.ant-modal-cust-warp{height: 100%}
.ant-modal-cust-warp .ant-modal-body{height:calc(100% - 110px) !important;overflow-y: auto}
.ant-modal-cust-warp .ant-modal-content{height:90% !important;overflow-y: hidden}
</style>

View File

@ -109,6 +109,7 @@ export function getMasterTableInitialData() {
// table2
isShowForm: '0',
isShowList: '0',
isReadOnly: '1',
fieldShowType: 'text',
fieldLength: '120',
queryMode: 'single',

View File

@ -31,7 +31,21 @@
@change="handleChange">
<a-button>
<a-icon type="upload"/>
OSS
</a-button>
</a-upload>
<a-upload
name="file"
:multiple="false"
:action="minioUploadAction"
:headers="tokenHeader"
:showUploadList="false"
:beforeUpload="beforeUpload"
@change="handleChange">
<a-button>
<a-icon type="upload"/>
MINIO
</a-button>
</a-upload>
</div>
@ -58,7 +72,9 @@
@change="handleTableChange">
<span slot="action" slot-scope="text, record">
<a @click="ossDelete(record.id)"></a>
<a @click="handlePreview(record)"></a>
<a-divider type="vertical"/>
<a @click="ossDelete(record.id)"></a>
</span>
</a-table>
@ -108,14 +124,18 @@
url: {
upload: "/oss/file/upload",
list: "/oss/file/list",
delete: "/oss/file/delete"
delete: "/oss/file/delete",
minioUpload: "/sys/upload/uploadMinio"
}
}
},
computed: {
uploadAction() {
return window._CONFIG['domianURL'] + this.url.upload;
}
},
minioUploadAction() {
return window._CONFIG['domianURL'] + this.url.minioUpload;
},
},
methods: {
beforeUpload(file) {
@ -139,10 +159,10 @@
this.loadData()
this.$message.success(`${info.file.name} !`);
} else {
this.$message.error(`${info.file.name} .`);
this.$message.error(`${info.file.response.message}`);
}
} else if (info.file.status === 'error') {
this.$message.error(`${info.file.name} .`);
this.$message.error(`${info.file.response.message}`);
}
},
ossDelete(id) {
@ -154,11 +174,17 @@
that.handleDelete(id)
}
});
},
handlePreview(record) {
if (record && record.url) {
let url = window._CONFIG['onlinePreviewDomainURL'] + '?url=' + encodeURIComponent(record.url)
window.open(url, '_blank')
}
}
}
}
</script>
<style scoped>
@import '~@assets/less/common.less'
@import '~@assets/less/common.less';
</style>

View File

@ -17,8 +17,7 @@
<div style="background: #fff;padding-left:16px;height: 100%; margin-top: 5px">
<a-alert type="info" :showIcon="true">
<div slot="message">
<a v-if="this.currSelected.title">{{ getCurrSelectedTitle() }}</a>
<span v-if="this.currSelected.title">{{ getCurrSelectedTitle() }}</span>
<a v-if="this.currSelected.title" style="margin-left: 10px" @click="onClearSelected"></a>
</div>
</a-alert>
@ -72,82 +71,90 @@
<!---- author:os_chengtgen -- date:20190827 -- for: =======------>
</a-col>
<a-col :md="12" :sm="24">
<a-card :bordered="false">
<a-form :form="form">
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="机构名称">
<a-input placeholder="请输入机构/部门名称" v-decorator="['departName', validatorRules.departName ]"/>
</a-form-item>
<a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="上级部门">
<a-tree-select
style="width:100%"
:dropdownStyle="{maxHeight:'200px',overflow:'auto'}"
:treeData="treeData"
:disabled="disable"
v-model="model.parentId"
placeholder="无">
</a-tree-select>
</a-form-item>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="机构编码">
<a-input disabled placeholder="请输入机构编码" v-decorator="['orgCode', validatorRules.orgCode ]"/>
</a-form-item>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="机构类型">
<template v-if="orgCategoryDisabled">
<a-radio-group v-decorator="['orgCategory',validatorRules.orgCategory]" placeholder="请选择机构类型">
<a-radio value="1">
</a-radio>
</a-radio-group>
</template>
<template v-else>
<a-radio-group v-decorator="['orgCategory',validatorRules.orgCategory]" placeholder="请选择机构类型">
<a-radio value="2">
</a-radio>
<a-radio value="3">
</a-radio>
</a-radio-group>
</template>
</a-form-item>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="排序">
<a-input-number v-decorator="[ 'departOrder',{'initialValue':0}]"/>
</a-form-item>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="手机号">
<a-input placeholder="请输入手机号" v-decorator="['mobile', {'initialValue':''}]"/>
</a-form-item>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="地址">
<a-input placeholder="请输入地址" v-decorator="['address', {'initialValue':''}]"/>
</a-form-item>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="备注">
<a-textarea placeholder="请输入备注" v-decorator="['memo', {'initialValue':''}]"/>
</a-form-item>
</a-form>
<div class="anty-form-btn">
<a-button @click="emptyCurrForm" type="default" htmlType="button" icon="sync"></a-button>
<a-button @click="submitCurrForm" type="primary" htmlType="button" icon="form"></a-button>
</div>
</a-card>
<a-tabs defaultActiveKey="1">
<a-tab-pane tab="基本信息" key="1" >
<a-card :bordered="false">
<a-form :form="form">
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="机构名称">
<a-input placeholder="请输入机构/部门名称" v-decorator="['departName', validatorRules.departName ]"/>
</a-form-item>
<a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="上级部门">
<a-tree-select
style="width:100%"
:dropdownStyle="{maxHeight:'200px',overflow:'auto'}"
:treeData="treeData"
:disabled="disable"
v-model="model.parentId"
placeholder="无">
</a-tree-select>
</a-form-item>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="机构编码">
<a-input disabled placeholder="请输入机构编码" v-decorator="['orgCode', validatorRules.orgCode ]"/>
</a-form-item>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="机构类型">
<template v-if="orgCategoryDisabled">
<a-radio-group v-decorator="['orgCategory',validatorRules.orgCategory]" placeholder="请选择机构类型">
<a-radio value="1">
</a-radio>
</a-radio-group>
</template>
<template v-else>
<a-radio-group v-decorator="['orgCategory',validatorRules.orgCategory]" placeholder="请选择机构类型">
<a-radio value="2">
</a-radio>
<a-radio value="3">
</a-radio>
</a-radio-group>
</template>
</a-form-item>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="排序">
<a-input-number v-decorator="[ 'departOrder',{'initialValue':0}]"/>
</a-form-item>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="手机号">
<a-input placeholder="请输入手机号" v-decorator="['mobile', {'initialValue':''}]"/>
</a-form-item>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="地址">
<a-input placeholder="请输入地址" v-decorator="['address', {'initialValue':''}]"/>
</a-form-item>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="备注">
<a-textarea placeholder="请输入备注" v-decorator="['memo', {'initialValue':''}]"/>
</a-form-item>
</a-form>
<div class="anty-form-btn">
<a-button @click="emptyCurrForm" type="default" htmlType="button" icon="sync"></a-button>
<a-button @click="submitCurrForm" type="primary" htmlType="button" icon="form"></a-button>
</div>
</a-card>
</a-tab-pane>
<a-tab-pane tab="部门权限" key="2" forceRender>
<depart-auth-modal ref="departAuth"/>
</a-tab-pane>
</a-tabs>
</a-col>
<depart-modal ref="departModal" @ok="loadTree"></depart-modal>
</a-row>
@ -158,6 +165,7 @@
import {queryDepartTreeList, searchByKeywords, deleteByDepartId} from '@/api/api'
import {httpAction, deleteAction} from '@/api/manage'
import {JeecgListMixin} from '@/mixins/JeecgListMixin'
import DepartAuthModal from './modules/DepartAuthModal'
// 表头
const columns = [
{
@ -201,6 +209,7 @@
name: 'DepartList',
mixins: [JeecgListMixin],
components: {
DepartAuthModal,
DepartModal
},
data() {
@ -403,7 +412,7 @@
this.selectedKeys = [record.key]
this.model.parentId = record.parentId
this.setValuesToForm(record)
this.$refs.departAuth.show(record.id);
},
// 触发onSelect事件时,为部门树右侧的form表单赋值
@ -425,6 +434,7 @@
this.currSelected = {}
this.form.resetFields()
this.selectedKeys = []
this.$refs.departAuth.departId = ''
},
handleNodeTypeChange(val) {
this.currSelected.nodeType = val

View File

@ -6,7 +6,7 @@
<a-input-search @search="onSearch" style="width:100%;margin-top: 10px" placeholder="请输入部门名称"/>
<!-- -->
<template>
<template v-if="userIdentity === '2' && departTree.length>0">
<!---->
<a-tree
@ -16,10 +16,14 @@
@select="onSelect"
:dropdownStyle="{maxHeight:'200px',overflow:'auto'}"
:treeData="departTree"
:autoExpandParent="autoExpandParent"
/>
</template>
<div style="margin-top: 24px;" v-else-if="userIdentity === '2' && departTree.length==0">
<h3><span></span></h3>
</div>
<div style="margin-top: 24px;" v-else><h3></h3></div>
</div>
</a-card>
</a-col>
@ -30,7 +34,10 @@
<Dept-Base-Info ref="DeptBaseInfo"></Dept-Base-Info>
</a-tab-pane>
<a-tab-pane tab="用户信息" key="2">
<Dept-User-Info ref="DeptUserInfo"></Dept-User-Info>
<Dept-User-Info ref="DeptUserInfo" @clearSelectedDepartKeys="clearSelectedDepartKeys"></Dept-User-Info>
</a-tab-pane>
<a-tab-pane tab="部门角色" key="3" forceRender>
<dept-role-info ref="DeptRoleInfo" @clearSelectedDepartKeys="clearSelectedDepartKeys"/>
</a-tab-pane>
</a-tabs>
</a-card>
@ -40,13 +47,15 @@
<script>
import DeptBaseInfo from './modules/DeptBaseInfo'
import DeptUserInfo from './modules/DeptUserInfo'
import {queryDepartTreeList, searchByKeywords} from '@/api/api'
import {queryMyDepartTreeList, searchByKeywords} from '@/api/api'
import {JeecgListMixin} from '@/mixins/JeecgListMixin'
import DeptRoleInfo from './modules/DeptRoleInfo'
export default {
name: 'DepartUserList',
mixins: [JeecgListMixin],
components: {
DeptRoleInfo,
DeptBaseInfo,
DeptUserInfo,
},
@ -85,6 +94,7 @@
nodes: [],
edges: []
},
userIdentity:"",
}
},
methods: {
@ -94,12 +104,19 @@
loadData() {
this.refresh();
},
clearSelectedDepartKeys() {
this.checkedKeys = [];
this.selectedKeys = [];
this.currentDeptId = '';
this.$refs.DeptUserInfo.currentDeptId='';
this.$refs.DeptRoleInfo.currentDeptId='';
},
loadTree() {
var that = this
that.treeData = []
that.departTree = []
queryDepartTreeList().then((res) => {
if (res.success) {
queryMyDepartTreeList().then((res) => {
if (res.success && res.result ) {
for (let i = 0; i < res.result.length; i++) {
let temp = res.result[i]
that.treeData.push(temp)
@ -109,6 +126,7 @@
}
this.loading = false
}
that.userIdentity = res.message
})
},
setThisExpandedKeys(node) {
@ -161,6 +179,7 @@
this.$refs.DeptBaseInfo.open(record);
this.$refs.DeptUserInfo.open(record);
this.$refs.DeptRoleInfo.open(record);
// }
// else {
// this.checkedKeys = [];
@ -180,6 +199,8 @@
this.$refs.DeptBaseInfo.open(record);
this.$refs.DeptUserInfo.onClearSelected();
this.$refs.DeptUserInfo.open(record);
this.$refs.DeptRoleInfo.onClearSelected();
this.$refs.DeptRoleInfo.open(record);
},
},
created() {

View File

@ -30,6 +30,7 @@
<a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
<a-button type="primary" icon="import"></a-button>
</a-upload>
<a-button type="primary" icon="sync" @click="refleshCache()"></a-button>
<a-button type="primary" icon="hdd" @click="openDeleteList"></a-button>
</div>
@ -70,6 +71,7 @@
import DictModal from './modules/DictModal'
import DictItemList from './DictItemList'
import DictDeleteList from './DictDeleteList'
import { getAction } from '@/api/manage'
export default {
name: "DictList",
@ -132,6 +134,7 @@
delete: "/sys/dict/delete",
exportXlsUrl: "sys/dict/exportXls",
importExcelUrl: "sys/dict/importExcel",
refleshCache: "sys/dict/refleshCache",
},
}
},
@ -165,9 +168,18 @@
that.queryParam.dictCode = "";
that.loadData(this.ipagination.current);
},
openDeleteList(){
this.$refs.dictDeleteList.show()
},
refleshCache(){
getAction(this.url.refleshCache).then((res) => {
if (res.success) {
this.$message.success("刷新缓存完成!");
}
}).catch(e=>{
this.$message.warn("刷新缓存失败!");
console.log("刷新失败",e)
})
}
},
watch: {

View File

@ -29,7 +29,9 @@
:dataSource="dataSource"
:loading="loading"
@expand="expandSubmenu"
:rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}">
:expandedRowKeys="expandedRowKeys"
:rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
@expandedRowsChange="handleExpandedRowsChange">
<span slot="action" slot-scope="text, record">
<a @click="handleEdit(record)"></a>
@ -79,7 +81,7 @@
<script>
import PermissionModal from './modules/PermissionModal'
import { getSystemMenuList,getSystemSubmenu } from '@/api/api'
import { getSystemMenuList, getSystemSubmenu, getSystemSubmenuBatch } from '@/api/api'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import PermissionDataRuleList from './PermissionDataRuleList'
import JEllipsis from '@/components/jeecg/JEllipsis'
@ -140,7 +142,7 @@
]
export default {
name: 'PermissionList',
name: 'PermissionListAsync',
mixins: [JeecgListMixin],
components: {
PermissionDataRuleList,
@ -153,6 +155,8 @@
// 表头
columns: columns,
loading: false,
// 展开的行,受控属性
expandedRowKeys: [],
url: {
list: '/sys/permission/list',
delete: '/sys/permission/delete',
@ -162,23 +166,45 @@
},
methods: {
loadData() {
this.dataSource = []
this.loading = true
getSystemMenuList().then((res) => {
if (res.success) {
console.log(res.result)
this.dataSource = res.result
return this.loadDataByExpandedRows(this.dataSource)
}
}).finally(()=>{
this.loading = false
})
},
expandSubmenu(expanded, record){
if(expanded){
if (expanded && (!record.children || record.children.length === 0)) {
getSystemSubmenu({parentId:record.id}).then((res) => {
if (res.success) {
record.children = res.result
}
})
}
},
// 根据已展开的行查询数据(用于保存后刷新时异步加载子级的数据)
loadDataByExpandedRows(dataList) {
if (this.expandedRowKeys.length > 0) {
return getSystemSubmenuBatch({ parentIds: this.expandedRowKeys.join(',') }).then((res) => {
if (res.success) {
let childrenMap = res.result
let fn = (list) => {
list.forEach(data => {
if (this.expandedRowKeys.includes(data.id)) {
data.children = childrenMap[data.id]
fn(data.children)
}
})
}
fn(dataList)
}
})
} else {
return Promise.resolve()
}
},
// 打开数据规则编辑
handleDataRule(record) {
@ -189,10 +215,13 @@
this.$refs.modalForm.localMenuType = 1;
this.$refs.modalForm.disableSubmit = false;
this.$refs.modalForm.edit({status:'1',permsType:'1',route:true,'parentId':record.id});
}
},
handleExpandedRowsChange(expandedRows) {
this.expandedRowKeys = expandedRows
},
}
}
</script>
<style scoped>
@import '~@assets/less/common.less'
@import '~@assets/less/common.less';
</style>

View File

@ -28,7 +28,9 @@
:pagination="false"
:dataSource="dataSource"
:loading="loading"
:rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}">
:expandedRowKeys="expandedRowKeys"
:rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
@expandedRowsChange="handleExpandedRowsChange">
<span slot="action" slot-scope="text, record">
<a @click="handleEdit(record)"></a>
@ -152,6 +154,8 @@
// 表头
columns: columns,
loading: false,
// 展开的行,受控属性
expandedRowKeys: [],
url: {
list: '/sys/permission/list',
delete: '/sys/permission/delete',
@ -178,10 +182,13 @@
this.$refs.modalForm.localMenuType = 1;
this.$refs.modalForm.disableSubmit = false;
this.$refs.modalForm.edit({status:'1',permsType:'1',route:true,'parentId':record.id});
}
},
handleExpandedRowsChange(expandedRows) {
this.expandedRowKeys = expandedRows
},
}
}
</script>
<style scoped>
@import '~@assets/less/common.less'
@import '~@assets/less/common.less';
</style>

View File

@ -67,8 +67,8 @@
<span slot="action" slot-scope="text, record">
<a @click="handleEdit(record)"></a>
<a-divider type="vertical" />
<a-dropdown>
<a class="ant-dropdown-link">
<a-icon type="down" />

View File

@ -60,26 +60,27 @@
:rowSelection="{selectedRowKeys: selectedRowKeys1, onChange: onSelectChange1, type:'radio'}"
@change="handleTableChange">
<span slot="action" slot-scope="text, record">
<a @click="handleOpen(record)"></a>
<a-divider type="vertical"/>
<a-dropdown>
<a class="ant-dropdown-link">
<a-icon type="down"/>
</a>
<a-menu slot="overlay">
<a-menu-item>
<a @click="handlePerssion(record.id)"></a>
</a-menu-item>
<a-menu-item>
<a @click="handleEdit(record)"></a>
</a-menu-item>
<a-menu-item>
<a-popconfirm title="确定删除吗?" @confirm="() => handleDelete1(record.id)">
<a></a>
</a-popconfirm>
</a-menu-item>
</a-menu>
</a-dropdown>
<a @click="handleOpen(record)"></a>
<a-divider type="vertical"/>
<a-dropdown>
<a class="ant-dropdown-link">
<a-icon type="down"/>
</a>
<a-menu slot="overlay">
<a-menu-item>
<a @click="handlePerssion(record.id)"></a>
</a-menu-item>
<a-menu-item>
<a @click="handleEdit(record)"></a>
</a-menu-item>
<a-menu-item>
<a-popconfirm title="确定删除吗?" @confirm="() => handleDelete1(record.id)">
<a></a>
</a-popconfirm>
</a-menu-item>
</a-menu>
</a-dropdown>
</span>
</a-table>
</div>
@ -530,7 +531,7 @@
},
handlePerssion(roleId){
this.$refs.modalUserRole.show(roleId);
}
},
}
}
</script>

View File

@ -0,0 +1,178 @@
<template>
<a-card :bordered="false">
<!-- -->
<div class="table-page-search-wrapper">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<a-col :md="6" :sm="8">
<a-form-item label="规则名称">
<a-input placeholder="请输入规则名称" v-model="queryParam.ruleName"/>
</a-form-item>
</a-col>
<a-col :md="6" :sm="8">
<a-form-item label="规则Code">
<a-input placeholder="请输入规则Code" v-model="queryParam.ruleCode"/>
</a-form-item>
</a-col>
<template v-if="toggleSearchStatus">
</template>
<a-col :md="6" :sm="8">
<span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
<a-button type="primary" @click="searchQuery" icon="search"></a-button>
<a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px"></a-button>
<a @click="handleToggleSearch" style="margin-left: 8px">
{{ toggleSearchStatus ? '' : '' }}
<a-icon :type="toggleSearchStatus ? 'up' : 'down'"/>
</a>
</span>
</a-col>
</a-row>
</a-form>
</div>
<!-- -->
<div class="table-operator">
<a-button @click="handleAdd" type="primary" icon="plus"></a-button>
<a-button type="primary" icon="download" @click="handleExportXls('编码校验规则')"></a-button>
<a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
<a-button type="primary" icon="import"></a-button>
</a-upload>
<a-dropdown v-if="selectedRowKeys.length > 0">
<a-menu slot="overlay">
<a-menu-item key="1" @click="batchDel">
<a-icon type="delete"/>
</a-menu-item>
</a-menu>
<a-button style="margin-left: 8px">
<a-icon type="down"/>
</a-button>
</a-dropdown>
</div>
<!-- table-begin -->
<a-alert type="info" showIcon style="margin-bottom: 16px;">
<template slot="message">
<span></span>
<a style="font-weight: 600;padding: 0 4px;">{{ selectedRowKeys.length }}</a>
<span></span>
<template v-if="selectedRowKeys.length>0">
<a-divider type="vertical"/>
<a @click="onClearSelected"></a>
</template>
</template>
</a-alert>
<a-table
ref="table"
size="middle"
bordered
rowKey="id"
:columns="columns"
:dataSource="dataSource"
:pagination="ipagination"
:loading="loading"
:rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
@change="handleTableChange">
<template slot="action" slot-scope="text, record">
<a @click="handleEdit(record)"></a>
<a-divider type="vertical"/>
<a @click="handleTest(record)"></a>
<a-divider type="vertical"/>
<a-dropdown>
<a class="ant-dropdown-link">
<span></span>
<a-icon type="down"/>
</a>
<a-menu slot="overlay">
<a-menu-item>
<a-popconfirm title="确定删除吗?" @confirm="handleDelete(record.id)"></a-popconfirm>
</a-menu-item>
</a-menu>
</a-dropdown>
</template>
</a-table>
<!-- table-end -->
<!-- -->
<sys-check-rule-modal ref="modalForm" @ok="modalFormOk"/>
<sys-check-rule-test-modal ref="testModal"/>
</a-card>
</template>
<script>
import JEllipsis from '@/components/jeecg/JEllipsis'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import SysCheckRuleModal from './modules/SysCheckRuleModal'
import SysCheckRuleTestModal from './modules/SysCheckRuleTestModal'
export default {
name: 'SysCheckRuleList',
mixins: [JeecgListMixin],
components: { SysCheckRuleModal, SysCheckRuleTestModal, JEllipsis },
data() {
return {
description: '',
// 表头
columns: [
{
title: '#',
key: 'rowIndex',
width: 60,
align: 'center',
customRender: (t, r, i) => i + 1
},
{
title: '',
align: 'center',
dataIndex: 'ruleName'
},
{
title: 'Code',
align: 'center',
dataIndex: 'ruleCode'
},
{
title: '',
align: 'center',
dataIndex: 'ruleDescription',
customRender: (t) => (<j-ellipsis value={t} length={48}/>)
},
{
title: '',
dataIndex: 'action',
align: 'center',
scopedSlots: { customRender: 'action' },
}
],
url: {
list: '/sys/checkRule/list',
delete: '/sys/checkRule/delete',
deleteBatch: '/sys/checkRule/deleteBatch',
exportXlsUrl: 'sys/checkRule/exportXls',
importExcelUrl: 'sys/checkRule/importExcel',
},
}
},
computed: {
importExcelUrl: function () {
return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`
}
},
methods: {
handleTest(record) {
this.$refs.testModal.open(record.ruleCode)
}
}
}
</script>
<style scoped>
@import '~@assets/less/common.less';
</style>

View File

@ -0,0 +1,194 @@
<template>
<a-card :bordered="false">
<!-- -->
<div class="table-page-search-wrapper">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<a-col :md="6" :sm="8">
<a-form-item label="数据源名称">
<a-input placeholder="请输入数据源名称" v-model="queryParam.name"/>
</a-form-item>
</a-col>
<a-col :md="6" :sm="8">
<a-form-item label="数据库类型">
<j-dict-select-tag v-model="queryParam.dbType" placeholder="请选择数据库类型" dict-code="database_type"/>
</a-form-item>
</a-col>
<a-col :md="6" :sm="8">
<span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
<a-button type="primary" @click="searchQuery" icon="search"></a-button>
<a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px"></a-button>
</span>
</a-col>
</a-row>
</a-form>
</div>
<!-- -->
<div class="table-operator">
<a-button @click="handleAdd" type="primary" icon="plus"></a-button>
<a-button type="primary" icon="download" @click="handleExportXls('多数据源管理')"></a-button>
<a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
<a-button type="primary" icon="import"></a-button>
</a-upload>
<a-dropdown v-if="selectedRowKeys.length > 0">
<a-menu slot="overlay">
<a-menu-item key="1" @click="batchDel">
<a-icon type="delete"/>
</a-menu-item>
</a-menu>
<a-button style="margin-left: 8px">
<a-icon type="down"/>
</a-button>
</a-dropdown>
</div>
<!-- table-begin -->
<div>
<a-alert type="info" showIcon style="margin-bottom: 16px;">
<template slot="message">
<span></span>
<a style="font-weight: 600;padding: 0 4px;">{{ selectedRowKeys.length }}</a>
<span></span>
<a style="margin-left: 24px" @click="onClearSelected"></a>
</template>
</a-alert>
<a-table
ref="table"
size="middle"
bordered
rowKey="id"
:columns="columns"
:dataSource="dataSource"
:pagination="ipagination"
:loading="loading"
:rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
@change="handleTableChange">
<span slot="action" slot-scope="text, record">
<a @click="handleEdit(record)"></a>
<a-divider type="vertical"/>
<a-dropdown>
<a class="ant-dropdown-link"> <a-icon type="down"/></a>
<a-menu slot="overlay">
<a-menu-item>
<a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
<a></a>
</a-popconfirm>
</a-menu-item>
</a-menu>
</a-dropdown>
</span>
</a-table>
</div>
<!-- table-end -->
<!-- -->
<sys-data-source-modal ref="modalForm" @ok="modalFormOk"/>
</a-card>
</template>
<script>
import JEllipsis from '@/components/jeecg/JEllipsis'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import SysDataSourceModal from './modules/SysDataSourceModal'
export default {
name: 'SysDataSourceList',
mixins: [JeecgListMixin],
components: { JEllipsis, SysDataSourceModal },
data() {
let ellipsis = (v, l = 20) => (<j-ellipsis value={v} length={l}/>)
return {
description: '',
// 表头
columns: [
{
title: '#',
dataIndex: '',
key: 'rowIndex',
width: 60,
align: 'center',
customRender: (t, r, index) => index + 1
},
{
title: '',
align: 'center',
dataIndex: 'name'
},
{
title: '',
align: 'center',
dataIndex: 'code'
},
{
title: '',
align: 'center',
dataIndex: 'remark',
customRender: (t) => ellipsis(t)
},
{
title: '',
align: 'center',
dataIndex: 'dbType_dictText'
},
{
title: '',
align: 'center',
dataIndex: 'dbDriver',
customRender: (t) => ellipsis(t)
},
{
title: '',
align: 'center',
dataIndex: 'dbUrl',
customRender: (t) => ellipsis(t)
},
{
title: '',
align: 'center',
dataIndex: 'dbName'
},
{
title: '',
align: 'center',
dataIndex: 'dbUsername'
},
{
title: '',
dataIndex: 'action',
align: 'center',
scopedSlots: { customRender: 'action' },
}
],
url: {
list: '/sys/dataSource/list',
delete: '/sys/dataSource/delete',
deleteBatch: '/sys/dataSource/deleteBatch',
exportXlsUrl: 'sys/dataSource/exportXls',
importExcelUrl: 'sys/dataSource/importExcel',
},
}
},
computed: {
importExcelUrl() {
return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`
}
},
methods: {}
}
</script>
<style scoped>
@import '~@assets/less/common.less';
</style>

View File

@ -46,6 +46,7 @@
</span>
</a-table>
<show-announcement ref="ShowAnnouncement"></show-announcement>
<dynamic-notice ref="showDynamNotice" :path="openPath" :formData="formData"/>
</a-card>
</template>
@ -54,11 +55,13 @@
import { getAction,putAction } from '@/api/manage'
import ShowAnnouncement from '@/components/tools/ShowAnnouncement'
import {JeecgListMixin} from '@/mixins/JeecgListMixin'
import DynamicNotice from '../../components/tools/DynamicNotice'
export default {
name: "UserAnnouncementList",
mixins: [JeecgListMixin],
components: {
DynamicNotice,
ShowAnnouncement
},
data () {
@ -130,6 +133,7 @@
readAllMsg:"sys/sysAnnouncementSend/readAll",
},
loading:false,
openPath:''
}
},
methods: {
@ -143,7 +147,13 @@
this.loadData();
}
});
this.$refs.ShowAnnouncement.detail(record);
if(record.openType==='component'){
this.openPath = record.openPage;
this.formData = {id:record.busId};
this.$refs.showDynamNotice.detail();
}else{
this.$refs.ShowAnnouncement.detail(record);
}
},
readAll(){
var that = this;

View File

@ -66,10 +66,12 @@
<!-- -->
<div class="table-operator" style="border-top: 5px">
<a-button @click="handleAdd" type="primary" icon="plus"></a-button>
<a-button @click="handleSyncUser" v-has="'user:syncbpm'" type="primary" icon="plus"></a-button>
<a-button type="primary" icon="download" @click="handleExportXls('用户信息')"></a-button>
<a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
<a-button type="primary" icon="import"></a-button>
</a-upload>
<a-button type="primary" icon="hdd" @click="recycleBinVisible=true"></a-button>
<a-dropdown v-if="selectedRowKeys.length > 0">
<a-menu slot="overlay" @click="handleMenuClick">
<a-menu-item key="1">
@ -171,17 +173,22 @@
<password-modal ref="passwordmodal" @ok="passwordModalOk"></password-modal>
<sys-user-agent-modal ref="sysUserAgentModal"></sys-user-agent-modal>
<!-- -->
<user-recycle-bin-modal :visible.sync="recycleBinVisible" @ok="modalFormOk"/>
</a-card>
</template>
<script>
import UserModal from './modules/UserModal'
import PasswordModal from './modules/PasswordModal'
import {putAction} from '@/api/manage';
import {putAction,getFileAccessHttpUrl} from '@/api/manage';
import {frozenBatch} from '@/api/api'
import {JeecgListMixin} from '@/mixins/JeecgListMixin'
import SysUserAgentModal from "./modules/SysUserAgentModal";
import JInput from '@/components/jeecg/JInput'
import UserRecycleBinModal from './modules/UserRecycleBinModal'
export default {
name: "UserList",
@ -190,12 +197,14 @@
SysUserAgentModal,
UserModal,
PasswordModal,
JInput
JInput,
UserRecycleBinModal
},
data() {
return {
description: '',
queryParam: {},
recycleBinVisible: false,
columns: [
/*{
title: '#',
@ -214,7 +223,7 @@
width: 120
},
{
title: '',
title: '',
align: "center",
width: 100,
dataIndex: 'realname',
@ -237,7 +246,7 @@
{
title: '',
align: "center",
width: 180,
width: 100,
dataIndex: 'birthday'
},
{
@ -247,9 +256,10 @@
dataIndex: 'phone'
},
{
title: '',
title: '',
align: "center",
dataIndex: 'email'
width: 180,
dataIndex: 'orgCode'
},
{
title: '',
@ -257,13 +267,6 @@
width: 80,
dataIndex: 'status_dictText'
},
/* {
title: '',
align: "center",
width: 150,
dataIndex: 'createTime',
sorter: true
},*/
{
title: '',
dataIndex: 'action',
@ -274,7 +277,7 @@
],
url: {
imgerver: window._CONFIG['domianURL'] + "/sys/common/view",
imgerver: window._CONFIG['staticDomainURL'],
syncUser: "/process/extActProcess/doSyncUser",
list: "/sys/user/list",
delete: "/sys/user/delete",
@ -291,7 +294,7 @@
},
methods: {
getAvatarView: function (avatar) {
return this.url.imgerver + "/" + avatar;
return getFileAccessHttpUrl(avatar,this.url.imgerver,"http")
},
batchFrozen: function (status) {
@ -363,6 +366,8 @@
this.$refs.sysUserAgentModal.agentSettings(username);
this.$refs.sysUserAgentModal.title = "用户代理人设置";
},
handleSyncUser() {
},
passwordModalOk() {
//TODO 密码修改完成 不需要刷新页面可以把datasource中的数据更新一下
}
@ -372,4 +377,4 @@
</script>
<style scoped>
@import '~@assets/less/common.less'
</style>
</style>

View File

@ -1,7 +1,7 @@
<template>
<a-card :loading="cardLoading" :bordered="false" style="height: 100%;">
<a-spin :spinning="loading">
<a-input-search @search="handleSearch" style="width:100%;margin-top: 10px" placeholder="输入组织机构名称进行查询..."/>
<a-input-search @search="handleSearch" style="width:100%;margin-top: 10px" placeholder="输入机构名称查询..." allowClear enterButton />
<a-tree
showLine
@ -67,20 +67,21 @@
promise.then(res => {
if (res.success) {
this.treeDataSource = res.result
// update-begin- --- author:wangshuai ------ date:20200102 ---- for:去除默认选中第一条数据、默认展开所有第一级
// 默认选中第一条数据、默认展开所有第一级
if (res.result.length > 0) {
this.expandedKeys = []
res.result.forEach((item, index) => {
if (index === 0) {
this.selectedKeys = [item.id]
this.emitInput(item.orgCode)
}
this.expandedKeys.push(item.id)
})
}
// if (res.result.length > 0) {
// this.expandedKeys = []
// res.result.forEach((item, index) => {
// if (index === 0) {
// this.selectedKeys = [item.id]
// this.emitInput(item.orgCode)
// }
// this.expandedKeys.push(item.id)
// })
// }
// update-end- --- author:wangshuai ------ date:20200102 ---- for:去除默认选中第一条数据、默认展开所有第一级
} else {
this.$message.warn('' + res.message)
this.$message.warn(res.message)
console.error(':', res)
}
}).finally(() => {

View File

@ -65,12 +65,6 @@
align: 'center',
customRender: (t, r, i) => parseInt(i) + 1
},
{
title: '',
width: '20%',
align: 'center',
dataIndex: 'departName'
},
{
title: '',
width: '15%',
@ -83,6 +77,12 @@
align: 'center',
dataIndex: 'workNo'
},
{
title: '',
width: '20%',
align: 'center',
dataIndex: 'departName'
},
{
title: '',
width: '15%',
@ -91,7 +91,7 @@
customRender: (text) => (text || '').split(',').map(t => this.positionInfo[t] ? this.positionInfo[t] : t).join(',')
},
{
title: '',
title: '',
width: '15%',
align: 'center',
dataIndex: 'telephone'
@ -130,14 +130,26 @@
methods: {
loadData(pageNum, orgCode) {
if (!orgCode) {
return
}
//加载数据 若传入参数1则加载第一页的内容
if (pageNum === 1) {
this.ipagination.current = 1
}
this.loading = true
if (pageNum === 1) {
this.ipagination.current = 1
}
// update-begin- --- author:wangshuai ------ date:20200102 ---- for:传过来的部门编码为空全查
if (!orgCode) {
getAction(this.url.list, {
...this.getQueryParams()
}).then((res) => {
if (res.success) {
this.dataSource = res.result.records
this.ipagination.total = res.result.total
}
}).finally(() => {
this.loading = false
this.cardLoading = false
})
// update-end- --- author:wangshuai ------ date:20200102 ---- for:传过来的部门编码为空全查
}else{
//加载数据 若传入参数1则加载第一页的内容
getAction(this.url.list, {
orgCode,
...this.getQueryParams()
@ -150,6 +162,7 @@
this.loading = false
this.cardLoading = false
})
}
},
searchQuery() {

View File

@ -0,0 +1,184 @@
<template>
<a-card :bordered="false">
<template v-if="this.departId">
<a-form>
<a-form-item label=''>
<a-tree
checkable
@check="onCheck"
:checkedKeys="checkedKeys"
:treeData="treeData"
@expand="onExpand"
@select="onTreeNodeSelect"
:selectedKeys="selectedKeys"
:expandedKeys="expandedKeysss"
:checkStrictly="checkStrictly"
style="height:500px;overflow: auto;">
<span slot="hasDatarule" slot-scope="{slotTitle,ruleFlag}">
{{ slotTitle }}
<a-icon v-if="ruleFlag" type="align-left" style="margin-left:5px;color: red;"></a-icon>
</span>
</a-tree>
</a-form-item>
</a-form>
<div class="anty-form-btn">
<a-dropdown style="float: left" :trigger="['click']" placement="topCenter">
<a-menu slot="overlay">
<!-- Tree使checkStrictlyfalse
<a-menu-item key="1" @click="switchCheckStrictly(1)"></a-menu-item>
<a-menu-item key="2" @click="switchCheckStrictly(2)"></a-menu-item>
-->
<a-menu-item key="3" @click="checkALL"></a-menu-item>
<a-menu-item key="4" @click="cancelCheckALL"></a-menu-item>
<a-menu-item key="5" @click="expandAll"></a-menu-item>
<a-menu-item key="6" @click="closeAll"></a-menu-item>
</a-menu>
<a-button>
<a-icon type="up" />
</a-button>
</a-dropdown>
<a-button style="float: right" @click="handleSubmit" type="primary" htmlType="button" icon="form"></a-button>
</div>
</template>
<div v-else style="height:330px;"><h3>!</h3></div>
<depart-datarule-modal ref="datarule"/>
</a-card>
</template>
<script>
import {queryTreeListForRole,queryDepartPermission,saveDepartPermission} from '@/api/api'
import DepartDataruleModal from './DepartDataruleModal'
export default {
name: 'DepartAuthModal',
components: { DepartDataruleModal },
data(){
return {
departId:"",
treeData: [],
defaultCheckedKeys:[],
checkedKeys:[],
halfCheckedKeys:[],
expandedKeysss:[],
allTreeKeys:[],
autoExpandParent: true,
checkStrictly: false,
title:"部门权限配置",
visible: false,
loading: false,
selectedKeys:[]
}
},
methods: {
onTreeNodeSelect(id){
if(id && id.length>0){
this.selectedKeys = id
}
this.$refs.datarule.show(this.selectedKeys[0],this.departId)
},
onCheck (checkedKeys, { halfCheckedKeys }) {
// 保存选中的和半选中的,后面保存的时候合并提交
this.checkedKeys = checkedKeys
this.halfCheckedKeys = halfCheckedKeys
},
show(departId){
this.departId=departId
this.loadData();
},
close () {
this.reset()
this.$emit('close');
this.visible = false;
},
onExpand(expandedKeys){
this.expandedKeysss = expandedKeys;
this.autoExpandParent = false
},
reset () {
this.expandedKeysss = []
this.checkedKeys = []
this.defaultCheckedKeys = []
this.loading = false
},
expandAll () {
this.expandedKeysss = this.allTreeKeys
},
closeAll () {
this.expandedKeysss = []
},
checkALL () {
this.checkedKeys = this.allTreeKeys
},
cancelCheckALL () {
this.checkedKeys = []
},
handleCancel () {
this.close()
},
handleSubmit() {
let that = this;
if(!that.departId){
this.$message.warning('!')
}
let checkedKeys = [...that.checkedKeys, ...that.halfCheckedKeys]
const permissionIds = checkedKeys.join(",")
let params = {
departId:that.departId,
permissionIds,
lastpermissionIds:that.defaultCheckedKeys.join(","),
};
that.loading = true;
saveDepartPermission(params).then((res)=>{
if(res.success){
that.$message.success(res.message);
that.loading = false;
that.loadData();
}else {
that.$message.error(res.message);
that.loading = false;
}
})
},
convertTreeListToKeyLeafPairs(treeList, keyLeafPair = []) {
for(const {key, isLeaf, children} of treeList) {
keyLeafPair.push({key, isLeaf})
if(children && children.length > 0) {
this.convertTreeListToKeyLeafPairs(children, keyLeafPair)
}
}
return keyLeafPair;
},
emptyCurrForm() {
this.form.resetFields()
},
loadData(){
queryTreeListForRole().then((res) => {
this.treeData = res.result.treeList
this.allTreeKeys = res.result.ids
const keyLeafPairs = this.convertTreeListToKeyLeafPairs(this.treeData)
queryDepartPermission({departId:this.departId}).then((res)=>{
// 过滤出 leaf node 即可,即选中的
// Tree组件中checkStrictly默认为false的时候选中子节点父节点会自动设置选中或半选中
// 保存 checkedKeys 以及 halfCheckedKeys 以便于未做任何操作时提交表单数据
const checkedKeys = [...res.result].filter(key => {
const keyLeafPair = keyLeafPairs.filter(item => item.key === key)[0]
return keyLeafPair && keyLeafPair.isLeaf
})
const halfCheckedKeys = [...res.result].filter(key => {
const keyLeafPair = keyLeafPairs.filter(item => item.key === key)[0]
return keyLeafPair && !keyLeafPair.isLeaf
})
this.checkedKeys = [...checkedKeys];
this.halfCheckedKeys = [...halfCheckedKeys]
this.defaultCheckedKeys = [...halfCheckedKeys, ...checkedKeys];
this.expandedKeysss = this.allTreeKeys;
})
})
}
},
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,116 @@
<template>
<a-drawer
title="数据规则/按钮权限配置"
width="365"
:closable="false"
@close="onClose"
:visible="visible"
>
<a-tabs defaultActiveKey="1">
<a-tab-pane tab="数据规则" key="1">
<a-checkbox-group v-model="dataruleChecked" v-if="dataruleList.length>0">
<a-row>
<a-col :span="24" v-for="(item,index) in dataruleList" :key=" 'dr'+index ">
<a-checkbox :value="item.id">{{ item.ruleName }}</a-checkbox>
</a-col>
<a-col :span="24">
<div style="width: 100%;margin-top: 15px">
<a-button @click="saveDataruleForRole" type="primary" size="small" icon="save"></a-button>
</div>
</a-col>
</a-row>
</a-checkbox-group>
<div v-else><h3>!</h3></div>
</a-tab-pane>
</a-tabs>
</a-drawer>
</template>
<script>
import ARow from 'ant-design-vue/es/grid/Row'
import ACol from 'ant-design-vue/es/grid/Col'
import { getAction,postAction } from '@/api/manage'
export default {
name: 'DepartDataruleModal',
components: { ACol, ARow },
data(){
return {
functionId:'',
departId:'',
visible:false,
tabList: [{
key: '1',
tab: '',
}, {
key: '2',
tab: '',
}],
activeTabKey: '1',
url:{
datarule:"/sys/sysDepartPermission/datarule",
},
dataruleList:[],
dataruleChecked:[]
}
},
methods:{
loadData(){
getAction(`${this.url.datarule}/${this.functionId}/${this.departId}`).then(res=>{
if(res.success){
this.dataruleList = res.result.datarule
let drChecked = res.result.drChecked
if(drChecked){
this.dataruleChecked = drChecked.split(",")
}
}
})
},
saveDataruleForRole(){
if(!this.dataruleChecked || this.dataruleChecked.length==0){
this.$message.warning("请注意,现未勾选任何数据权限!")
}
let params = {
permissionId:this.functionId,
departId:this.departId,
dataRuleIds:this.dataruleChecked.join(",")
}
postAction(this.url.datarule,params).then(res=>{
if(res.success){
this.$message.success(res.message)
}else{
this.$message.error(res.message)
}
})
},
show(functionId,departId){
this.onReset()
this.functionId = functionId
this.departId = departId
this.visible=true
this.loadData()
},
onClose(){
this.visible=false
this.onReset()
},
onTabChange (key) {
this.activeTabKey = key
},
onReset(){
this.functionId=''
this.departId=''
this.dataruleList=[]
this.dataruleChecked=[]
}
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,217 @@
<template>
<a-drawer
:title="title"
:maskClosable="true"
width=650
placement="right"
:closable="true"
@close="close"
:visible="visible"
style="height: calc(100% - 55px);overflow: auto;padding-bottom: 53px;">
<a-form>
<a-form-item label=''>
<a-tree
v-if="treeData.length>0"
checkable
@check="onCheck"
:checkedKeys="checkedKeys"
:treeData="treeData"
@expand="onExpand"
@select="onTreeNodeSelect"
:selectedKeys="selectedKeys"
:expandedKeys="expandedKeysss"
:checkStrictly="checkStrictly">
<span slot="hasDatarule" slot-scope="{slotTitle,ruleFlag}">
{{ slotTitle }}<a-icon v-if="ruleFlag" type="align-left" style="margin-left:5px;color: red;"></a-icon>
</span>
</a-tree>
<div v-else><h3>!</h3></div>
</a-form-item>
</a-form>
<div class="drawer-bootom-button">
<a-dropdown style="float: left" :trigger="['click']" placement="topCenter">
<a-menu slot="overlay">
<a-menu-item key="3" @click="checkALL"></a-menu-item>
<a-menu-item key="4" @click="cancelCheckALL"></a-menu-item>
<a-menu-item key="5" @click="expandAll"></a-menu-item>
<a-menu-item key="6" @click="closeAll"></a-menu-item>
</a-menu>
<a-button>
<a-icon type="up" />
</a-button>
</a-dropdown>
<a-popconfirm title="确定放弃编辑?" @confirm="close" okText="确定" cancelText="取消">
<a-button style="margin-right: .8rem"></a-button>
</a-popconfirm>
<a-button @click="handleSubmit(false)" type="primary" :loading="loading" ghost style="margin-right: 0.8rem"></a-button>
<a-button @click="handleSubmit(true)" type="primary" :loading="loading"></a-button>
</div>
<dept-role-datarule-modal ref="datarule"></dept-role-datarule-modal>
</a-drawer>
</template>
<script>
import {queryTreeListForDeptRole,queryDeptRolePermission,saveDeptRolePermission} from '@/api/api'
import RoleDataruleModal from './RoleDataruleModal.vue'
import DeptRoleDataruleModal from './DeptRoleDataruleModal'
export default {
name: "DeptRoleAuthModal",
components:{
DeptRoleDataruleModal,
RoleDataruleModal
},
data(){
return {
departId:"",
roleId:"",
treeData: [],
defaultCheckedKeys:[],
checkedKeys:[],
halfCheckedKeys:[],
expandedKeysss:[],
allTreeKeys:[],
autoExpandParent: true,
checkStrictly: false,
title:"部门角色权限配置",
visible: false,
loading: false,
selectedKeys:[]
}
},
methods: {
onTreeNodeSelect(id){
if(id && id.length>0){
this.selectedKeys = id
}
this.$refs.datarule.show(this.selectedKeys[0],this.departId,this.roleId)
},
onCheck (checkedKeys, { halfCheckedKeys }) {
// 保存选中的和半选中的,后面保存的时候合并提交
this.checkedKeys = checkedKeys
this.halfCheckedKeys = halfCheckedKeys
},
show(roleId,departId){
this.departId = departId
this.roleId=roleId
this.visible = true;
},
close () {
this.reset()
this.$emit('close');
this.visible = false;
},
onExpand(expandedKeys){
this.expandedKeysss = expandedKeys;
this.autoExpandParent = false
},
reset () {
this.expandedKeysss = []
this.checkedKeys = []
this.defaultCheckedKeys = []
this.loading = false
},
expandAll () {
this.expandedKeysss = this.allTreeKeys
},
closeAll () {
this.expandedKeysss = []
},
checkALL () {
this.checkedKeys = this.allTreeKeys
},
cancelCheckALL () {
this.checkedKeys = []
},
handleCancel () {
this.close()
},
handleSubmit(exit) {
let that = this;
let checkedKeys = [...that.checkedKeys, ...that.halfCheckedKeys]
const permissionIds = checkedKeys.join(",")
let params = {
roleId:that.roleId,
permissionIds,
lastpermissionIds:that.defaultCheckedKeys.join(","),
};
that.loading = true;
console.log("请求参数:",params);
saveDeptRolePermission(params).then((res)=>{
if(res.success){
that.$message.success(res.message);
that.loading = false;
if (exit) {
that.close()
}
}else {
that.$message.error(res.message);
that.loading = false;
if (exit) {
that.close()
}
}
this.loadData();
})
},
convertTreeListToKeyLeafPairs(treeList, keyLeafPair = []) {
for(const {key, isLeaf, children} of treeList) {
keyLeafPair.push({key, isLeaf})
if(children && children.length > 0) {
this.convertTreeListToKeyLeafPairs(children, keyLeafPair)
}
}
return keyLeafPair;
},
loadData(){
queryTreeListForDeptRole({departId:this.departId}).then((res) => {
this.treeData = res.result.treeList
this.allTreeKeys = res.result.ids
const keyLeafPairs = this.convertTreeListToKeyLeafPairs(this.treeData)
queryDeptRolePermission({roleId:this.roleId}).then((res)=>{
// 过滤出 leaf node 即可,即选中的
// Tree组件中checkStrictly默认为false的时候选中子节点父节点会自动设置选中或半选中
// 保存 checkedKeys 以及 halfCheckedKeys 以便于未做任何操作时提交表单数据
const checkedKeys = [...res.result].filter(key => {
const keyLeafPair = keyLeafPairs.filter(item => item.key === key)[0]
return keyLeafPair && keyLeafPair.isLeaf
})
const halfCheckedKeys = [...res.result].filter(key => {
const keyLeafPair = keyLeafPairs.filter(item => item.key === key)[0]
return keyLeafPair && !keyLeafPair.isLeaf
})
this.checkedKeys = [...checkedKeys];
this.halfCheckedKeys = [...halfCheckedKeys]
this.defaultCheckedKeys = [...halfCheckedKeys, ...checkedKeys];
this.expandedKeysss = this.allTreeKeys;
})
})
}
},
watch: {
visible () {
if (this.visible ) {
this.loadData();
}
}
}
}
</script>
<style lang="scss" scoped>
.drawer-bootom-button {
position: absolute;
bottom: 0;
width: 100%;
border-top: 1px solid #e8e8e8;
padding: 10px 16px;
text-align: right;
left: 0;
background: #fff;
border-radius: 0 0 2px 2px;
}
</style>

View File

@ -0,0 +1,122 @@
<template>
<a-drawer
title="数据规则/按钮权限配置"
width="365"
:closable="false"
@close="onClose"
:visible="visible"
>
<a-tabs defaultActiveKey="1">
<a-tab-pane tab="数据规则" key="1">
<a-checkbox-group v-model="dataruleChecked" v-if="dataruleList.length>0">
<a-row>
<a-col :span="24" v-for="(item,index) in dataruleList" :key=" 'dr'+index ">
<a-checkbox :value="item.id">{{ item.ruleName }}</a-checkbox>
</a-col>
<a-col :span="24">
<div style="width: 100%;margin-top: 15px">
<a-button @click="saveDataruleForRole" type="primary" size="small" icon="save"></a-button>
</div>
</a-col>
</a-row>
</a-checkbox-group>
<div v-else><h3>!</h3></div>
</a-tab-pane>
<!--<a-tab-pane tab="按钮权限" key="2">!!!</a-tab-pane>-->
</a-tabs>
</a-drawer>
</template>
<script>
import ARow from 'ant-design-vue/es/grid/Row'
import ACol from 'ant-design-vue/es/grid/Col'
import { getAction,postAction } from '@/api/manage'
export default {
name: 'DeptRoleDataruleModal',
components: { ACol, ARow },
data(){
return {
departId:'',
functionId:'',
roleId:'',
visible:false,
tabList: [{
key: '1',
tab: '',
}, {
key: '2',
tab: '',
}],
activeTabKey: '1',
url:{
datarule:"/sys/sysDepartRole/datarule",
},
dataruleList:[],
dataruleChecked:[]
}
},
methods:{
loadData(){
getAction(`${this.url.datarule}/${this.functionId}/${this.departId}/${this.roleId}`).then(res=>{
console.log(res)
if(res.success){
this.dataruleList = res.result.datarule
let drChecked = res.result.drChecked
if(drChecked){
this.dataruleChecked = drChecked.split(",")
}
}
})
},
saveDataruleForRole(){
if(!this.dataruleChecked || this.dataruleChecked.length==0){
this.$message.warning("请注意,现未勾选任何数据权限!")
}
let params = {
permissionId:this.functionId,
roleId:this.roleId,
dataRuleIds:this.dataruleChecked.join(",")
}
console.log("保存数据权限",params)
postAction(this.url.datarule,params).then(res=>{
if(res.success){
this.$message.success(res.message)
}else{
this.$message.error(res.message)
}
})
},
show(functionId,departId,roleId){
this.onReset()
this.departId = departId
this.functionId = functionId
this.roleId = roleId
this.visible=true
this.loadData()
},
onClose(){
this.visible=false
this.onReset()
},
onTabChange (key) {
this.activeTabKey = key
},
onReset(){
this.functionId=''
this.roleId=''
this.dataruleList=[]
this.dataruleChecked=[]
}
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,196 @@
<template>
<a-card :bordered="false">
<!-- -->
<div class="table-page-search-wrapper">
<!-- -->
<a-form layout="inline">
<a-row :gutter="10">
<a-col :md="10" :sm="12">
<a-form-item label="部门角色名称" style="margin-left:8px">
<a-input placeholder="请输入部门角色" v-model="queryParam.roleName"></a-input>
</a-form-item>
</a-col>
<span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
<a-col :md="6" :sm="24">
<a-button type="primary" @click="searchQuery" icon="search" style="margin-left: 18px"></a-button>
<a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px"></a-button>
</a-col>
</span>
</a-row>
</a-form>
</div>
<!-- -->
<div class="table-operator" :md="24" :sm="24">
<a-button @click="handleAdd" type="primary" icon="plus"></a-button>
<a-dropdown v-if="selectedRowKeys.length > 0">
<a-menu slot="overlay">
<a-menu-item key="1" @click="batchDel"><a-icon type="delete"/></a-menu-item>
</a-menu>
<a-button style="margin-left: 8px"> <a-icon type="down" /></a-button>
</a-dropdown>
</div>
<!-- table-begin -->
<div>
<div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
<i class="anticon anticon-info-circle ant-alert-icon"></i> <a style="font-weight: 600">
{{selectedRowKeys.length }}</a>
<a style="margin-left: 24px" @click="onClearSelected"></a>
</div>
<a-table
ref="table"
size="middle"
bordered
rowKey="id"
:columns="columns"
:dataSource="dataSource"
:pagination="ipagination"
:loading="loading"
:rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
@change="handleTableChange">
<span slot="action" slot-scope="text, record">
<a @click="handleEdit(record)"></a>
<a-divider type="vertical"/>
<a-dropdown>
<a class="ant-dropdown-link">
<a-icon type="down"/>
</a>
<a-menu slot="overlay">
<a-menu-item>
<a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
<a></a>
</a-popconfirm>
</a-menu-item>
<a-menu-item>
<a href="javascript:;" @click="handleDetail(record)"></a>
</a-menu-item>
<a-menu-item>
<a @click="handlePerssion(record)"></a>
</a-menu-item>
</a-menu>
</a-dropdown>
</span>
</a-table>
</div>
<!-- table-end -->
<!-- -->
<sys-depart-role-modal ref="modalForm" @ok="modalFormOk"/>
<dept-role-auth-modal ref="modalDeptRole" />
</a-card>
</template>
<script>
import {JeecgListMixin} from '@/mixins/JeecgListMixin'
import {getAction} from '@/api/manage'
import SysDepartRoleModal from './SysDepartRoleModal'
import DeptRoleAuthModal from './DeptRoleAuthModal'
export default {
name: 'DeptRoleInfo',
components: { DeptRoleAuthModal, SysDepartRoleModal },
mixins: [JeecgListMixin],
data() {
return {
description: '',
currentDeptId: '',
// 表头
columns: [{
title: '',
align: "center",
dataIndex: 'roleName'
},
{
title: '',
align: "center",
dataIndex: 'roleCode'
},
{
title: '',
align: "center",
dataIndex: 'departId_dictText'
},
{
title: '',
align: "center",
dataIndex: 'description'
},
{
title: '',
dataIndex: 'action',
scopedSlots: {customRender: 'action'},
align: "center",
width: 170
}],
url: {
list: "/sys/sysDepartRole/list",
delete: "/sys/sysDepartRole/delete",
deleteBatch: "/sys/sysDepartRole/deleteBatch",
}
}
},
created() {
},
methods: {
searchReset() {
this.queryParam = {}
this.currentDeptId = '';
this.loadData(1);
this.$emit('clearSelectedDepartKeys')
},
loadData(arg) {
if (!this.url.list) {
this.$message.error("请设置url.list属性!")
return
}
//加载数据 若传入参数1则加载第一页的内容
if (arg === 1) {
this.ipagination.current = 1;
}
let params = this.getQueryParams();//查询条件
params.deptId = this.currentDeptId;
getAction(this.url.list, params).then((res) => {
if (res.success && res.result) {
this.dataSource = res.result.records;
this.ipagination.total = res.result.total;
}
})
},
open(record) {
this.currentDeptId = record.id;
this.loadData(1);
},
clearList() {
this.currentDeptId = '';
this.dataSource = [];
},
hasSelectDept() {
if (this.currentDeptId == '') {
this.$message.error("请选择一个部门!")
return false;
}
return true;
},
handleEdit: function (record) {
this.$refs.modalForm.title = "编辑";
this.$refs.modalForm.departDisabled = true;
this.$refs.modalForm.disableSubmit = false;
this.$refs.modalForm.edit(record,record.departId);
},
handleAdd: function () {
if (this.currentDeptId == '') {
this.$message.error("请选择一个部门!")
} else {
this.$refs.modalForm.departDisabled = true;
this.$refs.modalForm.add(this.currentDeptId);
this.$refs.modalForm.title = "新增";
}
},
handlePerssion: function(record){
this.$refs.modalDeptRole.show(record.id,record.departId);
},
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,200 @@
<template>
<a-drawer
:title="title"
:maskClosable="true"
width=600
placement="right"
:closable="true"
@close="close"
:visible="visible"
style="height: calc(100% - 55px);overflow: auto;padding-bottom: 53px;">
<a-spin :spinning="confirmLoading">
<a-form :form="form" v-if="designNameOption.length>0">
<a-form-item label=''>
<a-col :xl="24" :lg="24" :md="24" :sm="24" :xs="24">
<a-card :style="{ marginTop: '12px',height:'auto' }">
<a-checkbox-group @change="designNameChange" v-model="designNameValue" style="width: 100%">
<a-row>
<template v-for="(des) in designNameOption">
<a-col :span="6">
<a-checkbox :value="des.value">{{ des.text }}</a-checkbox>
</a-col>
</template>
</a-row>
</a-checkbox-group>
</a-card>
</a-col>
</a-form-item>
</a-form>
<div v-else><h3>!</h3></div>
</a-spin>
<div class="drawer-bootom-button">
<a-dropdown style="float: left" :trigger="['click']" placement="topCenter">
<a-menu slot="overlay">
<a-menu-item key="1" @click="checkALL"></a-menu-item>
<a-menu-item key="2" @click="cancelCheckALL"></a-menu-item>
</a-menu>
<a-button>
<a-icon type="up" />
</a-button>
</a-dropdown>
<a-popconfirm title="确定放弃编辑?" @confirm="close" okText="确定" cancelText="取消">
<a-button style="margin-right: .8rem"></a-button>
</a-popconfirm>
<a-button @click="handleSubmit(true)" type="primary"></a-button>
</div>
</a-drawer>
</template>
<script>
import {httpAction, getAction} from '@/api/manage'
import JEllipsis from '@/components/jeecg/JEllipsis'
import {initDictOptions} from '@/components/dict/JDictSelectUtil'
export default {
name: 'DeptRoleUserModal',
components: {
JEllipsis
},
data() {
return {
currentDeptId:"",
title: "部门角色分配",
visible: false,
model: {},
labelCol: {
xs: {span: 24},
sm: {span: 5},
},
wrapperCol: {
xs: {span: 24},
sm: {span: 16},
},
confirmLoading: false,
form: this.$form.createForm(this),
validatorRules: {},
url: {
add: "/sys/sysDepartRole/deptRoleUserAdd",
getDeptRoleList:"/sys/sysDepartRole/getDeptRoleList",
getDeptRoleByUserId:"/sys/sysDepartRole/getDeptRoleByUserId"
},
designNameOption: [],
userId: "",
newRoleId:"",
oldRoleId:"",
designNameValue:[],
desformList: [],
}
},
created() {
},
methods: {
add(record,departId) {
this.userId = record.id;
this.currentDeptId = departId;
this.loadDesformList();
this.edit({});
},
edit(record) {
this.form.resetFields();
this.model = Object.assign({}, record);
this.visible = true;
getAction(this.url.getDeptRoleByUserId,{userId:this.userId}).then((res) => {
if (res.success) {
var designName = [];
for (let value of res.result) {
designName.push(value.droleId)
}
this.oldRoleId=designName.join(",");
this.designNameValue = designName;
this.newRoleId = designName.join(",");
}
});
},
close() {
this.$emit('close');
this.visible = false;
},
handleSubmit() {
const that = this;
// 触发表单验证
that.confirmLoading = true;
let httpurl = this.url.add;
let method = 'post';
let formData = Object.assign(this.model, {});
//时间格式化
formData.userId = this.userId;
formData.newRoleId=this.newRoleId;
formData.oldRoleId=this.oldRoleId;
httpAction(httpurl, formData, method).then((res) => {
if (res.success) {
that.$message.success(res.message);
that.$emit('reload');
that.$emit('ok');
} else {
that.$message.warning(res.message);
}
}).finally(() => {
that.confirmLoading = false;
that.close();
})
},
handleCancel() {
this.designNameOption=[];
this.designNameValue=[];
this.close()
},
designNameChange(selectedValue) {
this.newRoleId=selectedValue.join(",");
},
checkALL(){
var designName = [];
for (let value of this.desformList) {
designName.push(
value.id
)
}
this.designNameValue = designName;
this.newRoleId=designName.join(",");
},
cancelCheckALL(){
this.designNameValue=[];
this.newRoleId="";
},
/** 加载desform */
loadDesformList() {
getAction(this.url.getDeptRoleList, { departId: this.currentDeptId }).then((res) => {
if (res.success) {
this.desformList = res.result
var designName = [];
for (let value of this.desformList) {
designName.push({
value: value.id,
text: value.roleName,
})
}
this.designNameOption = designName;
}
});
},
}
}
</script>
<style scoped>
.drawer-bootom-button {
position: absolute;
bottom: 0;
width: 100%;
border-top: 1px solid #e8e8e8;
padding: 10px 16px;
text-align: right;
left: 0;
background: #fff;
border-radius: 0 0 2px 2px;
}
</style>

View File

@ -7,7 +7,7 @@
<a-row :gutter="10">
<a-col :md="10" :sm="12">
<a-form-item label="用户账号" style="margin-left:8px">
<a-input placeholder="请输入名称查询" v-model="queryParam.username"></a-input>
<a-input placeholder="请输入账号" v-model="queryParam.username"></a-input>
</a-form-item>
</a-col>
<!--<a-col :md="8" :sm="8">-->
@ -25,7 +25,7 @@
</a-form>
</div>
<!-- -->
<div class="table-operator" :md="24" :sm="24" style="margin: -46px 0px 10px 2px">
<div class="table-operator" :md="24" :sm="24" style="margin-top: -15px">
<a-button @click="handleAdd" type="primary" icon="plus" style="margin-top: 16px"></a-button>
<!--<a-button @click="handleEdit" type="primary" icon="edit" style="margin-top: 16px"></a-button>-->
<a-button @click="handleAddUserDepart" type="primary" icon="plus"></a-button>
@ -34,7 +34,7 @@
<a-menu slot="overlay">
<a-menu-item key="1" @click="batchDel">
<a-icon type="delete"/>
</a-menu-item>
</a-menu>
<a-button style="margin-left: 8px">
@ -80,10 +80,13 @@
</a-menu-item>
<a-menu-item>
<a-popconfirm title="确定要删除关系吗?" @confirm="() => handleDelete(record.id)">
<a></a>
<a-popconfirm title="确定取消与选中部门关联吗?" @confirm="() => handleDelete(record.id)">
<a></a>
</a-popconfirm>
</a-menu-item>
<a-menu-item>
<a href="javascript:;" @click="handleDeptRole(record)"></a>
</a-menu-item>
</a-menu>
</a-dropdown>
</span>
@ -96,6 +99,7 @@
<!-- -->
<user-modal ref="modalForm" @ok="modalFormOk"></user-modal>
<Select-User-Modal ref="selectUserModal" @selectFinished="selectOK"></Select-User-Modal>
<dept-role-user-modal ref="deptRoleUser"></dept-role-user-modal>
</a-card>
</template>
@ -104,11 +108,13 @@
import {getAction, postAction, deleteAction} from '@/api/manage'
import SelectUserModal from './SelectUserModal'
import UserModal from './UserModal'
import DeptRoleUserModal from './DeptRoleUserModal'
export default {
name: "DeptUserInfo",
mixins: [JeecgListMixin],
components: {
DeptRoleUserModal,
SelectUserModal,
UserModal
},
@ -127,6 +133,21 @@
align: "center",
dataIndex: 'realname'
},
{
title: '',
align: "center",
dataIndex: 'sex_dictText'
},
{
title: '',
align: "center",
dataIndex: 'phone'
},
{
title: '',
align: "center",
dataIndex: 'orgCode'
},
{
title: '',
dataIndex: 'action',
@ -146,7 +167,12 @@
},
methods: {
searchReset() {
this.queryParam = {}
this.currentDeptId = '';
this.loadData(1);
this.$emit('clearSelectedDepartKeys')
},
loadData(arg) {
if (!this.url.list) {
this.$message.error("请设置url.list属性!")
@ -156,11 +182,11 @@
if (arg === 1) {
this.ipagination.current = 1;
}
if (this.currentDeptId === '') return;
var params = this.getQueryParams();//查询条件
//if (this.currentDeptId === '') return;
let params = this.getQueryParams();//查询条件
params.depId = this.currentDeptId;
getAction(this.url.list, params).then((res) => {
if (res.success) {
if (res.success && res.result) {
this.dataSource = res.result.records;
this.ipagination.total = res.result.total;
}
@ -172,6 +198,11 @@
this.$message.error("请设置url.deleteBatch属性!")
return
}
if (!this.currentDeptId) {
this.$message.error("未选中任何部门,无法取消部门与用户的关联!")
return
}
if (this.selectedRowKeys.length <= 0) {
this.$message.warning('');
return;
@ -183,12 +214,12 @@
var that = this;
console.log(this.currentDeptId);
this.$confirm({
title: "确认删除",
content: "是否删除选中数据?",
title: "确认取消",
content: "是否取消用户与选中部门的关联?",
onOk: function () {
deleteAction(that.url.deleteBatch, {depId: that.currentDeptId, userIds: ids}).then((res) => {
if (res.success) {
that.$message.success(res.message);
that.$message.success("删除用户与选中部门关系成功!");
that.loadData();
that.onClearSelected();
} else {
@ -204,10 +235,15 @@
this.$message.error("请设置url.delete属性!")
return
}
if (!this.currentDeptId) {
this.$message.error("未选中任何部门,无法取消部门与用户的关联!")
return
}
var that = this;
deleteAction(that.url.delete, {depId: this.currentDeptId, userId: id}).then((res) => {
if (res.success) {
that.$message.success(res.message);
that.$message.success("删除用户与选中部门关系成功!");
if (this.selectedRowKeys.length>0){
for(let i =0; i<this.selectedRowKeys.length;i++){
if (this.selectedRowKeys[i] == id){
@ -232,14 +268,14 @@
this.dataSource = [];
},
hasSelectDept() {
if (this.currentDeptId == null) {
if (this.currentDeptId == '') {
this.$message.error("请选择一个部门!")
return false;
}
return true;
},
handleAddUserDepart() {
if (this.currentDeptId == '') {
if (this.currentDeptId == '' ) {
this.$message.error("请选择一个部门!")
} else {
this.$refs.selectUserModal.visible = true;
@ -277,6 +313,10 @@
this.$message.warning(res.message);
}
})
},
handleDeptRole(record){
this.$refs.deptRoleUser.add(record,this.currentDeptId);
this.$refs.deptRoleUser.title = "部门角色分配";
}
}
}

View File

@ -30,7 +30,7 @@
</template>
<script>
import {changPassword} from '@/api/api'
import {changePassword} from '@/api/api'
export default {
name: "PasswordModal",
@ -96,7 +96,7 @@
if (!err) {
this.confirmLoading = true;
let formData = Object.assign(this.model, values);
changPassword(formData).then((res)=>{
changePassword(formData).then((res)=>{
if(res.success){
this.$message.success(res.message);
this.$emit('ok');

View File

@ -13,13 +13,13 @@
<a-col :span="6">
<a-form-item label="账号">
<a-input placeholder="请输入账号查询" v-model="queryParam.username"></a-input>
<a-input placeholder="请输入账号" v-model="queryParam.username"></a-input>
</a-form-item>
</a-col>
<a-col :span="6">
<a-form-item label="性别">
<a-select v-model="queryParam.sex" placeholder="请选择性别查询">
<a-select v-model="queryParam.sex" placeholder="请选择性别">
<a-select-option value=""></a-select-option>
<a-select-option value="1"></a-select-option>
<a-select-option value="2"></a-select-option>
@ -31,20 +31,20 @@
<template v-if="toggleSearchStatus">
<a-col :span="6">
<a-form-item label="邮箱">
<a-input placeholder="请输入邮箱查询" v-model="queryParam.email"></a-input>
<a-input placeholder="请输入邮箱" v-model="queryParam.email"></a-input>
</a-form-item>
</a-col>
<a-col :span="6">
<a-form-item label="手机号码">
<a-input placeholder="请输入手机号码查询" v-model="queryParam.phone"></a-input>
<a-input placeholder="请输入手机号码" v-model="queryParam.phone"></a-input>
</a-form-item>
</a-col>
<a-col :span="6">
<a-form-item label="状态">
<a-select v-model="queryParam.status" placeholder="请选择用户状态查询">
<a-select-option value=""></a-select-option>
<a-select v-model="queryParam.status" placeholder="请选择状态">
<a-select-option value=""></a-select-option>
<a-select-option value="1"></a-select-option>
<a-select-option value="2"></a-select-option>
</a-select>
@ -101,7 +101,7 @@
fixed:'left',
width:200
},{
title: '',
title: '',
align:"center",
dataIndex: 'realname',
},{

View File

@ -12,12 +12,12 @@
<!-- -->
<div class="table-page-search-wrapper">
<a-form layout="inline">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<a-col :span="10">
<a-form-item label="姓名">
<a-input placeholder="请输入姓名" v-model="queryParam.username"></a-input>
<a-form-item label="用户账号">
<a-input placeholder="请输入用户账号" v-model="queryParam.username"></a-input>
</a-form-item>
</a-col>
<a-col :span="8">
@ -83,7 +83,7 @@
{
title: '',
align: "center",
width: 113,
width: 100,
dataIndex: 'username'
},
{
@ -93,10 +93,22 @@
dataIndex: 'realname'
},
{
title: '',
title: '',
align: "center",
width: 100,
dataIndex: 'status'
dataIndex: 'sex_dictText'
},
{
title: '',
align: "center",
width: 100,
dataIndex: 'phone'
},
{
title: '',
align: "center",
width: 150,
dataIndex: 'orgCode'
}
],
columns2: [

View File

@ -12,16 +12,16 @@
<a-spin :spinning="confirmLoading">
<a-form :form="form">
<a-row class="form-row" :gutter="{ xs: 8, sm: 16, md: 24, lg: 32 }">
<a-col :lg="12">
<a-row style="width: 100%;">
<a-col :span="24/2">
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="标题">
<a-input placeholder="请输入标题" v-decorator="['titile', validatorRules.title]" :readOnly="disableSubmit" style="width: 90%"/>
<a-input placeholder="请输入标题" v-decorator="['titile', validatorRules.title]" :readOnly="disableSubmit"/>
</a-form-item>
</a-col>
<a-col :lg="12">
<a-col :span="24/2">
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
@ -30,76 +30,68 @@
v-decorator="[ 'msgCategory', validatorRules.msgCategory]"
placeholder="请选择消息类型"
:disabled="disableSubmit"
:getPopupContainer = "(target) => target.parentNode"
style="width: 80%" >
:getPopupContainer = "(target) => target.parentNode">
<a-select-option value="1"></a-select-option>
<a-select-option value="2"></a-select-option>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-row class="form-row" :gutter="24">
<a-col :lg="12">
<a-row style="width: 100%;">
<a-col :span="24/2">
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="开始时间:"
style="margin-left: 27px">
<j-date v-decorator="[ 'startTime', validatorRules.startTime]" placeholder="请选择开始时间" showTime dateFormat="YYYY-MM-DD HH:mm:ss" ></j-date>
label="开始时间:">
<j-date style="width: 100%" :getCalendarContainer="node => node.parentNode" v-decorator="[ 'startTime', validatorRules.startTime]" placeholder="请选择开始时间" showTime dateFormat="YYYY-MM-DD HH:mm:ss" ></j-date>
</a-form-item>
</a-col>
<a-col :lg="12">
<a-col :span="24/2">
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="结束时间"
class="endTime">
<j-date v-decorator="[ 'endTime', validatorRules.endTime]" placeholder="请选择结束时间" showTime dateFormat="YYYY-MM-DD HH:mm:ss"></j-date>
<j-date style="width: 100%" :getCalendarContainer="node => node.parentNode" v-decorator="[ 'endTime', validatorRules.endTime]" placeholder="请选择结束时间" showTime dateFormat="YYYY-MM-DD HH:mm:ss"></j-date>
</a-form-item>
</a-col>
</a-row>
<a-row class="form-row" :gutter="32">
<a-col :lg="9">
<a-row style="width: 100%;">
<a-col :span="24/2">
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="优先级"
style="margin-left: 27px">
label="优先级">
<a-select
v-decorator="[ 'priority', {}]"
placeholder="请选择优先级"
:disabled="disableSubmit"
:getPopupContainer = "(target) => target.parentNode"
style="margin-left: 5px;width: 135%">
:getPopupContainer = "(target) => target.parentNode">
<a-select-option value="L"></a-select-option>
<a-select-option value="M"></a-select-option>
<a-select-option value="H"></a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :lg="15" push="3">
<a-col :span="24/2">
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="通告对象类型"
style="margin-left: -14px">
label="通告类型">
<a-select
v-decorator="[ 'msgType', validatorRules.msgType]"
placeholder="请选择通告对象类型"
placeholder="请选择通告类型"
:disabled="disableSubmit"
@change="chooseMsgType"
:getPopupContainer = "(target) => target.parentNode"
style="width: 200px;margin-left: 5px">
:getPopupContainer = "(target) => target.parentNode">
<a-select-option value="USER"></a-select-option>
<a-select-option value="ALL"></a-select-option>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-row>
<a-col :lg="24" pull="2">
<a-row style="width: 100%;">
<a-col :span="24/2">
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
@ -110,20 +102,19 @@
placeholder="请选择用户"
v-model="selectedUser"
@dropdownVisibleChange="selectUserIds"
style="width: 119%"
>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-row>
<a-col :lg="24" pull="3">
<a-row style="width: 100%;">
<a-col :span="24">
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
:labelCol="labelColX1"
:wrapperCol="wrapperColX1"
label="内容"
style="margin-left: 5px">
<j-editor style="width: 130%" v-decorator="[ 'msgContent', {} ]" triggerChange></j-editor>
class="j-field-content">
<j-editor v-decorator="[ 'msgContent', {} ]" triggerChange></j-editor>
</a-form-item>
</a-col>
</a-row>
@ -153,11 +144,19 @@
model: {},
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
sm: { span: 6 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
sm: { span: 18 },
},
labelColX1: {
xs: { span: 24 },
sm: { span: 3 },
},
wrapperColX1: {
xs: { span: 24 },
sm: { span: 21 },
},
confirmLoading: false,

View File

@ -0,0 +1,379 @@
<template>
<a-modal
:title="title"
:width="1000"
:visible="visible"
:confirmLoading="confirmLoading"
@ok="handleOk"
@cancel="handleCancel"
cancelText="关闭">
<a-spin :spinning="confirmLoading">
<a-form :form="form">
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="规则名称">
<a-input placeholder="请输入规则名称" v-decorator="['ruleName', validatorRules.ruleName]"/>
</a-form-item>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="规则Code">
<a-input placeholder="请输入规则Code" v-decorator="['ruleCode', validatorRules.ruleCode]"/>
</a-form-item>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="规则描述">
<a-textarea placeholder="请输入规则描述" v-decorator="['ruleDescription', {}]"/>
</a-form-item>
</a-form>
<!-- -->
<a-tabs v-model="tabs.activeKey">
<a-tab-pane tab="局部规则" :key="tabs.design.key" forceRender>
<a-alert type="info" showIcon message="局部规则按照你输入的位数有序的校验。"/>
<j-editable-table
ref="designTable"
dragSort
rowNumber
:maxHeight="240"
:columns="tabs.design.columns"
:dataSource="tabs.design.dataSource"
style="margin-top: 8px;"
>
<template #action="props">
<my-action-button :rowEvent="props"/>
</template>
</j-editable-table>
</a-tab-pane>
<a-tab-pane tab="全局规则" :key="tabs.global.key" forceRender>
<j-editable-table
ref="globalTable"
dragSort
rowNumber
actionButton
:maxHeight="240"
:columns="tabs.global.columns"
:dataSource="tabs.global.dataSource"
>
<template #actionButtonAfter>
<a-alert type="info" showIcon message="全局规则可校验用户输入的所有字符;全局规则的优先级比局部规则的要高。" style="margin-bottom: 8px;"/>
</template>
<template #action="props">
<my-action-button :rowEvent="props" allowEmpty/>
</template>
</j-editable-table>
</a-tab-pane>
</a-tabs>
</a-spin>
</a-modal>
</template>
<script>
import pick from 'lodash.pick'
import { httpAction } from '@/api/manage'
import { validateDuplicateValue, alwaysResolve, failedSymbol } from '@/utils/util'
import { FormTypes } from '@/utils/JEditableTableUtil'
import JEditableTable from '@comp/jeecg/JEditableTable'
export default {
name: 'SysCheckRuleModal',
components: {
JEditableTable,
'my-action-button': {
props: { rowEvent: Object, allowEmpty: Boolean },
methods: {
confirmIsShow() {
const { index, allValues: { inputValues } } = this.rowEvent
let value = inputValues[index]
return value.digits || value.pattern
},
handleLineAdd() {
const { target } = this.rowEvent
target.add()
},
handleLineDelete() {
const { rowId, target } = this.rowEvent
target.removeRows(rowId)
},
renderDeleteButton() {
if (this.allowEmpty || this.rowEvent.index > 0) {
if (this.confirmIsShow()) {
return (
<a-popconfirm title="确定要删除吗?" onConfirm={this.handleLineDelete}>
<a-button icon="minus"/>
</a-popconfirm>
)
} else {
return (
<a-button icon="minus" onClick={this.handleLineDelete}/>
)
}
}
return ''
},
},
render() {
return (
<div>
<a-button onClick={this.handleLineAdd} icon="plus"/>
&nbsp;
{this.renderDeleteButton()}
</div>
)
}
}
},
data() {
return {
title: '',
visible: false,
model: {},
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
confirmLoading: false,
form: this.$form.createForm(this),
validatorRules: {
ruleName: { rules: [{ required: true, message: '!' },] },
ruleCode: {
rules: [
{ required: true, message: 'Code!' },
{ validator: (rule, value, callback) => validateDuplicateValue('sys_check_rule', 'rule_code', value, this.model.id, callback) }
]
},
},
tabs: {
activeKey: 'design',
global: {
key: 'global',
columns: [
{
title: '',
key: 'priority',
width: '15%',
type: FormTypes.select,
defaultValue: '1',
options: [
{ title: '', value: '1' },
{ title: '', value: '0' },
],
validateRules: []
},
{
title: '',
key: 'pattern',
width: '50%',
type: FormTypes.input,
validateRules: [
{ required: true, message: '' },
{ handler: this.validatePatternHandler },
]
},
{
title: '',
key: 'message',
width: '20%',
type: FormTypes.input,
validateRules: [
{ required: true, message: '${title}' },
]
},
{
title: '',
key: 'action',
width: '15%',
slotName: 'action',
type: FormTypes.slot
}
],
dataSource: [],
},
design: {
key: 'design',
columns: [
{
title: '',
key: 'digits',
width: '15%',
type: FormTypes.inputNumber,
validateRules: [
{ required: true, message: '${title}' },
{ pattern: /^[1-9]\d*$/, message: '' },
]
},
{
title: '',
key: 'pattern',
width: '50%',
type: FormTypes.input,
validateRules: [
{ required: true, message: '' },
{ handler: this.validatePatternHandler }
]
},
{
title: '',
key: 'message',
width: '20%',
type: FormTypes.input,
validateRules: [
{ required: true, message: '${title}' },
]
},
{
title: '',
key: 'action',
width: '15%',
slotName: 'action',
type: FormTypes.slot
},
],
dataSource: [],
}
},
url: {
add: '/sys/checkRule/add',
edit: '/sys/checkRule/edit',
},
}
},
created() {
},
methods: {
validatePatternHandler(type, value, row, column, callback, target) {
if (type === 'blur' || type === 'getValues') {
try {
new RegExp(value)
callback(true)
} catch (e) {
callback(false, '')
}
} else {
callback(true) // 不填写或者填写 null 代表不进行任何操作
}
},
add() {
this.edit({})
},
edit(record) {
this.form.resetFields()
this.tabs.activeKey = this.tabs.design.key
this.tabs.global.dataSource = []
this.tabs.design.dataSource = [{ digits: '', pattern: '', message: '' }]
this.model = Object.assign({}, record)
this.visible = true
this.$nextTick(() => {
this.form.setFieldsValue(pick(this.model, 'ruleName', 'ruleCode', 'ruleDescription'))
// 子表数据
let ruleJson = this.model.ruleJson
if (ruleJson) {
let ruleList = JSON.parse(ruleJson)
// 筛选出全局规则和局部规则
let global = [], design = [], priority = '1'
ruleList.forEach(rule => {
if (rule.digits === '*') {
global.push(Object.assign(rule, { priority }))
} else {
priority = '0'
design.push(rule)
}
})
this.tabs.global.dataSource = global
this.tabs.design.dataSource = design
}
})
},
close() {
this.$emit('close')
this.visible = false
},
handleOk() {
Promise.all([
// 主表单校验
alwaysResolve(new Promise((resolve, reject) => {
this.form.validateFields((error, values) => error ? reject(error) : resolve(values))
})),
// 局部规则子表校验
alwaysResolve(this.$refs.designTable.getValuesPromise),
// 全局规则子表校验
alwaysResolve(this.$refs.globalTable.getValuesPromise),
]).then(results => {
let [mainResult, designResult, globalResult] = results
if (mainResult.type === failedSymbol) {
return Promise.reject('')
} else if (designResult.type === failedSymbol) {
this.tabs.activeKey = this.tabs.design.key
return Promise.reject('')
} else if (globalResult.type === failedSymbol) {
this.tabs.activeKey = this.tabs.global.key
return Promise.reject('')
} else {
// 所有校验已通过,这一步是整合数据
let mainValues = mainResult.data, globalValues = globalResult.data, designValues = designResult.data
// 整合两个子表的数据
let firstGlobal = [], afterGlobal = []
globalValues.forEach(v => {
v.digits = '*'
if (v.priority === '1') {
firstGlobal.push(v)
} else {
afterGlobal.push(v)
}
})
let concatValues = firstGlobal.concat(designValues).concat(afterGlobal)
let subValues = concatValues.map(i => pick(i, 'digits', 'pattern', 'message'))
// 生成 formData用于传入后台
let ruleJson = JSON.stringify(subValues)
let formData = Object.assign(this.model, mainValues, { ruleJson })
// 判断请求方式和请求地址,并发送请求
let method = 'post', httpUrl = this.url.add
if (this.model.id) {
method = 'put'
httpUrl = this.url.edit
}
this.confirmLoading = true
return httpAction(httpUrl, formData, method)
}
}).then((res) => {
if (res.success) {
this.$message.success(res.message)
this.$emit('ok')
this.close()
} else {
this.$message.warning(res.message)
}
}).catch(e => {
console.error(e)
}).finally(() => {
this.confirmLoading = false
})
},
handleCancel() {
this.close()
},
}
}
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,58 @@
<template>
<a-modal
title="功能测试"
:width="800"
:visible="visible"
@ok="visible=false"
@cancel="visible=false"
>
<a-form :form="form">
<a-form-item label="功能测试">
<a-input placeholder="请输入" v-decorator="['test', validatorRules.test]" @change="e=>testValue=e.target.value"/>
</a-form-item>
</a-form>
<a-row type="flex" :gutter="8">
<a-col v-for="(str,index) of testValue">
<a-row>
<a-col>
<a-input :value="str" style="text-align: center;width: 40px;"/>
</a-col>
<a-col style="text-align: center;">{{index+1}}</a-col>
</a-row>
</a-col>
</a-row>
</a-modal>
</template>
<script>
import { validateCheckRule } from '@/utils/util'
export default {
name: 'SysCheckRuleModal',
data() {
return {
title: '',
visible: false,
ruleCode: '',
testValue: '',
form: this.$form.createForm(this),
validatorRules: {
test: {
rules: [{ validator: (rule, value, callback) => validateCheckRule(this.ruleCode, value, callback) }]
}
},
}
},
methods: {
open(ruleCode) {
this.ruleCode = ruleCode
this.form.resetFields()
this.testValue = ''
this.visible = true
},
}
}
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,227 @@
<template>
<a-modal
:title="title"
:width="800"
:visible="visible"
:confirmLoading="confirmLoading"
@ok="handleOk"
@cancel="handleCancel"
cancelText="关闭">
<a-spin :spinning="confirmLoading">
<a-form :form="form">
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="数据源名称">
<a-input placeholder="请输入数据源名称" v-decorator="['name', validatorRules.name]"/>
</a-form-item>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="数据源编码">
<a-input placeholder="请输入数据源编码" :disabled="!!model.id" v-decorator="['code', validatorRules.code]"/>
</a-form-item>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="数据库类型">
<j-dict-select-tag placeholder="请选择数据库类型" dict-code="database_type" triggerChange v-decorator="['dbType', validatorRules.dbType]" @change="handleDbTypeChange"/>
</a-form-item>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="驱动类">
<a-input placeholder="请输入驱动类" v-decorator="['dbDriver', validatorRules.dbDriver]"/>
</a-form-item>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="数据源地址">
<a-input placeholder="请输入数据源地址" v-decorator="['dbUrl', validatorRules.dbUrl]"/>
</a-form-item>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="数据库名称">
<a-input placeholder="请输入数据库名称" v-decorator="['dbName', validatorRules.dbName]"/>
</a-form-item>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="用户名">
<a-input placeholder="请输入用户名" v-decorator="['dbUsername', validatorRules.dbUsername]"/>
</a-form-item>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="密码">
<a-row :gutter="8">
<a-col :span="21">
<a-input-password placeholder="请输入密码" v-decorator="['dbPassword', validatorRules.dbPassword]"/>
</a-col>
<a-col :span="3">
<a-button type="primary" size="small" style="width: 100%" @click="handleTest"></a-button>
</a-col>
</a-row>
</a-form-item>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="备注">
<a-textarea placeholder="请输入备注" v-decorator="['remark', {}]"/>
</a-form-item>
</a-form>
</a-spin>
</a-modal>
</template>
<script>
import pick from 'lodash.pick'
import { httpAction, postAction } from '@/api/manage'
import { validateDuplicateValue } from '@/utils/util'
export default {
name: 'SysDataSourceModal',
components: {},
data() {
return {
title: '',
visible: false,
model: {},
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
confirmLoading: false,
form: this.$form.createForm(this),
validatorRules: {
code: {
validateFirst: true,
rules: [
{ required: true, message: '!' },
{
validator: (rule, value, callback) => {
let pattern = /^[a-z|A-Z][a-z|A-Z\d_-]{0,}$/
if (!pattern.test(value)) {
callback('线')
} else {
validateDuplicateValue('sys_data_source', 'code', value, this.model.id, callback)
}
}
}
]
},
name: { rules: [{ required: true, message: '!' }] },
dbType: { rules: [{ required: true, message: '!' }] },
dbDriver: { rules: [{ required: true, message: '!' }] },
dbUrl: { rules: [{ required: true, message: '!' }] },
dbName: { rules: [{ required: true, message: '!' }] },
dbUsername: { rules: [{ required: true, message: '!' }] },
dbPassword: { rules: [{ required: true, message: '!' }] }
},
url: {
add: '/sys/dataSource/add',
edit: '/sys/dataSource/edit',
},
dbDriverMap: {
// MySQL 数据库
'1': { dbDriver: 'com.mysql.jdbc.Driver' },
// Oracle
'2': { dbDriver: 'oracle.jdbc.OracleDriver' },
// SQLServer 数据库
'3': { dbDriver: 'com.microsoft.sqlserver.jdbc.SQLServerDriver' },
}
}
},
created() {
},
methods: {
add() {
this.edit({})
},
edit(record) {
this.form.resetFields()
this.model = Object.assign({}, record)
this.visible = true
this.$nextTick(() => {
this.form.setFieldsValue(pick(this.model, 'code', 'name', 'remark', 'dbType', 'dbDriver', 'dbUrl', 'dbName', 'dbUsername', 'dbPassword'))
})
},
close() {
this.$emit('close')
this.visible = false
},
handleOk() {
// 触发表单验证
this.form.validateFields((err, values) => {
if (!err) {
this.confirmLoading = true
let formData = Object.assign(this.model, values)
let httpUrl = this.url.add, method = 'post'
if (this.model.id) {
httpUrl = this.url.edit
method = 'put'
// 由于编码的特殊性,所以不能更改
formData['code'] = undefined
}
httpAction(httpUrl, formData, method).then((res) => {
if (res.success) {
this.$message.success(res.message)
this.$emit('ok')
this.close()
} else {
this.$message.warning(res.message)
}
}).finally(() => {
this.confirmLoading = false
})
}
})
},
handleCancel() {
this.close()
},
// 测试数据源配置是否可以正常连接
handleTest() {
let keys = ['dbType', 'dbDriver', 'dbUrl', 'dbName', 'dbUsername', 'dbPassword']
// 获取以上字段的值,并清除校验状态
let fieldsValues = this.form.getFieldsValue(keys)
let setFields = {}
keys.forEach(key => setFields[key] = { value: fieldsValues[key], errors: null })
// 清除校验状态,目的是可以让错误文字闪烁
this.form.setFields(setFields)
// 重新校验
this.$nextTick(() => {
this.form.validateFields(keys, (errors, values) => {
if (!errors) {
let loading = this.$message.loading('', 0)
postAction('/online/cgreport/api/testConnection', fieldsValues).then(res => {
if (res.success) {
this.$message.success('')
} else throw new Error(res.message)
}).catch(error => {
this.$warning({ title: '', content: error.message || error })
}).finally(() => loading())
}
})
})
},
// 数据库类型更改时,联动更改数据库驱动
handleDbTypeChange(val) {
let dbDriver = this.dbDriverMap[val]
if (dbDriver) {
this.form.setFieldsValue(dbDriver)
}
},
}
}
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,162 @@
<template>
<a-modal
:title="title"
:width="800"
:visible="visible"
:confirmLoading="confirmLoading"
@ok="handleOk"
@cancel="handleCancel"
cancelText="关闭">
<a-spin :spinning="confirmLoading">
<a-form :form="form">
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="部门角色名称">
<a-input placeholder="请输入部门角色名称" v-decorator="['roleName', validatorRules.roleName]" />
</a-form-item>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="部门角色编码">
<a-input placeholder="请输入部门角色编码" v-decorator="['roleCode', validatorRules.roleCode]" />
</a-form-item>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="描述">
<a-input placeholder="请输入描述" v-decorator="['description', validatorRules.description]" />
</a-form-item>
</a-form>
</a-spin>
</a-modal>
</template>
<script>
import { httpAction } from '@/api/manage'
import pick from 'lodash.pick'
import {duplicateCheck } from '@/api/api'
export default {
name: "SysDepartRoleModal",
data () {
return {
title:"操作",
visible: false,
model: {},
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
confirmLoading: false,
form: this.$form.createForm(this),
validatorRules:{
roleName:{
rules: [
{ required: true, message: '!' },
{ min: 2, max: 30, message: ' 2 30 ', trigger: 'blur' }
]},
roleCode:{
rules: [
{ required: true, message: '!'},
{ min: 0, max: 64, message: ' 64 ', trigger: 'blur' },
{ validator: this.validateRoleCode}
]},
description:{
rules: [
{ min: 0, max: 126, message: ' 126 ', trigger: 'blur' }
]}
},
url: {
add: "/sys/sysDepartRole/add",
edit: "/sys/sysDepartRole/edit",
},
}
},
created () {
},
methods: {
add (departId) {
this.edit({},departId);
},
edit (record,departId) {
this.departId = departId;
this.form.resetFields();
this.model = Object.assign({}, record);
this.visible = true;
this.$nextTick(() => {
this.form.setFieldsValue(pick(this.model,'roleName','roleCode','description'))
});
},
close () {
this.$emit('close');
this.visible = false;
},
handleOk () {
const that = this;
// 触发表单验证
this.form.validateFields((err, values) => {
if (!err) {
that.confirmLoading = true;
let httpurl = '';
let method = '';
if(!this.model.id){
httpurl+=this.url.add;
method = 'post';
}else{
httpurl+=this.url.edit;
method = 'put';
}
let formData = Object.assign(this.model, values);
formData.departId = this.departId;
httpAction(httpurl,formData,method).then((res)=>{
if(res.success){
that.$message.success(res.message);
that.$emit('ok');
}else{
that.$message.warning(res.message);
}
}).finally(() => {
that.confirmLoading = false;
that.close();
})
}
})
},
handleCancel () {
this.close()
},
validateRoleCode(rule, value, callback){
if(/[\u4E00-\u9FA5]/g.test(value)){
callback("部门角色编码不可输入汉字!");
}else{
var params = {
tableName: "sys_depart_role",
fieldName: "role_code",
fieldVal: value,
dataId: this.model.id,
};
duplicateCheck(params).then((res)=>{
if(res.success){
callback();
}else{
callback(res.message);
}
});
}
}
}
}
</script>
<style lang="less" scoped>
</style>

View File

@ -36,8 +36,8 @@
</a-form-item>
</template>
<a-form-item label="用户" :labelCol="labelCol" :wrapperCol="wrapperCol" >
<a-input placeholder="请输入用户" v-decorator="[ 'realname', validatorRules.realname]" />
<a-form-item label="用户名" :labelCol="labelCol" :wrapperCol="wrapperCol" >
<a-input placeholder="请输入用户名" v-decorator="[ 'realname', validatorRules.realname]" />
</a-form-item>
<a-form-item label="工号" :labelCol="labelCol" :wrapperCol="wrapperCol">
@ -71,23 +71,33 @@
<a-button slot="enterButton" icon="search"></a-button>
</a-input-search>
</a-form-item>
<a-form-item label="头像" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-upload
listType="picture-card"
class="avatar-uploader"
:showUploadList="false"
:action="uploadAction"
:data="{'isup':1}"
:headers="headers"
:beforeUpload="beforeUpload"
@change="handleChange"
<!-- update--begin--autor:wangshuai-----date:20200108------for------ -->
<a-form-item label="身份" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group
v-model="identity"
@change="identityChange">
<a-radio value="1"></a-radio>
<a-radio value="2"></a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="负责部门" :labelCol="labelCol" :wrapperCol="wrapperCol" v-if="departIdShow==true">
<a-select
mode="multiple"
style="width: 100%"
placeholder="请选择负责部门"
v-model="departIds"
optionFilterProp = "children"
:getPopupContainer = "(target) => target.parentNode"
:dropdownStyle="{maxHeight:'200px',overflow:'auto'}"
>
<img v-if="picUrl" :src="getAvatarView()" alt="头像" style="height:104px;max-width:300px"/>
<div v-else>
<a-icon :type="uploadLoading ? 'loading' : 'plus'" />
<div class="ant-upload-text"></div>
</div>
</a-upload>
<a-select-option v-for="item in resultDepartOptions" :key="item.key" :value="item.key"
>{{item.title}}</a-select-option
>
</a-select>
</a-form-item>
<!-- update--end--autor:wangshuai-----date:20200108------for------ -->
<a-form-item label="头像" :labelCol="labelCol" :wrapperCol="wrapperCol">
<j-image-upload class="avatar-uploader" text="上传" v-model="fileList" ></j-image-upload>
</a-form-item>
<a-form-item label="生日" :labelCol="labelCol" :wrapperCol="wrapperCol">
@ -145,10 +155,12 @@
import {addUser,editUser,queryUserRole,queryall } from '@/api/api'
import { disabledAuthFilter } from "@/utils/authFilter"
import {duplicateCheck } from '@/api/api'
import JImageUpload from '../../../components/jeecg/JImageUpload'
export default {
name: "UserModal",
components: {
JImageUpload,
departWindow,
JSelectPosition
},
@ -164,6 +176,7 @@
checkedDepartKeys:[],
checkedDepartNames:[], // 保存部门的名称 =>title
checkedDepartNameString:"", // 保存部门的名称 =>title
resultDepartOptions:[],
userId:"", //保存用户id
disableSubmit:false,
userDepartModel:{userId:'',departIdList:[]}, // 保存SysUserDepart的用户部门中间表数据需要的对象
@ -213,6 +226,8 @@
]
}
},
departIdShow:false,
departIds:[], //负责部门id
title:"操作",
visible: false,
model: {},
@ -233,11 +248,13 @@
picUrl: "",
url: {
fileUpload: window._CONFIG['domianURL']+"/sys/common/upload",
imgerver: window._CONFIG['domianURL']+"/sys/common/view",
imgerver: window._CONFIG['staticDomainURL'],
userWithDepart: "/sys/user/userDepartList", // 引入为指定用户查看部门信息需要的url
userId:"/sys/user/generateUserId", // 引入生成添加用户情况下的url
syncUserByUserName:"/process/extActProcess/doSyncUserByUserName",//同步用户到工作流
},
identity:"1",
fileList:[],
}
},
created () {
@ -287,6 +304,9 @@
this.checkedDepartNames=[];
this.checkedDepartNameString = "";
this.userId=""
this.resultDepartOptions=[];
this.departId=[];
this.departIdShow=false;
},
add () {
this.picUrl = "";
@ -301,7 +321,9 @@
that.form.resetFields();
if(record.hasOwnProperty("id")){
that.loadUserRoles(record.id);
this.picUrl = "Has no pic url yet";
setTimeout(() => {
this.fileList = record.avatar;
}, 5)
}
that.userId = record.id;
that.visible = true;
@ -309,6 +331,14 @@
that.$nextTick(() => {
that.form.setFieldsValue(pick(this.model,'username','sex','realname','email','phone','activitiSync','workNo','telephone','post'))
});
//身份为上级显示负责部门,否则不显示
if(this.model.identity=="2"){
this.identity="2";
this.departIdShow=true;
}else{
this.identity="1";
this.departIdShow=false;
}
// 调用查询用户对应的部门信息的方法
that.checkedDepartKeys = [];
that.loadCheckedDeparts();
@ -320,10 +350,25 @@
getAction(that.url.userWithDepart,{userId:that.userId}).then((res)=>{
that.checkedDepartNames = [];
if(res.success){
var depart=[];
var departId=[];
for (let i = 0; i < res.result.length; i++) {
that.checkedDepartNames.push(res.result[i].title);
this.checkedDepartNameString = this.checkedDepartNames.join(",");
that.checkedDepartKeys.push(res.result[i].key);
//新增负责部门选择下拉框
depart.push({
key:res.result[i].key,
title:res.result[i].title
})
departId.push(res.result[i].key)
}
that.resultDepartOptions=depart;
//判断部门id是否存在不存在择直接默认当前所在部门
if(this.model.departIds){
this.departIds=this.model.departIds.split(",");
}else{
this.departIds=departId;
}
that.userDepartModel.departIdList = that.checkedDepartKeys
}else{
@ -341,6 +386,11 @@
this.checkedDepartNameString='';
this.checkedDepartKeys = [];
this.selectedDepartKeys = [];
this.resultDepartOptions=[];
this.departIds=[];
this.departIdShow=false;
this.identity="1";
this.fileList=[];
},
moment,
handleSubmit () {
@ -350,17 +400,22 @@
this.form.validateFields((err, values) => {
if (!err) {
that.confirmLoading = true;
let avatar = that.model.avatar;
if(!values.birthday){
values.birthday = '';
}else{
values.birthday = values.birthday.format(this.dateFormat);
}
let formData = Object.assign(this.model, values);
formData.avatar = avatar;
formData.avatar = that.fileList;
formData.selectedroles = this.selectedRole.length>0?this.selectedRole.join(","):'';
formData.selecteddeparts = this.userDepartModel.departIdList.length>0?this.userDepartModel.departIdList.join(","):'';
formData.identity=this.identity;
//如果是上级择传入departIds,否则为空
if(this.identity==="2"){
formData.departIds=this.departIds.join(",");
}else{
formData.departIds="";
}
// that.addDepartsToUser(that,formData); // 调用根据当前用户添加部门信息的方法
let obj;
if(!this.model.id){
@ -380,7 +435,6 @@
that.confirmLoading = false;
that.checkedDepartNames = [];
that.userDepartModel.departIdList = {userId:'',departIdList:[]};
that.close();
})
@ -528,9 +582,6 @@
}
}
},
getAvatarView(){
return this.url.imgerver +"/"+ this.model.avatar;
},
// 搜索用户对应的部门API
onSearch(){
this.$refs.departWindow.add(this.checkedDepartKeys,this.userId);
@ -543,11 +594,21 @@
this.checkedDepartNameString = '';
this.userId = formData.userId;
this.userDepartModel.userId = formData.userId;
this.departIds=[];
this.resultDepartOptions=[];
var depart=[];
for (let i = 0; i < formData.departIdList.length; i++) {
this.selectedDepartKeys.push(formData.departIdList[i].key);
this.checkedDepartNames.push(formData.departIdList[i].title);
this.checkedDepartNameString = this.checkedDepartNames.join(",");
//新增部门选择,如果上面部门选择后不为空直接付给负责部门
depart.push({
key:formData.departIdList[i].key,
title:formData.departIdList[i].title
})
this.departIds.push(formData.departIdList[i].key)
}
this.resultDepartOptions=depart;
this.userDepartModel.departIdList = this.selectedDepartKeys;
this.checkedDepartKeys = this.selectedDepartKeys //更新当前的选择keys
},
@ -560,6 +621,13 @@
this.drawerWidth = 700;
}
},
identityChange(e){
if(e.target.value==="1"){
this.departIdShow=false;
}else{
this.departIdShow=true;
}
}
}
}
</script>

View File

@ -0,0 +1,191 @@
<template>
<a-modal
:width="1000"
:title="title"
:visible="innerVisible"
@cancel="handleCancel"
cancelText="关闭"
:okButtonProps="{style:{display:'none'}}"
>
<a-alert type="info" showIcon style="margin-bottom: 16px;">
<template slot="message">
<span></span>
<a style="font-weight: 600;padding: 0 4px;">{{ selectedRowKeys.length }}</a>
<span></span>
<template v-if="selectedRowKeys.length>0">
<a-divider type="vertical"/>
<a @click="handleClearSelection"></a>
<a-divider type="vertical"/>
<a @click="handleRevertBatch"></a>
<a-divider type="vertical"/>
<a @click="handleDeleteBatch"></a>
</template>
</template>
</a-alert>
<a-table
ref="table"
rowKey="id"
size="middle"
bordered
:columns="columns"
:loading="loading"
:dataSource="dataSource"
:pagination="false"
:rowSelection="{selectedRowKeys, onChange: handleTableSelectChange}"
>
<!-- -->
<template slot="avatarslot" slot-scope="text, record, index">
<div class="anty-img-wrap">
<a-avatar shape="square" :src="url.getAvatar(record.avatar)" icon="user"/>
</div>
</template>
<span slot="action" slot-scope="text, record">
<a @click="handleRevert([record.id])"><a-icon type="redo"/> </a>
<a-divider type="vertical"/>
<a @click="handleDelete([record.id])"><a-icon type="delete"/> </a>
</span>
</a-table>
</a-modal>
</template>
<script>
// 高度封装的请求,请务必使用 superRequest.call(this,{}) 的方式调用
function superRequest(options) {
this.loading = !!options.loading
options.promise.then(res => {
if (res.success && typeof options.success === 'function') {
options.success(res)
} else {
throw new Error(res.message)
}
}).catch(e => {
console.error('', e)
this.$message.warning('' + (e.message || e))
}).finally(() => {
this.loading = false
})
}
export default {
name: 'UserRecycleBinModal',
props: {
visible: {
type: Boolean,
default: false
},
},
data() {
return {
title: '',
loading: false,
innerVisible: false,
selectedRowKeys: [],
dataSource: [],
columns: [
{ title: '#', align: 'center', key: 'rowIndex', width: 80, customRender: (t, r, i) => i + 1 },
{ title: '', align: 'center', dataIndex: 'username' },
{ title: '', align: 'center', dataIndex: 'realname', },
{ title: '', align: 'center', dataIndex: 'avatar', scopedSlots: { customRender: 'avatarslot' } },
{ title: '', align: 'center', dataIndex: 'orgCode' },
{ title: '', align: 'center', dataIndex: 'action', width: 200, scopedSlots: { customRender: 'action' } }
],
url: {
getAvatar: (path) => `window._CONFIG['staticDomainURL']/${path}`,
// 回收站操作get = 获取列表put = 取回delete = 彻底删除
recycleBin: '/sys/user/recycleBin',
},
}
},
watch: {
visible: {
immediate: true,
handler(val) {
if (val) {
this.loadData()
}
this.innerVisible = val
}
},
innerVisible(val) {
this.$emit('update:visible', val)
},
},
methods: {
loadData() {
superRequest.call(this, {
loading: true,
promise: this.$http.get(this.url.recycleBin),
success: res => this.dataSource = res.result
})
},
handleOk() {
this.loadData()
this.$emit('ok')
},
handleCancel() {
this.innerVisible = false
},
// 还原用户
handleRevert(userIds) {
this.$confirm({
title: '',
content: ` ${userIds.length} `,
centered: true,
onOk: () => {
superRequest.call(this, {
loading: true,
promise: this.$http.put(this.url.recycleBin, userIds),
success: () => {
this.handleOk()
this.handleClearSelection()
this.$message.success(` ${userIds.length} `)
}
})
}
})
},
// 彻底删除用户
handleDelete(userIds) {
this.$confirm({
title: '',
content: (<div>
<p> {userIds.length} </p>
<p style="color:red;"></p>
</div>),
centered: true,
onOk: () => {
superRequest.call(this, {
loading: true,
promise: this.$http.delete(this.url.recycleBin + `?userIds=${userIds.join(',')}`),
success: () => {
this.loadData()
this.handleClearSelection()
this.$message.success(` ${userIds.length} `)
}
})
},
})
},
handleRevertBatch() {
this.handleRevert(this.selectedRowKeys)
},
handleDeleteBatch() {
this.handleDelete(this.selectedRowKeys)
},
handleClearSelection() {
this.handleTableSelectChange([], [])
},
handleTableSelectChange(selectedRowKeys, selectionRows) {
this.selectedRowKeys = selectedRowKeys
this.selectionRows = selectionRows
},
}
}
</script>
<style lang="scss" scoped></style>

View File

@ -45,7 +45,8 @@
<a-popconfirm title="确定放弃编辑?" @confirm="close" okText="确定" cancelText="取消">
<a-button style="margin-right: .8rem"></a-button>
</a-popconfirm>
<a-button @click="handleSubmit" type="primary" :loading="loading"></a-button>
<a-button @click="handleSubmit(false)" type="primary" :loading="loading" ghost style="margin-right: 0.8rem"></a-button>
<a-button @click="handleSubmit(true)" type="primary" :loading="loading"></a-button>
</div>
<role-datarule-modal ref="datarule"></role-datarule-modal>
@ -134,7 +135,7 @@
handleCancel () {
this.close()
},
handleSubmit(){
handleSubmit(exit) {
let that = this;
let params = {
roleId:that.roleId,
@ -147,18 +148,20 @@
if(res.success){
that.$message.success(res.message);
that.loading = false;
that.close();
if (exit) {
that.close()
}
}else {
that.$message.error(res.message);
that.loading = false;
that.close();
if (exit) {
that.close()
}
}
this.loadData();
})
},
},
watch: {
visible () {
if (this.visible) {
loadData(){
queryTreeListForRole().then((res) => {
this.treeData = res.result.treeList
this.allTreeKeys = res.result.ids
@ -170,6 +173,12 @@
})
})
}
},
watch: {
visible () {
if (this.visible) {
this.loadData();
}
}
}
}

View File

@ -1,13 +1,13 @@
<template>
<a-card :bordered="false" style="width: 160%;text-align: center;margin-left:-25%">
<a-card :bordered="false" style="width: 130%;text-align: center;margin-left:-10%">
<a-steps class="steps" :current="currentTab">
<a-step title="账户信息" />
<a-step title="身份验证" />
<a-step title="更改密码" />
<a-step title="完成" />
<a-step title="用户账户"/>
<a-step title="手机验证"/>
<a-step title="密码"/>
<a-step title="完成"/>
</a-steps>
<div class="content">
<step1 v-if="currentTab === 0" @nextStep="nextStep" />
<step1 v-if="currentTab === 0" @nextStep="nextStep"/>
<step2 v-if="currentTab === 1" @nextStep="nextStep" @prevStep="prevStep" :userList="userList"/>
<step3 v-if="currentTab === 2" @nextStep="nextStep" @prevStep="prevStep" :userList="userList"/>
<step4 v-if="currentTab === 3" @prevStep="prevStep" @finish="finish" :userList="userList"/>
@ -20,6 +20,7 @@
import Step2 from './Step2'
import Step3 from './Step3'
import Step4 from './Step4'
export default {
name: "Alteration",
components: {
@ -28,11 +29,11 @@
Step3,
Step4
},
data () {
data() {
return {
description: '',
currentTab: 0,
userList:{},
userList: {},
// form
form: null,
}
@ -40,19 +41,19 @@
methods: {
// handler
nextStep (data) {
this.userList=data;
nextStep(data) {
this.userList = data;
if (this.currentTab < 4) {
this.currentTab += 1
}
},
prevStep (data) {
this.userList=data;
prevStep(data) {
this.userList = data;
if (this.currentTab > 0) {
this.currentTab -= 1
}
},
finish () {
finish() {
this.currentTab = 0
}
}

View File

@ -9,7 +9,7 @@
<a-form-item>
<a-input
size="large"
v-decorator="['username',validatorRules.username,{ validator: this.handleUsernameOrEmail }]"
v-decorator="['username',{initialValue:'admin', rules: validatorRules.username.rules}]"
type="text"
placeholder="请输入帐户名 / jeecg">
<a-icon slot="prefix" type="user" :style="{ color: 'rgba(0,0,0,.25)' }"/>
@ -18,7 +18,7 @@
<a-form-item>
<a-input
v-decorator="['password',validatorRules.password]"
v-decorator="['password',{initialValue:'123456', rules: validatorRules.password.rules}]"
size="large"
type="password"
autocomplete="false"
@ -28,7 +28,7 @@
</a-form-item>
<a-row :gutter="0">
<a-col :span="14">
<a-col :span="16">
<a-form-item>
<a-input
v-decorator="['inputCode',validatorRules.inputCode]"
@ -36,13 +36,13 @@
type="text"
@change="inputCodeChange"
placeholder="请输入验证码">
<a-icon slot="prefix" v-if=" inputCodeContent==verifiedCode " type="smile" :style="{ color: 'rgba(0,0,0,.25)' }"/>
<a-icon slot="prefix" v-else type="frown" :style="{ color: 'rgba(0,0,0,.25)' }"/>
<a-icon slot="prefix" type="smile" :style="{ color: 'rgba(0,0,0,.25)' }"/>
</a-input>
</a-form-item>
</a-col>
<a-col :span="10">
<j-graphic-code @success="generateCode" ref="jgraphicCodeRef" style="float: right" remote></j-graphic-code>
<a-col :span="8" style="text-align: right">
<img style="margin-top: 2px;" :src="randCodeImage" @click="handleChangeCheckCode"/>
<!--<j-graphic-code @success="generateCode" ref="jgraphicCodeRef" style="float: right" remote></j-graphic-code>-->
</a-col>
</a-row>
@ -88,7 +88,7 @@
<router-link :to="{ name: 'alteration'}" class="forge-password" style="float: right;">
</router-link>
<router-link :to="{ name: 'register'}" class="forge-password" style="float: right;margin-right: 10px" >
<router-link :to="{ name: 'register'}" class="forge-password" style="float: right;margin-right: 10px" >
</router-link>
</a-form-item>
@ -173,8 +173,7 @@
import Vue from 'vue'
import { ACCESS_TOKEN ,ENCRYPTED_STRING} from "@/store/mutation-types"
import JGraphicCode from '@/components/jeecg/JGraphicCode'
import { putAction } from '@/api/manage'
import { postAction } from '@/api/manage'
import { putAction,postAction,getAction } from '@/api/manage'
import { encryption , getEncryptedString } from '@/utils/encryption/aesEncrypt'
import store from '@/store/'
import { USER_INFO } from "@/store/mutation-types"
@ -202,11 +201,11 @@
smsSendBtn: false,
},
validatorRules:{
username:{rules: [{ required: true, message: '!',validator: 'click'}]},
username:{rules: [{ required: true, message: '!'},{validator: this.handleUsernameOrEmail}]},
password:{rules: [{ required: true, message: '!',validator: 'click'}]},
mobile:{rules: [{validator:this.validateMobile}]},
captcha:{rule: [{ required: true, message: '!'}]},
inputCode:{rules: [{ required: true, message: '!'},{validator: this.validateInputCode}]}
inputCode:{rules: [{ required: true, message: '!'}]}
},
verifiedCode:"",
inputCodeContent:"",
@ -216,12 +215,16 @@
departVisible:false,
departSelected:"",
currentUsername:"",
validate_status:""
validate_status:"",
currdatetime:'',
randCodeImage:''
}
},
created () {
this.currdatetime = new Date().getTime();
Vue.ls.remove(ACCESS_TOKEN)
this.getRouterData();
this.handleChangeCheckCode();
// update-begin- --- author:scott ------ date:20190805 ---- for:密码加密逻辑暂时注释掉,有点问题
//this.getEncrypte();
// update-end- --- author:scott ------ date:20190805 ---- for:密码加密逻辑暂时注释掉,有点问题
@ -257,10 +260,9 @@
loginParams.password = values.password
loginParams.remember_me = values.rememberMe
// update-begin- --- author:scott ------ date:20190805 ---- for:密码加密逻辑暂时注释掉,有点问题
let checkParams = this.$refs.jgraphicCodeRef.getLoginParam()
loginParams.captcha = checkParams.checkCode
loginParams.checkKey = checkParams.checkKey
loginParams.captcha = that.inputCodeContent
loginParams.checkKey = that.currdatetime
console.log("登录参数",loginParams)
that.Login(loginParams).then((res) => {
this.departConfirm(res)
}).catch((err) => {
@ -339,6 +341,16 @@
this.stepCaptchaVisible = false
})
},
handleChangeCheckCode(){
this.currdatetime = new Date().getTime();
getAction(`/sys/randomImage/${this.currdatetime}`).then(res=>{
if(res.success){
this.randCodeImage = res.result
}else{
this.$message.error(res.message)
}
})
},
loginSuccess () {
// update-begin- author:sunjianlei --- date:20190812 --- for: 登录成功后不解除禁用按钮,防止多次点击
// this.loginBtn = false
@ -384,12 +396,6 @@
},
inputCodeChange(e){
this.inputCodeContent = e.target.value
if(!e.target.value||0==e.target.value){
this.inputCodeNull=true
}else{
this.inputCodeContent = this.inputCodeContent.toLowerCase()
this.inputCodeNull=false
}
},
departConfirm(res){
if(res.success){
@ -452,10 +458,12 @@
},
getRouterData(){
this.$nextTick(() => {
this.form.setFieldsValue({
'username': this.$route.params.username
});
})
if (this.$route.params.username) {
this.form.setFieldsValue({
'username': this.$route.params.username
});
}
})
},
//获取密码加密规则
getEncrypte(){

View File

@ -26,7 +26,7 @@
},
computed: {
email () {
let v = this.form && this.form.username || 'xxx'
let v = this.form ? this.form.username || this.form.mobile : ' XXX '
let title = `${v} `
this.username = v;
return title

View File

@ -1,14 +1,14 @@
<template>
<div class="main">
<a-form style="max-width: 500px; margin: 40px auto 0;" :form="form">
<a-form style="max-width: 500px; margin: 40px auto 0;" :form="form" @keyup.enter.native="nextStep">
<a-form-item>
<a-input
v-decorator="['username',validatorRules.username]"
size="large"
type="text"
autocomplete="false"
placeholder="请输入用户或手机号">
placeholder="请输入用户账号或手机号">
<a-icon slot="prefix" type="lock" :style="{ color: 'rgba(0,0,0,.25)' }"/>
</a-input>
</a-form-item>
@ -32,6 +32,7 @@
</a-col>
</a-row>
<a-form-item :wrapperCol="{span: 19, offset: 5}">
<router-link style="float: left;line-height: 40px;" :to="{ name: 'login' }">使</router-link>
<a-button type="primary" @click="nextStep"></a-button>
</a-form-item>
</a-form>
@ -40,95 +41,99 @@
<script>
import JGraphicCode from '@/components/jeecg/JGraphicCode'
import { getAction } from '@/api/manage'
import {checkOnlyUser } from '@/api/api'
import {getAction} from '@/api/manage'
import {checkOnlyUser} from '@/api/api'
export default {
name: "Step1",
components: {
JGraphicCode
},
data () {
data() {
return {
form: this.$form.createForm(this),
inputCodeContent: "",
inputCodeNull:true,
verifiedCode:"",
inputCodeNull: true,
verifiedCode: "",
validatorRules: {
username:{rules: [{ required: false},{validator: this.validateInputUsername}]},
inputCode:{rules: [{ required: true, message: '!'},{validator: this.validateInputCode}]},
username: {rules: [{required: false}, {validator: this.validateInputUsername}]},
inputCode: {rules: [{required: true, message: '!'}, {validator: this.validateInputCode}]},
},
}
},
methods: {
nextStep () {
nextStep() {
let that = this
this.form.validateFields((err, values) => {
if (!err){
var params={}
var reg=/^[1-9]\d*$|^0$/;
var username=values.username;
if(reg.test(username)==true) {
params.phone=username;
}else{
params.username=username;
if (!err) {
let isPhone = false;
var params = {}
var reg = /^[1-9]\d*$|^0$/;
var username = values.username;
if (reg.test(username) == true) {
params.phone = username;
isPhone = true
} else {
params.username = username;
}
getAction("/sys/user/querySysUser", params).then((res) => {
if (res.success) {
var userList = {
username: res.result.username,
phone: res.result.phone,
isPhone: isPhone
};
setTimeout(function () {
that.$emit('nextStep', userList)
})
}
});
}
getAction("/sys/user/querySysUser",params).then((res)=>{
if(res.success){
var userList={
username:res.result.username,
phone:res.result.phone
};
setTimeout(function () {
that.$emit('nextStep',userList)
})
}
});
}
})
})
},
validateInputCode(rule, value, callback){
validateInputCode(rule, value, callback) {
if (!value || this.verifiedCode == this.inputCodeContent) {
callback();
} else {
callback(new Error("您输入的验证码不正确!"));
}
},
inputCodeChange(e){
inputCodeChange(e) {
this.inputCodeContent = e.target.value;
console.log(this.inputCodeContent)
if(!e.target.value||0==e.target.value){
this.inputCodeNull=true
}else{
if (!e.target.value || 0 == e.target.value) {
this.inputCodeNull = true
} else {
this.inputCodeContent = this.inputCodeContent.toLowerCase()
this.inputCodeNull=false
this.inputCodeNull = false
}
},
generateCode(value){
generateCode(value) {
this.verifiedCode = value.toLowerCase();
console.log(this.verifiedCode);
},
validateInputUsername(rule, value, callback){
validateInputUsername(rule, value, callback) {
console.log(value);
var reg=/^[0-9]+.?[0-9]*/;
if(!value){
var reg = /^[0-9]+.?[0-9]*/;
if (!value) {
callback("请输入用户名和手机号!");
}
//判断用户输入账号还是手机号码
if(reg.test(value)){
if (reg.test(value)) {
var params = {
phone : value,
phone: value,
};
checkOnlyUser(params).then((res) => {
if (res.success) {
callback("用户名不存在!")
} else {
callback()
}
})
}else{
callback("用户名不存在!")
} else {
callback()
}
})
} else {
var params = {
username: value,
};

View File

@ -1,80 +1,79 @@
<template>
<div>
<a-form :form="form" style="max-width: 500px; margin: 40px auto 0;">
<a-form-item
label="账号名"
:labelCol="{span: 5}"
:wrapperCol="{span: 19}"
>
<a-input
type="text"
autocomplete="false"
:style="{width:'310px'}"
:value="accountName"
disabled>
</a-input>
</a-form-item>
<a-form-item
label="手机"
:labelCol="{span: 5}"
:wrapperCol="{span: 19}"
>
<a-input
type="text"
autocomplete="false"
:style="{width:'310px'}"
placeholder="请输入手机号"
:value="phone"
disabled>
<a-icon slot="prefix" type="phone" :style="{ color: 'rgba(0,0,0,.25)'}" />
</a-input>
</a-form-item>
<a-form :form="form" style="max-width: 500px; margin: 40px auto 0;" @keyup.enter.native="nextStep">
<a-form-item
label="账号名"
:labelCol="{span: 5}"
:wrapperCol="{span: 19}"
>
<a-input
type="text"
autocomplete="false"
:style="{width:'310px'}"
:value="accountName"
disabled>
</a-input>
</a-form-item>
<a-form-item
label="手机"
:labelCol="{span: 5}"
:wrapperCol="{span: 19}"
>
<a-input
type="text"
autocomplete="false"
:style="{width:'310px'}"
v-decorator="['phone',{initialValue: defaultPhone, rules: validatorRules.phone.rule}]"
placeholder="请输入手机号">
<a-icon slot="prefix" type="phone" :style="{ color: 'rgba(0,0,0,.25)'}"/>
</a-input>
</a-form-item>
<a-form-item
label="验证码"
:labelCol="{span: 5}"
:wrapperCol="{span: 19}"
v-if="show">
<a-row :gutter="16" style="margin-left: 35px">
<a-col class="gutter-row" :span="10">
<a-input
v-decorator="['captcha',validatorRules.captcha]"
type="text"
placeholder="手机短信验证码" >
</a-input>
</a-col>
<a-col class="gutter-row" :span="8" >
<a-button
tabindex="-1"
size="default"
:disabled="state.smsSendBtn"
@click.stop.prevent="getCaptcha"
v-text="!state.smsSendBtn && '获取验证码' || (state.time+' s')"></a-button>
</a-col>
</a-row>
<a-row :gutter="16" style="margin-left: 2px">
<a-col class="gutter-row" :span="12">
<a-input
v-decorator="['captcha',validatorRules.captcha]"
type="text"
placeholder="手机短信验证码">
</a-input>
</a-col>
<a-col class="gutter-row" :span="8">
<a-button
tabindex="-1"
size="default"
:disabled="state.smsSendBtn"
@click.stop.prevent="getCaptcha"
v-text="!state.smsSendBtn && '获取验证码' || (state.time+' s')"></a-button>
</a-col>
</a-row>
</a-form-item>
<a-form-item :wrapperCol="{span: 19, offset: 5}">
<a-button style="margin-left: 8px" @click="prevStep"></a-button>
<a-button type="primary" @click="nextStep" style="margin-left: 20px"></a-button>
</a-form-item>
<a-button style="margin-left: 8px" @click="prevStep"></a-button>
<a-button type="primary" @click="nextStep" style="margin-left: 20px"></a-button>
</a-form-item>
</a-form>
</div>
</template>
<script>
import { postAction } from '@/api/manage'
import {postAction} from '@/api/manage'
export default {
name: "Step2",
props:['userList'],
data () {
props: ['userList'],
data() {
return {
form: this.$form.createForm(this),
loading: false,
accountName:this.userList.username,
phone:this.userList.phone,
dropList:"0",
accountName: this.userList.username,
dropList: "0",
captcha: "",
show:true,
show: true,
state: {
time: 60,
smsSendBtn: false,
@ -83,58 +82,66 @@
captcha: "",
mobile: "",
},
validatorRules:{
captcha:{rule: [{ required: true, message: '!'},{validator:this.validateCaptcha}]},
validatorRules: {
captcha: {rule: [{required: true, message: '!'}, {validator: this.validateCaptcha}]},
phone: {rule: [{required: true, message: '!'}]},
},
}
},
computed: {
defaultPhone: function(){
if(this.userList.isPhone){
return this.userList.phone
}
return null;
}
},
methods: {
nextStep () {
nextStep() {
let that = this
that.loading = true
this.form.validateFields((err, values) => {
console.log(values);
if (!err) {
if(that.dropList=="0"){
if(values.captcha==undefined){
if (that.dropList == "0") {
if (values.captcha == undefined) {
this.cmsFailed("请输入短信验证码!");
}else{
var params={}
params.phone=this.userList.phone;
params.smscode=values.captcha;
postAction("/sys/user/phoneVerification",params).then((res)=>{
if(res.success){
console.log(res);
var userList={
username:this.userList.username,
phone:this.userList.phone,
smscode:res.result
};
setTimeout(function () {
that.$emit('nextStep',userList)
},0)
}else{
this.cmsFailed(res.message);
}
})
} else {
var params = {}
params.phone = this.userList.phone;
params.smscode = values.captcha;
postAction("/sys/user/phoneVerification", params).then((res) => {
if (res.success) {
console.log(res);
var userList = {
username: this.userList.username,
phone: this.userList.phone,
smscode: res.result
};
setTimeout(function () {
that.$emit('nextStep', userList)
}, 0)
} else {
this.cmsFailed(res.message);
}
})
}
}
}
})
}
})
},
prevStep () {
this.$emit('prevStep',this.userList);
prevStep() {
this.$emit('prevStep', this.userList);
},
getCaptcha (e) {
getCaptcha(e) {
e.preventDefault();
let that = this;
this.state.smsSendBtn = true;
let interval = window.setInterval(() => {
if (that.state.time-- <= 0) {
this.state.smsSendBtn = true;
let interval = window.setInterval(() => {
if (that.state.time-- <= 0) {
that.state.time = 60;
that.state.smsSendBtn = false;
window.clearInterval(interval);
@ -147,30 +154,30 @@
smsmode: "2"
};
postAction("/sys/sms", smsParams).then(res => {
if(!res.success ){
setTimeout(hide, 1);
this.cmsFailed(res.message);
}
setTimeout(hide, 500);
})
if (!res.success) {
setTimeout(hide, 1);
this.cmsFailed(res.message);
}
setTimeout(hide, 500);
})
},
cmsFailed(err){
this.$notification[ 'error' ]({
cmsFailed(err) {
this.$notification['error']({
message: "验证错误",
description:err,
description: err,
duration: 4,
});
},
handleChangeSelect(value){
var that=this;
handleChangeSelect(value) {
var that = this;
console.log(value);
if(value==0){
that.dropList="0";
that.show=true;
}else{
that.dropList="1";
that.show=false;
}
if (value == 0) {
that.dropList = "0";
that.show = true;
} else {
that.dropList = "1";
that.show = false;
}
},
}
@ -181,10 +188,11 @@
.stepFormText {
margin-bottom: 24px;
}
.ant-form-item-label,
.ant-form-item-control {
line-height: 22px;
}
.ant-form-item-label,
.ant-form-item-control {
line-height: 22px;
}
.getCaptcha {
display: block;

View File

@ -30,7 +30,6 @@ module.exports = {
.set('@comp', resolve('src/components'))
.set('@views', resolve('src/views'))
.set('@layout', resolve('src/layout'))
.set('@static', resolve('src/static'))
},
css: {

File diff suppressed because it is too large Load Diff

View File

@ -50,7 +50,7 @@ RUN cd /etc/yum.repos.d/ \
# 前端迁移到系统文件中 默认是80端口 同级目录下的html地址
ADD ant-design-vue-jeecg/dist/ /var/www/html/
# 拷贝相关的jar包
ADD jeecg-boot/jeecg-boot-module-system/target/jeecg-boot-module-system-2.1.1.jar jeecgboot.jar
ADD jeecg-boot/jeecg-boot-module-system/target/jeecg-boot-module-system-2.1.4.jar jeecgboot.jar
EXPOSE 80 8080 81
ENTRYPOINT /bin/sh -c /etc/init.d/start.sh

View File

@ -1,7 +1,7 @@
Jeecg-Boot 快速开发平台
===============
当前最新版本: 2.1.3发布日期20191226
当前最新版本: 2.1.4发布日期20200224
## 后端技术架构
@ -37,11 +37,11 @@ Jeecg-Boot 快速开发平台
## 技术文档
- 在线演示 [http://boot.jeecg.org](http://boot.jeecg.org)
- 在线演示 [http://boot.jeecg.com](http://boot.jeecg.com)
- 在线文档: [http://doc.jeecg.com/1273753](http://doc.jeecg.com/1273753)
- 常见问题: [入门常见问题大全](http://www.jeecg.org/forum.php?mod=viewthread&tid=7816&extra=page%3D1)
- 常见问题: [入门常见问题大全](http://bbs.jeecg.com/forum.php?mod=viewthread&tid=7816&extra=page%3D1)
- QQ交流群 ①284271917、②769925425

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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