Compare commits

..

45 Commits

Author SHA1 Message Date
046831e700 浏览器支持说明 2020-03-31 11:20:24 +08:00
e7ad502390 提供oracle11g、sqlserver2017脚步 2020-03-12 18:47:42 +08:00
9f1a2b89b7 oracle11g 脚步提供 2020-03-12 18:37:51 +08:00
5878fcb12b 删除不需要的代码 2020-03-11 21:19:21 +08:00
27e280bd97 build后online表单无法添加/编辑问题处理 2020-03-09 10:54:08 +08:00
91594ddb1a 1.项目样式 scss 全部转换为 less,且移除了项目 node-sass 依赖;
2.online开发ButtonExpHandler is not defined #957;
3.关于打包后JS文件过大,导致加载缓慢的建议 #969
2020-03-04 22:37:17 +08:00
4c0c0945a1 修改新版上传组件,保存路径问题 2020-02-25 20:45:53 +08:00
2b3e157d88 Jeecg-Boot 2.1.4 版本发布 (版本问题修复) 2020-02-25 17:14:10 +08:00
e2d4bb29db Jeecg-Boot 2.1.4 版本发布 (升级ant-design-vue版本) 2020-02-25 16:37:20 +08:00
865ace6db0 Jeecg-Boot 2.1.4 版本发布 (新版问题修复) 2020-02-25 14:52:29 +08:00
7bc3931e1a Jeecg-Boot 2.1.4 版本发布 | 重构较大,较多新功能 2020-02-24 18:10:58 +08:00
94a945291d Jeecg-Boot 2.1.4 版本发布 | 重构较大,较多新功能 2020-02-24 17:55:42 +08:00
49a303d5e8 解决新版2.1.4 online表单插入行,添加报错问题 2020-02-24 17:48:23 +08:00
1cabc94cea Jeecg-Boot 2.1.4 版本发布 | 重构较大,较多新功能 2020-02-24 11:58:21 +08:00
760f8e9f46 Jeecg-Boot 2.1.4 版本发布 | 重构较大,较多新功能 2020-02-24 11:47:24 +08:00
38e6586c84 Jeecg-Boot 2.1.4 版本发布 | 重构较大,较多新功能 2020-02-24 03:24:28 +08:00
d7ca307fa2 Jeecg-Boot 2.1.4 版本发布 | 重构较大,较多新功能 2020-02-24 03:15:14 +08:00
188cec1646 Jeecg-Boot 2.1.4 版本发布 | 重构较大,较多新功能 2020-02-24 02:48:58 +08:00
4a4f236772 Jeecg-Boot 2.1.4 版本发布 | 重构较大,较多新功能 2020-02-24 02:44:53 +08:00
06847cd801 论坛变更域名:bbs.jeecg.com 2020-01-19 09:28:12 +08:00
365810d4e6 字典排序问题合并 2020-01-13 12:03:30 +08:00
ed83135062 Merge pull request #844 from yyri/master
<a-form-item> should be nested under <a-col>
2020-01-13 11:47:00 +08:00
beabf9b6dd README.md 2020-01-13 11:37:30 +08:00
238b4898c7 20191227 取消系统功能的权限注解 2019-12-27 15:00:22 +08:00
4372773924 <a-form-item> should be nested under <a-col> 2019-12-26 11:11:12 +08:00
d399ec904a Jeecg-Boot 2.1.3 大屏版本发布 2019-12-25 15:50:15 +08:00
8ecc971940 Jeecg-Boot 2.1.3 大屏版本发布 2019-12-25 15:14:54 +08:00
66b3b290fb Jeecg-Boot 2.1.3 大屏版本发布 2019-12-25 13:36:36 +08:00
a9c7f3e547 Jeecg-Boot 2.1.3 大屏版本发布 2019-12-25 13:34:06 +08:00
b54dada91e 2.1.2 大屏版本发布 2019-12-25 13:28:04 +08:00
3ead7c3ae1 Merge branch 'master' of https://github.com/zhangdaiscott/jeecg-boot.git 2019-12-25 13:26:13 +08:00
9c44ffaa8e 2.1.3 大屏版本发布 2019-12-25 13:25:10 +08:00
ea5ef384f2 2.1.3 大屏版本发布 2019-12-25 13:14:08 +08:00
73f7acfd5a Merge pull request #787 from a63149300/patch-1
Update UserList.vue
2019-12-15 16:38:43 +08:00
728d62f851 Jeecg-Boot 2.1.2版本发布 2019-12-09 14:46:40 +08:00
cd471735d7 Update UserList.vue
修改状态文字
2019-12-06 09:13:44 +08:00
30b35af000 提供oracle11g\sqlserver2017脚步 2019-11-27 15:56:17 +08:00
3372c88607 统计 2019-11-25 15:04:34 +08:00
ce95008fdd 统计下载量 2019-11-25 14:58:00 +08:00
bb54b20734 统计下载 2019-11-25 14:56:27 +08:00
bd790ee24b 统计下载 2019-11-25 14:54:46 +08:00
11018ab29f 统计下载 2019-11-25 14:53:26 +08:00
67c4f7b3d9 Jeecg-Boot 2.1.2 版本发布 2019-11-22 09:45:28 +08:00
9bd67f9905 Jeecg-Boot 2.1.2版本发布 2019-11-21 18:20:40 +08:00
283be0480e Jeecg-Boot 2.1.2版本发布 2019-11-21 18:17:25 +08:00
528 changed files with 79586 additions and 24021 deletions

10
.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
## ide
**/.idea
*.iml
## backend
**/target
**/logs
## front
**/*.lock

View File

@ -1,8 +1,4 @@
2019年度最受欢迎中国开源软件评选
请给JeecgBoot 投票,谢谢支持。
https://www.oschina.net/p/jeecg-boot
![JEECG](https://static.oschina.net/uploads/img/201905/24164523_XDhg.png "JeecgBoot快速开发平台")
@ -11,11 +7,12 @@ https://www.oschina.net/p/jeecg-boot
Jeecg-Boot 快速开发平台(前后端分离版本)
===============
当前最新版本: 2.1.1发布日期20191021
当前最新版本: 2.1.4发布日期2020-02-24
[![AUR](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE)
[![](https://img.shields.io/badge/Author-JEECG团队-orange.svg)](http://www.jeecg.com)
[![](https://img.shields.io/badge/version-2.0-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot)
[![](https://img.shields.io/badge/version-2.1.4-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot)
[![GitHub stars](https://img.shields.io/github/stars/zhangdaiscott/jeecg-boot.svg?style=social&label=Stars)](https://github.com/zhangdaiscott/jeecg-boot)
[![GitHub forks](https://img.shields.io/github/forks/zhangdaiscott/jeecg-boot.svg?style=social&label=Fork)](https://github.com/zhangdaiscott/jeecg-boot)
@ -46,11 +43,11 @@ Jeecg-Boot快速开发平台可以应用在任何J2EE项目的开发中
- 技术官网: [http://www.jeecg.com](http://www.jeecg.com)
- 开发文档: [http://doc.jeecg.com/1273753](http://doc.jeecg.com/1273753)
- 开发文档: [http://doc.jeecg.com](http://doc.jeecg.com/1273753)
- 视频教程 [JeecgBoot入门系列视频](https://space.bilibili.com/454617261/channel/detail?cid=84186)
- 常见问题: [入门常见问题大全](http://www.jeecg.org/forum.php?mod=viewthread&tid=7816&extra=page%3D1)
- 常见问题: [入门常见问题大全](http://bbs.jeecg.com/forum.php?mod=viewthread&tid=7816&extra=page%3D1)
- 更新日志: [版本日志](http://www.jeecg.com/#/doc/changelog)
@ -98,7 +95,7 @@ Jeecg-Boot快速开发平台可以应用在任何J2EE项目的开发中
* 24.数据变更记录日志,可记录数据每次变更内容,通过版本对比功能查看历史变化
* 25.平台UI强大实现了移动自适应
* 26.平台首页风格,提供多种组合模式,支持自定义风格
* 27.提供简单易用的打印插件,支持谷歌、IE浏览器等各种浏览器
* 27.提供简单易用的打印插件,支持谷歌、火狐、IE11+ 等各种浏览器
* 28.示例代码丰富,提供很多学习案例参考
* 29.采用maven分模块开发方式
* 30.支持菜单动态路由
@ -168,6 +165,8 @@ Jeecg-Boot快速开发平台可以应用在任何J2EE项目的开发中
│ └─树分类字典
│ └─系统公告
│ └─我的组织机构
│ └─职务管理
│ └─通讯录
├─消息中心
│ ├─消息管理
│ ├─模板管理
@ -205,7 +204,12 @@ Jeecg-Boot快速开发平台可以应用在任何J2EE项目的开发中
│ └─进度条
│ └─排名列表
│ └─等等
│─大屏模板
│ ├─作战指挥中心大屏
│ └─物流服务中心大屏
│─常用示例
│ ├─自定义组件
│ ├─对象存储(对接阿里云)
│ ├─单表模型例子
│ └─一对多模型例子
│ └─打印例子
@ -214,7 +218,10 @@ Jeecg-Boot快速开发平台可以应用在任何J2EE项目的开发中
│ └─常用选择组件
│ └─异步树table
│ └─接口模拟测试
│ └─表格合计示例
│ └─异步树列表示例
│ └─一对多JEditable
│ └─JEditable组件示例
│ └─图片拖拽排序
│ └─图片翻页
│ └─图片预览
@ -246,15 +253,16 @@ Jeecg-Boot快速开发平台可以应用在任何J2EE项目的开发中
│ └─异常页面
│ └─个人页面
├─高级功能
│ ├─系统编码规则
│ ├─提供单点登录CAS集成方案
│ ├─提供APP发布方案
│ ├─集成Websocket消息通知机制
├─Online在线开发(暂未开源)
│ ├─Online在线表单 - 功能已开放
│ ├─在线代码生成器 - 功能已开放
│ ├─Online在线报表 - 功能已开放
│ ├─Online在线图表
│ ├─Online图表模板配置
│ ├─Online在线报表
│ ├─高级表单设计器
│─流程模块功能 (暂不开源)
│ ├─流程设计器
@ -283,7 +291,7 @@ Jeecg-Boot快速开发平台可以应用在任何J2EE项目的开发中
- jdk8
- mysql
- redis
- 数据库脚jeecg-boot\docs\jeecg-boot-mysql.sql
- 数据库脚jeecg-boot\docs\jeecg-boot-mysql.sql
- 默认登录账号: admin/123456
@ -333,10 +341,13 @@ yarn run lint
系统效果
----
##### 大屏模板
![输入图片说明](https://static.oschina.net/uploads/img/201912/25133248_Ag1C.jpg "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201912/25133301_k9Kc.jpg "在这里输入图片标题")
##### PC端
![输入图片说明](https://static.oschina.net/uploads/img/201904/14155402_AmlV.png "在这里输入图片标题")
![输入图片说明](https://oscimg.oschina.net/oscnet/ba807921197596ba56f495d4b22ee3280ca.jpg "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160657_cHwb.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160813_KmXS.png "在这里输入图片标题")
![输入图片说明](https://static.oschina.net/uploads/img/201904/14160935_Nibs.png "在这里输入图片标题")

View File

@ -1,7 +1,7 @@
Ant Design Jeecg Vue
====
当前最新版本: 2.0.2发布日期20190708
当前最新版本: 2.1.4发布日期2020-02-24
Overview
----

View File

@ -6,19 +6,19 @@ function resolve (dir) {
}
module.exports = {
context: path.resolve(__dirname, './'),
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'config': resolve('config'),
'@': resolve('src'),
'@views': resolve('src/views'),
'@comp': resolve('src/components'),
'@core': resolve('src/core'),
'@utils': resolve('src/utils'),
'@entry': resolve('src/entry'),
'@router': resolve('src/router'),
'@store': resolve('src/store')
}
},
}
context: path.resolve(__dirname, './'),
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'config': resolve('config'),
'@': resolve('src'),
'@views': resolve('src/views'),
'@comp': resolve('src/components'),
'@core': resolve('src/core'),
'@utils': resolve('src/utils'),
'@entry': resolve('src/entry'),
'@router': resolve('src/router'),
'@store': resolve('src/store')
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "vue-antd-jeecg",
"version": "2.1.1",
"version": "2.1.4",
"private": true,
"scripts": {
"pre": "cnpm install || yarn --registry https://registry.npm.taobao.org || npm install --registry https://registry.npm.taobao.org ",
@ -10,9 +10,9 @@
},
"dependencies": {
"@antv/data-set": "^0.10.2",
"@jeecg/antd-online": "1.2.0",
"@jeecg/antd-online-214": "^2.1.41",
"@tinymce/tinymce-vue": "^2.0.0",
"ant-design-vue": "^1.4.0",
"ant-design-vue": "^1.4.11",
"apexcharts": "^3.6.5",
"axios": "^0.18.0",
"clipboard": "^2.0.4",
@ -24,7 +24,7 @@
"lodash.pick": "^4.4.0",
"md5": "^2.2.1",
"nprogress": "^0.2.0",
"tinymce": "^5.0.2",
"tinymce": "^5.1.4",
"viser-vue": "^2.4.4",
"vue": "^2.6.10",
"vue-apexcharts": "^1.3.2",
@ -34,7 +34,7 @@
"vue-loader": "^15.7.0",
"vue-ls": "^3.2.0",
"vue-photo-preview": "^1.1.3",
"vue-print-nb-jeecg": "^1.0.8",
"vue-print-nb-jeecg": "^1.0.9",
"vue-property-decorator": "^7.3.0",
"vue-router": "^3.0.1",
"vue-splitpane": "^1.0.4",
@ -51,10 +51,9 @@
"babel-eslint": "^10.0.1",
"eslint": "^5.16.0",
"eslint-plugin-vue": "^5.1.0",
"html-webpack-plugin": "^4.0.0-beta.11",
"less": "^3.9.0",
"less-loader": "^4.1.0",
"node-sass": "^4.11.0",
"sass-loader": "^7.0.1",
"vue-template-compiler": "^2.6.10"
},
"eslintConfig": {
@ -64,7 +63,7 @@
},
"extends": [
"plugin:vue/strongly-recommended",
"eslint:recommended"
"@vue/standard"
],
"parserOptions": {
"parser": "babel-eslint"
@ -92,7 +91,9 @@
"vue/no-use-v-if-with-v-for": 0,
"vue/html-closing-bracket-newline": 0,
"vue/no-parsing-error": 0,
"no-console": 0
"no-console": 0,
"no-tabs": 0,
"indent": [1, 4]
}
},
"postcss": {
@ -103,6 +104,6 @@
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
"not ie <= 10"
]
}

View File

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

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@ -5,7 +5,7 @@
}
/** Button按钮间距 */
.table-operator .ant-btn {
margin-right: 6px
margin: 8px 8px 0 0;
}
/*列表td的padding设置 可以控制列表大小*/
.ant-table-tbody .ant-table-row td {
@ -40,3 +40,8 @@
/*列表中范围查询样式*/
.query-group-cust{width: calc(50% - 10px)}
.query-group-split-cust:before{content:"~";width: 20px;display: inline-block;text-align: center}
/*erp风格子表外框padding设置*/
.ant-card-wider-padding.cust-erp-sub-tab>.ant-card-body{padding:5px 12px}

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -42,7 +42,7 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
.chart-card-header {
position: relative;
overflow: hidden;

View File

@ -83,6 +83,6 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
@import "chart";
</style>

View File

@ -1,7 +1,7 @@
<template>
<div :style="{ padding: '0 0 32px 32px' }">
<div :style="{ padding: '0 50px 32px 0' }">
<h4 :style="{ marginBottom: '20px' }">{{ title }}</h4>
<v-chart :forceFit="true" :height="height" :data="data" :scale="scale">
<v-chart :forceFit="true" :height="height" :data="data" :scale="scale" :padding=" padding" :onClick="handleClick">
<v-tooltip/>
<v-legend/>
<v-axis/>
@ -12,9 +12,11 @@
</template>
<script>
import { ChartEventMixins } from './mixins/ChartMixins'
export default {
name: 'BarMultid',
name: 'BarAndLine',
mixins: [ChartEventMixins],
props: {
title: {
type: String,
@ -23,13 +25,13 @@
dataSource: {
type: Array,
default: () => [
{ type: '10:10', bar: 2, line: 2 },
{ type: '10:15', bar: 6, line: 3 },
{ type: '10:20', bar: 2, line: 5 },
{ type: '10:25', bar: 9, line: 1 },
{ type: '10:30', bar: 2, line: 3 },
{ type: '10:35', bar: 2, line: 1 },
{ type: '10:40', bar: 1, line: 2 }
{ type: '10:10', bar: 200, line: 1000 },
{ type: '10:15', bar: 600, line: 1000},
{ type: '10:20', bar: 200, line: 1000},
{ type: '10:25', bar: 900, line: 1000},
{ type: '10:30', bar: 200, line: 1000},
{ type: '10:35', bar: 200, line: 1000},
{ type: '10:40', bar: 100, line: 1000}
]
},
height: {
@ -39,6 +41,7 @@
},
data() {
return {
padding: { top:50, right:50, bottom:100, left:50 },
scale: [{
dataKey: 'bar',
min: 0

View File

@ -1,36 +1,43 @@
<template>
<div :style="{ padding: '0 0 32px 32px' }">
<h4 :style="{ marginBottom: '20px' }">{{ title }}</h4>
<v-chart :forceFit="true" :height="height" :data="data">
<v-tooltip />
<v-axis />
<v-legend />
<v-bar position="x*y" color="type" :adjust="adjust" />
<v-chart :data="data" :height="height" :force-fit="true" :onClick="handleClick">
<v-tooltip/>
<v-axis/>
<v-legend/>
<v-bar position="x*y" color="type" :adjust="adjust"/>
</v-chart>
</div>
</template>
<script>
import { DataSet } from '@antv/data-set'
import { ChartEventMixins } from './mixins/ChartMixins'
export default {
name: 'BarMultid',
mixins: [ChartEventMixins],
props: {
title: {
type: String,
default: ''
},
dataSource:{
dataSource: {
type: Array,
default: () => [
{ type: 'Jeecg', 'Jan.': 18.9, 'Feb.': 28.8, 'Mar.': 39.3, 'Apr.': 81.4, 'May': 47, 'Jun.': 20.3, 'Jul.': 24, 'Aug.': 35.6 },
{ type: 'Jeebt', 'Jan.': 12.4, 'Feb.': 23.2, 'Mar.': 34.5, 'Apr.': 99.7, 'May': 52.6, 'Jun.': 35.5, 'Jul.': 37.4, 'Aug.': 42.4 }
]
},
fields:{
fields: {
type: Array,
default: () => ['Jan.', 'Feb.', 'Mar.', 'Apr.', 'May', 'Jun.', 'Jul.', 'Aug.']
},
// 别名,需要的格式:[{field:'name',alias:'姓名'}, {field:'sex',alias:'性别'}]
aliases: {
type: Array,
default: () => []
},
height: {
type: Number,
default: 254
@ -55,13 +62,22 @@
})
// bar 使用不了 - 和 / 所以替换下
return dv.rows.map(row => {
let rows = dv.rows.map(row => {
if (typeof row.x === 'string') {
row.x = row.x.replace(/[-/]/g, '_')
}
return row
})
// 替换别名
rows.forEach(row => {
for (let item of this.aliases) {
if (item.field === row.type) {
row.type = item.alias
break
}
}
})
return rows
}
}
}

View File

@ -1,6 +1,6 @@
<template>
<div :style="{ padding: '0 0 32px 32px' }">
<v-chart :forceFit="true" :height="350" :data="chartData" :scale="scale">
<v-chart :forceFit="true" :height="300" :data="chartData" :scale="scale">
<v-coord type="polar" :startAngle="-202.5" :endAngle="22.5" :radius="0.75"></v-coord>
<v-axis
dataKey="value"
@ -32,7 +32,7 @@
type="arc"
:zIndex="1"
:start="arcGuide2Start"
:end="getArcGuide2End()"
:end="getArcGuide2End"
:vStyle="arcGuide2Style"
></v-guide>
<v-guide
@ -88,7 +88,7 @@
}];
const data = [
{ value: 0},
{ value: 7.0 },
];
export default {
@ -96,7 +96,7 @@
props:{
datasource:{
type: Number,
default:0
default:7
},
title: {
type: String,

View File

@ -0,0 +1,61 @@
<template>
<div :style="{ padding: '0 0 32px 32px' }">
<h4 :style="{ marginBottom: '20px' }">{{ title }}</h4>
<v-chart
height="254"
:data="datasource"
:forceFit="true"
:padding="['auto', 'auto', '40', '50']">
<v-tooltip />
<v-axis />
<v-bar position="x*y"/>
</v-chart>
</div>
</template>
<script>
const data = []
for (let i = 0; i < 12; i += 1) {
data.push({
x: `${i + 1}`,
y: Math.floor(Math.random() * 1000) + 200
})
}
const tooltip = [
'x*y',
(x, y) => ({
name: x,
value: y
})
]
const scale = [{
dataKey: 'x',
min: 2
}, {
dataKey: 'y',
title: '时间',
min: 1,
max: 22
}]
export default {
name: "Bar",
props: {
title: {
type: String,
default: ''
}
},
mounted(){
this.datasource = data
},
data () {
return {
datasource:[],
scale,
tooltip
}
}
}
</script>

View File

@ -1,7 +1,7 @@
<template>
<div :style="{ padding: '0 0 32px 32px' }">
<h4 :style="{ marginBottom: '20px' }">{{ title }}</h4>
<v-chart :force-fit="true" :height="height" :data="data" :scale="scale">
<v-chart :force-fit="true" :height="height" :data="data" :scale="scale" :onClick="handleClick">
<v-tooltip/>
<v-axis/>
<v-legend/>
@ -13,9 +13,11 @@
<script>
import { DataSet } from '@antv/data-set'
import { ChartEventMixins } from './mixins/ChartMixins'
export default {
name: 'LineChartMultid',
mixins: [ChartEventMixins],
props: {
title: {
type: String,
@ -42,6 +44,11 @@
type: Array,
default: () => ['jeecg', 'jeebt']
},
// 别名,需要的格式:[{field:'name',alias:'姓名'}, {field:'sex',alias:'性别'}]
aliases:{
type: Array,
default: () => []
},
height: {
type: Number,
default: 254
@ -66,7 +73,17 @@
key: 'x',
value: 'y'
})
return dv.rows
let rows = dv.rows
// 替换别名
rows.forEach(row => {
for (let item of this.aliases) {
if (item.field === row.x) {
row.x = item.alias
break
}
}
})
return rows
}
}
}

View File

@ -64,6 +64,6 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
@import "chart";
</style>

View File

@ -71,6 +71,6 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
@import "chart";
</style>

View File

@ -34,7 +34,7 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
.chart-mini-progress {
padding: 5px 0;
position: relative;

View File

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

View File

@ -32,7 +32,7 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
.rank {
padding: 0 32px 32px 72px;

View File

@ -52,7 +52,7 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
.chart-trend {
display: inline-block;
font-size: 14px;

View File

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

View File

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

View File

@ -28,13 +28,16 @@ export async function initDictOptions(dictCode) {
* @return String
*/
export function filterDictText(dictOptions, text) {
let re = "";
dictOptions.forEach(function (option) {
if (text === option.value) {
re = option.text;
//--update-begin----author:sunjianlei---date:20191025------for:修复字典替换方法在字典没有加载完成之前报错的问题、修复没有找到字典时返回空值的问题---
if (dictOptions instanceof Array) {
for (let dictItem of dictOptions) {
if (text === dictItem.value) {
return dictItem.text
}
}
});
return re;
}
return text
//--update-end----author:sunjianlei---date:20191025------for:修复字典替换方法在字典没有加载完成之前报错的问题、修复没有找到字典时返回空值的问题---
}
/**
@ -44,10 +47,20 @@ export function filterDictText(dictOptions, text) {
* @return String
*/
export function filterMultiDictText(dictOptions, text) {
//js “!text” 认为0为空所以做提前处理
if(text === 0 || text === '0'){
for (let dictItem of dictOptions) {
if (text == dictItem.value) {
return dictItem.text
}
}
}
if(!text || !dictOptions || dictOptions.length==0){
return ""
}
let re = "";
text = text.toString()
let arr = text.split(",")
dictOptions.forEach(function (option) {
for(let i=0;i<arr.length;i++){
@ -58,7 +71,7 @@ export function filterMultiDictText(dictOptions, text) {
}
});
if(re==""){
return "";
return text;
}
return re.substring(0,re.length-1);
}

View File

@ -119,7 +119,7 @@
/** 数据回显*/
loadItemByCode(){
if(!this.value || this.value=="0"){
this.treeValue = ""
this.treeValue = []
}else{
getAction(this.view,{ids:this.value}).then(res=>{
console.log(124345)

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,7 @@
import Editor from '@tinymce/tinymce-vue'
import 'tinymce/themes/silver/theme'
import 'tinymce/plugins/image'
import 'tinymce/plugins/link'
import 'tinymce/plugins/media'
import 'tinymce/plugins/table'
import 'tinymce/plugins/lists'
@ -42,11 +43,12 @@
},
plugins: {
type: [String, Array],
default: 'lists image media table textcolor wordcount contextmenu fullscreen'
default: 'lists image link media table textcolor wordcount contextmenu fullscreen'
},
toolbar: {
type: [String, Array],
default: 'undo redo | formatselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | lists image media table | removeformat | fullscreen'
default: 'undo redo | formatselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | lists link unlink image media table | removeformat | fullscreen',
branding:false
}
},
data() {
@ -61,6 +63,7 @@
toolbar: this.toolbar,
branding: false,
menubar: false,
toolbar_drawer: false,
images_upload_handler: (blobInfo, success) => {
const img = 'data:image/jpeg;base64,' + blobInfo.base64()
success(img)

View File

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

View File

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

View File

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

View File

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

View File

@ -1,11 +1,29 @@
<template>
<div class="j-super-query-box">
<div @click="visible=true">
<slot>
<a-tooltip v-if="superQueryFlag" :mouseLeaveDelay="0.2">
<template slot="title">
<span>已有高级查询条件生效</span>
<a-divider type="vertical"/>
<a @click="handleReset">清空</a>
</template>
<a-button type="primary">
<a-icon type="appstore" theme="twoTone" :spin="true"></a-icon>
<span>高级查询</span>
</a-button>
</a-tooltip>
<a-button v-else type="primary" icon="filter" @click="visible=true">高级查询</a-button>
</slot>
</div>
<a-modal
title="高级查询构造器"
:width="1000"
:visible="visible"
@cancel="handleCancel"
:mask="false"
wrapClassName="ant-modal-cust-warp"
class="j-super-query-modal"
style="top:5%;max-height: 95%;">
@ -33,7 +51,7 @@
<a-form v-else layout="inline">
<a-form-item label="过滤条件匹配" style="margin-bottom: 12px;">
<a-select v-model="selectValue">
<a-select v-model="selectValue" :getPopupContainer="node=>node.parentNode">
<a-select-option value="and">AND所有条件都要求匹配</a-select-option>
<a-select-option value="or">OR条件中的任意一个匹配</a-select-option>
</a-select>
@ -42,13 +60,23 @@
<a-row type="flex" style="margin-bottom:10px" :gutter="16" v-for="(item, index) in queryParamsModel" :key="index">
<a-col :span="8">
<a-select placeholder="选择查询字段" v-model="item.field" @select="(val,option)=>handleSelected(option,item)">
<a-select-option v-for="(f,fIndex) in fieldList" :key=" 'field'+fIndex" :value="f.value" :data-idx="fIndex">{{ f.text }}</a-select-option>
</a-select>
<a-tree-select
showSearch
v-model="item.field"
:treeData="fieldTreeData"
:dropdownStyle="{ maxHeight: '400px', overflow: 'auto' }"
placeholder="选择查询字段"
allowClear
treeDefaultExpandAll
:getPopupContainer="node=>node.parentNode"
style="width: 100%"
@select="(val,option)=>handleSelected(option,item)"
>
</a-tree-select>
</a-col>
<a-col :span="4">
<a-select placeholder="匹配规则" v-model="item.rule">
<a-select placeholder="匹配规则" v-model="item.rule" :getPopupContainer="node=>node.parentNode">
<a-select-option value="eq">等于</a-select-option>
<a-select-option value="ne">不等于</a-select-option>
<a-select-option value="gt">大于</a-select-option>
@ -63,7 +91,34 @@
</a-col>
<a-col :span="8">
<j-dict-select-tag v-if="item.dictCode" v-model="item.val" :dictCode="item.dictCode" placeholder="请选择"/>
<template v-if="item.dictCode">
<template v-if="item.type === 'table-dict'">
<j-popup
v-model="item.val"
:code="item.dictTable"
:field="item.dictCode"
:orgFields="item.dictCode"
:destFields="item.dictCode"
></j-popup>
</template>
<j-dict-select-tag v-else v-model="item.val" :dictCode="item.dictCode" placeholder="请选择"/>
</template>
<j-select-multi-user
v-else-if="item.type === 'select-user'"
v-model="item.val"
:buttons="false"
:multiple="false"
placeholder="请选择用户"
:returnKeys="['id', item.customReturnField || 'username']"
/>
<j-select-depart
v-else-if="item.type === 'select-depart'"
v-model="item.val"
:multi="false"
placeholder="请选择部门"
:customReturnField="item.customReturnField || 'id'"
/>
<a-select v-else-if="item.options instanceof Array" v-model="item.val" :options="item.options" allowClear placeholder="请选择"/>
<j-date v-else-if=" item.type=='date' " v-model="item.val" placeholder="请选择日期" style="width: 100%"></j-date>
<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-input-number v-else-if=" item.type=='int'||item.type=='number' " style="width: 100%" placeholder="请输入数值" v-model="item.val"/>
@ -86,7 +141,10 @@
<div slot="title">
保存的查询
</div>
<a-empty v-if="treeData.length === 0" class="j-super-query-history-empty" description="没有保存任何查询"/>
<a-tree
v-else
class="j-super-query-history-tree"
showIcon
:treeData="treeData"
@ -108,15 +166,18 @@
</a-modal>
</a-modal>
</div>
</template>
<script>
import * as utils from '@/utils/util'
import JDate from '@/components/jeecg/JDate.vue'
import JSelectDepart from '@/components/jeecgbiz/JSelectDepart'
import JSelectMultiUser from '@/components/jeecgbiz/JSelectMultiUser'
export default {
name: 'JSuperQuery',
components: { JDate },
components: { JDate, JSelectDepart, JSelectMultiUser },
props: {
/*
fieldList: [{
@ -155,6 +216,7 @@
},
data() {
return {
fieldTreeData: [],
prompt: {
visible: false,
@ -168,6 +230,7 @@
// 保存查询条件的前缀名
saveCodeBefore: 'JSuperQuerySaved_',
selectValue: 'and',
superQueryFlag: false
}
},
watch: {
@ -182,7 +245,35 @@
return item
})
}
console.log({ list })
}
},
fieldList: {
deep: true,
immediate: true,
handler(val) {
let mainData = [], subData = []
val.forEach(item => {
let data = { ...item }
data.label = data.label || data.text
let hasChildren = (data.children instanceof Array)
data.disabled = hasChildren
data.selectable = !hasChildren
if (hasChildren) {
data.children = data.children.map(item2 => {
let child = { ...item2 }
child.label = child.label || child.text
child.label = data.label + '-' + child.label
child.value = data.value + ',' + child.value
child.val = ''
return child
})
data.val = ''
subData.push(data)
} else {
mainData.push(data)
}
})
this.fieldTreeData = mainData.concat(subData)
}
}
},
@ -195,17 +286,21 @@
this.visible = true
},
handleOk() {
console.log('---高级查询参数--->', this.queryParamsModel)
if (!this.isNullArray(this.queryParamsModel)) {
let event = {
matchType: this.selectValue,
params: this.removeEmptyObject(utils.cloneObject(this.queryParamsModel))
}
this.$emit(this.callback, event.params, event.matchType)
console.log('---高级查询参数--->', event)
this.emitCallback(event.params, event.matchType)
} else {
this.$emit(this.callback)
this.emitCallback()
}
},
emitCallback(params, matchType) {
this.superQueryFlag = !!params
this.$emit(this.callback, params, matchType)
},
handleCancel() {
this.close()
},
@ -219,16 +314,19 @@
handleDel(index) {
this.queryParamsModel.splice(index, 1)
},
handleSelected(option, item) {
let index = option.data.attrs['data-idx']
let { type, dictCode } = this.fieldList[index]
handleSelected(node, item) {
let { type, options, dictCode, dictTable, customReturnField } = node.dataRef
item['type'] = type
item['options'] = options
item['dictCode'] = dictCode
item['dictTable'] = dictTable
item['customReturnField'] = customReturnField
this.$set(item, 'val', undefined)
},
handleReset() {
this.superQueryFlag = false
this.queryParamsModel = [{}]
this.$emit(this.callback)
this.emitCallback()
},
handleSave() {
let queryParams = this.removeEmptyObject(utils.cloneObject(this.queryParamsModel))
@ -299,7 +397,7 @@
}
if (array.length === 1) {
let obj = array[0]
if (!obj.field || !obj.val || !obj.rule) {
if (!obj.field || (obj.val == null || obj.val === '') || !obj.rule) {
return true
}
}
@ -311,6 +409,9 @@
let item = array[i]
if (item == null || Object.keys(item).length <= 0) {
array.splice(i--, 1)
} else {
// 去掉特殊属性
delete item.options
}
}
return array
@ -319,13 +420,14 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
.j-super-query-box {
display: inline-block;
}
.j-super-query-modal {
/deep/ {
}
.j-super-query-history-card /deep/ {
.ant-card-body,
.ant-card-head-title {
@ -338,6 +440,24 @@
}
}
.j-super-query-history-empty /deep/ {
.ant-empty-image {
height: 80px;
line-height: 80px;
margin-bottom: 0;
}
img {
width: 80px;
height: 65px;
}
.ant-empty-description {
color: #afafaf;
margin: 8px 0;
}
}
.j-super-query-history-tree /deep/ {
.ant-tree-switcher {
display: none;

View File

@ -22,7 +22,7 @@
data(){
return {
treeData:[],
treeValue:"",
treeValue: null,
url_root:"/sys/category/loadTreeRoot",
url_children:"/sys/category/loadTreeChildren",
url_view:'/sys/category/loadOne',
@ -97,7 +97,7 @@
methods:{
loadViewInfo(){
if(!this.value || this.value=="0"){
this.treeValue = ""
this.treeValue = null
}else{
let param = {
field:this.field,

View File

@ -77,7 +77,7 @@
},
data () {
return {
treeValue:"",
treeValue: null,
treeData:[],
url:"/sys/dict/loadTreeData",
view:'/sys/dict/loadDictItem/',
@ -106,7 +106,7 @@
methods: {
loadItemByCode(){
if(!this.value || this.value=="0"){
this.treeValue = ""
this.treeValue = null
}else{
getAction(`${this.view}${this.dict}`,{key:this.value}).then(res=>{
if(res.success){
@ -211,7 +211,7 @@
onChange(value){
if(!value){
this.$emit('change', '');
this.treeValue = ''
this.treeValue = null
} else if (value instanceof Array) {
this.$emit('change', value.map(item => item.value).join(','))
this.treeValue = value

View File

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

View File

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

View File

@ -829,7 +829,7 @@
}
</script>
<style lang="scss">
<style lang="less">
.card-container {
background: #fff;
overflow: hidden;
@ -877,7 +877,7 @@
}
}
</style>
<style lang="scss" scoped>
<style lang="less" scoped>
.container-widthEn{
width: 755px;
}

View File

@ -2,7 +2,7 @@
<a-modal
centered
:title="name + '选择'"
:width="900"
:width="width"
:visible="visible"
@ok="handleOk"
@cancel="close"
@ -17,7 +17,7 @@
<a-col :span="14">
<a-form-item :label="(queryParamText||name)">
<a-input :placeholder="'请输入' + (queryParamText||name)" v-model="queryParam[valueKey]"></a-input>
<a-input v-model="queryParam[queryParamCode||valueKey]" :placeholder="'请输入' + (queryParamText||name)" @pressEnter="searchQuery"/>
</a-form-item>
</a-col>
<a-col :span="8">
@ -34,8 +34,8 @@
<a-table
size="small"
bordered
rowKey="id"
:columns="columns"
:rowKey="rowKey"
:columns="innerColumns"
:dataSource="dataSource"
:pagination="ipagination"
:loading="loading"
@ -49,7 +49,7 @@
<a-col :span="8">
<a-card :title="'已选' + name" :bordered="false" :head-style="{padding:0}" :body-style="{padding:0}">
<a-table rowKey="id" size="small" bordered v-bind="selectedTable">
<a-table size="small" :rowKey="rowKey" bordered v-bind="selectedTable">
<span slot="action" slot-scope="text, record, index">
<a @click="handleDeleteSelected(record, index)">删除</a>
</span>
@ -62,7 +62,9 @@
</template>
<script>
import { getAction } from '@/api/manage'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import { cloneObject, pushIfNotExist } from '@/utils/util'
export default {
name: 'JSelectBizComponentModal',
@ -84,6 +86,10 @@
type: Boolean,
default: true
},
width: {
type: Number,
default: 900
},
name: {
type: String,
@ -94,60 +100,110 @@
required: true,
default: ''
},
// 根据 value 获取显示文本的地址,例如存的是 username可以通过该地址获取到 realname
valueUrl: {
type: String,
default: ''
},
displayKey: {
type: String,
default: null
},
propColumns: {
columns: {
type: Array,
required: true,
default: () => []
},
// 查询条件Code
queryParamCode: {
type: String,
default: null
},
// 查询条件文字
queryParamText: {
type: String,
default: null
},
rowKey: {
type: String,
default: 'id'
},
},
data() {
return {
innerValue: [],
// 表头
columns: this.propColumns,
innerColumns: this.columns,
// 已选择列表
selectedTable: {
pagination: false,
scroll: { y: 240 },
columns: [
this.propColumns[0],
{
...this.columns[0],
width: this.columns[0].widthRight || this.columns[0].width,
},
{ title: '操作', dataIndex: 'action', align: 'center', width: 60, scopedSlots: { customRender: 'action' }, }
],
dataSource: [],
},
url: { list: this.listUrl }
url: { list: this.listUrl },
/* 分页参数 */
ipagination: {
current: 1,
pageSize: 5,
pageSizeOptions: ['5', '10', '20', '30'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' 共' + total + '条'
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
},
options: [],
dataSourceMap: {},
}
},
watch: {
value: {
deep: true,
immediate: true,
handler(val) {
this.innerValue = cloneObject(val)
this.selectedRowKeys = []
this.valueWatchHandler(val)
this.queryOptionsByValue(val)
}
},
dataSource: {
deep: true,
handler(val) {
let options = val.map(data => ({ label: data[this.displayKey || this.valueKey], value: data[this.valueKey] }))
this.$emit('ok', options)
this.valueWatchHandler(this.value)
this.emitOptions(val)
this.valueWatchHandler(this.innerValue)
}
},
selectionRows: {
selectedRowKeys: {
immediate: true,
deep: true,
handler(val) {
this.selectedTable.dataSource = val
this.selectedTable.dataSource = val.map(key => {
for (let data of this.dataSource) {
if (data[this.rowKey] === key) {
pushIfNotExist(this.innerValue, data[this.valueKey])
return data
}
}
for (let data of this.selectedTable.dataSource) {
if (data[this.rowKey] === key) {
pushIfNotExist(this.innerValue, data[this.valueKey])
return data
}
}
console.warn('未找到选择的行信息key' + key)
return {}
})
},
},
}
},
methods: {
@ -158,18 +214,63 @@
},
valueWatchHandler(val) {
let dataSource = []
let selectedRowKeys = []
val.forEach(item => {
this.dataSource.forEach(data => {
this.dataSource.concat(this.selectedTable.dataSource).forEach(data => {
if (data[this.valueKey] === item) {
dataSource.push(data)
selectedRowKeys.push(data.id)
pushIfNotExist(this.selectedRowKeys, data[this.rowKey])
}
})
})
this.selectedTable.dataSource = dataSource
this.selectedRowKeys = selectedRowKeys
},
queryOptionsByValue(value) {
if (!value || value.length === 0) {
return
}
// 判断options是否存在value如果已存在数据就不再请求后台了
let notExist = false
for (let val of value) {
let find = false
for (let option of this.options) {
if (val === option.value) {
find = true
break
}
}
if (!find) {
notExist = true
break
}
}
if (!notExist) return
getAction(this.valueUrl || this.listUrl, {
// 这里最后加一个 , 的原因是因为无论如何都要使用 in 查询,防止后台进行了模糊匹配,导致查询结果不准确
[this.valueKey]: value.join(',') + ',',
pageNo: 1,
pageSize: value.length
}).then((res) => {
if (res.success) {
let dataSource = res.result
if (!(dataSource instanceof Array)) {
dataSource = res.result.records
}
this.emitOptions(dataSource, (data) => {
pushIfNotExist(this.innerValue, data[this.valueKey])
pushIfNotExist(this.selectedRowKeys, data[this.rowKey])
pushIfNotExist(this.selectedTable.dataSource, data, this.rowKey)
})
}
})
},
emitOptions(dataSource, callback) {
dataSource.forEach(data => {
let key = data[this.valueKey]
this.dataSourceMap[key] = data
pushIfNotExist(this.options, { label: data[this.displayKey || this.valueKey], value: key }, 'value')
typeof callback === 'function' ? callback(data) : ''
})
this.$emit('options', this.options, this.dataSourceMap)
},
/** 完成选择 */
@ -181,22 +282,30 @@
/** 删除已选择的 */
handleDeleteSelected(record, index) {
this.selectedRowKeys.splice(this.selectedRowKeys.indexOf(record.id), 1)
this.selectedRowKeys.splice(this.selectedRowKeys.indexOf(record[this.rowKey]), 1)
this.selectedTable.dataSource.splice(index, 1)
},
customRowFn(record) {
if (!this.multiple) {
return {
on: {
click: () => {
this.selectedRowKeys = [record.id]
return {
on: {
click: () => {
let key = record[this.rowKey]
if (!this.multiple) {
this.selectedRowKeys = [key]
this.selectedTable.dataSource = [record]
} else {
let index = this.selectedRowKeys.indexOf(key)
if (index === -1) {
this.selectedRowKeys.push(key)
this.selectedTable.dataSource.push(record)
} else {
this.handleDeleteSelected(record, index)
}
}
}
}
}
return {}
},
}

View File

@ -16,11 +16,21 @@ export default {
### 配置参数
- `name`:`String` 显示名字,例如选择部门就填写'部门'
- `listUrl`:`String` 数据请求地址,必须是封装了分页的地址
- `displayKey`:`String` 显示在标签上的字段 key
- `returnKeys`:`Array` v-model 绑定的 keys是个数组默认使用第二项当配置了 `returnId=true` 就返回第一项
- `returnId`:`Boolean` 返回ID设为true后将返回配置的 `returnKeys` 中的第一项
- `selectButtonText`:`String` 选择按钮的文字
- `queryParamText`:`String` 查询条件显示文字
- `columns`:`Array` 列配置项与a-table的列配置项相同会将第一项配置成已选择的列表
| 参数名 | 类型 | 必填 | 默认值 | 备注 |
|-----------------------|---------|------|--------------|--------------------------------------------------------------------------------------|
| rowKey | String | | "id" | 唯一标识的字段名 |
| value(v-model) | String | | "" | 默认选择的数据,多个用半角逗号分割 |
| name | String | | "" | 显示名字,例如选择用户就填写"用户" |
| listUrl | String | 是 | | 数据请求地址,必须是封装了分页的地址 |
| valueUrl | String | | "" | 获取显示文本的地址,例如存的是 username可以通过该地址获取到 realname |
| displayKey | String | | null | 显示在标签上的字段 key ,不传则直接显示数据 |
| returnKeys | Array | | ['id', 'id'] | v-model 绑定的 keys是个数组默认使用第二项当配置了 `returnId=true` 就返回第一项 |
| returnId | Boolean | | false | 返回ID设为true后将返回配置的 `returnKeys` 中的第一项 |
| selectButtonText | String | | "选择" | 选择按钮的文字 |
| queryParamText | String | | null | 查询条件显示文字,不传则使用 `name` |
| columns | Array | 是 | | 列配置项与antd的table的配置完全一致。列的第一项会被配置成右侧已选择的列表上 |
| columns[0].widthRight | Array | | null | 仅列的第一项可以应用此配置,表示右侧已选择列表的宽度,建议 `70%`,不传则应用`width` |
| placeholder | String | | "请选择" | 占位符 |
| disabled | Boolean | | false | 是否禁用 |
| multiple | Boolean | | false | 是否可多选 |
| buttons | Boolean | | true | 是否显示"选择"按钮,如果不显示,可以直接点击文本框打开选择界面 |

View File

@ -1,29 +1,30 @@
<template>
<a-row class="j-select-biz-component-box" type="flex" :gutter="8">
<a-col class="left">
<a-select
mode="multiple"
:placeholder="placeholder"
v-model="selectValue"
:options="selectOptions"
allowClear
:disabled="disabled"
:open="false"
style="width: 100%;"
/>
<a-col class="left" :class="{'full': !buttons}">
<slot name="left">
<a-select
mode="multiple"
:placeholder="placeholder"
v-model="selectValue"
:options="selectOptions"
allowClear
:disabled="disabled"
:open="false"
style="width: 100%;"
@click.native="visible=(buttons?visible:true)"
/>
</slot>
</a-col>
<a-col class="right">
<a-col v-if="buttons" class="right">
<a-button type="primary" icon="search" :disabled="disabled" @click="visible=true">{{selectButtonText}}</a-button>
</a-col>
<j-select-biz-component-modal
v-model="selectValue"
:name="name" :listUrl="listUrl" :returnKeys="returnKeys" :displayKey="displayKey"
:propColumns="columns" :queryParamText="queryParamText" :multiple="multiple"
:visible.sync="visible"
:valueKey="valueKey"
@ok="selectOptions=$event"
v-bind="modalProps"
@options="handleOptions"
/>
</a-row>
</template>
@ -57,19 +58,10 @@
type: Boolean,
default: true
},
/* 可复用属性 */
// 被选择的名字,例如选择部门就填写'部门'
name: {
type: String,
default: ''
},
// list 接口地址
listUrl: {
type: String,
required: true,
default: ''
// 是否显示按钮,默认 true
buttons: {
type: Boolean,
default: true
},
// 显示的 Key
displayKey: {
@ -86,29 +78,28 @@
type: String,
default: '选择'
},
// 查询条件文字
queryParamText: {
type: String,
default: null
},
// columns
columns: {
type: Array,
default: () => []
}
},
data() {
return {
selectValue: [],
selectOptions: [],
dataSourceMap: {},
visible: false
}
},
computed: {
valueKey() {
return this.returnId ? this.returnKeys[0] : this.returnKeys[1]
}
},
modalProps() {
return Object.assign({
valueKey: this.valueKey,
multiple: this.multiple,
returnKeys: this.returnKeys,
displayKey: this.displayKey || this.valueKey
}, this.$attrs)
},
},
watch: {
value: {
@ -124,34 +115,42 @@
selectValue: {
deep: true,
handler(val) {
const data = val.join(',')
let rows = val.map(key => this.dataSourceMap[key])
this.$emit('select', rows)
let data = val.join(',')
this.$emit('input', data)
this.$emit('change', data)
}
}
},
methods: {}
methods: {
handleOptions(options, dataSourceMap) {
this.selectOptions = options
this.dataSourceMap = dataSourceMap
},
}
}
</script>
<style lang="scss">
.j-select-biz-component-box {
.ant-select-search__field {
display: none !important;
}
}
</style>
<style lang="scss" scoped>
<style lang="less" scoped>
.j-select-biz-component-box {
$width: 82px;
@width: 82px;
.left {
width: calc(100% - #{$width} - 8px);
width: calc(100% - @width - 8px);
}
.right {
width: #{$width};
width: @width ;
}
.full {
width: 100%;
}
/deep/ .ant-select-search__field {
display: none !important;
}
}
</style>

View File

@ -11,7 +11,7 @@
:modal-width="modalWidth"
:multi="multi"
:rootOpened="rootOpened"
:depart-id="value"
:depart-id="departIds"
@ok="handleOK"
@initComp="initComp"/>
</div>
@ -48,6 +48,11 @@
type: Boolean,
required: false,
default: false
},
// 自定义返回字段,默认返回 id
customReturnField: {
type: String,
default: 'id'
}
},
data(){
@ -63,7 +68,9 @@
},
watch:{
value(val){
this.departIds = val
if (this.customReturnField === 'id') {
this.departIds = val
}
}
},
methods:{
@ -73,21 +80,17 @@
openModal(){
this.$refs.innerDepartSelectModal.show()
},
handleOK(rows,idstr){
console.log("当前选中部门",rows)
console.log("当前选中部门ID",idstr)
if(!rows){
handleOK(rows, idstr) {
let value = ''
if (!rows && rows.length <= 0) {
this.departNames = ''
this.departIds=''
}else{
let temp = ''
for(let item of rows){
temp+=','+item.departName
}
this.departNames = temp.substring(1)
this.departIds=idstr
this.departIds = ''
} else {
value = rows.map(row => row[this.customReturnField]).join(',')
this.departNames = rows.map(row => row['departName']).join(',')
this.departIds = idstr
}
this.$emit("change",this.departIds)
this.$emit("change", value)
},
getDepartNames(){
return this.departNames

View File

@ -1,17 +1,11 @@
<template>
<!-- 定义在这里的参数都是不可在外部覆盖的防止出现问题 -->
<j-select-biz-component
:value="value"
name="用户"
displayKey="realname"
:returnKeys="returnKeys"
:listUrl="url.list"
:columns="columns"
queryParamText="账号"
v-on="$listeners"
v-bind="$attrs"
v-bind="attrs"
/>
</template>
@ -24,17 +18,29 @@
props: ['value'],
data() {
return {
returnKeys: ['id', 'username'],
url: { list: '/sys/user/list' },
columns: [
{ title: '姓名', align: 'center', width: 100, dataIndex: 'realname' },
{ title: '账号', align: 'center', width: 100, dataIndex: 'username' },
{ title: '电话', align: 'center', width: 100, dataIndex: 'phone' },
{ title: '出生日期', align: 'center', width: 100, dataIndex: 'birthday' }
]
{ title: '姓名', align: 'center', width: '20%', widthRight: '70%', dataIndex: 'realname' },
{ title: '账号', align: 'center', width: '20%', dataIndex: 'username' },
{ title: '电话', align: 'center', width: '23%', dataIndex: 'phone' },
{ title: '出生日期', align: 'center', width: '23%', dataIndex: 'birthday' }
],
// 定义在这里的参数都是可以在外部传递覆盖的,可以更灵活的定制化使用的组件
default: {
name: '用户',
width: 1000,
displayKey: 'realname',
returnKeys: ['id', 'username'],
queryParamText: '账号',
}
}
},
computed: {
attrs() {
return Object.assign(this.default, this.$attrs)
}
}
}
</script>
<style lang="scss" scoped></style>
<style lang="less" scoped></style>

View File

@ -1,5 +1,5 @@
<template>
<j-select-biz-component v-bind="configs" v-on="$listeners"/>
<j-select-biz-component :width="1000" v-bind="configs" v-on="$listeners"/>
</template>
<script>
@ -16,11 +16,12 @@
displayKey: 'name',
returnKeys: ['id', 'code'],
listUrl: '/sys/position/list',
queryParamText: '职务编码',
queryParamCode: 'name',
queryParamText: '职务名称',
columns: [
{ title: '职务名称', dataIndex: 'name', align: 'center', width: 100 },
{ title: '职务编码', dataIndex: 'code', align: 'center', width: 100 },
{ title: '职级', dataIndex: 'rank_dictText', align: 'center', width: 100 }
{ title: '职务名称', dataIndex: 'name', align: 'center', width: '30%', widthRight: '70%' },
{ title: '职务编码', dataIndex: 'code', align: 'center', width: '35%' },
{ title: '职级', dataIndex: 'rank_dictText', align: 'center', width: '25%' }
]
}
}
@ -33,4 +34,4 @@
}
</script>
<style lang="scss" scoped></style>
<style lang="less" scoped></style>

View File

@ -35,4 +35,4 @@
}
</script>
<style lang="scss" scoped></style>
<style lang="less" scoped></style>

View File

@ -63,7 +63,7 @@
handler() {
if (this.departId) {
this.checkedKeys = this.departId.split(",");
console.log('this.departId', this.departId)
// console.log('this.departId', this.departId)
} else {
this.checkedKeys = [];
}
@ -75,7 +75,6 @@
this.visible=true
this.checkedRows=[]
this.checkedKeys=[]
console.log("this.multi",this.multi)
},
loadDepart(){
queryDepartTreeList().then(res=>{
@ -133,39 +132,29 @@
},
onCheck (checkedKeys,info) {
if(!this.multi){
let arr = checkedKeys.checked.filter(item=>{
return this.checkedKeys.indexOf(item)<0
})
let arr = checkedKeys.checked.filter(item => this.checkedKeys.indexOf(item) < 0)
this.checkedKeys = [...arr]
this.checkedRows=[info.node.dataRef]
this.checkedRows = (this.checkedKeys.length === 0) ? [] : [info.node.dataRef]
}else{
this.checkedKeys = checkedKeys.checked
this.checkedRows.push(info.node.dataRef)
this.checkedRows = this.getCheckedRows(this.checkedKeys)
}
//this.$emit("input",this.checkedKeys.join(","))
//console.log(this.checkedKeys.join(","))
},
onSelect (selectedKeys,info) {
console.log(selectedKeys)
onSelect(selectedKeys,info) {
let keys = []
keys.push(selectedKeys[0])
if(!this.checkedKeys || this.checkedKeys.length==0 || !this.multi){
if(!this.checkedKeys || this.checkedKeys.length===0 || !this.multi){
this.checkedKeys = [...keys]
this.checkedRows=[info.node.dataRef]
}else{
let currKey = info.node.dataRef.key
if(this.checkedKeys.indexOf(currKey)>=0){
this.checkedKeys = this.checkedKeys.filter(item=>{
return item !=currKey
})
this.checkedRows=this.checkedRows.filter(item=>{
return item.key !=currKey
})
this.checkedKeys = this.checkedKeys.filter(item=> item !==currKey)
}else{
this.checkedRows.push(info.node.dataRef)
this.checkedKeys.push(...keys)
}
}
this.checkedRows = this.getCheckedRows(this.checkedKeys)
},
onExpand (expandedKeys) {
this.expandedKeys = expandedKeys
@ -215,6 +204,32 @@
})
},
// 根据 checkedKeys 获取 rows
getCheckedRows(checkedKeys) {
const forChildren = (list, key) => {
for (let item of list) {
if (item.id === key) {
return item
}
if (item.children instanceof Array) {
let value = forChildren(item.children, key)
if (value != null) {
return value
}
}
}
return null
}
let rows = []
for (let key of checkedKeys) {
let row = forChildren(this.treeData, key)
if (row != null) {
rows.push(row)
}
}
return rows
}
}
}

View File

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

View File

@ -46,7 +46,7 @@
width: 200
},
{
title: '用户真实姓名',
title: '用户姓名',
align: "center",
dataIndex: 'realname',
},

View File

@ -33,7 +33,7 @@
}
</script>
<style lang="scss">
<style lang="less">
/*
* The following styles are auto-applied to elements with

View File

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

View File

@ -60,7 +60,7 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
.extra-img {
margin-top: -60px;
text-align: center;

View File

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

View File

@ -17,12 +17,12 @@
<div class="footer">
<div class="links">
<a href="http://jeecg-boot.mydoc.io" target="_blank">帮助</a>
<a href="http://doc.jeecg.com" target="_blank">帮助</a>
<a href="https://github.com/zhangdaiscott/jeecg-boot" target="_blank">隐私</a>
<a href="https://github.com/zhangdaiscott/jeecg-boot" target="_blank">条款</a>
<a href="https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE" target="_blank">条款</a>
</div>
<div class="copyright">
Copyright &copy; 2019 <a href="http://www.jeecg.org" target="_blank">JEECG开源社区</a> 出品
Copyright &copy; 2019 <a href="http://www.jeecg.com" target="_blank">JEECG开源社区</a> 出品
</div>
</div>
</div>
@ -49,7 +49,7 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
#userLayout.user-layout-wrapper {
height: 100%;

View File

@ -72,18 +72,18 @@
}
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
/* update_begin author:sunjianlei date:20190509 for: 修改侧边导航栏滚动条的样式 */
.sider {
$scrollBarSize: 10px;
@scrollBarSize: 10px;
ul.ant-menu {
/* 定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸*/
&::-webkit-scrollbar {
width: $scrollBarSize;
height: $scrollBarSize;
width: @scrollBarSize;
height: @scrollBarSize;
background-color: transparent;
display: none;
}
@ -109,7 +109,7 @@
/* 定义滑块 */
&::-webkit-scrollbar-thumb {
border-radius: $scrollBarSize;
border-radius: @scrollBarSize;
background-color: #eee;
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1);
@ -145,7 +145,7 @@
</style>
<!-- update_begin author:sunjianlei date:20190530 for: 选中首页的时候不显示背景颜色 -->
<style lang="scss">
<style lang="less">
.ant-menu.ant-menu-root {
& > .ant-menu-item:first-child {
background-color: transparent;
@ -156,7 +156,7 @@
&.ant-menu-item-selected {
& > a, & > a:hover {
color: #1890ff;
color: @primary-color;
}
}
}

View File

@ -1,7 +1,7 @@
<template>
<div class="footer">
<div class="links">
<a href="http://www.jeecg.org" target="_blank">JEECG 首页</a>
<a href="http://www.jeecg.com" target="_blank">JEECG 首页</a>
<a href="https://github.com/zhangdaiscott/jeecg-boot" target="_blank">
<a-icon type="github"/>
</a>
@ -22,7 +22,7 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
.footer {
padding: 0 16px;
margin: 48px 0 24px;

View File

@ -10,12 +10,12 @@
v-if="device==='mobile'"
class="trigger"
:type="collapsed ? 'menu-fold' : 'menu-unfold'"
@click.native="toggle"></a-icon>
@click="toggle"></a-icon>
<a-icon
v-else
class="trigger"
:type="collapsed ? 'menu-unfold' : 'menu-fold'"
@click.native="toggle"/>
@click="toggle"/>
<span v-if="device === 'desktop'">欢迎进入 Jeecg-Boot 企业级快速开发平台</span>
<span v-else>Jeecg-Boot</span>
@ -37,7 +37,7 @@
v-else
class="trigger"
:type="collapsed ? 'menu-fold' : 'menu-unfold'"
@click.native="toggle"></a-icon>
@click="toggle"></a-icon>
</div>
<user-menu class="header-index-right" :theme="theme" :style="topMenuStyle.headerIndexRight"/>
</div>
@ -161,10 +161,10 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
/* update_begin author:scott date:20190220 for: 缩小首页布局顶部的高度*/
$height: 59px;
@height: 59px;
.layout {
@ -174,8 +174,8 @@
margin-left: 10px;
.ant-menu.ant-menu-horizontal {
height: $height;
line-height: $height;
height: @height;
line-height: @height;
}
}
.trigger {
@ -189,8 +189,8 @@
.header {
z-index: 2;
color: white;
height: $height;
background-color: #1890ff;
height: @height;
background-color: @primary-color;
transition: background 300ms;
/* dark 样式 */
@ -209,8 +209,8 @@
}
.ant-layout-header {
height: $height;
line-height: $height;
height: @height;
line-height: @height;
}
/* update_end author:scott date:20190220 for: 缩小首页布局顶部的高度*/

View File

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

View File

@ -100,7 +100,7 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
.page-header {
background: #fff;

View File

@ -84,7 +84,7 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
.content {
margin: 24px 24px 0;

View File

@ -47,7 +47,7 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
.header-notice{
display: inline-block;
transition: all 0.3s;

View File

@ -255,7 +255,7 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
.setting-drawer-index-content {

View File

@ -22,7 +22,7 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
.setting-drawer-index-item {
margin-bottom: 24px;

View File

@ -77,7 +77,7 @@
}
</script>
<style lang="scss">
<style lang="less">
.detail-list {

View File

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

View File

@ -15,7 +15,7 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
.toolbar {
position: fixed;
width: 100%;

View File

@ -30,7 +30,7 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
.head-info {
position: relative;
text-align: left;

View File

@ -31,7 +31,7 @@
<a-list>
<a-list-item :key="index" v-for="(record, index) in announcement1">
<div style="margin-left: 5%;width: 80%">
<p><a @click="showAnnouncement(record)">标题{{ record.titile }}</a></p>
<p><a @click="showAnnouncement(record)">{{ record.titile }}</a></p>
<p style="color: rgba(0,0,0,.45);margin-bottom: 0px">{{ record.createTime }} 发布</p>
</div>
<div style="text-align: right">
@ -49,7 +49,7 @@
<a-list>
<a-list-item :key="index" v-for="(record, index) in announcement2">
<div style="margin-left: 5%;width: 80%">
<p><a @click="showAnnouncement(record)">标题{{ record.titile }}</a></p>
<p><a @click="showAnnouncement(record)">{{ record.titile }}</a></p>
<p style="color: rgba(0,0,0,.45);margin-bottom: 0px">{{ record.createTime }} 发布</p>
</div>
<div style="text-align: right">
@ -72,6 +72,7 @@
</a-badge>
</span>
<show-announcement ref="ShowAnnouncement" @ok="modalFormOk"></show-announcement>
<dynamic-notice ref="showDynamNotice" :path="openPath" :formData="formData"/>
</a-popover>
</template>
@ -79,11 +80,13 @@
import { getAction,putAction } from '@/api/manage'
import ShowAnnouncement from './ShowAnnouncement'
import store from '@/store/'
import DynamicNotice from './DynamicNotice'
export default {
name: "HeaderNotice",
components: {
DynamicNotice,
ShowAnnouncement,
},
data () {
@ -105,6 +108,8 @@
websock: null,
lockReconnect:false,
heartCheck:null,
formData:{},
openPath:''
}
},
computed:{
@ -172,7 +177,13 @@
}
});
this.hovered = false;
this.$refs.ShowAnnouncement.detail(record);
if(record.openType==='component'){
this.openPath = record.openPage;
this.formData = {id:record.busId};
this.$refs.showDynamNotice.detail(record.openPage);
}else{
this.$refs.ShowAnnouncement.detail(record);
}
},
toMyAnnouncement(){
@ -191,24 +202,24 @@
// WebSocket与普通的请求所用协议有所不同ws等同于httpwss等同于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;
this.websock.onmessage = this.websocketonmessage;
this.websock.onclose = this.websocketclose;
this.websock.onopen = this.websocketOnopen;
this.websock.onerror = this.websocketOnerror;
this.websock.onmessage = this.websocketOnmessage;
this.websock.onclose = this.websocketOnclose;
},
websocketonopen: function () {
websocketOnopen: function () {
console.log("WebSocket连接成功");
//心跳检测重置
this.heartCheck.reset().start();
},
websocketonerror: function (e) {
websocketOnerror: function (e) {
console.log("WebSocket连接发生错误");
this.reconnect();
},
websocketonmessage: function (e) {
//console.log("-----接收消息-------",e.data);
websocketOnmessage: function (e) {
console.log("-----接收消息-------",e.data);
var data = eval("(" + e.data + ")"); //解析对象
if(data.cmd == "topic"){
//系统通知
@ -217,22 +228,20 @@
//用户消息
this.loadData();
}
//心跳检测重置
this.heartCheck.reset().start();
},
websocketsend(text) { // 数据发送
websocketOnclose: function (e) {
console.log("connection closed (" + e.code + ")");
this.reconnect();
},
websocketSend(text) { // 数据发送
try {
this.websock.send(text);
} catch (err) {
console.log("send failed (" + err.code + ")");
}
},
websocketclose: function (e) {
console.log("connection closed (" + e.code + ")");
this.reconnect();
},
openNotification (data) {
var text = data.msgTxt;
@ -284,7 +293,7 @@
this.timeoutObj = setTimeout(function(){
//这里发送一个心跳,后端收到后,返回一个心跳消息,
//onmessage拿到返回的心跳就说明连接正常
that.websocketsend("HeartBeat");
that.websocketSend("HeartBeat");
console.info("客户端发送心跳");
//self.serverTimeoutObj = setTimeout(function(){//如果超过一定时间还没重置,说明后端主动断开了
// that.websock.close();//如果onclose会执行reconnect我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
@ -315,7 +324,7 @@
top: 50px !important;
}
</style>
<style lang="scss" scoped>
<style lang="less" scoped>
.header-notice{
display: inline-block;
transition: all 0.3s;

View File

@ -32,15 +32,15 @@
}
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
/*缩小首页布 局顶部的高度*/
$height: 59px;
@height: 59px;
.sider {
box-shadow: none !important;
.logo {
height: $height !important;
line-height: $height !important;
height: @height !important;
line-height: @height !important;
box-shadow: none !important;
transition: background 300ms;
@ -53,7 +53,7 @@
}
&.light .logo {
background-color: #1890ff;
background-color: @primary-color;
}
}
</style>

View File

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

View File

@ -80,7 +80,7 @@ export default {
}
};
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
.step-form-wrapper {
margin: 0 auto;
width: 80%;

View File

@ -1,7 +1,33 @@
<template>
<div class="user-wrapper" :class="theme">
<!-- update_begin author:zhaoxin date:20191129 for: 做头部菜单栏导航 -->
<!-- update-begin author:sunjianlei date:20191@20 for: 解决全局样式冲突的问题 -->
<span class="action" @click="showClick">
<a-icon type="search"></a-icon>
</span>
<!-- update-begin author:sunjianlei date:20200219 for: 菜单搜索改为动态组件,在手机端呈现出弹出框 -->
<component :is="searchMenuComp" v-show="searchMenuVisible || isMobile()" class="borders" :visible="searchMenuVisible" title="搜索菜单" :footer="null" @cancel="searchMenuVisible=false">
<a-select
class="search-input"
showSearch
:showArrow="false"
placeholder="搜索菜单"
optionFilterProp="children"
:filterOption="filterOption"
:open="isMobile()?true:null"
:getPopupContainer="(node) => node.parentNode"
:style="isMobile()?{width: '100%',marginBottom:'50px'}:{}"
@change="searchMethods"
@blur="hiddenClick"
>
<a-select-option v-for="(site,index) in searchMenuOptions" :key="index" :value="site.id">{{site.meta.title}}</a-select-option>
</a-select>
</component>
<!-- update-end author:sunjianlei date:20200219 for: 菜单搜索改为动态组件,在手机端呈现出弹出框 -->
<!-- update-end author:sunjianlei date:20191220 for: 解决全局样式冲突的问题 -->
<!-- update_end author:zhaoxin date:20191129 for: 做头部菜单栏导航 -->
<span class="action">
<a class="logout_title" target="_blank" href="http://jeecg-boot.mydoc.io">
<a class="logout_title" target="_blank" href="http://doc.jeecg.com">
<a-icon type="question-circle-o"></a-icon>
</a>
</span>
@ -66,12 +92,21 @@
import UserPassword from './UserPassword'
import SettingDrawer from "@/components/setting/SettingDrawer";
import DepartSelect from './DepartSelect'
import { mapActions, mapGetters } from 'vuex'
import { mapActions, mapGetters,mapState } from 'vuex'
import { mixinDevice } from '@/utils/mixin.js'
export default {
name: "UserMenu",
mixins: [mixinDevice],
data(){
return{
// update-begin author:sunjianlei date:20200219 for: 头部菜单搜索规范命名 --------------
searchMenuOptions:[],
searchMenuComp: 'span',
searchMenuVisible: false,
// update-begin author:sunjianlei date:20200219 for: 头部菜单搜索规范命名 --------------
}
},
components: {
HeaderNotice,
UserPassword,
@ -85,12 +120,45 @@
default: 'dark'
}
},
/* update_begin author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
created() {
let lists = []
this.searchMenus(lists,this.permissionMenuList)
this.searchMenuOptions=[...lists]
},
computed: {
...mapState({
// 后台菜单
permissionMenuList: state => state.user.permissionList
})
},
/* update_end author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
watch: {
// update-begin author:sunjianlei date:20200219 for: 菜单搜索改为动态组件,在手机端呈现出弹出框
device: {
immediate: true,
handler() {
this.searchMenuVisible = false
this.searchMenuComp = this.isMobile() ? 'a-modal' : 'span'
},
},
// update-end author:sunjianlei date:20200219 for: 菜单搜索改为动态组件,在手机端呈现出弹出框
},
methods: {
/* update_begin author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
showClick() {
this.searchMenuVisible = true
},
hiddenClick(){
this.shows = false
},
/* update_end author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
...mapActions(["Logout"]),
...mapGetters(["nickname", "avatar","userInfo"]),
getAvatar(){
console.log('url = '+ window._CONFIG['imgDomainURL']+"/"+this.avatar())
return window._CONFIG['imgDomainURL']+"/"+this.avatar()
console.log('url = '+ window._CONFIG['staticDomainURL']+"/"+this.avatar())
return window._CONFIG['staticDomainURL']+"/"+this.avatar()
},
handleLogout() {
const that = this
@ -122,11 +190,57 @@
},
systemSetting(){
this.$refs.settingDrawer.showDrawer()
},
/* update_begin author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
searchMenus(arr,menus){
for(let i of menus){
if(!i.hidden && "layouts/RouteView"!==i.component){
arr.push(i)
}
if(i.children&& i.children.length>0){
this.searchMenus(arr,i.children)
}
}
},
filterOption(input, option) {
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
},
// update_begin author:sunjianlei date:20191230 for: 解决外部链接打开失败的问题
searchMethods(value) {
let route = this.searchMenuOptions.filter(item => item.id === value)[0]
if (route.meta.internalOrExternal === true || route.component.includes('layouts/IframePageView')) {
window.open(route.meta.url, '_blank')
} else {
this.$router.push({ path: route.path })
}
this.searchMenuVisible = false
}
// update_end author:sunjianlei date:20191230 for: 解决外部链接打开失败的问题
/*update_end author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
}
}
</script>
<style lang="less" scoped>
/* update_begin author:zhaoxin date:20191129 for: 让搜索框颜色能随主题颜色变换*/
/* update-begin author:sunjianlei date:20191220 for: 解决全局样式冲突问题 */
.user-wrapper .search-input {
width: 180px;
color: inherit;
/deep/ .ant-select-selection {
background-color: inherit;
border: 0;
border-bottom: 1px solid white;
&__placeholder, &__field__placeholder {
color: inherit;
}
}
}
/* update-end author:sunjianlei date:20191220 for: 解决全局样式冲突问题 */
/* update_end author:zhaoxin date:20191129 for: 让搜索框颜色能随主题颜色变换*/
</style>
<style scoped>
.logout_title {
color: inherit;

View File

@ -22,7 +22,7 @@ export default {
fixSiderbar: false, // sticky siderbar
autoHideHeader: false, // auto hide header
colorWeak: false,
multipage: false, //默认多页签模式
multipage: true, //默认多页签模式
// vue-ls options
storageOptions: {
namespace: 'pro__', // key prefix

View File

@ -18,8 +18,9 @@ import VueApexCharts from 'vue-apexcharts'
import preview from 'vue-photo-preview'
import 'vue-photo-preview/dist/skin.css'
import "@jeecg/antd-online"
import '@jeecg/antd-online/dist/OnlineForm.css'
require('@jeecg/antd-online-214')
require('@jeecg/antd-online-214/dist/OnlineForm.css')
import {
ACCESS_TOKEN,
@ -69,7 +70,7 @@ new Vue({
store.commit('TOGGLE_WEAK', Vue.ls.get(DEFAULT_COLOR_WEAK, config.colorWeak))
store.commit('TOGGLE_COLOR', Vue.ls.get(DEFAULT_COLOR, config.primaryColor))
store.commit('SET_TOKEN', Vue.ls.get(ACCESS_TOKEN))
store.commit('SET_MULTI_PAGE',Vue.ls.get(DEFAULT_MULTI_PAGE,true))
store.commit('SET_MULTI_PAGE',Vue.ls.get(DEFAULT_MULTI_PAGE,config.multipage))
},
render: h => h(App)
}).$mount('#app')

View File

@ -80,10 +80,11 @@ export const JEditableTableMixin = {
},
/** 查询某个tab的数据 */
requestSubTableData(url, params, tab) {
requestSubTableData(url, params, tab, success) {
tab.loading = true
getAction(url, params).then(res => {
tab.dataSource = res.result || []
typeof success === 'function' ? success(res) : ''
}).finally(() => {
tab.loading = false
})

View File

@ -51,9 +51,12 @@ export const JeecgListMixin = {
}
},
created() {
this.loadData();
//初始化字典配置 在自己页面定义
this.initDictConfig();
if(!this.disableMixinCreated){
console.log(' -- mixin created -- ')
this.loadData();
//初始化字典配置 在自己页面定义
this.initDictConfig();
}
},
methods:{
loadData(arg) {
@ -149,6 +152,7 @@ export const JeecgListMixin = {
title: "确认删除",
content: "是否删除选中数据?",
onOk: function () {
that.loading = true;
deleteAction(that.url.deleteBatch, {ids: ids}).then((res) => {
if (res.success) {
that.$message.success(res.message);
@ -157,6 +161,8 @@ export const JeecgListMixin = {
} else {
that.$message.warning(res.message);
}
}).finally(() => {
that.loading = false;
});
}
});
@ -230,9 +236,9 @@ export const JeecgListMixin = {
return
}
if (typeof window.navigator.msSaveBlob !== 'undefined') {
window.navigator.msSaveBlob(new Blob([data]), fileName+'.xls')
window.navigator.msSaveBlob(new Blob([data],{type: 'application/vnd.ms-excel'}), fileName+'.xls')
}else{
let url = window.URL.createObjectURL(new Blob([data]))
let url = window.URL.createObjectURL(new Blob([data],{type: 'application/vnd.ms-excel'}))
let link = document.createElement('a')
link.style.display = 'none'
link.href = url
@ -280,7 +286,7 @@ export const JeecgListMixin = {
if(text && text.indexOf(",")>0){
text = text.substring(0,text.indexOf(","))
}
return window._CONFIG['imgDomainURL']+"/"+text
return window._CONFIG['staticDomainURL']+"/"+text
},
/* 文件下载 */
uploadFile(text){
@ -291,7 +297,7 @@ export const JeecgListMixin = {
if(text.indexOf(",")>0){
text = text.substring(0,text.indexOf(","))
}
window.open(window._CONFIG['domianURL'] + "/sys/common/download/"+text);
window.open(window._CONFIG['staticDomainURL']+ "/"+text);
},
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,3 +1,4 @@
import * as api from '@/api/api'
import { isURL } from '@/utils/validate'
export function timeFix() {
@ -254,4 +255,163 @@ export function cssExpand(css, id) {
}
// 应用新样式
document.head.appendChild(style)
}
/** 用于js增强事件运行JS代码可以传参 */
// options 所需参数:
// 参数名 类型 说明
// vm VueComponent vue实例
// event Object event对象
// jsCode String 待执行的js代码
// errorMessage String 执行出错后的提示(控制台)
export function jsExpand(options = {}) {
// 绑定到window上的keyName
let windowKeyName = 'J_CLICK_EVENT_OPTIONS'
if (typeof window[windowKeyName] != 'object') {
window[windowKeyName] = {}
}
// 随机生成JS增强的执行id防止冲突
let id = randomString(16, 'qwertyuioplkjhgfdsazxcvbnm'.toUpperCase())
// 封装按钮点击事件
let code = `
(function (o_${id}) {
try {
(function (globalEvent, vm) {
${options.jsCode}
})(o_${id}.event, o_${id}.vm)
} catch (e) {
o_${id}.error(e)
}
o_${id}.done()
})(window['${windowKeyName}']['EVENT_${id}'])
`
// 创建script标签
const script = document.createElement('script')
// 将需要传递的参数挂载到window对象上
window[windowKeyName]['EVENT_' + id] = {
vm: options.vm,
event: options.event,
// 当执行完成时,无论如何都会调用的回调事件
done() {
// 执行完后删除新增的 script 标签不会撤销执行结果(已产生的结果不会被撤销)
script.outerHTML = ''
delete window[windowKeyName]['EVENT_' + id]
},
// 当js运行出错的时候调用的事件
error(e) {
console.group(`${options.errorMessage || '用户自定义JS增强代码运行出错'}${new Date()}`)
console.error(e)
console.groupEnd()
}
}
// 将事件挂载到document中
script.innerHTML = code
document.body.appendChild(script)
}
/**
* 重复值验证工具方法
*
* 使用示例:
* { validator: (rule, value, callback) => validateDuplicateValue('sys_fill_rule', 'rule_code', value, this.model.id, callback) }
*
* @param tableName 被验证的表名
* @param fieldName 被验证的字段名
* @param fieldVal 被验证的值
* @param dataId 数据ID可空
* @param callback
*/
export function validateDuplicateValue(tableName, fieldName, fieldVal, dataId, callback) {
if (fieldVal) {
let params = { tableName, fieldName, fieldVal, dataId }
api.duplicateCheck(params).then(res => {
res['success'] ? callback() : callback(res['message'])
}).catch(err => {
callback(err.message || err)
})
} else {
callback()
}
}
/**
* 根据编码校验规则code校验传入的值是否合法
*
* 使用示例:
* { validator: (rule, value, callback) => validateCheckRule('common', value, callback) }
*
* @param ruleCode 编码校验规则 code
* @param value 被验证的值
* @param callback
*/
export function validateCheckRule(ruleCode, value, callback) {
if (ruleCode && value) {
value = encodeURIComponent(value)
api.checkRuleByCode({ ruleCode, value }).then(res => {
res['success'] ? callback() : callback(res['message'])
}).catch(err => {
callback(err.message || err)
})
} else {
callback()
}
}
/**
* 如果值不存在就 push 进数组,反之不处理
* @param array 要操作的数据
* @param value 要添加的值
* @param key 可空,如果比较的是对象,可能存在地址不一样但值实际上是一样的情况,可以传此字段判断对象中唯一的字段,例如 id。不传则直接比较实际值
* @returns {boolean} 成功 push 返回 true不处理返回 false
*/
export function pushIfNotExist(array, value, key) {
for (let item of array) {
if (key && (item[key] === value[key])) {
return false
} else if (item === value) {
return false
}
}
array.push(value)
return true
}
/**
* 可用于判断是否成功
* @type {symbol}
*/
export const succeedSymbol = Symbol()
/**
* 可用于判断是否失败
* @type {symbol}
*/
export const failedSymbol = Symbol()
/**
* 使 promise 无论如何都会 resolve除非传入的参数不是一个Promise对象或返回Promise对象的方法
* 一般用在 Promise.all 中
*
* @param promise 可传Promise对象或返回Promise对象的方法
* @returns {Promise<any>}
*/
export function alwaysResolve(promise) {
return new Promise((resolve, reject) => {
let p = promise
if (typeof promise === 'function') {
p = promise()
}
if (p instanceof Promise) {
p.then(data => {
resolve({ type: succeedSymbol, data })
}).catch(error => {
resolve({ type: failedSymbol, error })
})
} else {
reject('alwaysResolve: 传入的参数不是一个Promise对象或返回Promise对象的方法')
}
})
}

View File

@ -133,7 +133,7 @@
methods: {
...mapGetters(["nickname", "avatar"]),
getAvatar(){
return window._CONFIG['imgDomainURL']+"/"+this.avatar();
return window._CONFIG['staticDomainURL']+"/"+this.avatar();
},
getTeams() {
this.$http.get('/api/workplace/teams')
@ -180,7 +180,7 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
.page-header-wrapper-grid-content-main {
width: 100%;
height: 100%;

View File

@ -79,7 +79,7 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
.app-list {

View File

@ -83,7 +83,7 @@
};
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
.avatar-upload-preview {
position: absolute;

View File

@ -103,7 +103,7 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
.avatar-upload-wrapper {
height: 200px;

View File

@ -106,7 +106,7 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
.account-settings-info-main {
width: 100%;
display: flex;

View File

@ -1,269 +1,41 @@
<template>
<div class="page-header-index-wide">
<a-row :gutter="24">
<a-col :sm="24" :md="12" :xl="6" :style="{ marginBottom: '24px' }">
<chart-card :loading="loading" title="总销售额" total="126,560">
<a-tooltip title="指标说明" slot="action">
<a-icon type="info-circle-o" />
</a-tooltip>
<div>
<trend flag="up" style="margin-right: 16px;">
<span slot="term">周同比</span>
12%
</trend>
<trend flag="down">
<span slot="term">日同比</span>
11%
</trend>
</div>
<template slot="footer">日均销售额<span>¥ 234.56</span></template>
</chart-card>
</a-col>
<a-col :sm="24" :md="12" :xl="6" :style="{ marginBottom: '24px' }">
<chart-card :loading="loading" title="访问量" :total="8846 | NumberFormat">
<a-tooltip title="指标说明" slot="action">
<a-icon type="info-circle-o" />
</a-tooltip>
<div>
<mini-area />
</div>
<template slot="footer">日访问量<span> {{ '1234' | NumberFormat }}</span></template>
</chart-card>
</a-col>
<a-col :sm="24" :md="12" :xl="6" :style="{ marginBottom: '24px' }">
<chart-card :loading="loading" title="支付笔数" :total="6560 | NumberFormat">
<a-tooltip title="指标说明" slot="action">
<a-icon type="info-circle-o" />
</a-tooltip>
<div>
<mini-bar :height="40" />
</div>
<template slot="footer">转化率 <span>60%</span></template>
</chart-card>
</a-col>
<a-col :sm="24" :md="12" :xl="6" :style="{ marginBottom: '24px' }">
<chart-card :loading="loading" title="运营活动效果" total="78%">
<a-tooltip title="指标说明" slot="action">
<a-icon type="info-circle-o" />
</a-tooltip>
<div>
<mini-progress color="rgb(19, 194, 194)" :target="80" :percentage="78" :height="8" />
</div>
<template slot="footer">
<trend flag="down" style="margin-right: 16px;">
<span slot="term">同周比</span>
12%
</trend>
<trend flag="up">
<span slot="term">日环比</span>
80%
</trend>
</template>
</chart-card>
</a-col>
</a-row>
<a-card :loading="loading" :bordered="false" :body-style="{padding: '0'}">
<div class="salesCard">
<a-tabs default-active-key="1" size="large" :tab-bar-style="{marginBottom: '24px', paddingLeft: '16px'}">
<div class="extra-wrapper" slot="tabBarExtraContent">
<div class="extra-item">
<a>今日</a>
<a>本周</a>
<a>本月</a>
<a>本年</a>
</div>
<a-range-picker :style="{width: '256px'}" />
</div>
<a-tab-pane loading="true" tab="销售额" key="1">
<a-row>
<a-col :xl="16" :lg="12" :md="12" :sm="24" :xs="24">
<bar title="销售额排行" :dataSource="barData"/>
</a-col>
<a-col :xl="8" :lg="12" :md="12" :sm="24" :xs="24">
<rank-list title="门店销售排行榜" :list="rankList"/>
</a-col>
</a-row>
</a-tab-pane>
<a-tab-pane tab="访问量" key="2">
<a-row>
<a-col :xl="16" :lg="12" :md="12" :sm="24" :xs="24">
<bar title="销售额趋势" :dataSource="barData"/>
</a-col>
<a-col :xl="8" :lg="12" :md="12" :sm="24" :xs="24">
<rank-list title="门店销售排行榜" :list="rankList"/>
</a-col>
</a-row>
</a-tab-pane>
</a-tabs>
</div>
</a-card>
<a-row>
<a-col :span="24">
<a-card :loading="loading" :bordered="false" title="最近一周访问次数统计" :style="{ marginTop: '24px' }">
<a-row>
<a-col :span="6">
<head-info title="今日访问IP数" :content="loginfo.todayIp"></head-info>
</a-col>
<a-col :span="2">
<a-spin class='circle-cust'>
<a-icon slot="indicator" type="environment" style="font-size: 24px" />
</a-spin>
</a-col>
<a-col :span="6">
<head-info title="今日访问次数" :content="loginfo.todayVisitCount"></head-info>
</a-col>
<a-col :span="2">
<a-spin class='circle-cust'>
<a-icon slot="indicator" type="team" style="font-size: 24px" />
</a-spin>
</a-col>
<a-col :span="6">
<head-info title="访问总次数" :content="loginfo.totalVisitCount"></head-info>
</a-col>
<a-col :span="2">
<a-spin class='circle-cust'>
<a-icon slot="indicator" type="rise" style="font-size: 24px" />
</a-spin>
</a-col>
</a-row>
<line-chart-multid :fields="visitFields" :dataSource="visitInfo"></line-chart-multid>
</a-card>
</a-col>
</a-row>
<div>
<index-chart v-if="indexStyle==1"></index-chart>
<index-bdc v-if="indexStyle==2"></index-bdc>
<index-task v-if="indexStyle==3"></index-task>
<div style="width: 100%;text-align: right;margin-top: 20px">
请选择首页样式
<a-radio-group v-model="indexStyle">
<a-radio :value="1">统计图表</a-radio>
<a-radio :value="2">统计图表2</a-radio>
<a-radio :value="3">任务表格</a-radio>
</a-radio-group>
</div>
</div>
</template>
<script>
import ChartCard from '@/components/ChartCard'
import ACol from "ant-design-vue/es/grid/Col"
import ATooltip from "ant-design-vue/es/tooltip/Tooltip"
import MiniArea from '@/components/chart/MiniArea'
import MiniBar from '@/components/chart/MiniBar'
import MiniProgress from '@/components/chart/MiniProgress'
import RankList from '@/components/chart/RankList'
import Bar from '@/components/chart/Bar'
import LineChartMultid from '@/components/chart/LineChartMultid'
import HeadInfo from '@/components/tools/HeadInfo.vue'
import IndexChart from './IndexChart'
import IndexTask from "./IndexTask"
import IndexBdc from './IndexBdc'
import Trend from '@/components/Trend'
import { getLoginfo,getVisitInfo } from '@/api/api'
const rankList = []
for (let i = 0; i < 7; i++) {
rankList.push({
name: '白鹭岛 ' + (i+1) + ' 号店',
total: 1234.56 - i * 100
})
}
const barData = []
for (let i = 0; i < 12; i += 1) {
barData.push({
x: `${i + 1}月`,
y: Math.floor(Math.random() * 1000) + 200
})
}
export default {
name: "Analysis",
components: {
ATooltip,
ACol,
ChartCard,
MiniArea,
MiniBar,
MiniProgress,
RankList,
Bar,
Trend,
LineChartMultid,
HeadInfo
IndexChart,
IndexTask,
IndexBdc
},
data() {
return {
loading: true,
center: null,
rankList,
barData,
loginfo:{},
visitFields:['ip','visit'],
visitInfo:[],
indicator: <a-icon type="loading" style="font-size: 24px" spin />
indexStyle:1
}
},
created() {
setTimeout(() => {
this.loading = !this.loading
}, 1000)
this.initLogInfo();
},
methods: {
initLogInfo () {
getLoginfo(null).then((res)=>{
if(res.success){
Object.keys(res.result).forEach(key=>{
res.result[key] =res.result[key]+""
})
this.loginfo = res.result;
}
})
getVisitInfo().then(res=>{
if(res.success){
console.log("aaaaaa",res.result)
this.visitInfo = res.result;
}
})
},
}
}
</script>
<style lang="scss" scoped>
.circle-cust{
position: relative;
top: 28px;
left: -100%;
}
.extra-wrapper {
line-height: 55px;
padding-right: 24px;
.extra-item {
display: inline-block;
margin-right: 24px;
a {
margin-left: 24px;
}
}
}
/* 首页访问量统计 */
.head-info {
position: relative;
text-align: left;
padding: 0 32px 0 0;
min-width: 125px;
&.center {
text-align: center;
padding: 0 32px;
}
span {
color: rgba(0, 0, 0, .45);
display: inline-block;
font-size: .95rem;
line-height: 42px;
margin-bottom: 4px;
}
p {
line-height: 42px;
margin: 0;
a {
font-weight: 600;
font-size: 1rem;
}
}
}
</style>
</script>

View File

@ -0,0 +1,519 @@
<template>
<div class="page-header-index-wide">
<a-row :gutter="24">
<a-col :sm="24" :md="12" :xl="6" :style="{ marginBottom: '24px' }">
<chart-card :loading="loading" title="受理量" :total="cardCount.sll | NumberFormat">
<a-tooltip title="指标说明" slot="action">
<a-icon type="info-circle-o" />
</a-tooltip>
<div>
<mini-area :datasource="chartData.sll" />
</div>
<template slot="footer">今日受理量:<span>{{ todaySll }}</span></template>
</chart-card>
</a-col>
<a-col :sm="24" :md="12" :xl="6" :style="{ marginBottom: '24px' }">
<chart-card :loading="loading" title="办结量" :total="cardCount.bjl | NumberFormat">
<a-tooltip title="指标说明" slot="action">
<a-icon type="info-circle-o" />
</a-tooltip>
<div>
<mini-area :datasource="chartData.bjl"/>
</div>
<template slot="footer">今日办结量:<span>{{ todayBjl }}</span></template>
</chart-card>
</a-col>
<a-col :sm="24" :md="12" :xl="6" :style="{ marginBottom: '24px' }">
<chart-card :loading="loading" title="用户受理量" :total="cardCount.isll | NumberFormat">
<a-tooltip title="指标说明" slot="action">
<a-icon type="info-circle-o" />
</a-tooltip>
<div>
<mini-bar :datasource="chartData.isll" :height="50"/>
</div>
<template slot="footer">用户今日受理量:<span>{{ todayISll }}</span></template>
</chart-card>
</a-col>
<a-col :sm="24" :md="12" :xl="6" :style="{ marginBottom: '24px' }">
<chart-card :loading="loading" title="用户办结量" :total="cardCount.ibjl | NumberFormat">
<a-tooltip title="指标说明" slot="action">
<a-icon type="info-circle-o" />
</a-tooltip>
<div>
<mini-bar :datasource="chartData.ibjl" :height="50"/>
</div>
<template slot="footer">用户今日办结量:<span>{{ todayIBjl }}</span></template>
</chart-card>
</a-col>
</a-row>
<a-card :loading="loading" :bordered="false" :body-style="{padding: '0'}">
<div class="salesCard">
<a-tabs default-active-key="1" size="large" :tab-bar-style="{marginBottom: '24px', paddingLeft: '16px'}">
<div class="extra-wrapper" slot="tabBarExtraContent">
<div class="extra-item">
<a>今日</a>
<a>本周</a>
<a>本月</a>
<a>本年</a>
</div>
<a-range-picker :style="{width: '256px'}" />
</div>
<a-tab-pane loading="true" tab="受理监管" key="1">
<a-row>
<a-col :xl="16" :lg="12" :md="12" :sm="24" :xs="24">
<index-bar title="受理量统计" />
</a-col>
<a-col :xl="8" :lg="12" :md="12" :sm="24" :xs="24">
<a-card title="快速开始 / 便捷导航" style="margin-bottom: 24px" :bordered="false" :body-style="{padding: 0}">
<div class="item-group">
<a-row>
<a-col :class="'more-btn'" :span="12" v-for="(item,index) in registerTypeList" :key=" 'registerType'+index ">
<a-button @click="goPage(index)" style="margin-bottom:10px" size="small" type="primary" ghost>{{ item.text }}</a-button>
</a-col>
</a-row>
</div>
</a-card>
</a-col>
</a-row>
</a-tab-pane>
<a-tab-pane tab="交互监管" key="2">
<a-row>
<a-col :xl="16" :lg="12" :md="12" :sm="24" :xs="24">
<bar-multid :sourceData="jhjgData" :fields="jhjgFields" title="平台与部门交互量统计"></bar-multid>
</a-col>
<a-col :xl="8" :lg="12" :md="12" :sm="24" :xs="24">
<a-card title="快速开始 / 便捷导航" style="margin-bottom: 24px" :bordered="false" :body-style="{padding: 0}">
<div class="item-group">
<a-row>
<a-col :class="'more-btn'" :span="12" v-for="(item,index) in registerTypeList" :key=" 'registerType'+index ">
<a-button @click="goPage(index)" style="margin-bottom:10px" size="small" type="primary" ghost>{{ item.text }}</a-button>
</a-col>
</a-row>
</div>
</a-card>
</a-col>
</a-row>
</a-tab-pane>
<a-tab-pane tab="存储监管" key="4">
<a-row>
<a-col :xl="16" :lg="12" :md="12" :sm="24" :xs="24">
<a-row>
<template v-if="diskInfo && diskInfo.length>0">
<a-col :span="12" v-for="(item,index) in diskInfo" :key=" 'diskInfo'+index ">
<dash-chart-demo :title="item.name" :datasource="item.restPPT"></dash-chart-demo>
</a-col>
</template>
</a-row>
</a-col>
<a-col :xl="8" :lg="12" :md="12" :sm="24" :xs="24">
<a-card title="快速开始 / 便捷导航" style="margin-bottom: 24px" :bordered="false" :body-style="{padding: 0}">
<div class="item-group">
<a-row>
<a-col :class="'more-btn'" :span="10" v-for="(item,index) in registerTypeList" :key=" 'registerType'+index ">
<a-button @click="goPage(index)" style="margin-bottom:10px" size="small" type="primary" ghost>{{ item.text }}</a-button>
</a-col>
</a-row>
</div>
</a-card>
</a-col>
</a-row>
</a-tab-pane>
</a-tabs>
</div>
</a-card>
<a-row :gutter="12">
<a-card :loading="loading" :class="{ 'anty-list-cust':true }" :bordered="false" :style="{ marginTop: '24px' }">
<a-tabs v-model="indexBottomTab" size="large" :tab-bar-style="{marginBottom: '24px', paddingLeft: '16px'}">
<div class="extra-wrapper" slot="tabBarExtraContent">
<a-radio-group v-model="indexRegisterType" @change="changeRegisterType">
<a-radio-button value="转移登记">转移登记</a-radio-button>
<a-radio-button value="抵押登记">抵押登记</a-radio-button>
<a-radio-button value="">所有</a-radio-button>
</a-radio-group>
</div>
<a-tab-pane loading="true" tab="业务流程限时监管" key="1">
<a-table :dataSource="dataSource1" size="default" rowKey="id" :columns="columns" :pagination="ipagination1" @change="tableChange1">
<template slot="flowRate" slot-scope="text, record, index">
<a-progress :strokeColor="getPercentColor(record.flowRate)" :format="getPercentFormat" :percent="getFlowRateNumber(record.flowRate)" style="width:80px" />
</template>
</a-table>
</a-tab-pane>
<a-tab-pane loading="true" tab="业务节点限时监管" key="2">
<a-table :dataSource="dataSource2" size="default" rowKey="id" :columns="columns2" :pagination="ipagination2" @change="tableChange2">
<template slot="flowRate" slot-scope="text, record, index">
<span style="color: red;">{{ record.flowRate }}小时</span>
</template>
</a-table>
</a-tab-pane>
</a-tabs>
</a-card>
</a-row>
</div>
</template>
<script>
import ACol from "ant-design-vue/es/grid/Col"
import ATooltip from "ant-design-vue/es/tooltip/Tooltip"
import ChartCard from '@/components/ChartCard'
import MiniBar from '@/components/chart/MiniBar'
import MiniArea from '@/components/chart/MiniArea'
import IndexBar from '@/components/chart/IndexBar'
import BarMultid from '@/components/chart/BarMultid'
import DashChartDemo from '@/components/chart/DashChartDemo'
const jhjgData = [
{ type: '房管', '1月': 900, '2月': 1120, '3月': 1380, '4月': 1480, '5月': 1450, '6月': 1100, '7月':1300, '8月':900,'9月':1000 ,'10月':1200 ,'11月':600 ,'12月':900 },
{ type: '税务', '1月':1200, '2月': 1500, '3月': 1980, '4月': 2000, '5月': 1000, '6月': 600, '7月':900, '8月':1100,'9月':1300 ,'10月':2000 ,'11月':900 ,'12月':1100 },
{ type: '不动产', '1月':2000, '2月': 1430, '3月': 1300, '4月': 1400, '5月': 900, '6月': 500, '7月':600, '8月':1000,'9月':600 ,'10月':1000 ,'11月':1500 ,'12月':1200 }
]
const jhjgFields=[
'1月','2月','3月','4月','5月','6月',
'7月','8月','9月','10月','11月','12月'
]
const xljgData = [
{type:'一月',"房管":1.12,"税务":1.55,"不动产":1.2},
{type:'二月',"房管":1.65,"税务":1.32,"不动产":1.42},
{type:'三月',"房管":1.85,"税务":1.1,"不动产":1.5},
{type:'四月',"房管":1.33,"税务":1.63,"不动产":1.4},
{type:'五月',"房管":1.63,"税务":1.8,"不动产":1.7},
{type:'六月',"房管":1.85,"税务":1.98,"不动产":1.8},
{type:'七月',"房管":1.98,"税务":1.5,"不动产":1.76},
{type:'八月',"房管":1.48,"税务":1.2,"不动产":1.3},
{type:'九月',"房管":1.41,"税务":1.9,"不动产":1.6},
{type:'十月',"房管":1.1,"税务":1.1,"不动产":1.4},
{type:'十一月',"房管":1.85,"税务":1.6,"不动产":1.5},
{type:'十二月',"房管":1.5,"税务":1.4,"不动产":1.3}
]
const xljgFields=["房管","税务","不动产"]
const dataCol1 = [{
title: '业务号',
align:"center",
dataIndex: 'reBizCode'
},{
title: '业务类型',
align:"center",
dataIndex: 'type'
},{
title: '受理人',
align:"center",
dataIndex: 'acceptBy'
},{
title: '受理时间',
align:"center",
dataIndex: 'acceptDate'
},{
title: '当前节点',
align:"center",
dataIndex: 'curNode'
},{
title: '办理时长',
align:"center",
dataIndex: 'flowRate',
scopedSlots: { customRender: 'flowRate' }
}];
const dataSource1=[
{reBizCode:"1",type:"转移登记",acceptBy:'张三',acceptDate:"2019-01-22",curNode:"任务分派",flowRate:60},
{reBizCode:"2",type:"抵押登记",acceptBy:'李四',acceptDate:"2019-01-23",curNode:"领导审核",flowRate:30},
{reBizCode:"3",type:"转移登记",acceptBy:'王武',acceptDate:"2019-01-25",curNode:"任务处理",flowRate:20},
{reBizCode:"4",type:"转移登记",acceptBy:'赵楼',acceptDate:"2019-11-22",curNode:"部门审核",flowRate:80},
{reBizCode:"5",type:"转移登记",acceptBy:'钱就',acceptDate:"2019-12-12",curNode:"任务分派",flowRate:90},
{reBizCode:"6",type:"转移登记",acceptBy:'孙吧',acceptDate:"2019-03-06",curNode:"任务处理",flowRate:10},
{reBizCode:"7",type:"抵押登记",acceptBy:'周大',acceptDate:"2019-04-13",curNode:"任务分派",flowRate:100},
{reBizCode:"8",type:"抵押登记",acceptBy:'吴二',acceptDate:"2019-05-09",curNode:"任务上报",flowRate:50},
{reBizCode:"9",type:"抵押登记",acceptBy:'郑爽',acceptDate:"2019-07-12",curNode:"任务处理",flowRate:63},
{reBizCode:"20",type:"抵押登记",acceptBy:'林有',acceptDate:"2019-12-12",curNode:"任务打回",flowRate:59},
{reBizCode:"11",type:"转移登记",acceptBy:'码云',acceptDate:"2019-09-10",curNode:"任务签收",flowRate:87},
]
const dataCol2 = [{
title: '业务号',
align:"center",
dataIndex: 'reBizCode'
},{
title: '受理人',
align:"center",
dataIndex: 'acceptBy'
},{
title: '发起时间',
align:"center",
dataIndex: 'acceptDate'
},{
title: '当前节点',
align:"center",
dataIndex: 'curNode'
},{
title: '超时时间',
align:"center",
dataIndex: 'flowRate',
scopedSlots: { customRender: 'flowRate' }
}];
const dataSource2=[
{reBizCode:"A001",type:"转移登记",acceptBy:'张四',acceptDate:"2019-01-22",curNode:"任务分派",flowRate:12},
{reBizCode:"A002",type:"抵押登记",acceptBy:'李吧',acceptDate:"2019-01-23",curNode:"任务签收",flowRate:3},
{reBizCode:"A003",type:"转移登记",acceptBy:'王三',acceptDate:"2019-01-25",curNode:"任务处理",flowRate:24},
{reBizCode:"A004",type:"转移登记",acceptBy:'赵二',acceptDate:"2019-11-22",curNode:"部门审核",flowRate:10},
{reBizCode:"A005",type:"转移登记",acceptBy:'钱大',acceptDate:"2019-12-12",curNode:"任务签收",flowRate:8},
{reBizCode:"A006",type:"转移登记",acceptBy:'孙就',acceptDate:"2019-03-06",curNode:"任务处理",flowRate:10},
{reBizCode:"A007",type:"抵押登记",acceptBy:'周晕',acceptDate:"2019-04-13",curNode:"部门审核",flowRate:24},
{reBizCode:"A008",type:"抵押登记",acceptBy:'吴有',acceptDate:"2019-05-09",curNode:"部门审核",flowRate:30},
{reBizCode:"A009",type:"抵押登记",acceptBy:'郑武',acceptDate:"2019-07-12",curNode:"任务分派",flowRate:1},
{reBizCode:"A0010",type:"抵押登记",acceptBy:'林爽',acceptDate:"2019-12-12",curNode:"部门审核",flowRate:16},
{reBizCode:"A0011",type:"转移登记",acceptBy:'码楼',acceptDate:"2019-09-10",curNode:"部门审核",flowRate:7},
]
export default {
name: "IndexBdc",
components: {
ATooltip,
ACol,
ChartCard,
MiniArea,
MiniBar,
DashChartDemo,
BarMultid,
IndexBar
},
data() {
return {
loading: true,
cardCount:{
sll:100,
bjl:87,
isll:15,
ibjl:9
},
todaySll:60,
todayBjl:54,
todayISll:13,
todayIBjl:7,
chartData:{
sll:[],
bjl:[],
isll:[],
ibjl:[]
},
jhjgFields,
jhjgData,
xljgData,
xljgFields,
diskInfo:[
{name:"C盘",restPPT:7},
{name:"D盘",restPPT:5}
],
registerTypeList:[{
text:"业务受理"
},{
text:"业务管理"
},{
text:"文件管理"
},{
text:"信息查询"
}],
dataSource1:[],
dataSource2:[],
columns:dataCol1,
columns2:dataCol2,
ipagination1:{
current: 1,
pageSize: 5,
pageSizeOptions: ['10', '20', '30'],
showTotal: (total, range) => {
return range[0] + "-" + range[1] + " " + total + ""
},
showQuickJumper: true,
showSizeChanger: true,
total: 0,
},
ipagination2:{
current: 1,
pageSize: 5,
pageSizeOptions: ['10', '20', '30'],
showTotal: (total, range) => {
return range[0] + "-" + range[1] + " " + total + ""
},
showQuickJumper: true,
showSizeChanger: true,
total: 0,
},
indexRegisterType:"转移登记",
indexBottomTab:"1"
}
},
methods:{
goPage(){
this.$message.success("根据业务自行处理跳转页面!")
},
changeRegisterType(e){
this.indexRegisterType = e.target.value
if(this.indexBottomTab=="1"){
this.loadDataSource1()
}else{
this.loadDataSource2()
}
},
tableChange1(pagination){
this.ipagination1.current = pagination.current
this.ipagination1.pageSize = pagination.pageSize
this.queryTimeoutInfo()
},
tableChange2(pagination){
this.ipagination2.current = pagination.current
this.ipagination2.pageSize = pagination.pageSize
this.queryNodeTimeoutInfo()
},
getFlowRateNumber(value){
return Number(value)
},
getPercentFormat(value){
if(value==100){
return "超时"
}else{
return value+"%"
}
},
getPercentColor(value){
let p = Number(value)
if(p>=90 && p<100){
return 'rgb(244, 240, 89)'
}else if(p>=100){
return 'red'
}else{
return 'rgb(16, 142, 233)'
}
},
loadDataSource1(){
this.dataSource1 = dataSource1.filter(item=>{
if(!this.indexRegisterType){
return true
}
return item.type==this.indexRegisterType
})
},
loadDataSource2(){
this.dataSource2 = dataSource2.filter(item=>{
if(!this.indexRegisterType){
return true
}
return item.type==this.indexRegisterType
})
}
},
created() {
this.loadDataSource1()
this.loadDataSource2()
setTimeout(() => {
this.loading = !this.loading
}, 1000)
}
}
</script>
<style lang="less" scoped>
.extra-wrapper {
line-height: 55px;
padding-right: 24px;
.extra-item {
display: inline-block;
margin-right: 24px;
a {
margin-left: 24px;
}
}
}
.item-group {
padding: 20px 0 8px 24px;
font-size: 0;
a {
color: rgba(0, 0, 0, 0.65);
display: inline-block;
font-size: 14px;
margin-bottom: 13px;
width: 25%;
}
}
.item-group {
.more-btn {
margin-bottom: 13px;
text-align: center;
}
}
.list-content-item {
color: rgba(0, 0, 0, .45);
display: inline-block;
vertical-align: middle;
font-size: 14px;
margin-left: 40px;
}
@media only screen and (min-width: 1600px) {
.list-content-item{
margin-left:60px;
}
}
@media only screen and (max-width: 1300px) {
.list-content-item{
margin-left:20px;
}
.width-hidden4{
display:none
}
}
.list-content-item{
span{line-height: 20px;}
}
.list-content-item{
p{margin-top: 4px;margin-bottom:0;line-height:22px;}
}
.anty-list-cust {
.ant-list-item-meta{flex: 0.3 !important;}
}
.anty-list-cust {
.ant-list-item-content{flex:1 !important; justify-content:flex-start !important;margin-left: 20px;}
}
</style>

View File

@ -0,0 +1,269 @@
<template>
<div class="page-header-index-wide">
<a-row :gutter="24">
<a-col :sm="24" :md="12" :xl="6" :style="{ marginBottom: '24px' }">
<chart-card :loading="loading" title="总销售额" total="126,560">
<a-tooltip title="指标说明" slot="action">
<a-icon type="info-circle-o" />
</a-tooltip>
<div>
<trend flag="up" style="margin-right: 16px;">
<span slot="term">周同比</span>
12%
</trend>
<trend flag="down">
<span slot="term">日同比</span>
11%
</trend>
</div>
<template slot="footer">日均销售额<span>¥ 234.56</span></template>
</chart-card>
</a-col>
<a-col :sm="24" :md="12" :xl="6" :style="{ marginBottom: '24px' }">
<chart-card :loading="loading" title="订单量" :total="8846 | NumberFormat">
<a-tooltip title="指标说明" slot="action">
<a-icon type="info-circle-o" />
</a-tooltip>
<div>
<mini-area />
</div>
<template slot="footer">日订单量<span> {{ '1234' | NumberFormat }}</span></template>
</chart-card>
</a-col>
<a-col :sm="24" :md="12" :xl="6" :style="{ marginBottom: '24px' }">
<chart-card :loading="loading" title="支付笔数" :total="6560 | NumberFormat">
<a-tooltip title="指标说明" slot="action">
<a-icon type="info-circle-o" />
</a-tooltip>
<div>
<mini-bar :height="40" />
</div>
<template slot="footer">转化率 <span>60%</span></template>
</chart-card>
</a-col>
<a-col :sm="24" :md="12" :xl="6" :style="{ marginBottom: '24px' }">
<chart-card :loading="loading" title="运营活动效果" total="78%">
<a-tooltip title="指标说明" slot="action">
<a-icon type="info-circle-o" />
</a-tooltip>
<div>
<mini-progress color="rgb(19, 194, 194)" :target="80" :percentage="78" :height="8" />
</div>
<template slot="footer">
<trend flag="down" style="margin-right: 16px;">
<span slot="term">同周比</span>
12%
</trend>
<trend flag="up">
<span slot="term">日环比</span>
80%
</trend>
</template>
</chart-card>
</a-col>
</a-row>
<a-card :loading="loading" :bordered="false" :body-style="{padding: '0'}">
<div class="salesCard">
<a-tabs default-active-key="1" size="large" :tab-bar-style="{marginBottom: '24px', paddingLeft: '16px'}">
<div class="extra-wrapper" slot="tabBarExtraContent">
<div class="extra-item">
<a>今日</a>
<a>本周</a>
<a>本月</a>
<a>本年</a>
</div>
<a-range-picker :style="{width: '256px'}" />
</div>
<a-tab-pane loading="true" tab="销售额" key="1">
<a-row>
<a-col :xl="16" :lg="12" :md="12" :sm="24" :xs="24">
<bar title="销售额排行" :dataSource="barData"/>
</a-col>
<a-col :xl="8" :lg="12" :md="12" :sm="24" :xs="24">
<rank-list title="门店销售排行榜" :list="rankList"/>
</a-col>
</a-row>
</a-tab-pane>
<a-tab-pane tab="销售趋势" key="2">
<a-row>
<a-col :xl="16" :lg="12" :md="12" :sm="24" :xs="24">
<bar title="销售额趋势" :dataSource="barData"/>
</a-col>
<a-col :xl="8" :lg="12" :md="12" :sm="24" :xs="24">
<rank-list title="门店销售排行榜" :list="rankList"/>
</a-col>
</a-row>
</a-tab-pane>
</a-tabs>
</div>
</a-card>
<a-row>
<a-col :span="24">
<a-card :loading="loading" :bordered="false" title="最近一周访问量统计" :style="{ marginTop: '24px' }">
<a-row>
<a-col :span="6">
<head-info title="今日IP" :content="loginfo.todayIp"></head-info>
</a-col>
<a-col :span="2">
<a-spin class='circle-cust'>
<a-icon slot="indicator" type="environment" style="font-size: 24px" />
</a-spin>
</a-col>
<a-col :span="6">
<head-info title="今日访问" :content="loginfo.todayVisitCount"></head-info>
</a-col>
<a-col :span="2">
<a-spin class='circle-cust'>
<a-icon slot="indicator" type="team" style="font-size: 24px" />
</a-spin>
</a-col>
<a-col :span="6">
<head-info title="总访问量" :content="loginfo.totalVisitCount"></head-info>
</a-col>
<a-col :span="2">
<a-spin class='circle-cust'>
<a-icon slot="indicator" type="rise" style="font-size: 24px" />
</a-spin>
</a-col>
</a-row>
<line-chart-multid :fields="visitFields" :dataSource="visitInfo"></line-chart-multid>
</a-card>
</a-col>
</a-row>
</div>
</template>
<script>
import ChartCard from '@/components/ChartCard'
import ACol from "ant-design-vue/es/grid/Col"
import ATooltip from "ant-design-vue/es/tooltip/Tooltip"
import MiniArea from '@/components/chart/MiniArea'
import MiniBar from '@/components/chart/MiniBar'
import MiniProgress from '@/components/chart/MiniProgress'
import RankList from '@/components/chart/RankList'
import Bar from '@/components/chart/Bar'
import LineChartMultid from '@/components/chart/LineChartMultid'
import HeadInfo from '@/components/tools/HeadInfo.vue'
import Trend from '@/components/Trend'
import { getLoginfo,getVisitInfo } from '@/api/api'
const rankList = []
for (let i = 0; i < 7; i++) {
rankList.push({
name: '白鹭岛 ' + (i+1) + ' 号店',
total: 1234.56 - i * 100
})
}
const barData = []
for (let i = 0; i < 12; i += 1) {
barData.push({
x: `${i + 1}月`,
y: Math.floor(Math.random() * 1000) + 200
})
}
export default {
name: "IndexChart",
components: {
ATooltip,
ACol,
ChartCard,
MiniArea,
MiniBar,
MiniProgress,
RankList,
Bar,
Trend,
LineChartMultid,
HeadInfo
},
data() {
return {
loading: true,
center: null,
rankList,
barData,
loginfo:{},
visitFields:['ip','visit'],
visitInfo:[],
indicator: <a-icon type="loading" style="font-size: 24px" spin />
}
},
created() {
setTimeout(() => {
this.loading = !this.loading
}, 1000)
this.initLogInfo();
},
methods: {
initLogInfo () {
getLoginfo(null).then((res)=>{
if(res.success){
Object.keys(res.result).forEach(key=>{
res.result[key] =res.result[key]+""
})
this.loginfo = res.result;
}
})
getVisitInfo().then(res=>{
if(res.success){
console.log("aaaaaa",res.result)
this.visitInfo = res.result;
}
})
},
}
}
</script>
<style lang="less" scoped>
.circle-cust{
position: relative;
top: 28px;
left: -100%;
}
.extra-wrapper {
line-height: 55px;
padding-right: 24px;
.extra-item {
display: inline-block;
margin-right: 24px;
a {
margin-left: 24px;
}
}
}
/* 首页访问量统计 */
.head-info {
position: relative;
text-align: left;
padding: 0 32px 0 0;
min-width: 125px;
&.center {
text-align: center;
padding: 0 32px;
}
span {
color: rgba(0, 0, 0, .45);
display: inline-block;
font-size: .95rem;
line-height: 42px;
margin-bottom: 4px;
}
p {
line-height: 42px;
margin: 0;
a {
font-weight: 600;
font-size: 1rem;
}
}
}
</style>

View File

@ -0,0 +1,372 @@
<template>
<div class="index-container-ty">
<a-spin :spinning="loading">
<a-row type="flex" justify="start" :gutter="3">
<a-col :sm="24" :lg="12">
<a-card>
<div slot="title" class="index-md-title">
<img src="../../assets/daiban.png"/>
我的待办【{{ dataSource1.length }}】
</div>
<div slot="extra">
<a v-if="dataSource1 && dataSource1.length>0" slot="footer" @click="goPage">更多 <a-icon type="double-right" /></a>
</div>
<a-table
:class="'my-index-table tytable1'"
ref="table1"
size="small"
rowKey="id"
:columns="columns"
:dataSource="dataSource1"
:pagination="false">
<template slot="ellipsisText" slot-scope="text">
<j-ellipsis :value="text" :length="textMaxLength"></j-ellipsis>
</template>
<template slot="dayWarnning" slot-scope="text,record">
<a-icon type="bulb" theme="twoTone" style="font-size:22px" :twoToneColor="getTipColor(record)"/>
</template>
<span slot="action" slot-scope="text, record">
<a @click="handleData">办理</a>
</span>
</a-table>
</a-card>
</a-col>
<a-col :sm="24" :lg="12">
<a-card>
<div slot="title" class="index-md-title">
<img src="../../assets/zaiban.png"/>
我的在办【{{ dataSource2.length }}】
</div>
<div slot="extra">
<a v-if="dataSource2 && dataSource2.length>0" slot="footer" @click="goPage">更多 <a-icon type="double-right" /></a>
</div>
<a-table
:class="'my-index-table tytable2'"
ref="table2"
size="small"
rowKey="id"
:columns="columns"
:dataSource="dataSource2"
:pagination="false">
<template slot="ellipsisText" slot-scope="text">
<j-ellipsis :value="text" :length="textMaxLength"></j-ellipsis>
</template>
<template slot="dayWarnning" slot-scope="text,record">
<a-icon type="bulb" theme="twoTone" style="font-size:22px" :twoToneColor="getTipColor(record)"/>
</template>
<span slot="action" slot-scope="text, record">
<a @click="handleData">办理</a>
</span>
</a-table>
</a-card>
</a-col>
<a-col :span="24">
<div style="height: 5px;"></div>
</a-col>
<a-col :sm="24" :lg="12">
<a-card>
<div slot="title" class="index-md-title">
<img src="../../assets/guaz.png"/>
我的挂账【{{ dataSource4.length }}】
</div>
<a-table
:class="'my-index-table tytable4'"
ref="table4"
size="small"
rowKey="id"
:columns="columns"
:dataSource="dataSource4"
:pagination="false">
<template slot="ellipsisText" slot-scope="text">
<j-ellipsis :value="text" :length="textMaxLength"></j-ellipsis>
</template>
<template slot="dayWarnning" slot-scope="text,record">
<a-icon type="bulb" theme="twoTone" style="font-size:22px" :twoToneColor="getTipColor(record)"/>
</template>
<span slot="action" slot-scope="text, record">
<a @click="handleData">办理</a>
</span>
</a-table>
</a-card>
</a-col>
<a-col :sm="24" :lg="12">
<a-card>
<div slot="title" class="index-md-title">
<img src="../../assets/duban.png"/>
我的督办【{{ dataSource3.length }}】
</div>
<a-table
:class="'my-index-table tytable3'"
ref="table3"
size="small"
rowKey="id"
:columns="columns"
:dataSource="dataSource3"
:pagination="false">
<template slot="ellipsisText" slot-scope="text">
<j-ellipsis :value="text" :length="textMaxLength"></j-ellipsis>
</template>
<template slot="dayWarnning" slot-scope="text,record">
<a-icon type="bulb" theme="twoTone" style="font-size:22px" :twoToneColor="getTipColor(record)"/>
</template>
<span slot="action" slot-scope="text, record">
<a @click="handleData">办理</a>
</span>
</a-table>
</a-card>
</a-col>
</a-row>
</a-spin>
</div>
</template>
<script>
import noDataPng from '@/assets/nodata.png'
import JEllipsis from '@/components/jeecg/JEllipsis'
const tempSs1=[{
id:"001",
orderNo:"[1]1267102",
orderTitle:"药品出问题了",
restDay:1
},{
id:"002",
orderNo:"[4]5967102",
orderTitle:"吃了xxx医院的药病情越来越严重",
restDay:0
},{
id:"003",
orderNo:"[3]5988987",
orderTitle:"今天去超市买鸡蛋鸡蛋都是坏的",
restDay:7
},{
id:"004",
orderNo:"[2]5213491",
orderTitle:"xx宝实体店高价售卖xx",
restDay:5
},{
id:"005",
orderNo:"[1]1603491",
orderTitle:"以红利相诱答应退保后扣一年费用",
restDay:0
}]
const tempSs2=[{
id:"001",
orderTitle:"我要投诉这个大超市",
orderNo:"[1]10299456",
restDay:6
},{
id:"002",
orderTitle:"xxx医院乱开药方,售卖假药",
orderNo:"[2]20235691",
restDay:0
},{
id:"003",
orderTitle:"我想问问这家店是干啥的",
orderNo:"[3]495867322",
restDay:7
},{
id:"004",
orderTitle:"我要举报朝阳区奥森公园酒店",
orderNo:"[2]1193849",
restDay:3
},{
id:"005",
orderTitle:"我今天吃饭吃到一个石头子",
orderNo:"[4]56782344",
restDay:9
}]
//4-7天
const tip_green = "rgba(0, 255, 0, 1)"
//1-3天
const tip_yellow = "rgba(255, 255, 0, 1)"
//超期
const tip_red = "rgba(255, 0, 0, 1)"
export default {
name: "IndexTask",
components:{ JEllipsis },
data() {
return {
loading:false,
textMaxLength:8,
dataSource1:[],
dataSource2:[],
dataSource3:[],
dataSource4:[],
columns: [
{
title: '',
dataIndex: '',
key:'rowIndex',
width:50,
fixed:'left',
align:"center",
scopedSlots: {customRender: "dayWarnning"}
},
{
title:'剩余天数',
align:"center",
dataIndex: 'restDay',
width:80
},
{
title:'工单标题',
align:"center",
dataIndex: 'orderTitle',
scopedSlots: {customRender: "ellipsisText"}
},
{
title:'工单编号',
align:"center",
dataIndex: 'orderNo',
},
{
title: '操作',
dataIndex: 'action',
align:"center",
scopedSlots: { customRender: 'action' }
}
]
}
},
created() {
this.mock();
},
mounted(){
},
methods: {
getTipColor(rd){
let num = rd.restDay
if(num<=0){
return tip_red
}else if(num>=1 && num<4){
return tip_yellow
}else if(num>=4){
return tip_green
}
},
goPage(){
this.$message.success("请根据具体业务跳转页面")
//this.$router.push({ path: '/comp/mytask' })
},
mock(){
this.dataSource1=tempSs1
this.dataSource2=tempSs2
this.dataSource3=tempSs1
this.dataSource4=[]
this.ifNullDataSource(this.dataSource4,'.tytable4')
},
ifNullDataSource(ds,tb){
this.$nextTick(()=>{
if(!ds || ds.length==0){
var tmp = document.createElement('img');
tmp.src=noDataPng
tmp.width=300
let tbclass=`${tb} .ant-table-placeholder`
document.querySelector(tbclass).innerHTML=""
document.querySelector(tbclass).appendChild(tmp)
}
})
},
handleData(){
this.$message.success("办理完成")
}
}
}
</script>
<style>
.my-index-table{height:270px}
.my-index-table table{font-size: 14px !important;}
.index-container-ty .ant-card-head-title{padding-top: 6px;padding-bottom: 6px;}
.index-container-ty .ant-card-extra{padding:0}
.index-container-ty .ant-card-extra a{color:#fff}
.index-container-ty .ant-card-extra a:hover{color:#152ede}
.index-container-ty .ant-card-head-wrapper,.index-container-ty .ant-card-head{
line-height:24px;
min-height:24px;
/*background: #90aeff;*/
background: #7196fb;
}
.index-container-ty .ant-card-body{padding: 10px 12px 0px 12px}
/* .index-container-ty .ant-card-actions{background: #fff}
.index-container-ty .ant-card-actions li {margin:2px 0;}
.index-container-ty .ant-card-actions > li > span{width: 100%}*/
.index-container-ty .ant-table-footer{text-align: right;padding:6px 12px 6px 6px;background: #fff;border-top: 2px solid #f7f1f1;}
.index-md-title{
postion:relative;
padding-left:24px;
width: 100%;
color: #fff;
font-size: 21px;
font-family: cursive;
}
.index-md-title img{
position: absolute;
height:32px;
top: 2px;
left:14px;
}
.index-container-ty .ant-card-body{
/*border-left:1px solid #90aeff;
/*border-right:1px solid #90aeff;
border-bottom:1px solid #90aeff;*/
}
.index-container-ty .ant-table-thead > tr > th,
.index-container-ty .ant-table-tbody > tr > td{
border-bottom: 1px solid #90aeff;
}
.index-container-ty .ant-table-small > .ant-table-content > .ant-table-fixed-left > .ant-table-body-outer > .ant-table-body-inner > table > .ant-table-thead > tr > th,
.index-container-ty .ant-table-small > .ant-table-content > .ant-table-fixed-right > .ant-table-body-outer > .ant-table-body-inner > table > .ant-table-thead > tr > th{
border-bottom: 1px solid #90aeff;
}
.index-container-ty .ant-table-small > .ant-table-content > .ant-table-scroll > .ant-table-body > table > .ant-table-thead > tr > th{
border-bottom: 1px solid #90aeff;
}
.index-container-ty .ant-table-small{
border: 1px solid #90aeff;
}
.index-container-ty .ant-table-placeholder {
padding: 0
}
</style>

View File

@ -185,7 +185,7 @@
},
created() {
this.user = this.userInfo
this.avatar = window._CONFIG['imgDomainURL'] +"/"+ this.userInfo.avatar
this.avatar = window._CONFIG['staticDomainURL'] +"/"+ this.userInfo.avatar
console.log('this.avatar :'+ this.avatar)
getRoleList().then(res => {
@ -245,7 +245,7 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
.project-list {
.card-title {

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