Commit 109a95a9 by zhangdaiscott

Jeecg Boot 2.2.1 版本发布,低代码平台

parent cb7ae9ca
......@@ -7,7 +7,7 @@
JEECG BOOT 低代码开发平台(前后端分离版本)
===============
当前最新版本: 2.2.0(发布日期:2020-05-06
当前最新版本: 2.2.1(发布日期:2020-07-11
[![AUR](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE)
......
docs
public
src
.dockerignore
.editorconfig
.eslintignore
.gitattributes
.gitignore
.prettierrc
babel.config.js
Dockerfile
idea.config.js
LICENSE
package.json
package-lock.json
README.md
vue.config.js
yarn
yarn.lock
yarn-error.log
.idea
.svn
node_modules
\ No newline at end of file
/src
\ No newline at end of file
FROM nginx
MAINTAINER jeecgos@163.com
VOLUME /tmp
ENV LANG en_US.UTF-8
RUN echo "server { \
listen 80; \
location ^~ /jeecg-boot { \
proxy_pass http://jeecg-boot-system:8080/jeecg-boot/; \
proxy_set_header Host jeecg-boot-system; \
proxy_set_header X-Real-IP \$remote_addr; \
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; \
} \
#解决Router(mode: 'history')模式下,刷新路由地址不能找到页面的问题 \
location / { \
root /var/www/html/; \
index index.html index.htm; \
if (!-e \$request_filename) { \
rewrite ^(.*)\$ /index.html?s=\$1 last; \
break; \
} \
} \
access_log /var/log/nginx/access.log ; \
} " > /etc/nginx/conf.d/default.conf \
&& mkdir -p /var/www \
&& mkdir -p /var/www/html
ADD dist/ /var/www/html/
EXPOSE 80
EXPOSE 443
\ No newline at end of file
Ant Design Jeecg Vue
====
当前最新版本: 2.2.0(发布日期:2020-05-06
当前最新版本: 2.2.1(发布日期:20200711
Overview
----
......@@ -103,4 +103,33 @@ yarn run lint
备注
----
> @vue/cli 升级后,eslint 规则更新了。由于影响到全部 .vue 文件,需要逐个验证。既暂时关闭部分原本不验证的规则,后期维护时,在逐步修正这些 rules
\ No newline at end of file
> @vue/cli 升级后,eslint 规则更新了。由于影响到全部 .vue 文件,需要逐个验证。既暂时关闭部分原本不验证的规则,后期维护时,在逐步修正这些 rules
Docker 镜像使用
----
```
# 1.修改前端项目的后台域名
public/index.html
域名改成: http://jeecg-boot-system:8080/jeecg-boot
# 2.先进入打包前端项目
yarn run build
# 3.构建镜像
docker build -t nginx:jeecgboot .
# 4.启动镜像
docker run --name jeecg-boot-nginx -p 80:80 -d nginx:jeecgboot
# 5.配置host
# jeecgboot
127.0.0.1 jeecg-boot-redis
127.0.0.1 jeecg-boot-mysql
127.0.0.1 jeecg-boot-system
# 6.访问前台项目
http://localhost:80
```
\ No newline at end of file
module.exports = {
presets: [
['@vue/app',
{ useBuiltIns: 'entry' }]
{ useBuiltIns: 'entry' }]
]
}
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "vue-antd-jeecg",
"version": "2.2.0",
"version": "2.2.1",
"private": true,
"scripts": {
"pre": "yarn --registry https://registry.npm.taobao.org || cnpm install || npm install --registry https://registry.npm.taobao.org ",
"pre": "cnpm install || yarn --registry https://registry.npm.taobao.org || npm install --registry https://registry.npm.taobao.org ",
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"@antv/data-set": "^0.11.2",
"@jeecg/antd-online-beta220": "^1.0.1",
"@tinymce/tinymce-vue": "^2.0.0",
"ant-design-vue": "1.5.2",
"area-data": "^5.0.6",
"ant-design-vue": "^1.6.3",
"@antv/data-set": "^0.11.4",
"@jeecg/antd-online-mini": "2.2.1",
"viser-vue": "^2.4.8",
"axios": "^0.18.0",
"clipboard": "^2.0.4",
"codemirror": "^5.46.0",
"dayjs": "^1.8.0",
"enquire.js": "^2.1.6",
"js-cookie": "^2.2.0",
......@@ -24,20 +21,25 @@
"lodash.pick": "^4.4.0",
"md5": "^2.2.1",
"nprogress": "^0.2.0",
"tinymce": "^5.1.4",
"viser-vue": "^2.4.4",
"vue": "^2.6.10",
"vue-area-linkage": "^5.1.0",
"vue-cropper": "^0.4.8",
"vue-cropper": "^0.5.4",
"vue-i18n": "^8.7.0",
"vue-loader": "^15.7.0",
"vue-ls": "^3.2.0",
"vue-photo-preview": "^1.1.3",
"vue-print-nb-jeecg": "^1.0.9",
"vue-router": "^3.0.1",
"vuex": "^3.1.0",
"vue-print-nb-jeecg": "^1.0.9",
"clipboard": "^2.0.4",
"vue-photo-preview": "^1.1.3",
"vue-splitpane": "^1.0.4",
"vuedraggable": "^2.20.0",
"vuex": "^3.1.0"
"codemirror": "^5.46.0",
"@tinymce/tinymce-vue": "^2.1.0",
"tinymce": "^5.3.2",
"@toast-ui/editor": "^2.1.2",
"vue-area-linkage": "^5.1.0",
"area-data": "^5.0.6",
"jsoneditor": "^9.0.0"
},
"devDependencies": {
"@babel/polyfill": "^7.2.5",
......@@ -45,7 +47,7 @@
"@vue/cli-plugin-eslint": "^3.3.0",
"@vue/cli-service": "^3.3.0",
"@vue/eslint-config-standard": "^4.0.0",
"babel-eslint": "^10.0.1",
"babel-eslint": "7.2.3",
"compression-webpack-plugin": "^3.1.0",
"eslint": "^5.16.0",
"eslint-plugin-vue": "^5.1.0",
......@@ -89,9 +91,10 @@
"vue/no-use-v-if-with-v-for": 0,
"vue/html-closing-bracket-newline": 0,
"vue/no-parsing-error": 0,
"no-console": 0,
"no-tabs": 0,
"indent": [1, 4]
"indent": ["off", 2],
"no-console": 0,
"space-before-function-paren": 0
}
},
"postcss": {
......
......@@ -7680,6 +7680,13 @@ font.weak {
color: #f5222d;
}
// 侧边导航栏首页颜色跟随主题变化
.ant-menu.ant-menu-root > .ant-menu-item:first-child.ant-menu-item-selected {
& > a,
& > a:hover {
color: @primary-color;
}
}
// begin -------- JAreaLinkage 三级联动样式 --------------
.cascader-menu-list .cascader-menu-option.hover,
......@@ -7698,4 +7705,14 @@ font.weak {
.area-select:active {
box-shadow: 0 0 0 2px color(~`colorPalette("@{primary-color}", 1)`);
}
// end -------- JAreaLinkage 三级联动样式 --------------
\ No newline at end of file
// end -------- JAreaLinkage 三级联动样式 --------------
// TESTA-521
.ant-menu-submenu-selected {
color: @primary-color;
}
// TESTA-521
.tab-layout-tabs.ant-tabs.ant-tabs-card > .ant-tabs-bar .ant-tabs-tab-active {
border-color: @primary-color !important;
}
\ No newline at end of file
......@@ -246,6 +246,7 @@
window._CONFIG['casPrefixUrl'] = 'http://cas.example.org:8443/cas';
window._CONFIG['onlinePreviewDomainURL'] = 'http://fileview.jeecg.com/onlinePreview'
window._CONFIG['staticDomainURL'] = window._CONFIG['domianURL'] + '/sys/common/static';
//window._CONFIG['downloadUrl'] = window._CONFIG['domianURL'] + '/sys/common/download';
window._CONFIG['pdfDomainURL'] = window._CONFIG['domianURL'] + '/sys/common/pdf/pdfPreviewIframe';
</script>
</head>
......
......@@ -2,10 +2,17 @@ import { getAction, deleteAction, putAction, postAction, httpAction } from '@/ap
import Vue from 'vue'
import {UI_CACHE_DB_DICT_DATA } from "@/store/mutation-types"
////根路径
// const doMian = "/jeecg-boot/";
////图片预览请求地址
// const imgView = "http://localhost:8080/jeecg-boot/sys/common/view/";
//角色管理
const addRole = (params)=>postAction("/sys/role/add",params);
const editRole = (params)=>putAction("/sys/role/edit",params);
// const getRoleList = (params)=>getAction("/sys/role/list",params);
// const deleteRole = (params)=>deleteAction("/sys/role/delete",params);
// const deleteRoleList = (params)=>deleteAction("/sys/role/deleteBatch",params);
const checkRoleCode = (params)=>getAction("/sys/role/checkRoleCode",params);
const queryall = (params)=>getAction("/sys/role/queryall",params);
......@@ -14,6 +21,8 @@ const addUser = (params)=>postAction("/sys/user/add",params);
const editUser = (params)=>putAction("/sys/user/edit",params);
const queryUserRole = (params)=>getAction("/sys/user/queryUserRole",params);
const getUserList = (params)=>getAction("/sys/user/list",params);
// const deleteUser = (params)=>deleteAction("/sys/user/delete",params);
// const deleteUserList = (params)=>deleteAction("/sys/user/deleteBatch",params);
const frozenBatch = (params)=>putAction("/sys/user/frozenBatch",params);
//验证用户是否存在
const checkOnlyUser = (params)=>getAction("/sys/user/checkOnlyUser",params);
......@@ -24,15 +33,20 @@ const changePassword = (params)=>putAction("/sys/user/changePassword",params);
const addPermission= (params)=>postAction("/sys/permission/add",params);
const editPermission= (params)=>putAction("/sys/permission/edit",params);
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);
// const deletePermissionList = (params)=>deleteAction("/sys/permission/deleteBatch",params);
const queryTreeList = (params)=>getAction("/sys/permission/queryTreeList",params);
const queryTreeListForRole = (params)=>getAction("/sys/role/queryTreeList",params);
const queryListAsync = (params)=>getAction("/sys/permission/queryListAsync",params);
const queryRolePermission = (params)=>getAction("/sys/permission/queryRolePermission",params);
const saveRolePermission = (params)=>postAction("/sys/permission/saveRolePermission",params);
//const queryPermissionsByUser = (params)=>getAction("/sys/permission/queryByUser",params);
const queryPermissionsByUser = (params)=>getAction("/sys/permission/getUserPermissionByToken",params);
const loadAllRoleIds = (params)=>getAction("/sys/permission/loadAllRoleIds",params);
const getPermissionRuleList = (params)=>getAction("/sys/permission/getPermRuleListByPermId",params);
......@@ -54,15 +68,21 @@ const saveDeptRolePermission = (params)=>postAction("/sys/sysDepartPermission/sa
const queryMyDepartTreeList = (params)=>getAction("/sys/sysDepart/queryMyDeptTreeList",params);
//日志管理
//const getLogList = (params)=>getAction("/sys/log/list",params);
const deleteLog = (params)=>deleteAction("/sys/log/delete",params);
const deleteLogList = (params)=>deleteAction("/sys/log/deleteBatch",params);
//数据字典
const addDict = (params)=>postAction("/sys/dict/add",params);
const editDict = (params)=>putAction("/sys/dict/edit",params);
//const getDictList = (params)=>getAction("/sys/dict/list",params);
const treeList = (params)=>getAction("/sys/dict/treeList",params);
// const delDict = (params)=>deleteAction("/sys/dict/delete",params);
//const getDictItemList = (params)=>getAction("/sys/dictItem/list",params);
const addDictItem = (params)=>postAction("/sys/dictItem/add",params);
const editDictItem = (params)=>putAction("/sys/dictItem/edit",params);
//const delDictItem = (params)=>deleteAction("/sys/dictItem/delete",params);
//const delDictItemList = (params)=>deleteAction("/sys/dictItem/deleteBatch",params);
//字典标签专用(通过code获取字典数组)
export const ajaxGetDictItems = (code, params)=>getAction(`/sys/dict/getDictItems/${code}`,params);
......@@ -81,18 +101,33 @@ const doReovkeData = (params)=>getAction("/sys/annountCement/doReovkeData",param
//获取系统访问量
const getLoginfo = (params)=>getAction("/sys/loginfo",params);
const getVisitInfo = (params)=>getAction("/sys/visitInfo",params);
//数据日志访问
// const getDataLogList = (params)=>getAction("/sys/dataLog/list",params);
// 根据部门主键查询用户信息
const queryUserByDepId = (params)=>getAction("/sys/user/queryUserByDepId",params);
// 查询用户角色表里的所有信息
// 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)
//我的通告
//加载我的通告信息
const getUserNoticeInfo= (params)=>getAction("/sys/sysAnnouncementSend/getMyAnnouncementSend",params);
const getTransitURL = url => `/sys/common/transitRESTful?url=${encodeURIComponent(url)}`
// 中转HTTP请求
export const transitRESTful = {
get: (url, parameter) => getAction(getTransitURL(url), parameter),
post: (url, parameter) => postAction(getTransitURL(url), parameter),
put: (url, parameter) => putAction(getTransitURL(url), parameter),
http: (url, parameter) => httpAction(getTransitURL(url), parameter),
}
export {
// imgView,
// doMian,
addRole,
editRole,
checkRoleCode,
......
......@@ -55,4 +55,7 @@
/* 内嵌子表背景颜色 */
.j-inner-table-wrapper /deep/ .ant-table-expanded-row .ant-table-wrapper .ant-table-tbody .ant-table-row {
background-color: #FFFFFF;
}
\ No newline at end of file
}
/**隐藏样式-modal确定按钮 */
.jee-hidden{display: none}
\ No newline at end of file
......@@ -7,7 +7,7 @@
<a-radio-button v-for="(item, key) in dictOptions" :key="key" :value="item.value">{{ item.text }}</a-radio-button>
</a-radio-group>
<a-select v-else-if="tagType=='select'" :getPopupContainer = "(target) => target.parentNode" :placeholder="placeholder" :disabled="disabled" :value="getValueSting" @change="handleInput">
<a-select v-else-if="tagType=='select'" :getPopupContainer = "getPopupContainer" :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 ">
......@@ -28,7 +28,11 @@
triggerChange: Boolean,
disabled: Boolean,
value: [String, Number],
type: String
type: String,
getPopupContainer:{
type: Function,
default: (node) => node.parentNode
}
},
data() {
return {
......@@ -56,7 +60,10 @@
},
computed: {
getValueSting(){
return this.value != null ? this.value.toString() : null;
// update-begin author:wangshuai date:20200601 for: 不显示placeholder的文字 ------
// 当有null或“” placeholder不显示
return this.value != null ? this.value.toString() : undefined;
// update-end author:wangshuai date:20200601 for: 不显示placeholder的文字 ------
},
},
methods: {
......
......@@ -36,15 +36,20 @@ export async function initDictOptions(dictCode) {
*/
export function filterDictText(dictOptions, text) {
// --update-begin----author:sunjianlei---date:20200323------for: 字典翻译 text 允许逗号分隔 ---
if (text != null && dictOptions instanceof Array) {
if (text != null && Array.isArray(dictOptions)) {
let result = []
// 允许多个逗号分隔
let splitText = text.toString().trim().split(',')
// 允许多个逗号分隔,允许传数组对象
let splitText
if (Array.isArray(text)) {
splitText = text
} else {
splitText = text.toString().trim().split(',')
}
for (let txt of splitText) {
let dictText = txt
for (let dictItem of dictOptions) {
if (txt === dictItem.value.toString()) {
dictText = dictItem.text
if (txt.toString() === dictItem.value.toString()) {
dictText = (dictItem.text || dictItem.title || dictItem.label)
break
}
}
......
<template>
<div v-if="!reloading" class="j-area-linkage">
<div class="j-area-linkage">
<div v-if="reloading">
<span> Reloading... </span>
</div>
<area-cascader
v-if="_type === enums.type[0]"
v-else-if="_type === enums.type[0]"
:value="innerValue"
:data="pcaa"
:level="1"
......@@ -90,19 +93,23 @@
this.initAreaData();
},
methods: {
/** 重新加载组件 */
reload() {
this.reloading = true
this.$nextTick(() => this.reloading = false)
},
/** 通过 value 反推 options */
loadDataByValue(value) {
if(!value || value.length==0){
if (!value || value.length === 0) {
this.innerValue = []
this.reloading = true;
setTimeout(()=>{
this.reloading = false
},100)
}else{
this.initAreaData();
let arr = this.areaData.getRealCode(value);
} else {
this.initAreaData()
let arr = this.areaData.getRealCode(value)
this.innerValue = arr
}
this.reload()
},
/** 通过地区code获取子级 */
loadDataByCode(value) {
......
......@@ -196,9 +196,14 @@
if(!value){
this.$emit('change', '');
this.treeValue = ''
} else if (value instanceof Array) {
//this.$emit('change', value.map(item => item.value).join(','))
//this.treeValue = value
} else if (Array.isArray(value)) {
let labels = []
let values = value.map(item => {
labels.push(item.label)
return item.value
})
this.backValue(values.join(','), labels.join(','))
this.treeValue = value
} else {
this.backValue(value.value,value.label)
this.treeValue = value
......
......@@ -46,6 +46,8 @@
import 'codemirror/mode/swift/swift.js'
import 'codemirror/mode/vue/vue.js'
import { isIE11, isIE } from '@/utils/browser'
// 尝试获取全局实例
const CodeMirror = window.CodeMirror || _CodeMirror
......@@ -85,7 +87,21 @@
zIndex: {
type: [Number, String],
default: 999
}
},
// 是否自适应高度,可以传String或Boolean
// 传 String 类型只能写"!ie" ,
// 填写这个字符串,代表其他浏览器自适应高度
// 唯独IE下不自适应高度,因为IE下不支持min、max-height样式
// 如果填写的不是"!ie"就视为true
autoHeight: {
type: [String, Boolean],
default: true
},
// 不自适应高度的情况下生效的固定高度
height: {
type: [String, Number],
default: '240px'
},
},
data () {
return {
......@@ -217,14 +233,30 @@
hintOptions: this.options.hintOptions
}
},
fullScreenParentProps(){
isAutoHeight() {
let {autoHeight} = this
if (typeof autoHeight === 'string' && autoHeight.toLowerCase().trim() === '!ie') {
autoHeight = !(isIE() || isIE11())
} else {
autoHeight = true
}
return autoHeight
},
fullScreenParentProps() {
let props = {
class: ['full-screen-parent', this.fullCoder ? 'full-screen' : ''],
class: {
'full-screen-parent': true,
'full-screen': this.fullCoder,
'auto-height': this.isAutoHeight
},
style: {}
}
if (this.fullCoder) {
props.style['z-index'] = this.zIndex
}
if (!this.isAutoHeight) {
props.style['height'] = (typeof this.height === 'number' ? this.height + 'px' : this.height)
}
return props
}
},
......@@ -240,7 +272,8 @@
// 编辑器赋值
if(this.value||this.code){
this.hasCode=true
this.coder.setValue(this.value || this.code)
//this.coder.setValue(this.value || this.code)
this.setCodeContent(this.value || this.code)
}else{
this.coder.setValue('')
this.hasCode=false
......@@ -408,6 +441,7 @@
top: 12px;
right: 12px;
}
.full-screen-child {
height: 100%;
max-height: 100%;
......@@ -416,9 +450,22 @@
}
.full-screen-child {
min-height: 120px;
max-height: 320px;
overflow:hidden;
height: 100%;
}
&.auto-height {
.full-screen-child {
min-height: 120px;
max-height: 320px;
height: unset;
overflow: hidden;
}
&.full-screen .full-screen-child {
height: 100%;
max-height: 100%;
min-height: 100%;
}
}
}
......
<template>
<a-date-picker
dropdownClassName="j-date-picker"
:disabled="disabled || readOnly"
:placeholder="placeholder"
@change="handleDateChange"
......
<template>
<div class="tinymce-editor">
<editor
v-if="!reloading"
v-model="myValue"
:init="init"
:disabled="disabled"
......@@ -23,7 +24,9 @@
import 'tinymce/plugins/colorpicker'
import 'tinymce/plugins/textcolor'
import 'tinymce/plugins/fullscreen'
import 'tinymce/icons/default'
import { uploadAction,getFileAccessHttpUrl } from '@/api/manage'
import { getVmParentByName } from '@/utils/util'
export default {
components: {
Editor
......@@ -83,21 +86,51 @@
})
}
},
myValue: this.value
myValue: this.value,
reloading: false,
}
},
mounted() {
tinymce.init({})
this.initATabsChangeAutoReload()
},
methods: {
reload() {
this.reloading = true
this.$nextTick(() => this.reloading = false)
},
onClick(e) {
this.$emit('onClick', e, tinymce)
},
//可以添加一些自己的自定义事件,如清空内容
clear() {
this.myValue = ''
}
},
/**
* 自动判断父级是否是 <a-tabs/> 组件,然后添加事件监听,自动触发reload()
*
* 由于 tabs 组件切换会导致 tinymce 无法输入,
* 只有重新加载才能使用(无论是vue版的还是jQuery版tinymce都有这个通病)
*/
initATabsChangeAutoReload() {
// 获取父级
let tabs = getVmParentByName(this, 'ATabs')
let tabPane = getVmParentByName(this, 'ATabPane')
if (tabs && tabPane) {
// 用户自定义的 key
let currentKey = tabPane.$vnode.key
// 添加事件监听
tabs.$on('change', (key) => {
// 切换到自己时执行reload
if (currentKey === key) {
this.reload()
}
})
}
},
},
watch: {
value(newValue) {
......
......@@ -86,6 +86,9 @@
} else {
this.initFileList(val)
}
if(!val || val.length==0){
this.picUrl = false;
}
}
},
created(){
......
export default {
minHeight: '200px',
previewStyle: 'vertical',
useCommandShortcut: true,
useDefaultHTMLSanitizer: true,
usageStatistics: false,
hideModeSwitch: false,
toolbarItems: [
'heading',
'bold',
'italic',
'strike',
'divider',
'hr',
'quote',
'divider',
'ul',
'ol',
'task',
'indent',
'outdent',
'divider',
'table',
'image',
'link',
'divider',
'code',
'codeblock'
]
}
<template>
<div class="j-markdown-editor" :id="id"/>
</template>
<script>
import 'codemirror/lib/codemirror.css'
import '@toast-ui/editor/dist/toastui-editor.css';
import '@toast-ui/editor/dist/i18n/zh-cn';
import Editor from '@toast-ui/editor';
import defaultOptions from './default-options'
export default {
name: 'JMarkdownEditor',
props: {
value: {
type: String,
default: ''
},
id: {
type: String,
required: false,
default() {
return 'markdown-editor-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
}
},
options: {
type: Object,
default() {
return defaultOptions
}
},
mode: {
type: String,
default: 'markdown'
},
height: {
type: String,
required: false,
default: '300px'
},
language: {
type: String,
required: false,
default: 'zh-CN'
}
},
data() {
return {
editor: null
}
},
computed: {
editorOptions() {
const options = Object.assign({}, defaultOptions, this.options)
options.initialEditType = this.mode
options.height = this.height
options.language = this.language
return options
}
},
watch: {
value(newValue, preValue) {
if (newValue !== preValue && newValue !== this.editor.getMarkdown()) {
this.editor.setMarkdown(newValue)
}
},
language(val) {
this.destroyEditor()
this.initEditor()
},
height(newValue) {
this.editor.height(newValue)
},
mode(newValue) {
this.editor.changeMode(newValue)
}
},
mounted() {
this.initEditor()
},
destroyed() {
this.destroyEditor()
},
methods: {
initEditor() {
this.editor = new Editor({
el: document.getElementById(this.id),
...this.editorOptions
})
if (this.value) {
this.editor.setMarkdown(this.value)
}
this.editor.on('change', () => {
this.$emit('change', this.editor.getMarkdown())
})
},
destroyEditor() {
if (!this.editor) return
this.editor.off('change')
this.editor.remove()
},
setMarkdown(value) {
this.editor.setMarkdown(value)
},
getMarkdown() {
return this.editor.getMarkdown()
},
setHtml(value) {
this.editor.setHtml(value)
},
getHtml() {
return this.editor.getHtml()
}
},
model: {
prop: 'value',
event: 'change'
}
}
</script>
<style scoped lang="less">
.j-markdown-editor {
/deep/ .tui-editor-defaultUI {
.te-mode-switch,
.tui-scrollsync
{
line-height: 1.5;
}
}
}
</style>
\ No newline at end of file
......@@ -39,6 +39,7 @@
<script>
import { getClass, getStyle } from '@/utils/props-util'
import { triggerWindowResizeEvent } from '@/utils/util'
export default {
name: 'JModal',
......@@ -151,6 +152,7 @@
/** 切换全屏 */
toggleFullscreen() {
this.innerFullscreen = !this.innerFullscreen
triggerWindowResizeEvent()
},
}
......@@ -165,7 +167,12 @@
left: 0;
padding: 0;
height: 100vh;
// 兼容1.6.2版本的antdv
& .ant-modal {
top: 0;
padding: 0;
height: 100vh;
}
& .ant-modal-content {
height: 100vh;
......@@ -189,7 +196,6 @@
height: 100%;
}
}
}
.j-modal-title-row {
......@@ -208,12 +214,9 @@
&:hover {
color: rgba(0, 0, 0, 0.75);
}
}
}
}
}
@media (max-width: 767px) {
......
<template>
<div class="components-input-demo-presuffix" v-if="avalid">
<!---->
<a-input @click="openModal" :placeholder="placeholder" v-model="showText" readOnly :disabled="disabled">
<a-icon slot="prefix" type="cluster" :title="title"/>
<a-icon v-if="showText" slot="suffix" type="close-circle" @click="handleEmpty" title="清空"/>
</a-input>
<j-popup-onl-report
ref="jPopupOnlReport"
:code="code"
:multi="multi"
:groupId="uniqGroupId"
@ok="callBack"
/>
</div>
</template>
<script>
import JPopupOnlReport from './modal/JPopupOnlReport'
export default {
name: 'JPopup',
components: {
JPopupOnlReport
},
props: {
code: {
type: String,
default: '',
required: false
},
field: {
type: String,
default: '',
required: false
},
orgFields: {
type: String,
default: '',
required: false
},
destFields: {
type: String,
default: '',
required: false
},
width: {
type: Number,
default: 1200,
required: false
},
placeholder: {
type: String,
default: '请选择',
required: false
},
value: {
type: String,
required: false
},
triggerChange: {
type: Boolean,
required: false,
default: false
},
disabled: {
type: Boolean,
required: false,
default: false
},
multi: {
type: Boolean,
required: false,
default: false
},
/** 分组ID,用于将多个popup的请求合并到一起,不传不分组 */
groupId: String
},
data() {
return {
showText: '',
title: '',
avalid: true
}
},
computed: {
uniqGroupId() {
if (this.groupId) {
let { groupId, code, field, orgFields, destFields } = this
return `${groupId}_${code}_${field}_${orgFields}_${destFields}`
}
}
},
watch: {
value: {
immediate: true,
handler: function(val) {
if (!val) {
this.showText = ''
} else {
this.showText = val
}
}
}
},
created() {
},
mounted() {
if (!this.orgFields || !this.destFields || !this.code) {
this.$message.error('popup参数未正确配置!')
this.avalid = false
}
if (this.destFields.split(',').length != this.orgFields.split(',').length) {
this.$message.error('popup参数未正确配置,原始值和目标值数量不一致!')
this.avalid = false
}
},
methods: {
openModal() {
if (this.disabled === false) {
this.$refs.jPopupOnlReport.show()
}
},
handleEmpty() {
this.showText = ''
let destFieldsArr = this.destFields.split(',')
if (destFieldsArr.length === 0) {
return
}
let res = {}
for (let i = 0; i < destFieldsArr.length; i++) {
res[destFieldsArr[i]] = ''
}
if (this.triggerChange) {
this.$emit('callback', res)
} else {
this.$emit('input', '', res)
}
},
callBack(rows) {
// update--begin--autor:lvdandan-----date:20200630------for:多选时未带回多个值------
let orgFieldsArr = this.orgFields.split(',')
let destFieldsArr = this.destFields.split(',')
let resetText = false
if (this.field && this.field.length > 0) {
this.showText = ''
resetText = true
}
let res = {}
if (orgFieldsArr.length > 0) {
for (let i = 0; i < orgFieldsArr.length; i++) {
let tempDestArr = []
for(let rw of rows){
let val = rw[orgFieldsArr[i]]
if(!val){
val = ""
}
tempDestArr.push(val)
}
res[destFieldsArr[i]] = tempDestArr.join(",")
}
if (resetText === true) {
let tempText = []
for(let rw of rows){
let val = rw[orgFieldsArr[destFieldsArr.indexOf(this.field)]]
if(!val){
val = ""
}
tempText.push(val)
}
this.showText = tempText.join(",")
}
// update--end--autor:lvdandan-----date:20200630------for:多选时未带回多个值------
}
if (this.triggerChange) {
//v-dec时即triggerChange为true时 将整个对象给form页面 让他自己setFieldsValue
this.$emit('callback', res)
} else {
//v-model时 需要传一个参数field 表示当前这个字段 从而根据这个字段的顺序找到原始值
// this.$emit("input",row[orgFieldsArr[destFieldsArr.indexOf(this.field)]])
this.$emit('input', this.showText, res)
}
}
}
}
</script>
<style scoped>
.components-input-demo-presuffix .anticon-close-circle {
cursor: pointer;
color: #ccc;
transition: color 0.3s;
font-size: 12px;
}
.components-input-demo-presuffix .anticon-close-circle:hover {
color: #f5222d;
}
.components-input-demo-presuffix .anticon-close-circle:active {
color: #666;
}
</style>
\ No newline at end of file
......@@ -145,6 +145,10 @@
<j-date v-else-if=" item.type=='datetime' " v-model="item.val" placeholder="请选择时间" :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" style="width: 100%"></j-date>
<a-time-picker v-else-if="item.type==='time'" :value="item.val ? moment(item.val,'HH:mm:ss') : null" format="HH:mm:ss" style="width: 100%" @change="(time,value)=>item.val=value"/>
<a-input-number v-else-if=" item.type=='int'||item.type=='number' " style="width: 100%" placeholder="请输入数值" v-model="item.val"/>
<a-select v-else-if="item.type=='switch'" placeholder="请选择" v-model="item.val">
<a-select-option value="Y"></a-select-option>
<a-select-option value="N"></a-select-option>
</a-select>
<a-input v-else v-model="item.val" placeholder="请输入值"/>
</a-col>
......@@ -508,8 +512,17 @@
renderSaveTreeData(item) {
item.icon = this.treeIcon
item.originTitle = item['title']
item.title = (fn, vNode) => {
let { originTitle } = vNode.dataRef
item.title = (arg1, arg2) => {
let vNode
// 兼容旧版的Antdv
if (arg1.dataRef) {
vNode = arg1
} else if (arg2.dataRef) {
vNode = arg2
} else {
return <span style="color:red;">Antdv版本不支持</span>
}
let {originTitle} = vNode.dataRef
return (
<div class="j-history-tree-title">
<span>{originTitle}</span>
......
<template>
<a-switch v-model="checkStatus" :disabled="disabled" @change="handleChange"/>
<div>
<a-select v-if="query" style="width: 100%" @change="handleSelectChange">
<a-select-option v-for="(item, index) in queryOption" :key="index" :value="item.value">
{{ item.text }}
</a-select-option>
</a-select>
<a-switch v-else v-model="checkStatus" :disabled="disabled" @change="handleChange"/>
</div>
</template>
<script>
......@@ -7,7 +14,7 @@
name: 'JSwitch',
props: {
value:{
type: String,
type: String | Number,
required: false
},
disabled:{
......@@ -19,6 +26,11 @@
type:Array,
required:false,
default:()=>['Y','N']
},
query:{
type: Boolean,
required: false,
default: false
}
},
data () {
......@@ -30,23 +42,37 @@
value:{
immediate: true,
handler(val){
if(!val){
this.checkStatus = false
this.$emit('change', this.options[1]);
}else{
if(this.options[0]==val){
this.checkStatus = true
}else{
if(!this.query){
if(!val){
this.checkStatus = false
this.$emit('change', this.options[1]);
}else{
if(this.options[0]==val){
this.checkStatus = true
}else{
this.checkStatus = false
}
}
}
}
}
},
computed:{
queryOption(){
let arr = []
arr.push({value:this.options[0],text:'是'})
arr.push({value:this.options[1],text:'否'})
return arr;
}
},
methods: {
handleChange(checked){
let flag = checked===false?this.options[1]:this.options[0];
this.$emit('change', flag);
},
handleSelectChange(value){
this.$emit('change', value);
}
},
model: {
......
......@@ -121,7 +121,6 @@
getAction(this.url_root,param).then(res=>{
if(res.success){
this.handleTreeNodeValue(res.result)
console.log("aaaa",res.result)
this.treeData = [...res.result]
}else{
this.$message.error(res.message)
......
......@@ -236,7 +236,6 @@
}else{
try {
let test=JSON.parse(mycondition);
console.log("aaaaasdsdd",typeof test)
if(typeof test == 'object' && test){
resolve()
}else{
......
......@@ -225,7 +225,13 @@
let arr = [];
for(var a=0;a<uploadFiles.length;a++){
arr.push(uploadFiles[a].response.message)
// update-begin-author:lvdandan date:20200603 for:【TESTA-514】【开源issue】多个文件同时上传时,控制台报错
if(uploadFiles[a].status === 'done' ) {
arr.push(uploadFiles[a].response.message)
}else{
return;
}
// update-end-author:lvdandan date:20200603 for:【TESTA-514】【开源issue】多个文件同时上传时,控制台报错
}
if(arr.length>0){
path = arr.join(",")
......@@ -279,12 +285,18 @@
//returnUrl为false时返回文件名称、文件路径及文件大小
this.newFileList = [];
for(var a=0;a<fileList.length;a++){
var fileJson = {
fileName:fileList[a].name,
filePath:fileList[a].response.message,
fileSize:fileList[a].size
};
this.newFileList.push(fileJson);
// update-begin-author:lvdandan date:20200603 for:【TESTA-514】【开源issue】多个文件同时上传时,控制台报错
if(fileList[a].status === 'done' ) {
var fileJson = {
fileName:fileList[a].name,
filePath:fileList[a].response.message,
fileSize:fileList[a].size
};
this.newFileList.push(fileJson);
}else{
return;
}
// update-end-author:lvdandan date:20200603 for:【TESTA-514】【开源issue】多个文件同时上传时,控制台报错
}
this.$emit('change', this.newFileList);
}
......
# JPopup 弹窗选择组件
## 参数配置
| 参数 | 类型 | 必填 |说明|
|--------------|---------|----|---------|
| placeholder |string | | placeholder |
| code |string | | online报表编码 |
| orgFields |string | | online报表中显示的列,多个以逗号隔开 |
| destFields |string | | 回调对象的属性,多个以逗号隔开,其顺序和orgFields一一对应 |
| field |string | | v-model模式专用,表示从destFields中选择一个属性的值返回给当前组件 |
| triggerChange |Boolean | | v-decorator模式下需设置成true |
| callback(事件) |function | | 回调事件,v-decorator模式下用到,用于设置form控件的值 |
使用示例
----
```vue
<template>
<a-form :form="form">
<a-form-item label="v-model模式指定一个值返回至当前组件" style="width: 300px">
<j-popup
v-model="selectValue"
code="user_msg"
org-fields="username,realname"
dest-fields="popup,other"
field="popup"/>
{{ selectValue }}
</a-form-item>
<a-form-item label="v-decorator模式支持回调多个值至当前表单" style="width: 300px">
<j-popup
v-decorator="['one']"
:trigger-change="true"
code="user_msg"
org-fields="username,realname"
dest-fields="one,two"
@callback="popupCallback"/>
{{ getFormFieldValue('one') }}
</a-form-item>
<a-form-item label="v-decorator模式被回调的值" style="width: 300px">
<a-input v-decorator="['two']"></a-input>
</a-form-item>
</a-form >
</template>
<script>
export default {
data() {
return {
form: this.$form.createForm(this),
selectValue:"",
}
},
methods:{
getFormFieldValue(field){
return this.form.getFieldValue(field)
},
popupCallback(row){
this.form.setFieldsValue(row)
}
}
}
</script>
import JModal from './JModal'
import JFormContainer from './JFormContainer.vue'
import JPopup from './JPopup.vue'
export default {
install(Vue) {
Vue.component('JFormContainer', JFormContainer)
Vue.component('JPopup', JPopup)
Vue.component(JModal.name, JModal)
}
}
\ No newline at end of file
<template>
<a-popover trigger="contextmenu" v-model="visible" :placement="position">
<a-popover trigger="contextmenu" v-model="visible" :placement="position" overlayClassName="j-input-pop">
<!--"(node) => node.parentNode.parentNode"-->
<div slot="title">
<span>{{ title }}</span>
......@@ -7,11 +7,11 @@
<a-icon type="close" @click="visible=false"/>
</span>
</div>
<a-input :value="inputContent" @change="handleInputChange">
<a-input :value="inputContent" :disabled="disabled" @change="handleInputChange">
<a-icon slot="suffix" type="fullscreen" @click.stop="pop" />
</a-input>
<div slot="content">
<textarea :value="inputContent" @input="handleInputChange" :style="{ height: height + 'px', width: width + 'px' }"></textarea>
<textarea :value="inputContent" :disabled="disabled" @input="handleInputChange" :style="{ height: height + 'px', width: width + 'px' }"></textarea>
</div>
</a-popover>
</template>
......@@ -48,7 +48,11 @@
type:String,
default:'',
required:false
}
},
disabled: {
type: Boolean,
default: false,
},
},
data(){
......
<template>
<a-modal
<j-modal
centered
:title="name + '选择'"
:width="width"
:visible="visible"
switchFullscreen
@ok="handleOk"
@cancel="close"
cancelText="关闭">
......@@ -32,7 +33,7 @@
</div>
<a-table
size="small"
size="middle"
bordered
:rowKey="rowKey"
:columns="innerColumns"
......@@ -49,7 +50,7 @@
<a-col :span="8">
<a-card :title="'已选' + name" :bordered="false" :head-style="{padding:0}" :body-style="{padding:0}">
<a-table size="small" :rowKey="rowKey" bordered v-bind="selectedTable">
<a-table size="middle" :rowKey="rowKey" bordered v-bind="selectedTable">
<span slot="action" slot-scope="text, record, index">
<a @click="handleDeleteSelected(record, index)">删除</a>
</span>
......@@ -58,7 +59,7 @@
</a-card>
</a-col>
</a-row>
</a-modal>
</j-modal>
</template>
<script>
......
......@@ -118,10 +118,12 @@
deep: true,
handler(val) {
let rows = val.map(key => this.dataSourceMap[key])
this.$emit('select', rows)
let data = val.join(',')
this.$emit('input', data)
this.$emit('change', data)
if (data !== this.value) {
this.$emit('select', rows)
this.$emit('input', data)
this.$emit('change', data)
}
}
}
},
......
......@@ -76,6 +76,18 @@
methods:{
initComp(departNames){
this.departNames = departNames
//update-begin-author:lvdandan date:20200513 for:TESTA-438 部门选择组件自定义返回值,数据无法回填
//TODO 当返回字段为部门名称时会有问题,因为部门名称不唯一
//返回字段不为id时,根据返回字段获取id
if(this.customReturnField !== 'id' && this.value){
const dataList = this.$refs.innerDepartSelectModal.dataList;
console.log('this.value',this.value)
this.departIds = this.value.split(',').map(item => {
const data = dataList.filter(d=>d[this.customReturnField] === item)
return data.length > 0 ? data[0].id : ''
}).join(',')
}
//update-end-author:lvdandan date:20200513 for:TESTA-438 部门选择组件自定义返回值,数据无法回填
},
openModal(){
this.$refs.innerDepartSelectModal.show()
......
......@@ -19,7 +19,7 @@
import JSelectBizComponent from './JSelectBizComponent'
export default {
name: 'JSelectMultiUser',
name: 'JSelectRole',
components: { JSelectBizComponent },
props: ['value'],
data() {
......
<template>
<a-modal
<j-modal
title="选择部门"
:width="modalWidth"
:visible="visible"
:confirmLoading="confirmLoading"
@ok="handleSubmit"
@cancel="handleCancel"
switchFullscreen
cancelText="关闭">
<a-spin tip="Loading..." :spinning="false">
<a-input-search style="margin-bottom: 1px" placeholder="请输入部门名称按回车进行搜索" @search="onSearch" />
......@@ -31,7 +32,7 @@
</a-tree>
</a-spin>
</a-modal>
</j-modal>
</template>
<script>
......
<template>
<a-modal
<j-modal
:width="modalWidth"
:visible="visible"
:title="title"
switchFullscreen
@ok="handleSubmit"
@cancel="close"
style="top:50px"
cancelText="关闭"
style="margin-top: -70px"
wrapClassName="ant-modal-cust-warp"
>
<a-row :gutter="10" style="background-color: #ececec; padding: 10px; margin: -10px">
<a-col :md="6" :sm="24">
......@@ -51,7 +51,7 @@
</a-card>
</a-col>
</a-row>
</a-modal>
</j-modal>
</template>
<script>
......
......@@ -82,16 +82,19 @@
if (this.$route.path != indexKey) {
this.addIndexToFirst()
}
// 复制一个route对象出来,不能影响原route
let currentRoute = Object.assign({}, this.$route)
currentRoute.meta = Object.assign({}, currentRoute.meta)
// update-begin-author:sunjianlei date:20191223 for: 修复刷新后菜单Tab名字显示异常
let storeKey = 'route:title:' + this.$route.fullPath
let storeKey = 'route:title:' + currentRoute.fullPath
let routeTitle = this.$ls.get(storeKey)
if (routeTitle) {
this.$route.meta.title = routeTitle
currentRoute.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
this.pageList.push(currentRoute)
this.linkList.push(currentRoute.fullPath)
this.activePage = currentRoute.fullPath
},
mounted() {
},
......@@ -126,8 +129,11 @@
'activePage': function(key) {
let index = this.linkList.lastIndexOf(key)
let waitRouter = this.pageList[index]
this.$router.push(Object.assign({},waitRouter));
this.changeTitle(waitRouter.meta.title)
// 【TESTA-523】修复:不允许重复跳转路由异常
if (waitRouter.fullPath !== this.$route.fullPath) {
this.$router.push(Object.assign({}, waitRouter))
this.changeTitle(waitRouter.meta.title)
}
},
'multipage': function(newVal) {
if(this.reloadFlag){
......@@ -352,7 +358,7 @@
}
.ant-tabs {
.tab-layout-tabs.ant-tabs {
&.ant-tabs-card .ant-tabs-tab {
......@@ -380,7 +386,7 @@
}
.ant-tabs.ant-tabs-card > .ant-tabs-bar {
.tab-layout-tabs.ant-tabs.ant-tabs-card > .ant-tabs-bar {
.ant-tabs-tab {
border: none !important;
border-bottom: 1px solid transparent !important;
......
......@@ -43,6 +43,7 @@
</div>
</div>
</a-layout-header>
</template>
......@@ -58,7 +59,7 @@
components: {
UserMenu,
SMenu,
Logo
Logo,
},
mixins: [mixin],
props: {
......@@ -96,7 +97,8 @@
topNavHeader: {},
headerIndexRight: {},
topSmenuStyle: {}
}
},
chatStatus: '',
}
},
watch: {
......
......@@ -131,10 +131,10 @@
//this.menus = this.mainRouters.find((item) => item.path === '/').children;
this.menus = this.permissionMenuList
// 根据后台配置菜单,重新排序加载路由信息
console.log('----加载菜单逻辑----')
console.log(this.mainRouters)
console.log(this.permissionMenuList)
console.log('----navTheme------'+this.navTheme)
//console.log('----加载菜单逻辑----')
//console.log(this.mainRouters)
//console.log(this.permissionMenuList)
//console.log('----navTheme------'+this.navTheme)
//--update-end----author:scott---date:20190320------for:根据后台菜单配置,判断是否路由菜单字段,动态选择是否生成路由(为了支持参数URL菜单)------
},
methods: {
......
......@@ -124,7 +124,7 @@
// this.heartCheckFun();
},
destroyed: function () { // 离开页面生命周期函数
this.websocketclose();
this.websocketOnclose();
},
methods: {
timerFun() {
......@@ -186,10 +186,8 @@
}
},
toMyAnnouncement(){
this.$router.push({
path: '/isps/userAnnouncement',
name: 'isps-userAnnouncement'
path: '/isps/userAnnouncement'
});
},
modalFormOk(){
......@@ -202,7 +200,7 @@
// WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
var userId = store.getters.userInfo.id;
var url = window._CONFIG['domianURL'].replace("https://","wss://").replace("http://","ws://")+"/websocket/"+userId;
console.log(url);
//console.log(url);
this.websock = new WebSocket(url);
this.websock.onopen = this.websocketOnopen;
this.websock.onerror = this.websocketOnerror;
......@@ -232,7 +230,10 @@
//this.heartCheck.reset().start();
},
websocketOnclose: function (e) {
console.log("connection closed (" + e.code + ")");
console.log("connection closed (" + e + ")");
if(e){
console.log("connection closed (" + e.code + ")");
}
this.reconnect();
},
websocketSend(text) { // 数据发送
......
......@@ -62,6 +62,10 @@
<a-icon type="cluster"/>
<span>切换部门</span>
</a-menu-item>
<a-menu-item key="6" @click="clearCache">
<a-icon type="sync"/>
<span>清理缓存</span>
</a-menu-item>
<!-- <a-menu-item key="2" disabled>
<a-icon type="setting"/>
<span>测试</span>
......@@ -94,7 +98,9 @@
import DepartSelect from './DepartSelect'
import { mapActions, mapGetters,mapState } from 'vuex'
import { mixinDevice } from '@/utils/mixin.js'
import { getFileAccessHttpUrl } from "@/api/manage"
import { getFileAccessHttpUrl,getAction } from "@/api/manage"
import Vue from 'vue'
import { UI_CACHE_DB_DICT_DATA } from "@/store/mutation-types"
export default {
name: "UserMenu",
......@@ -168,7 +174,9 @@
content: '真的要注销登录吗 ?',
onOk() {
return that.Logout({}).then(() => {
window.location.href="/";
// update-begin author:wangshuai date:20200601 for: 退出登录跳转登录页面
that.$router.push({ path: '/user/login' });
// update-end author:wangshuai date:20200601 for: 退出登录跳转登录页面
//window.location.reload()
}).catch(err => {
that.$message.error({
......@@ -214,9 +222,28 @@
this.$router.push({ path: route.path })
}
this.searchMenuVisible = false
}
},
// update_end author:sunjianlei date:20191230 for: 解决外部链接打开失败的问题
/*update_end author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
/*update_begin author:liushaoqian date:20200507 for: 刷新缓存*/
clearCache(){
getAction("sys/dict/refleshCache").then((res) => {
if (res.success) {
//重新加载缓存
getAction("sys/dict/queryAllDictItems").then((res) => {
if (res.success) {
Vue.ls.remove(UI_CACHE_DB_DICT_DATA)
Vue.ls.set(UI_CACHE_DB_DICT_DATA, res.result, 7 * 24 * 60 * 60 * 1000)
}
})
this.$message.success("刷新缓存完成!");
}
}).catch(e=>{
this.$message.warn("刷新缓存失败!");
console.log("刷新失败",e)
})
}
/*update_end author:liushaoqian date:20200507 for: 刷新缓存*/
}
}
</script>
......
......@@ -64,7 +64,7 @@ const updateTheme = primaryColor => {
const lessConfigNode = document.createElement('script');
const lessScriptNode = document.createElement('script');
lessStyleNode.setAttribute('rel', 'stylesheet/less');
lessStyleNode.setAttribute('href', '/color.less');
lessStyleNode.setAttribute('href', __webpack_public_path__ + 'color.less')
lessConfigNode.innerHTML = `
window.less = {
async: true,
......
......@@ -17,8 +17,8 @@ import Print from 'vue-print-nb-jeecg'
import preview from 'vue-photo-preview'
import 'vue-photo-preview/dist/skin.css'
require('@jeecg/antd-online-beta220')
require('@jeecg/antd-online-beta220/dist/OnlineForm.css')
require('@jeecg/antd-online-mini')
require('@jeecg/antd-online-mini/dist/OnlineForm.css')
import {
ACCESS_TOKEN,
......
......@@ -297,7 +297,8 @@ export const JeecgListMixin = {
return getFileAccessHttpUrl(text)
},
/* 文件下载 */
uploadFile(text){
// update--autor:lvdandan-----date:20200630------for:修改下载文件方法名uploadFile改为downloadFile------
downloadFile(text){
if(!text){
this.$message.warning("未知的文件")
return;
......
import store from '@/store/'
export const WebsocketMixin = {
mounted() {
this.initWebSocket();
},
destroyed: function () {
// 离开页面生命周期函数
this.websocketOnclose();
},
methods:{
initWebSocket: function () {
console.log("------------WebSocket连接成功");
// WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
var userId = store.getters.userInfo.id;
if(!this.socketUrl.startsWith('/')){
this.socketUrl = '/' + this.socketUrl
}
if(!this.socketUrl.endsWith('/')){
this.socketUrl = this.socketUrl + '/'
}
var url = window._CONFIG['domianURL'].replace("https://","wss://").replace("http://","ws://") + this.socketUrl + userId;
this.websock = new WebSocket(url);
this.websock.onopen = this.websocketOnopen;
this.websock.onerror = this.websocketOnerror;
this.websock.onmessage = this.websocketOnmessage;
this.websock.onclose = this.websocketOnclose;
},
websocketOnopen: function () {
console.log("WebSocket连接成功");
},
websocketOnerror: function (e) {
console.log("WebSocket连接发生错误");
this.reconnect();
},
websocketOnclose: function (e) {
this.reconnect();
},
websocketSend(text) {
// 数据发送
try {
this.websock.send(text);
} catch (err) {
console.log("send failed (" + err.code + ")");
}
},
reconnect() {
var that = this;
if(that.lockReconnect) return;
that.lockReconnect = true;
//没连接上会一直重连,设置延迟避免请求过多
setTimeout(function () {
console.info("尝试重连...");
that.initWebSocket();
that.lockReconnect = false;
}, 5000);
},
}
}
\ No newline at end of file
......@@ -23,7 +23,7 @@ router.beforeEach((to, from, next) => {
if (store.getters.permissionList.length === 0) {
store.dispatch('GetPermissionList').then(res => {
const menuData = res.result.menu;
console.log(res.message)
//console.log(res.message)
if (menuData === null || menuData === "" || menuData === undefined) {
return;
}
......
......@@ -2,16 +2,6 @@ import Vue from 'vue'
import Router from 'vue-router'
import { constantRouterMap } from '@/config/router.config'
//update-begin-author:taoyan date:20191011 for:TASK #3214 【优化】访问online功能测试 浏览器控制台抛出异常
try {
const originalPush = Router.prototype.push
Router.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err)
}
} catch (e) {
}
//update-end-author:taoyan date:20191011 for:TASK #3214 【优化】访问online功能测试 浏览器控制台抛出异常
Vue.use(Router)
export default new Router({
......
......@@ -60,7 +60,7 @@ const permission = {
SET_ROUTERS: (state, data) => {
state.addRouters = data
state.routers = constantRouterMap.concat(data)
console.log('-----mutations---SET_ROUTERS----', data)
//console.log('-----mutations---SET_ROUTERS----', data)
}
},
actions: {
......
import Vue from 'vue'
import { login, logout, phoneLogin, thirdLogin } from "@/api/login"
import { ACCESS_TOKEN, USER_NAME,USER_INFO,USER_AUTH,SYS_BUTTON_AUTH,UI_CACHE_DB_DICT_DATA } from "@/store/mutation-types"
import { ACCESS_TOKEN, USER_NAME,USER_INFO,USER_AUTH,SYS_BUTTON_AUTH,UI_CACHE_DB_DICT_DATA,TENANT_ID } from "@/store/mutation-types"
import { welcome } from "@/utils/util"
import { queryPermissionsByUser } from '@/api/api'
import { getAction } from '@/api/manage'
......@@ -10,6 +10,7 @@ const user = {
token: '',
username: '',
realname: '',
tenantid:'',
welcome: '',
avatar: '',
permissionList: [],
......@@ -34,6 +35,9 @@ const user = {
SET_INFO: (state, info) => {
state.info = info
},
SET_TENANT: (state, id) => {
state.tenantid = id
},
},
actions: {
......@@ -133,7 +137,7 @@ const user = {
}
}
})
console.log(" menu show json ", menuData)
//console.log(" menu show json ", menuData)
//update--end--autor:qinfeng-----date:20200109------for:JEECG-63 一级菜单的子菜单全部是隐藏路由,则一级菜单不显示------
commit('SET_PERMISSIONLIST', menuData)
} else {
......@@ -188,6 +192,11 @@ const user = {
})
})
},
saveTenant({ commit }, id){
Vue.ls.set(TENANT_ID, id, 7 * 24 * 60 * 60 * 1000)
commit('SET_TENANT', id)
}
}
}
......
......@@ -17,6 +17,7 @@ export const ENCRYPTED_STRING = 'ENCRYPTED_STRING'
export const ENHANCE_PRE = 'enhance_'
export const UI_CACHE_DB_DICT_DATA = 'UI_CACHE_DB_DICT_DATA'
export const INDEX_MAIN_PAGE_PATH = "/dashboard/analysis"
export const TENANT_ID = 'TENANT_ID'
export const CONTENT_WIDTH_TYPE = {
Fluid: 'Fluid',
......
import { getVmParentByName } from '@/utils/util'
const FormTypes = {
normal: 'normal',
input: 'input',
......@@ -88,7 +90,7 @@ export function validateTables(cases, deleteTempId) {
return new Promise((resolve, reject) => {
let tables = []
let index = 0;
if(!cases || cases.length==0){
if(!cases || cases.length === 0){
resolve()
}
(function next() {
......@@ -104,7 +106,13 @@ export function validateTables(cases, deleteTempId) {
}, error => {
// 出现未验证通过的表单,不再进行下一步校验,直接返回失败并跳转到该表格
if (error === VALIDATE_NO_PASSED) {
reject({ error: VALIDATE_NO_PASSED, index })
// 尝试获取tabKey,如果在ATab组件内即可获取
let paneKey;
let tabPane = getVmParentByName(vm, 'ATabPane')
if (tabPane) {
paneKey = tabPane.$vnode.key
}
reject({error: VALIDATE_NO_PASSED, index, paneKey})
}
reject(error)
})
......
//判断是否IE<11浏览器
export function isIE() {
return navigator.userAgent.indexOf('compatible') > -1 && navigator.userAgent.indexOf('MSIE') > -1
}
export function isIE11() {
return navigator.userAgent.indexOf('Trident') > -1 && navigator.userAgent.indexOf('rv:11.0') > -1
}
//判断是否IE的Edge浏览器
export function isEdge() {
return navigator.userAgent.indexOf('Edge') > -1 && !isIE()
}
export function getIEVersion() {
let userAgent = navigator.userAgent //取得浏览器的userAgent字符串
let isIE = isIE()
let isIE11 = isIE11()
let isEdge = isEdge()
if (isIE) {
let reIE = new RegExp('MSIE (\\d+\\.\\d+);')
reIE.test(userAgent)
let fIEVersion = parseFloat(RegExp['$1'])
if (fIEVersion === 7 || fIEVersion === 8 || fIEVersion === 9 || fIEVersion === 10) {
return fIEVersion
} else {
return 6//IE版本<7
}
} else if (isEdge) {
return 'edge'
} else if (isIE11) {
return 11
} else {
return -1
}
}
\ No newline at end of file
......@@ -2,7 +2,7 @@ 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("页面权限控制----");
......
......@@ -3,7 +3,7 @@ import axios from 'axios'
import store from '@/store'
import { VueAxios } from './axios'
import {Modal, notification} from 'ant-design-vue'
import { ACCESS_TOKEN } from "@/store/mutation-types"
import { ACCESS_TOKEN, TENANT_ID } from "@/store/mutation-types"
/**
* 【指定 axios的 baseURL】
......@@ -12,7 +12,7 @@ import { ACCESS_TOKEN } from "@/store/mutation-types"
* @type {*|string}
*/
let apiBaseUrl = window._CONFIG['domianURL'] || "/jeecg-boot";
console.log("apiBaseUrl= ",apiBaseUrl)
//console.log("apiBaseUrl= ",apiBaseUrl)
// 创建 axios 实例
const service = axios.create({
//baseURL: '/jeecg-boot',
......@@ -22,6 +22,7 @@ const service = axios.create({
const err = (error) => {
if (error.response) {
let that=this;
let data = error.response.data
const token = Vue.ls.get(ACCESS_TOKEN)
console.log("------异常响应------",token)
......@@ -45,7 +46,14 @@ const err = (error) => {
onOk: () => {
store.dispatch('Logout').then(() => {
Vue.ls.remove(ACCESS_TOKEN)
window.location.reload()
try {
let path=that.$route.path;
if(path.indexOf('/user/login')==-1){
window.location.reload()
}
}catch (e) {
window.location.reload()
}
})
}
})
......@@ -86,6 +94,13 @@ service.interceptors.request.use(config => {
if (token) {
config.headers[ 'X-Access-Token' ] = token // 让每个请求携带自定义 token 请根据实际情况自行修改
}
//update-begin-author:taoyan date:2020707 for:多租户
let tenantid = Vue.ls.get(TENANT_ID)
if (!tenantid) {
tenantid = 0;
}
config.headers[ 'tenant_id' ] = tenantid
//update-end-author:taoyan date:2020707 for:多租户
if(config.method=='get'){
if(config.url.indexOf("sys/dict/getDictItems")<0){
config.params = {
......
import * as api from '@/api/api'
import { isURL } from '@/utils/validate'
import onlineCommons from '@jeecg/antd-online-beta220'
import onlineCommons from '@jeecg/antd-online-mini'
export function timeFix() {
const time = new Date()
......@@ -115,7 +115,6 @@ function generateChildRouters (data) {
item.meta.url = URL;
}
//online菜单路由加载逻辑
let componentPath
if(item.component=="modules/online/cgform/OnlCgformHeadList"){
componentPath = onlineCommons.OnlCgformHeadList
......@@ -137,6 +136,7 @@ function generateChildRouters (data) {
componentPath = resolve => require(['@/' + component+'.vue'], resolve)
}
let menu = {
path: item.path,
name: item.name,
......@@ -478,3 +478,53 @@ export function replaceAll(text, checker, replacer) {
}
return text
}
/**
* 获取事件冒泡路径,兼容 IE11,Edge,Chrome,Firefox,Safari
* 目前使用的地方:JEditableTable Span模式
*/
export function getEventPath(event) {
let target = event.target
let path = (event.composedPath && event.composedPath()) || event.path
if (path != null) {
return (path.indexOf(window) < 0) ? path.concat(window) : path
}
if (target === window) {
return [window]
}
let getParents = (node, memo) => {
memo = memo || []
const parentNode = node.parentNode
if (!parentNode) {
return memo
} else {
return getParents(parentNode, memo.concat(parentNode))
}
}
return [target].concat(getParents(target), window)
}
/**
* 根据组件名获取父级
* @param vm
* @param name
* @returns {Vue | null|null|Vue}
*/
export function getVmParentByName(vm, name) {
let parent = vm.$parent
if (parent && parent.$options) {
if (parent.$options.name === name) {
return parent
} else {
let res = getVmParentByName(parent, name)
if (res) {
return res
}
}
}
return null
}
\ No newline at end of file
......@@ -7,7 +7,7 @@
<a-icon type="info-circle-o" />
</a-tooltip>
<div>
<mini-area :datasource="chartData.sll" />
<mini-area :data-source="chartData.sll" />
</div>
<template slot="footer">今日受理量:<span>{{ todaySll }}</span></template>
</chart-card>
......@@ -18,7 +18,7 @@
<a-icon type="info-circle-o" />
</a-tooltip>
<div>
<mini-area :datasource="chartData.bjl"/>
<mini-area :data-source="chartData.bjl"/>
</div>
<template slot="footer">今日办结量:<span>{{ todayBjl }}</span></template>
</chart-card>
......
......@@ -209,7 +209,6 @@
})
getVisitInfo().then(res=>{
if(res.success){
console.log("aaaaaa",res.result)
this.visitInfo = res.result;
}
})
......
......@@ -7,7 +7,7 @@ const types = {
404: {
img: 'https://gw.alipayobjects.com/zos/rmsportal/KpnpchXsobRgLElEozzI.svg',
title: '404',
desc: '抱歉,你访问的页面不存在或仍在开发中'
desc: '抱歉,你访问的页面不存在或无权访问'
},
500: {
img: 'https://gw.alipayobjects.com/zos/rmsportal/RVRUAYdCGeYNBWoKiIwB.svg',
......
......@@ -374,7 +374,7 @@
</a-col>
<a-col :span="12">输入的值(v-model):{{ formData.jInput }}</a-col>
</a-row>
<!-- <a-row :gutter="24">
<a-row :gutter="24">
<a-col :span="15">
<a-form-item label="MarkdownEditor" style="min-height: 300px">
<j-markdown-editor v-model="content"></j-markdown-editor>
......@@ -383,7 +383,7 @@
<a-col :span="9">
输入的值(v-model):{{ content }}
</a-col>
</a-row>-->
</a-row>
<!-- 省市县级联 -->
<a-row :gutter="24">
......@@ -456,12 +456,14 @@
import JMultiSelectTag from '@comp/dict/JMultiSelectTag'
import JInput from '@comp/jeecg/JInput'
import JAreaLinkage from '@comp/jeecg/JAreaLinkage'
import JMarkdownEditor from '@/components/jeecg/JMarkdownEditor/index'
import JSearchSelectTag from '@/components/dict/JSearchSelectTag'
export default {
name: 'SelectDemo',
inject:['closeCurrent'],
components: {
JMarkdownEditor,
JAreaLinkage,
JInput,
JCategorySelect,
......
......@@ -268,6 +268,9 @@
},
delRowCustom (index) {
console.log(index)
let all = this.form.getFieldsValue()
all['jeecgOrderCustomerList'].splice(index,1);
this.form.setFieldsValue(all)
this.orderMainModel.jeecgOrderCustomerList.splice(index,1);
this.$forceUpdate();
},
......@@ -278,6 +281,9 @@
},
delRowTicket (index) {
console.log(index)
let all = this.form.getFieldsValue()
all['jeecgOrderTicketList'].splice(index,1);
this.form.setFieldsValue(all)
this.orderMainModel.jeecgOrderTicketList.splice(index,1);
this.$forceUpdate();
},
......
......@@ -7,7 +7,7 @@
:closable="true"
@close="close"
:visible="visible"
style="height: calc(100% - 55px);overflow: auto;padding-bottom: 53px;">
style="overflow: auto;padding-bottom: 53px;">
<a-spin :spinning="confirmLoading">
<a-form :form="form">
......
......@@ -83,6 +83,7 @@
<a-dropdown>
<a class="ant-dropdown-link">更多 <a-icon type="down" /></a>
<a-menu slot="overlay">
<a-menu-item><a @click="executeImmediately(record)">立即执行</a></a-menu-item>
<a-menu-item><a @click="handleEdit(record)">编辑</a></a-menu-item>
<a-menu-item>
<a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
......@@ -192,6 +193,7 @@
resume: "/sys/quartzJob/resume",
exportXlsUrl: "sys/quartzJob/exportXls",
importExcelUrl: "sys/quartzJob/importExcel",
execute: "sys/quartzJob/execute"
},
}
},
......@@ -255,6 +257,25 @@
}
});
},
executeImmediately(record){
var that = this;
//立即执行定时任务
this.$confirm({
title:"确认提示",
content:"是否立即执行任务?",
onOk: function(){
getAction(that.url.execute,{id:record.id}).then((res)=>{
if(res.success){
that.$message.success(res.message);
that.loadData();
that.onClearSelected();
}else{
that.$message.warning(res.message);
}
});
}
});
}
}
}
</script>
......
......@@ -63,7 +63,6 @@
<a @click="handleOpen(record)">用户</a>
<a-divider type="vertical"/>
<a-dropdown>
<a class="ant-dropdown-link">
更多 <a-icon type="down"/>
......
......@@ -4,10 +4,10 @@
<!-- 操作按钮区域 -->
<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" :action="importExcelUrl" @change="handleImportExcel">
<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-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>
......
<template>
<a-card :bordered="false" style="height: 100%">
<div style="padding-bottom: 2px">
<a-alert type="warning" show-icon>
<div slot="message" style="width: 100%">
<span>路由配置请慎重</span>
<span style="display:inline-block;float:right;padding-right: 5px">
<a @click="clearRedis"><a-icon type="reload" />清除缓存</a>
</span>
</div>
</a-alert>
</div>
<div :id="eleId" :style="{ height: editorHeight + 'px', width: '100%' }"></div>
<div style="text-align: center;padding-top:10px">
<a-button type="primary" @click="submitForm" style="width:160px">保存</a-button>
</div>
</a-card>
</template>
<script>
import JsonEditor from 'jsoneditor'
import 'jsoneditor/dist/jsoneditor.min.css'
import { getAction, postAction } from '@/api/manage'
export default {
name: "SysGatewayRouteList",
data () {
return {
eleId:'jsoneditor',
description: 'gateway路由管理管理页面',
editor: null,
editorWidth:400,
editorHeight:500,
url:{
list: '/sys/gatewayRoute/list',
update: '/sys/gatewayRoute/updateAll',
clear: '/sys/gatewayRoute/clearRedis'
},
}
},
created() {
let winWidth = window.innerWidth;
console.log("页面宽度",winWidth)
this.editorWidth = winWidth
},
mounted(){
this.initJsonEditor();
},
methods: {
initJsonEditor() {
let container = document.getElementById(this.eleId);
let options = {
modes: ['text', 'code', 'tree', 'form', 'view'],
mode: 'tree',
ace: ace,
sortObjectKeys: 'code',
mainMenuBar:['format']
};
this.editor = new JsonEditor(container, options);
this.initRouteData();
},
initRouteData(){
getAction(this.url.list).then(res=>{
if(res.success){
let array = res.result
console.log('当前路由配置信息为', array)
this.editor.set(array)
}
})
},
// 获取json
submitForm() {
let text = this.editor.getText()
console.log("保存的json数据",text)
if(!text || text.length<=0 || text=='{}' || text=='[]'){
this.$message.warning('未录入任何信息')
return ;
}
postAction(this.url.update,{
routes:text
}).then(res=>{
if(res.success){
this.$message.success(res.message)
}else{
this.$message.error(res.message)
}
})
},
clearRedis(){
getAction(this.url.clear).then(res=>{
if(res.success){
this.$message.success(res.message)
}
})
}
}
}
</script>
<template>
<a-card :bordered="false">
<!-- 查询区域 -->
<div class="table-page-search-wrapper">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
</a-row>
</a-form>
</div>
<!-- 查询区域-END -->
<!-- 操作按钮区域 -->
<div class="table-operator">
<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"
:scroll="{x:true}"
bordered
rowKey="id"
:columns="columns"
:dataSource="dataSource"
:pagination="ipagination"
:loading="loading"
:rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
class="j-table-force-nowrap"
@change="handleTableChange">
<template slot="htmlSlot" slot-scope="text">
<div v-html="text"></div>
</template>
<template slot="imgSlot" slot-scope="text">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无图片</span>
<img v-else :src="getImgView(text)" height="25px" alt="" style="max-width:80px;font-size: 12px;font-style: italic;"/>
</template>
<template slot="fileSlot" slot-scope="text">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
<a-button
v-else
:ghost="true"
type="primary"
icon="download"
size="small"
@click="uploadFile(text)">
下载
</a-button>
</template>
<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 @click="handleDetail(record)">详情</a>
</a-menu-item>
<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>
<tenant-modal ref="modalForm" @ok="modalFormOk"></tenant-modal>
</a-card>
</template>
<script>
import '@/assets/less/TableExpand.less'
import { mixinDevice } from '@/utils/mixin'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import TenantModal from './modules/TenantModal'
export default {
name: "TenantList",
mixins:[JeecgListMixin, mixinDevice],
components: {
TenantModal
},
data () {
return {
description: 'adad管理页面',
// 表头
columns: [
{
title:'租户名称',
align:"center",
dataIndex: 'name'
},{
title:'租户编号',
align:"center",
dataIndex: 'id'
},
{
title:'开始时间',
align:"center",
dataIndex: 'beginDate'
},
{
title:'结束时间',
align:"center",
dataIndex: 'endDate'
},
{
title:'状态',
align:"center",
dataIndex: 'status_dictText'
},
{
title: '操作',
dataIndex: 'action',
align:"center",
fixed:"right",
width:147,
scopedSlots: { customRender: 'action' }
}
],
url: {
list: "/sys/tenant/list",
delete: "/sys/tenant/delete",
deleteBatch: "/sys/tenant/deleteBatch"
},
dictOptions:{},
}
},
created() {
},
computed: {
importExcelUrl: function(){
return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;
},
},
methods: {
initDictConfig(){
}
}
}
</script>
<style scoped>
@import '~@assets/less/common.less';
</style>
\ No newline at end of file
......@@ -119,10 +119,9 @@
</template>
<span slot="action" slot-scope="text, record">
<!-- <a @click="handleEdit(record)" v-has="'user:edit'">编辑</a>-->
<a @click="handleEdit(record)">编辑</a>
<a @click="handleEdit(record)" >编辑</a>
<a-divider type="vertical"/>
<a-divider type="vertical" />
<a-dropdown>
<a class="ant-dropdown-link">
......@@ -260,13 +259,7 @@
title: '部门',
align: "center",
width: 180,
dataIndex: 'orgCode'
},
{
title: '负责部门',
align: "center",
width: 180,
dataIndex: 'departIds_dictText'
dataIndex: 'orgCodeTxt'
},
{
title: '状态',
......
<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>
<a-spin :spinning="loading">
<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>
</a-spin>
<div class="anty-form-btn">
<a-dropdown style="float: left" :trigger="['click']" placement="topCenter">
<a-menu slot="overlay">
......@@ -156,6 +158,7 @@
this.form.resetFields()
},
loadData(){
this.loading = true;
queryTreeListForRole().then((res) => {
this.treeData = res.result.treeList
this.allTreeKeys = res.result.ids
......@@ -176,6 +179,7 @@
this.halfCheckedKeys = [...halfCheckedKeys]
this.defaultCheckedKeys = [...halfCheckedKeys, ...checkedKeys];
this.expandedKeysss = this.allTreeKeys;
this.loading = false;
})
})
}
......
......@@ -7,7 +7,7 @@
:closable="true"
@close="close"
:visible="visible"
style="height: calc(100% - 55px);overflow: auto;padding-bottom: 53px;">
style="overflow: auto;padding-bottom: 53px;">
<a-form>
<a-form-item label='所拥有的部门权限'>
......
......@@ -7,7 +7,7 @@
:closable="true"
@close="close"
:visible="visible"
style="height: calc(100% - 55px);overflow: auto;padding-bottom: 53px;">
style="overflow: auto;padding-bottom: 53px;">
<a-spin :spinning="confirmLoading">
......@@ -102,7 +102,7 @@
this.form.resetFields();
this.model = Object.assign({}, record);
this.visible = true;
getAction(this.url.getDeptRoleByUserId,{userId:this.userId}).then((res) => {
getAction(this.url.getDeptRoleByUserId,{userId:this.userId,departId:this.currentDeptId}).then((res) => {
if (res.success) {
var designName = [];
for (let value of res.result) {
......
......@@ -183,7 +183,7 @@
that.selectionRows=[];
selectUser.forEach(function(record,index){
console.log(record)
that.selectionRows.push({id: that.selectedRowKeys[index],realname:record})
that.selectionRows.push({id: that.selectedRowKeys[index],realname:record.label})
})
// this.selectionRows = selectUser;
}
......
......@@ -108,8 +108,10 @@
<a-select
mode="multiple"
placeholder="请选择用户"
:labelInValue=true
v-model="selectedUser"
@dropdownVisibleChange="selectUserIds"
@change="handleChange"
>
</a-select>
</a-form-item>
......@@ -166,7 +168,6 @@
xs: { span: 24 },
sm: { span: 21 },
},
confirmLoading: false,
form: this.$form.createForm(this),
validatorRules:{
......@@ -187,6 +188,7 @@
selectedUser:[],
disabled:false,
msgContent:"",
userList:[]
}
},
created () {
......@@ -210,15 +212,22 @@
this.userIds = record.userIds;
getAction(this.url.queryByIds,{userIds:this.userIds}).then((res)=>{
if(res.success){
//update--begin--autor:wangshuai-----date:20200601------for:系统公告选人后,不能删除------
var userList=[];
for(var i=0;i<res.result.length;i++){
this.selectedUser.push(res.result[i].realname);
var user={};
user.label =res.result[i].realname;
user.key=res.result[i].id;
userList.push(user);
}
this.selectedUser=userList;
//update--begin--autor:wangshuai-----date:20200601------for:系统公告选人后,不能删除------
this.$refs.UserListModal.edit(res.result,this.userIds);
}
});
}
this.$nextTick(() => {
this.form.setFieldsValue(pick(this.model,'endTime','startTime','titile','msgContent','sender','priority','msgCategory','msgType','sendStatus','delFlag','msgAbstract'))
this.form.setFieldsValue(pick(this.model,'endTime','startTime','titile','msgContent','priority','msgCategory','msgType','sendStatus','msgAbstract'))
});
},
close () {
......@@ -298,7 +307,12 @@
this.selectedUser = [];
this.userIds = [];
for(var i=0;i<userList.length;i++){
this.selectedUser.push(userList[i].realname);
//update--begin--autor:wangshuai-----date:20200601------for:系统公告选人后,不能删除------
var user={};
user.label =userList[i].realname;
user.key=userList[i].id;
this.selectedUser.push(user);
//update--end--autor:wangshuai-----date:20200601------for:系统公告选人后,不能删除------
this.userIds += userList[i].id+","
}
},
......@@ -321,8 +335,21 @@
}else{
callback("结束时间需大于开始时间")
}
},
handleChange(userList) {
if (userList) {
this.userIds = [];
var users=[];
for (var i = 0; i < userList.length; i++) {
var user={};
user.id=userList[i].key;
user.realname=userList[i].label;
this.userIds += userList[i].key + ',';
users.push(user);
}
}
this.$refs.UserListModal.edit(users,this.userIds);
}
}
}
</script>
......
......@@ -29,7 +29,7 @@
import { validateCheckRule } from '@/utils/util'
export default {
name: 'SysCheckRuleModal',
name: 'SysCheckRuleTestModal',
data() {
return {
title: '操作',
......
<template>
<a-spin :spinning="confirmLoading">
<j-form-container :disabled="formDisabled">
<a-form :form="form" slot="detail">
<a-row>
<a-col :span="24">
<a-form-item label="租户名称" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input v-decorator="['name']" placeholder="请输入租户名称"></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="租户编号" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input-number style="width: 100%" :min="1" v-decorator="['id',{rules: [{ required: true, message: '请输入租户编号'}]}]" placeholder="请输入租户编号"></a-input-number>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="开始时间" :labelCol="labelCol" :wrapperCol="wrapperCol">
<j-date placeholder="请选择开始时间" v-decorator="['beginDate']" :trigger-change="true" :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" style="width: 100%"/>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="结束时间" :labelCol="labelCol" :wrapperCol="wrapperCol">
<j-date placeholder="请选择结束时间" v-decorator="['endDate']" :trigger-change="true" :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" style="width: 100%"/>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="状态" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group name="tenantStatus" v-decorator="[ 'status', {initialValue:1}]">
<a-radio :value="1">正常</a-radio>
<a-radio :value="0">冻结</a-radio>
</a-radio-group>
</a-form-item>
</a-col>
<a-col v-if="showFlowSubmitButton" :span="24" style="text-align: center">
<a-button @click="submitForm">提 交</a-button>
</a-col>
</a-row>
</a-form>
</j-form-container>
</a-spin>
</template>
<script>
import { httpAction, getAction } from '@/api/manage'
import pick from 'lodash.pick'
import { validateDuplicateValue } from '@/utils/util'
import JFormContainer from '@/components/jeecg/JFormContainer'
import JDate from '@/components/jeecg/JDate'
import JDictSelectTag from "@/components/dict/JDictSelectTag"
export default {
name: "TenantForm",
components: {
JFormContainer,
JDate,
JDictSelectTag,
},
props: {
formData: {
type: Object,
default: ()=>{},
required: false
},
normal: {
type: Boolean,
default: false,
required: false
},
disabled: {
type: Boolean,
default: false,
required: false
}
},
data () {
return {
form: this.$form.createForm(this),
model: {},
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
confirmLoading: false,
validatorRules: {
},
url: {
add: "/sys/tenant/add",
edit: "/sys/tenant/edit",
queryById: "/sys/tenant/queryById"
}
}
},
computed: {
formDisabled(){
if(this.normal===false){
if(this.formData.disabled===false){
return false
}else{
return true
}
}
return this.disabled
},
showFlowSubmitButton(){
if(this.normal===false){
if(this.formData.disabled===false){
return true
}else{
return false
}
}else{
return false
}
}
},
created () {
this.showFlowData();
},
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,'id','name','beginDate','endDate','status'))
})
},
showFlowData(){
if(this.normal === false){
let params = {id:this.formData.dataId};
getAction(this.url.queryById,params).then((res)=>{
if(res.success){
this.edit (res.result);
}
});
}
},
submitForm () {
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);
console.log("表单提交数据",formData)
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;
})
}
})
},
popupCallback(row){
this.form.setFieldsValue(pick(row, 'id', 'name','beginDate','endDate','status'))
},
}
}
</script>
\ No newline at end of file
<template>
<j-modal
:title="title"
:width="width"
:visible="visible"
switchFullscreen
@ok="handleOk"
:okButtonProps="{ class:{'jee-hidden': disableSubmit} }"
@cancel="handleCancel"
cancelText="关闭">
<tenant-form ref="realForm" @ok="submitCallback" :disabled="disableSubmit" normal></tenant-form>
</j-modal>
</template>
<script>
import TenantForm from './TenantForm'
export default {
name: "TenantModal",
components: {
TenantForm
},
data () {
return {
title:'',
width:800,
visible: false,
disableSubmit: false
}
},
methods: {
add () {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.add();
})
},
edit (record) {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.edit(record);
})
},
close () {
this.$emit('close');
this.visible = false;
},
handleOk () {
this.$refs.realForm.submitForm();
},
submitCallback(){
this.$emit('ok');
this.visible = false;
},
handleCancel () {
this.close()
}
}
}
</script>
\ No newline at end of file
......@@ -7,7 +7,7 @@
:closable="true"
@close="handleCancel"
:visible="visible"
style="height: calc(100% - 55px);overflow: auto;padding-bottom: 53px;">
style="height: 100%;overflow: auto;padding-bottom: 53px;">
<template slot="title">
<div style="width: 100%;">
......@@ -28,7 +28,7 @@
<template v-if="!model.id">
<a-form-item label="登陆密码" :labelCol="labelCol" :wrapperCol="wrapperCol" >
<a-input type="password" placeholder="请输入登陆密码" v-decorator="[ 'password', validatorRules.password]" />
<a-input type="password" placeholder="请输入登陆密码" v-decorator="[ 'password']" />
</a-form-item>
<a-form-item label="确认密码" :labelCol="labelCol" :wrapperCol="wrapperCol" >
......@@ -72,6 +72,22 @@
<a-button slot="enterButton" icon="search">选择</a-button>
</a-input-search>
</a-form-item>
<!--租户分配-->
<a-form-item label="租户分配" :labelCol="labelCol" :wrapperCol="wrapperCol" v-show="!departDisabled">
<a-select
mode="multiple"
style="width: 100%"
placeholder="请选择租户分配"
:disabled="disableSubmit"
v-model="currentTenant">
<a-select-option v-for="(item, index) in tenantList" :key="index" :value="item.id">
{{ item.name }}
</a-select-option>
</a-select>
</a-form-item>
<!-- update--begin--autor:wangshuai-----date:20200108------for:新增身份和负责部门------ -->
<a-form-item label="身份" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group
......@@ -253,14 +269,18 @@
userWithDepart: "/sys/user/userDepartList", // 引入为指定用户查看部门信息需要的url
userId:"/sys/user/generateUserId", // 引入生成添加用户情况下的url
syncUserByUserName:"/process/extActProcess/doSyncUserByUserName",//同步用户到工作流
queryTenantList: '/sys/tenant/queryList'
},
identity:"1",
fileList:[],
tenantList: [],
currentTenant:[]
}
},
created () {
const token = Vue.ls.get(ACCESS_TOKEN);
this.headers = {"X-Access-Token":token}
this.initTenantList()
},
computed:{
......@@ -272,6 +292,13 @@
isDisabledAuth(code){
return disabledAuthFilter(code);
},
initTenantList(){
getAction(this.url.queryTenantList).then(res=>{
if(res.success){
this.tenantList = res.result
}
})
},
//窗口最大化切换
toggleScreen(){
if(this.modaltoggleFlag){
......@@ -308,6 +335,7 @@
this.resultDepartOptions=[];
this.departId=[];
this.departIdShow=false;
this.currentTenant = []
},
add () {
this.picUrl = "";
......@@ -343,6 +371,14 @@
// 调用查询用户对应的部门信息的方法
that.checkedDepartKeys = [];
that.loadCheckedDeparts();
//update-begin-author:taoyan date:2020710 for:多租户配置
if(!record.relTenantIds || record.relTenantIds.length==0){
this.currentTenant = []
}else{
this.currentTenant = record.relTenantIds.split(',').map(Number);
}
//update-end-author:taoyan date:2020710 for:多租户配置
},
//
loadCheckedDeparts(){
......@@ -412,6 +448,9 @@
}else{
formData.avatar = null;
}
//update-begin-author:taoyan date:2020710 for:多租户配置
formData.relTenantIds = this.currentTenant.length>0?this.currentTenant.join(','):''
//update-end-author:taoyan date:2020710 for:多租户配置
formData.selectedroles = this.selectedRole.length>0?this.selectedRole.join(","):'';
formData.selecteddeparts = this.userDepartModel.departIdList.length>0?this.userDepartModel.departIdList.join(","):'';
formData.userIdentity=this.identity;
......
......@@ -7,7 +7,7 @@
:closable="true"
@close="close"
:visible="visible"
style="height: calc(100% - 55px);overflow: auto;padding-bottom: 53px;">
style="overflow: auto;padding-bottom: 53px;">
<a-form>
<a-form-item label='所拥有的权限'>
......
<template>
<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-steps>
<div class="content">
<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"/>
<step2 v-if="currentTab === 0" @nextStep="nextStep"/>
<step3 v-if="currentTab === 1" @nextStep="nextStep" @prevStep="prevStep" :userList="userList"/>
<step4 v-if="currentTab === 2" @prevStep="prevStep" @finish="finish" :userList="userList"/>
</div>
</a-card>
</template>
......
......@@ -9,16 +9,16 @@
<a-form-item>
<a-input
size="large"
v-decorator="['username',{initialValue:'admin', rules: validatorRules.username.rules}]"
v-decorator="['username',validatorRules.username,{ validator: this.handleUsernameOrEmail }]"
type="text"
placeholder="请输入帐户名 / admin">
placeholder="请输入帐户名 / jeecg">
<a-icon slot="prefix" type="user" :style="{ color: 'rgba(0,0,0,.25)' }"/>
</a-input>
</a-form-item>
<a-form-item>
<a-input
v-decorator="['password',{initialValue:'123456', rules: validatorRules.password.rules}]"
v-decorator="['password',validatorRules.password]"
size="large"
type="password"
autocomplete="false"
......@@ -118,46 +118,7 @@
:visible="stepCaptchaVisible"
@success="stepCaptchaSuccess"
@cancel="stepCaptchaCancel"></two-step-captcha>
<a-modal
title="登录部门选择"
:width="450"
:visible="departVisible"
:closable="false"
:maskClosable="false">
<template slot="footer">
<a-button type="primary" @click="departOk">确认</a-button>
</template>
<a-form>
<a-form-item
:labelCol="{span:4}"
:wrapperCol="{span:20}"
style="margin-bottom:10px"
:validate-status="validate_status">
<a-tooltip placement="topLeft" >
<template slot="title">
<span>您隶属于多部门,请选择登录部门</span>
</template>
<a-avatar style="backgroundColor:#87d068" icon="gold" />
</a-tooltip>
<a-select @change="departChange" :class="{'valid-error':validate_status=='error'}" placeholder="请选择登录部门" style="margin-left:10px;width: 80%">
<a-icon slot="suffixIcon" type="gold" />
<a-select-option
v-for="d in departList"
:key="d.id"
:value="d.orgCode">
{{ d.departName }}
</a-select-option>
</a-select>
</a-form-item>
</a-form>
</a-modal>
<login-select-modal ref="loginSelect" @success="loginSelectOk"></login-select-modal>
</div>
</template>
......@@ -173,10 +134,12 @@
import { encryption , getEncryptedString } from '@/utils/encryption/aesEncrypt'
import store from '@/store/'
import { USER_INFO } from "@/store/mutation-types"
import LoginSelectModal from './LoginSelectModal.vue'
export default {
components: {
TwoStepCaptcha
TwoStepCaptcha,
LoginSelectModal
},
data () {
return {
......@@ -205,12 +168,7 @@
verifiedCode:"",
inputCodeContent:"",
inputCodeNull:true,
departList:[],
departVisible:false,
departSelected:"",
currentUsername:"",
validate_status:"",
currdatetime:'',
randCodeImage:'',
requestCodeSuccess:false
......@@ -281,7 +239,7 @@
loginParams.checkKey = that.currdatetime
console.log("登录参数",loginParams)
that.Login(loginParams).then((res) => {
this.departConfirm(res)
this.$refs.loginSelect.show(res.result)
}).catch((err) => {
that.requestFailed(err);
});
......@@ -300,7 +258,7 @@
loginParams.remember_me = values.rememberMe
that.PhoneLogin(loginParams).then((res) => {
console.log(res.result);
this.departConfirm(res)
this.$refs.loginSelect.show(res.result)
}).catch((err) => {
that.requestFailed(err);
})
......@@ -376,7 +334,9 @@
// update-begin- author:sunjianlei --- date:20190812 --- for: 登录成功后不解除禁用按钮,防止多次点击
// this.loginBtn = false
// update-end- author:sunjianlei --- date:20190812 --- for: 登录成功后不解除禁用按钮,防止多次点击
this.$router.push({ path: "/dashboard/analysis" })
this.$router.push({ path: "/dashboard/analysis" }).catch(()=>{
console.log('登录跳转首页出错,这个错误从哪里来的')
})
this.$notification.success({
message: '欢迎',
description: `${timeFix()},欢迎回来`,
......@@ -418,64 +378,8 @@
inputCodeChange(e){
this.inputCodeContent = e.target.value
},
departConfirm(res){
if(res.success){
let multi_depart = res.result.multi_depart
//0:无部门 1:一个部门 2:多个部门
if(multi_depart==0){
this.loginSuccess()
this.$notification.warn({
message: '提示',
description: `您尚未归属部门,请确认账号信息`,
duration:3
});
}else if(multi_depart==2){
this.departVisible=true
this.currentUsername=this.form.getFieldValue("username")
this.departList = res.result.departs
}else {
this.loginSuccess()
}
}else{
this.requestFailed(res)
this.Logout();
}
},
departOk(){
if(!this.departSelected){
this.validate_status='error'
return false
}
let obj = {
orgCode:this.departSelected,
username:this.form.getFieldValue("username")
}
putAction("/sys/selectDepart",obj).then(res=>{
if(res.success){
const userInfo = res.result.userInfo;
Vue.ls.set(USER_INFO, userInfo, 7 * 24 * 60 * 60 * 1000);
store.commit('SET_INFO', userInfo);
//console.log("---切换组织机构---userInfo-------",store.getters.userInfo.orgCode);
this.departClear()
this.loginSuccess()
}else{
this.requestFailed(res)
this.Logout().then(()=>{
this.departClear()
});
}
})
},
departClear(){
this.departList=[]
this.departSelected=""
this.currentUsername=""
this.departVisible=false
this.validate_status=''
},
departChange(value){
this.validate_status='success'
this.departSelected = value
loginSelectOk(){
this.loginSuccess()
},
getRouterData(){
this.$nextTick(() => {
......
<template>
<a-modal
:title="title"
:width="450"
:visible="visible"
:closable="false"
:maskClosable="false">
<template slot="footer">
<a-button type="primary" @click="selectOk">确认</a-button>
</template>
<a-form>
<a-form-item v-if="isMultiTenant" :labelCol="{span:4}" :wrapperCol="{span:20}" style="margin-bottom:10px" :validate-status="validate_status1">
<a-tooltip placement="topLeft" >
<template slot="title">
<span>您有多个租户,请选择登录租户</span>
</template>
<a-avatar style="backgroundColor:#87d068" icon="gold" />
</a-tooltip>
<a-select @change="handleTenantChange" :class="{'valid-error':validate_status1=='error'}" placeholder="请选择登录租户" style="margin-left:10px;width: 80%">
<a-icon slot="suffixIcon" type="gold" />
<a-select-option v-for="d in tenantList" :key="d.id" :value="d.id">
{{ d.name }}
</a-select-option>
</a-select>
</a-form-item>
<a-form-item v-if="isMultiDepart" :labelCol="{span:4}" :wrapperCol="{span:20}" style="margin-bottom:10px" :validate-status="validate_status2">
<a-tooltip placement="topLeft" >
<template slot="title">
<span>您有多个部门,请选择登录部门</span>
</template>
<a-avatar style="backgroundColor:rgb(104, 208, 203);" icon="gold" />
</a-tooltip>
<a-select @change="handleDepartChange" :class="{'valid-error':validate_status2=='error'}" placeholder="请选择登录部门" style="margin-left:10px;width: 80%">
<a-icon slot="suffixIcon" type="gold" />
<a-select-option v-for="d in departList" :key="d.id" :value="d.orgCode">
{{ d.departName }}
</a-select-option>
</a-select>
</a-form-item>
</a-form>
</a-modal>
</template>
<script>
import Vue from 'vue'
import { getAction,putAction } from '@/api/manage'
import { USER_INFO } from "@/store/mutation-types"
import store from './Login'
export default {
name: 'LoginSelectModal',
data(){
return {
visible: false,
isMultiDepart:false,
departList:[],
isMultiTenant:false,
tenantList:[],
username:'',
orgCode:'',
tenant_id:'',
validate_status1: "",
validate_status2: "",
}
},
computed:{
title(){
if(this.isMultiDepart && this.isMultiTenant){
return '请选择租户和部门'
}else if(this.isMultiDepart && !this.isMultiTenant){
return '请选择部门'
}else if(!this.isMultiDepart && this.isMultiTenant){
return '请选择租户'
}
}
},
methods:{
clear(){
this.departList = []
this.tenantList = []
this.visible=false
this.validate_status1=''
this.validate_status2=''
},
bizDepart(loginResult){
let multi_depart = loginResult.multi_depart
//0:无部门 1:一个部门 2:多个部门
if(multi_depart==0){
this.$notification.warn({
message: '提示',
description: `您尚未归属部门,请确认账号信息`,
duration:3
});
this.isMultiDepart = false
}else if(multi_depart==2){
this.visible=true
this.isMultiDepart = true
this.departList = loginResult.departs
}else {
this.isMultiDepart = false
}
},
bizTenant(ids){
if(!ids || ids.length==0){
this.isMultiTenant = false
} else if(ids.indexOf(',')<0){
this.tenant_id = ids;
this.isMultiTenant = false
}else{
this.visible = true
this.isMultiTenant = true
getAction('/sys/tenant/queryList', {ids: ids}).then(res=>{
this.tenantList = res.result
})
}
},
show(loginResult){
this.clear();
this.bizDepart(loginResult);
let user = Vue.ls.get(USER_INFO)
this.username = user.username
let ids = user.relTenantIds
this.bizTenant(ids);
if(this.visible===false){
this.$store.dispatch('saveTenant', this.tenant_id);
this.$emit('success')
}
},
requestFailed (err) {
this.$notification[ 'error' ]({
message: '登录失败',
description: ((err.response || {}).data || {}).message || err.message || "请求出现错误,请稍后再试",
duration: 4,
});
this.loginBtn = false;
},
departResolve(){
return new Promise((resolve, reject)=>{
if(this.isMultiDepart===false){
resolve();
}else{
let obj = {
orgCode:this.orgCode,
username:this.username
}
putAction("/sys/selectDepart",obj).then(res=>{
if(res.success){
const userInfo = res.result.userInfo;
Vue.ls.set(USER_INFO, userInfo, 7 * 24 * 60 * 60 * 1000);
this.$store.commit('SET_INFO', userInfo);
//console.log("---切换组织机构---userInfo-------",store.getters.userInfo.orgCode);
resolve();
}else{
this.requestFailed(res)
this.$store.dispatch('Logout');
reject();
}
})
}
})
},
selectOk(){
if(this.isMultiTenant && !this.tenant_id){
this.validate_status1='error'
return false
}
if(this.isMultiDepart && !this.orgCode){
this.validate_status2='error'
return false
}
this.departResolve().then(()=>{
if(this.isMultiTenant){
this.$store.dispatch('saveTenant', this.tenant_id);
this.$emit('success')
}else{
this.$emit('success')
}
}).catch(()=>{
console.log('登录选择出问题')
})
},
handleTenantChange(e){
this.validate_status1 = ''
this.tenant_id = e
},
handleDepartChange(e){
this.validate_status2 = ''
this.orgCode = e
}
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
......@@ -2,19 +2,6 @@
<div>
<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}"
......@@ -22,8 +9,8 @@
<a-input
type="text"
autocomplete="false"
:style="{width:'310px'}"
v-decorator="['phone',{initialValue: defaultPhone, rules: validatorRules.phone.rule}]"
style="width:310px;margin-left:-10px"
v-decorator="['phone',{ rules: validatorRules.phone.rule}]"
placeholder="请输入手机号">
<a-icon slot="prefix" type="phone" :style="{ color: 'rgba(0,0,0,.25)'}"/>
</a-input>
......@@ -52,10 +39,9 @@
</a-row>
</a-form-item>
<a-form-item :wrapperCol="{span: 19, offset: 5}">
<a-button style="margin-left: 8px" @click="prevStep">上一步</a-button>
<router-link style="float: left;line-height: 40px;" :to="{ name: 'login' }">使用已有账户登录</router-link>
<a-button type="primary" @click="nextStep" style="margin-left: 20px">下一步</a-button>
</a-form-item>
</a-form>
</div>
</template>
......@@ -70,7 +56,7 @@
return {
form: this.$form.createForm(this),
loading: false,
accountName: this.userList.username,
// accountName: this.userList.username,
dropList: "0",
captcha: "",
show: true,
......@@ -84,17 +70,11 @@
},
validatorRules: {
captcha: {rule: [{required: true, message: '请输入短信验证码!'}, {validator: this.validateCaptcha}]},
phone: {rule: [{required: true, message: '请输入手机号码!'}]},
phone: {rule: [{required: true, message: '请输入手机号码!'}, {validator: this.validatePhone}]},
},
}
},
computed: {
defaultPhone: function(){
if(this.userList.isPhone){
return this.userList.phone
}
return null;
}
},
methods: {
nextStep() {
......@@ -108,15 +88,15 @@
this.cmsFailed("请输入短信验证码!");
} else {
var params = {}
params.phone = this.userList.phone;
params.phone = values.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
username: res.result.username,
phone: values.phone,
smscode: res.result.smscode
};
setTimeout(function () {
that.$emit('nextStep', userList)
......@@ -133,12 +113,14 @@
}
})
},
prevStep() {
this.$emit('prevStep', this.userList);
},
getCaptcha(e) {
e.preventDefault();
let that = this;
let phone=that.form.getFieldValue("phone")
if(!phone){
this.cmsFailed("手机号不能为空!");
return;
}
this.state.smsSendBtn = true;
let interval = window.setInterval(() => {
if (that.state.time-- <= 0) {
......@@ -150,7 +132,7 @@
const hide = this.$message.loading('验证码发送中..', 0);
let smsParams = {
mobile: this.userList.phone,
mobile: phone,
smsmode: "2"
};
postAction("/sys/sms", smsParams).then(res => {
......@@ -179,6 +161,18 @@
that.show = false;
}
},
validatePhone(rule,value,callback){
if(value){
var myreg=/^[1][3,4,5,7,8][0-9]{9}$/;
if(!myreg.test(value)){
callback("请输入正确的手机号")
}else{
callback();
}
}else{
callback()
}
}
}
}
......
This source diff could not be displayed because it is too large. You can view the blob instead.
*.js linguist-language=Java
*.css linguist-language=Java
*.html linguist-language=Java
*.vue linguist-language=Java
/target/
/.idea/
*.iml
jeecg-boot-module-demo
rebel.xml
\ No newline at end of file
#https://blog.csdn.net/sinat_19528249/article/details/99994464
# Version 0.1
# 基础镜像
FROM centos:7
# 维护者信息
MAINTAINER kangxiaolin ksf@zgykkj.com
VOLUME /tmp
#自动安装依赖
RUN cd /etc/yum.repos.d/ \
&& yum -y install wget \
&& wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo \
&& yum clean all \
&& yum makecache \
&& yum update -y \
&& yum -y install nginx \
&& yum -y install java-1.8.0-openjdk java-1.8.0-openjdk-devel \
&& yum -y install redis \
#这里可以设置 域名
# 可以送本地加载 使用ADD 也可以直接写
&& echo "server { \
listen 81; \
location ^~ /jeecg-boot { \
proxy_pass http://127.0.0.1:8080/jeecg-boot/; \
proxy_set_header Host 127.0.0.1; \
proxy_set_header X-Real-IP \$remote_addr; \
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; \
} \
#解决Router(mode: 'history')模式下,刷新路由地址不能找到页面的问题 \
location / { \
root /var/www/html/; \
index index.html index.htm; \
if (!-e \$request_filename) { \
rewrite ^(.*)\$ /index.html?s=\$1 last; \
break; \
} \
} \
access_log /var/log/nginx/access.log ; \
} " > /etc/nginx/conf.d/default.conf \
# 设置启动脚本
&& touch /etc/init.d/start.sh \
&& touch jeecgboot.log \
&& chmod +x /etc/init.d/start.sh \
&& echo "#!/bin/bash " >> /etc/init.d/start.sh \
&& echo "/usr/bin/redis-server & " >> /etc/init.d/start.sh \
&& echo "/usr/sbin/nginx -c /etc/nginx/nginx.conf" >> /etc/init.d/start.sh \
&& echo " java -jar /jeecgboot.jar " >> /etc/init.d/start.sh \
&& mkdir -p /var/www \
&& mkdir -p /var/www/html
# 前端迁移到系统文件中 默认是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.2.0.jar jeecgboot.jar
EXPOSE 80 8080 81
ENTRYPOINT /bin/sh -c /etc/init.d/start.sh
#启动脚本
#docker rmi $(docker images | grep "^<none>" | awk "{print $3}") 删除<none>
#docker build -t jeecgboot:centos .
#docker run --privileged=true -itd --name test -v /sys/fs/cgroup:/sys/fs/cgroup:ro -p 81:81 -p 8080:8080 -p 82:80 jeecgboot:centos
MIT License
Copyright (c) 2019 jeecg-boot
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
\ No newline at end of file
-- 创建mysql库
create database `jeecg-boot` default character set utf8mb4 collate utf8mb4_general_ci;
\ No newline at end of file
FROM mysql:8.0.19
MAINTAINER jeecgos@163.com
ENV TZ=Asia/Shanghai
RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
COPY ./jeecgboot-mysql-5.7.sql /docker-entrypoint-initdb.d
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
版本升级方法?
版本升级方法?
JeecgBoot属于平台级产品,每次升级改动内容较多,目前做不到平滑升级。
这里给用户的升级建议是这样的:
1.代码升级 => 本地版本通过svn或者git做好主干,在分支上做业务开发,jeecg每次版本发布,可以手工覆盖主干的代码,对比代码进行提交;
2.数据库升级 => 针对数据库我们每次发布会提供增量升级SQL,可以通过增量SQL实现数据库的升级。
3.兼容问题 => 每次版本发布会针对不兼容地方标注说明,需要手工修改不兼容的代码。
注意: 升级sql目前只提供mysql版本,执行完脚步后,新菜单需要手工进行角色授权,刷新首页才会出现。
\ No newline at end of file
version: '2'
services:
jeecg-boot-mysql:
build:
context: ./db
environment:
MYSQL_ROOT_PASSWORD: root
restart: always
container_name: jeecg-boot-mysql
image: jeecg-boot-mysql
command:
--character-set-server=utf8mb4
--collation-server=utf8mb4_general_ci
--explicit_defaults_for_timestamp=true
--lower_case_table_names=1
--max_allowed_packet=128M
ports:
- 3306:3306
jeecg-boot-redis:
image: redis:5.0
ports:
- 6379:6379
restart: always
container_name: jeecg-boot-redis
jeecg-boot-system:
build:
context: ./jeecg-boot-module-system
restart: always
container_name: jeecg-boot-system
image: jeecg-boot-system
ports:
- 8080:8080
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment