Compare commits

..

2 Commits

Author SHA1 Message Date
d4f1f15491 多语言切换icon及切换方式代码调整 2023-08-23 10:02:52 +08:00
60f1f0dde4 系统多语言逻辑实现 2023-08-22 17:23:30 +08:00
312 changed files with 7374 additions and 1018151 deletions

View File

@ -1,9 +1,7 @@
NODE_ENV=development
VUE_APP_API_BASE_URL=http://182.92.183.230:9999
# VUE_APP_API_BASE_URL=http://192.168.0.111:9999
VUE_APP_CAS_BASE_URL=http://cas.example.org:8443/cas
VUE_APP_ONLINE_BASE_URL=http://fileview.jeecg.com/onlinePreview
VUE_APP_MAP_BASE_URL=https://ibasemaps-api.arcgis.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}?token=AAPK2b935e8bbf564ef581ca3c6fcaa5f2a71ZH84cPqqFvyz3KplFRHP8HyAwJJkh6cnpcQ-qkWh5aiyDQsGJbsXglGx0QM2cPm
# 微应用列表必须VUE_APP_SUB_开头,jeecg-app-1为子应用的项目名称,也是子应用的路由父路径
VUE_APP_SUB_jeecg-app-1 = '//localhost:8092'

View File

@ -1,5 +1,4 @@
NODE_ENV=production
VUE_APP_API_BASE_URL=/armd
VUE_APP_API_BASE_URL=http://localhost:8080/jeecg-boot
VUE_APP_CAS_BASE_URL=http://localhost:8888/cas
VUE_APP_ONLINE_BASE_URL=http://fileview.jeecg.com/onlinePreview
VUE_APP_MAP_BASE_URL=https://ibasemaps-api.arcgis.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}?token=AAPK2b935e8bbf564ef581ca3c6fcaa5f2a71ZH84cPqqFvyz3KplFRHP8HyAwJJkh6cnpcQ-qkWh5aiyDQsGJbsXglGx0QM2cPm
VUE_APP_ONLINE_BASE_URL=http://fileview.jeecg.com/onlinePreview

View File

@ -1,13 +0,0 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
},
"target": "ES6",
"module": "CommonJS",
"allowSyntheticDefaultImports": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}

View File

@ -11,13 +11,11 @@
},
"dependencies": {
"@antv/data-set": "^0.11.4",
"@antv/g2plot": "^2.4.23",
"@jeecg/antd-online-mini": "3.4.3-beta2",
"@tinymce/tinymce-vue": "2.1.0",
"@toast-ui/editor": "^2.1.2",
"ant-design-vue": "^1.7.2",
"axios": "^0.18.0",
"bignumber.js": "^9.1.2",
"china-area-data": "^5.0.1",
"clipboard": "^2.0.4",
"codemirror": "^5.46.0",
@ -28,9 +26,7 @@
"echarts": "^5.4.2",
"echarts-gl": "^2.0.9",
"enquire.js": "^2.1.6",
"file-saver": "^2.0.5",
"js-cookie": "^2.2.0",
"jszip": "^3.10.1",
"lodash.get": "^4.4.2",
"lodash.pick": "^4.4.0",
"md5": "^2.2.1",
@ -41,10 +37,8 @@
"viser-vue": "^2.4.8",
"vue": "^2.6.10",
"vue-area-linkage": "^5.1.0",
"vue-color": "^2.8.1",
"vue-cropper": "^0.5.4",
"vue-i18n": "^8.7.0",
"vue-infinite-scroll": "^2.0.2",
"vue-loader": "^15.7.0",
"vue-ls": "^3.2.0",
"vue-photo-preview": "^1.1.3",
@ -58,11 +52,9 @@
"vxe-table": "2.9.13",
"vxe-table-plugin-antd": "1.8.10",
"xe-utils": "2.4.8",
"xlsx": "^0.18.5",
"xss": "^1.0.13"
},
"devDependencies": {
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6",
"@babel/polyfill": "^7.2.5",
"@types/crypto-js": "^4.1.1",
"@vue/cli-plugin-babel": "^3.3.0",

5
public/index.html vendored
View File

@ -5,8 +5,7 @@
<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>ARMD</title>
<!-- <title>核素监测数据自动处理与交互分析系统</title> -->
<title>核素监测数据自动处理与交互分析系统</title>
<link rel="icon" href="<%= BASE_URL %>logo.png">
<script src="<%= BASE_URL %>cdn/babel-polyfill/polyfill_7_2_5.js"></script>
<style>
@ -252,7 +251,7 @@
<div class="loader-section section-right"></div>
</div>
</div>
<script src="/qtw.js"></script>
</body>
</html>

BIN
public/logo.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

1
public/qtw.js vendored

File diff suppressed because one or more lines are too long

BIN
public/qtw.wasm vendored

Binary file not shown.

View File

@ -7,7 +7,5 @@ window._CONFIG = {
//单点登录地址
VUE_APP_CAS_BASE_URL: '',
//文件预览路径
VUE_APP_ONLINE_BASE_URL: '',
// 离线地图
VUE_APP_MAP_BASE_URL_OFFLINE: 'http://localhost:8001/map/{z}/{x}/{y}.jpg'
VUE_APP_ONLINE_BASE_URL: ''
}

View File

@ -1,7 +1,6 @@
import Vue from 'vue'
import { axios } from '@/utils/request'
import signMd5Utils from '@/utils/encryption/signMd5Utils'
import qs from "qs";
const api = {
user: '/mock/api/user',
@ -14,116 +13,64 @@ const api = {
export default api
//post
export function postAction(url, parameter) {
export function postAction(url,parameter) {
let sign = signMd5Utils.getSign(url, parameter);
//将签名和时间戳,添加在请求接口 Header
// update-begin--author:taoyan---date:20220421--for: VUEN-410【签名改造】 X-TIMESTAMP牵扯
let signHeader = { "X-Sign": sign, "X-TIMESTAMP": signMd5Utils.getTimestamp() };
let signHeader = {"X-Sign": sign,"X-TIMESTAMP": signMd5Utils.getTimestamp()};
// update-end--author:taoyan---date:20220421--for: VUEN-410【签名改造】 X-TIMESTAMP牵扯
return axios({
url: url,
method: 'post',
method:'post' ,
data: parameter,
headers: signHeader
})
}
//post
export function postActionWithTimeOut(url, parameter, timeout) {
let sign = signMd5Utils.getSign(url, parameter);
//将签名和时间戳,添加在请求接口 Header
// update-begin--author:taoyan---date:20220421--for: VUEN-410【签名改造】 X-TIMESTAMP牵扯
let signHeader = { "X-Sign": sign, "X-TIMESTAMP": signMd5Utils.getTimestamp() };
// update-end--author:taoyan---date:20220421--for: VUEN-410【签名改造】 X-TIMESTAMP牵扯
return axios({
url: url,
method: 'post',
data: parameter,
headers: signHeader,
timeout
})
}
export function postFileAction(url, parameter) {
let sign = signMd5Utils.getSign(url, parameter);
//将签名和时间戳,添加在请求接口 Header
// update-begin--author:taoyan---date:20220421--for: VUEN-410【签名改造】 X-TIMESTAMP牵扯
let signHeader = { "X-Sign": sign, "X-TIMESTAMP": signMd5Utils.getTimestamp() };
// update-end--author:taoyan---date:20220421--for: VUEN-410【签名改造】 X-TIMESTAMP牵扯
return axios({
url: url,
method: 'post',
data: parameter,
responseType: "blob",
headers: signHeader
})
}
//post method= {post | put}
export function httpAction(url, parameter, method) {
export function httpAction(url,parameter,method) {
let sign = signMd5Utils.getSign(url, parameter);
//将签名和时间戳,添加在请求接口 Header
// update-begin--author:taoyan---date:20220421--for: VUEN-410【签名改造】 X-TIMESTAMP牵扯
let signHeader = { "X-Sign": sign, "X-TIMESTAMP": signMd5Utils.getTimestamp() };
let signHeader = {"X-Sign": sign,"X-TIMESTAMP": signMd5Utils.getTimestamp()};
// update-end--author:taoyan---date:20220421--for: VUEN-410【签名改造】 X-TIMESTAMP牵扯
return axios({
url: url,
method: method,
method:method ,
data: parameter,
headers: signHeader
})
}
//put
export function putAction(url, parameter) {
export function putAction(url,parameter) {
return axios({
url: url,
method: 'put',
method:'put',
data: parameter
})
}
//get
export function getAction(url, parameter, cancelToken) {
export function getAction(url,parameter) {
let sign = signMd5Utils.getSign(url, parameter);
//将签名和时间戳,添加在请求接口 Header
// update-begin--author:taoyan---date:20220421--for: VUEN-410【签名改造】 X-TIMESTAMP牵扯
let signHeader = { "X-Sign": sign, "X-TIMESTAMP": signMd5Utils.getTimestamp() };
let signHeader = {"X-Sign": sign,"X-TIMESTAMP": signMd5Utils.getTimestamp()};
// update-end--author:taoyan---date:20220421--for: VUEN-410【签名改造】 X-TIMESTAMP牵扯
return axios({
url: url,
method: 'get',
params: parameter,
paramsSerializer: function (params) {
return qs.stringify(params, { arrayFormat: "repeat" });
},
headers: signHeader,
cancelToken
})
}
export function getFileAction(url, parameter) {
let sign = signMd5Utils.getSign(url, parameter);
//将签名和时间戳,添加在请求接口 Header
// update-begin--author:taoyan---date:20220421--for: VUEN-410【签名改造】 X-TIMESTAMP牵扯
let signHeader = { "X-Sign": sign, "X-TIMESTAMP": signMd5Utils.getTimestamp() };
// update-end--author:taoyan---date:20220421--for: VUEN-410【签名改造】 X-TIMESTAMP牵扯
return axios({
url: url,
method: 'get',
params: parameter,
responseType: "blob",
paramsSerializer: function (params) {
return qs.stringify(params, { arrayFormat: "repeat" });
},
headers: signHeader
})
}
//deleteAction
export function deleteAction(url, parameter) {
export function deleteAction(url,parameter) {
return axios({
url: url,
method: 'delete',
@ -179,15 +126,15 @@ export function saveService(parameter) {
* @param parameter
* @returns {*}
*/
export function downFile(url, parameter, method = 'get') {
if (method == 'get') {
export function downFile(url,parameter, method='get'){
if(method=='get'){
return axios({
url: url,
params: parameter,
method: method,
method: method ,
responseType: 'blob'
})
} else {
}else{
return axios({
url: url,
method: method,
@ -233,11 +180,11 @@ export function downloadFile(url, fileName, parameter, method) {
* @param parameter
* @returns {*}
*/
export function uploadAction(url, parameter) {
export function uploadAction(url,parameter){
return axios({
url: url,
data: parameter,
method: 'post',
method:'post' ,
headers: {
'Content-Type': 'multipart/form-data', // 文件上传
},
@ -250,17 +197,17 @@ export function uploadAction(url, parameter) {
* @param subStr
* @returns {*}
*/
export function getFileAccessHttpUrl(avatar, subStr) {
if (!subStr) subStr = 'http'
export function getFileAccessHttpUrl(avatar,subStr) {
if(!subStr) subStr = 'http'
try {
if (avatar && avatar.startsWith(subStr)) {
if(avatar && avatar.startsWith(subStr)){
return avatar;
} else {
if (avatar && avatar.length > 0 && avatar.indexOf('[') == -1) {
}else{
if(avatar && avatar.length>0 && avatar.indexOf('[')==-1){
return window._CONFIG['staticDomainURL'] + "/" + avatar;
}
}
} catch (err) {
return;
}catch(err){
return;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1014 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1003 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1003 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 975 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1002 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1002 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1004 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1007 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -1,80 +0,0 @@
::v-deep {
.ant-tabs{
height: 100%;
.ant-tabs-top-content{
height: calc(100% - 50px);
.ant-tabs-tabpane{
height: 100%;
overflow: auto;
overflow: hidden;
}
}
}
.ant-tabs-bar{
width: 100%;
height: 40px;
margin: 0 0 10px 0;
background-color: rgba(12, 235, 201, 0.05);
border-top: 1px solid rgba(12, 235, 201, 0.3);
border-bottom: 1px solid rgba(12, 235, 201, 0.3);
}
.ant-tabs-nav .ant-tabs-tab{
height: 30px;
line-height: 30px;
background-color: rgba(58, 236, 240, 0.22);
font-family: BookmanOldStyle;
font-size: 16px;
font-weight: bold;
font-stretch: normal;
letter-spacing: 2px;
color: #c9f6f6;
margin: 0 0 0 10px;
padding: 0 23px;
position: relative;
&::before{
content: "";
position: absolute;
top: 0;
left: 0;
width: 7px;
height: 29px;
color: rgba(58, 236, 240, 0.22);
border: 1px solid #569e9e;
border-right: none;
border-radius: 0;
}
&::after{
content: "";
position: absolute;
top: 0;
right: 0;
width: 7px;
height: 29px;
color: rgba(58, 236, 240, 0.22);
border: 1px solid #569e9e;
border-left: none;
}
&-active{
&::before,
&::after {
border-color: #0cecca !important;
}
}
}
.ant-tabs-ink-bar{
display: none !important
}
.ant-tabs-nav .ant-tabs-tab-active{
color: #2affdf;
}
.ant-row{
height: 36px;
line-height: 36px;
}
.ant-tabs-tab-prev, .ant-tabs-tab-next{
color: #c9f6f6;
}
.ant-tabs-tab-prev:hover, .ant-tabs-tab-next:hover{
color: #2affdf;
}
}

View File

@ -1,16 +1,14 @@
/**
* 列表查询通用样式,移动端自适应
*/
.search {
/**
.search{
margin-bottom: 54px;
*/
}
.fold {
.fold{
width: calc(100% - 216px);
display: inline-block;
display: inline-block
}
.operator {
.operator{
margin-bottom: 18px;
}
@media screen and (max-width: 900px) {
@ -24,7 +22,7 @@
i {
cursor: pointer;
}
.trcolor {
.trcolor{
background-color: rgba(255, 192, 203, 0.31);
color: red;
color:red;
}

View File

@ -1,81 +0,0 @@
<template>
<div class="color-picker">
<div class="color-picker-toggle" @click="togglePanel">
<slot></slot>
</div>
<div class="color-picker-mask" :class="show ? 'show' : ''" @click="show = false">
<div class="color-picker-panel" :style="style" @click.stop>
<chrome v-model="color" disableAlpha></chrome>
</div>
</div>
</div>
</template>
<script>
import { Chrome } from 'vue-color'
export default {
props: {
value: {
type: String,
required: true
}
},
components: {
Chrome
},
data() {
return {
style: {
top: 0,
left: 0
},
show: false
}
},
methods: {
togglePanel(e) {
const { x, y, offsetX, offsetY, target } = e
this.style.top = y - offsetY + 'px'
this.style.left = x - offsetX + target.offsetWidth + 4 + 'px'
this.show = true
}
},
computed: {
color: {
set(val) {
this.$emit('input', val.hex)
},
get() {
return this.value
}
}
}
}
</script>
<style lang="less" scoped>
.color-picker {
&-mask {
display: none;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: transparent;
z-index: 99999999;
&.show {
display: block;
}
}
&-toggle {
cursor: pointer;
}
&-panel {
position: absolute;
}
}
</style>

View File

@ -0,0 +1,51 @@
<template>
<div class="custom-chart" ref="containerRef" :style="{ height: height + 'px' }"></div>
</template>
<script>
import * as echarts from 'echarts'
import 'echarts-gl'
export default {
props: {
option: {
type: Object,
default: () => ({})
},
height: {
type: Number,
default: 0
}
},
data() {
return {}
},
mounted() {
this.chart = echarts.init(this.$refs.containerRef)
this.chart.setOption(this.option)
},
methods: {
resize() {
this.chart && this.chart.resize()
}
},
watch: {
option: {
handler() {
if (this.chart) {
this.chart.setOption(this.option)
}
},
deep: true
},
height() {
this.$nextTick(() => {
this.chart && this.chart.resize()
})
}
}
}
</script>
<style lang="less" scoped>
.custom-chart {
height: 100% !important;
}
</style>

View File

@ -1,84 +0,0 @@
<template>
<a-select v-bind="$attrs" v-model="innerValue" show-arrow @change="onChange">
<img slot="suffixIcon" src="@/assets/images/global/select-down.png" alt="" />
<div slot="dropdownRender" slot-scope="menu">
<v-nodes :vnodes="menu" />
<a-divider style="margin: 0;" />
<div
style="padding: 4px 12px; cursor: pointer;"
@mousedown="e => e.preventDefault()"
>
<a-checkbox v-model="allVal" @change="checkedAll"><span @click.prevent="handleClick">ALL</span></a-checkbox>
</div>
</div>
</a-select>
</template>
<script>
export default {
props: {
value: {
type: [String, Number, Array],
},
allChecked: {
type: Boolean,
default:false
}
},
components: {
VNodes: {
functional: true,
render: (h, ctx) => ctx.props.vnodes,
},
},
data() {
return {
innerValue: this.value,
allVal:this.allChecked
}
},
methods: {
checkedAll(val) {
this.$emit('changeAll', val.target.checked)
},
handleClick(e) {
console.log("dfasdfasfad", e);
this.allVal = !this.allVal
this.$emit('changeAll', this.allVal)
},
onChange(val) {
this.$emit('input', val)
this.$emit('change', val)
}
},
watch: {
value: {
handler(val) {
this.innerValue = val
},
deep: true
},
allChecked: {
handler(val) {
this.allVal = val
}
}
}
}
</script>
<style lang="less" scoped>
.ant-select {
width: 100%;
.ant-select-arrow-icon {
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
}
&-open {
.ant-select-arrow-icon {
transform: rotate(180deg);
}
}
}
.ant-select-dropdown-content{
position: relative;
background: #03353f;
}
</style>

View File

@ -3,50 +3,40 @@
</template>
<script>
import * as echarts from 'echarts'
import 'echarts-gl'
const events = ['click', 'brushEnd', 'dataZoom']
const zrEvents = ['mousemove', 'mousedown', 'mouseup', 'click', 'dblclick', 'contextmenu']
const events = ['brushEnd']
const zrEvents = ['mousemove', 'mousedown', 'mouseup']
export default {
props: {
option: {
type: Object,
default: () => ({}),
},
opts: {
type: Object,
default: () => {},
default: () => ({})
},
height: {
type: Number,
default: null,
},
default: 0
}
},
data() {
return {}
},
mounted() {
this._chart = echarts.init(this.$refs.containerRef)
this._chart.setOption(this.option, this.opts)
this._chart.setOption(this.option)
this.initEventListener()
},
beforeDestroy() {
if (this._chart) {
this._chart.dispose()
this._chart = null
}
},
methods: {
initEventListener() {
events.forEach((eventName) => {
events.forEach(eventName => {
this._chart.on(eventName, (params) => {
this.$emit(eventName, params)
})
})
const zr = this.getZRender()
zrEvents.forEach((eventName) => {
zr.on(eventName, (params) => {
zrEvents.forEach(eventName => {
zr.on(eventName, params => {
this.$emit(`zr:${eventName}`, params)
})
})
@ -63,27 +53,27 @@ export default {
getZRender() {
return this._chart.getZr()
},
}
},
watch: {
option: {
handler() {
if (this._chart) {
this._chart.setOption(this.option, this.opts)
this._chart.setOption(this.option)
}
},
deep: true,
deep: true
},
height() {
this.$nextTick(() => {
this._chart && this._chart.resize()
})
},
},
}
}
}
</script>
<style lang="less" scoped>
.custom-chart {
height: 100%;
height: 100% !important;
}
</style>

View File

@ -1,5 +1,5 @@
<template>
<a-date-picker v-bind="$attrs" v-model="innerValue" @change="onChange">
<a-date-picker v-bind="$attrs" v-model="innerValue">
<img src="@/assets/images/global/calendar.png" slot="suffixIcon" alt="" srcset="" />
</a-date-picker>
</template>
@ -19,12 +19,7 @@ export default {
this.$emit('input', val)
}
}
},
methods: {
onChange(mont,date) {
this.$emit("change",mont,date)
}
},
}
}
</script>
<style lang=""></style>

View File

@ -1,22 +1,12 @@
<template>
<a-modal
:class="'custom-modal' + (innerFullscreen ? ' fullscreen' : '')"
v-bind="_attrs"
v-model="visible"
:maskClosable="false"
@cancel="handleCancel"
>
<a-modal :class="'custom-modal' + (innerFullscreen ? ' fullscreen' : '')" v-bind="_attrs" v-model="visible">
<img slot="closeIcon" src="@/assets/images/global/close.png" />
<div slot="title">
<div class="custom-modal-title">
<span>{{ title }}</span>
<template v-if="enableFullScreen">
<img
v-if="innerFullscreen"
src="@/assets/images/global/quit-fullscreen.png"
@click="innerFullscreen = false"
/>
<img v-else src="@/assets/images/global/fullscreen.png" @click="innerFullscreen = true" />
<img v-if="innerFullscreen" src="@/assets/images/global/quit-fullscreen.png" @click="innerFullscreen = false" />
<img v-else src="@/assets/images/global/fullscreen.png" @click="innerFullscreen = true" />
</template>
</div>
</div>
@ -34,24 +24,24 @@
export default {
props: {
value: {
type: Boolean,
type: Boolean
},
okHandler: {
type: Function,
type: Function
},
title: {
type: String,
type: String
},
enableFullScreen: {
type: Boolean,
default: false,
},
default: false
}
},
data() {
return {
visible: this.value,
confirmLoading: false,
innerFullscreen: false,
innerFullscreen: false
}
},
watch: {
@ -66,17 +56,15 @@ export default {
},
innerFullscreen(val) {
this.$emit('fullscreen', val)
},
}
},
methods: {
async onSave() {
if (this.okHandler instanceof Function) {
try {
this.confirmLoading = true
const success = await this.okHandler()
if (success !== false) {
this.visible = false
}
await this.okHandler()
this.visible = false
} catch (error) {
console.error(error)
} finally {
@ -88,10 +76,7 @@ export default {
},
onCancel() {
this.visible = false
},
handleCancel() {
this.$emit('cancel')
},
}
},
computed: {
_attrs() {
@ -106,8 +91,8 @@ export default {
// footer
hasCustomFooter() {
return !!this.$slots['custom-footer']
},
},
}
}
}
</script>
<style lang="less" scoped>

View File

@ -1,8 +1,6 @@
<template>
<a-table
ref="tableRef"
class="custom-table"
:class="['custom-table', canSelect && multiple && mouseMoveSelect ? 'mouse-move-select' : '']"
class="custom-table"
v-bind="$attrs"
:data-source="list"
:columns="columns"
@ -10,8 +8,8 @@
:row-key="rowKey"
:loading="loading"
:pagination="pagination"
:customRow="multiple && mouseMoveSelect ? customMouseMoveSelectRow : customRow"
:rowClassName="() => (canSelect ? 'custom-table-row' : '')"
:customRow="customRow"
:rowClassName="() => canSelect? 'custom-table-row': ''"
@change="handleTableChange"
>
<!-- 处理 scopedSlots -->
@ -25,174 +23,98 @@ export default {
props: {
list: {
type: Array,
default: () => [],
default: () => []
},
columns: {
type: Array,
default: () => [],
default: () => []
},
size: {
type: String,
default: 'middle',
default: 'middle'
},
rowKey: {
type: String,
default: 'id',
default: 'id'
},
loading: {
type: Boolean,
type: Boolean
},
pagination: {
type: [Object, Boolean],
type: [Object, Boolean]
},
selectedRowKeys: {
type: Array,
type: Array
},
selectionRows: {
type: Array,
type: Array
},
canSelect: {
type: Boolean,
default: true,
default: true
},
canDeselect: {
type: Boolean,
default: true,
},
//
multiple: {
type: Boolean,
default: false,
},
//
mouseMoveSelect: {
type: Boolean,
default: true,
},
default: false
}
},
data() {
return {
innerSelectedRowKeys: [],
innerSelectedRows: [],
}
},
mounted() {
if (this.canSelect && this.multiple && this.mouseMoveSelect) {
const tbody = this.$el.querySelector('.ant-table-tbody')
tbody.addEventListener('mouseleave', () => {
this.mouseMoveStartIndex = undefined
})
innerSelectedRowKeys: [],
innerSelectedRows: []
}
},
methods: {
// /
customRow(record, index) {
customRow(record) {
const key = record[this.rowKey]
return {
class: this.innerSelectedRowKeys.includes(key) ? 'ant-table-row-selected' : '',
on: {
click: () => {
if (!this.canSelect) {
if(!this.canSelect) {
return
}
//
if (this.innerSelectedRowKeys.includes(key)) {
if (this.multiple || this.canDeselect) {
const findIndex = this.innerSelectedRowKeys.findIndex((k) => k == key)
this.innerSelectedRowKeys.splice(findIndex, 1)
}
}
//
else {
if (this.multiple) {
const findIndex = this.innerSelectedRowKeys.findIndex(k => k == key)
this.innerSelectedRowKeys.splice(findIndex, 1)
} else {
if(this.multiple) {
this.innerSelectedRowKeys.push(key)
} else {
}
else {
this.innerSelectedRowKeys = [key]
}
}
this.$emit('detail', record)
this.$emit('rowClick', record, index)
},
dblclick: () => {
this.$emit('rowDblClick', record, index)
},
},
}
}
}
},
//
customMouseMoveSelectRow(record, index) {
const key = record[this.rowKey]
return {
class: this.innerSelectedRowKeys.includes(key) ? 'ant-table-row-selected' : '',
on: {
mousedown: () => {
this.innerSelectedRowKeys = []
this.mouseMoveStartIndex = index
},
mouseenter: () => {
if (this.mouseMoveStartIndex !== undefined) {
const indexes = [this.mouseMoveStartIndex, index].sort((a, b) => a - b)
this.innerSelectedRowKeys = this.list.slice(indexes[0], indexes[1] + 1).map((item) => item[this.rowKey])
}
},
mouseup: () => {
// click
if (this.mouseMoveStartIndex == index) {
this.innerSelectedRowKeys = [key]
}
this.mouseMoveStartIndex = undefined
},
},
}
},
handleTableChange(pagination, filters, sorter) {
this.$emit('change', pagination, filters, sorter)
},
// index
scrollIntoView(index) {
const tableEle = this.$refs.tableRef.$el
const tableBodyEle = tableEle.querySelector('.ant-table-body')
const prevEle = tableBodyEle.querySelector(`.ant-table-row:nth-child(${index + 1})`)
tableBodyEle.scrollTop = prevEle.offsetTop
},
}
},
watch: {
selectedRowKeys(val) {
this.innerSelectedRowKeys = val
selectedRowKeys (val) {
this.innerSelectedRowKeys = val
},
innerSelectedRowKeys() {
innerSelectedRowKeys () {
this.$emit('update:selectedRowKeys', this.innerSelectedRowKeys)
this.innerSelectedRows = this.innerSelectedRowKeys.map((key) => {
return this.list.find((item) => item[this.rowKey] === key)
return this.list.find(item => item[this.rowKey] === key)
})
this.$emit('update:selectionRows', this.innerSelectedRows)
},
}
},
computed: {
scopedSlotsKeys() {
return Object.keys(this.$scopedSlots)
},
},
}
</script>
<style lang="less" scoped>
::v-deep {
.custom-table-row {
cursor: pointer;
}
}
.mouse-move-select {
user-select: none;
::v-deep {
td {
transition: none !important;
}
}
}
</script>
<style lang="less">
.custom-table-row {
cursor: pointer;
}
</style>

View File

@ -1,98 +0,0 @@
<template>
<div class="custom-time-input">
<template v-for="(item, index) in setting">
<a-input-number
:key="index"
:formatter="(value) => `${value}`"
:precision="0"
:parser="(value) => value.replace('.', '')"
:step="1"
:max="item.max"
:min="item.min"
v-model="innerValue[index]"
></a-input-number>
<span v-if="index !== setting.length - 1" :key="'_' + index">:</span>
</template>
</div>
</template>
<script>
const setting = [
{
min: 0,
max: 23,
},
{
min: 0,
max: 59,
},
{
min: 0,
max: 59,
},
{
min: 0,
max: 999,
},
]
export default {
props: {
value: {
type: String,
},
},
data() {
this.setting = setting
return {
innerValue: this.splitValue(this.value),
}
},
methods: {
splitValue(value) {
if (value) {
const arr = value.split(':')
if (arr.length < setting.length) {
//
for (let i = 0; i < setting.length - arr.length; i++) {
arr.push(0)
}
}
return arr
} else {
return [0, 0, 0, 0]
}
},
},
watch: {
value(val) {
this.splitValue(val)
},
innerValue(val) {
const newVal = val.join(':')
this.$emit('input', newVal)
this.$emit('change', newVal)
},
},
}
</script>
<style lang="less" scoped>
.custom-time-input {
.ant-input-number {
width: 25px;
border: 0;
box-shadow: none;
::v-deep {
.ant-input-number-handler-wrap {
display: none;
}
input {
padding: 0;
text-align: center;
}
}
}
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<div class="search-form">
<a-form-model ref="form" :colon="false" :model="formModel" v-bind="$attrs">
<a-form-model ref="form" :colon="false" :model="formModel" v-bind="$attrs" @keyup.enter.native="onSearch">
<a-row v-if="type == 'single-line'" :gutter="20" style="margin-right: 0 !important;">
<a-col
class="search-form-item"
@ -10,15 +10,12 @@
:style="item.style"
>
<a-form-model-item :label="item.label" :prop="item.name" :labelCol="item.labelCol">
<a-checkbox v-if="item.type == 'a-checkbox'" v-model="formModel[item.name]" v-on="item.on">
{{ item.innerLabel }}
</a-checkbox>
<component v-else :is="item.type" v-bind="item.props" v-model="formModel[item.name]" v-on="item.on"></component>
<component :is="item.type" v-bind="item.props" v-model="formModel[item.name]" v-on="item.on"></component>
</a-form-model-item>
</a-col>
<a-button class="search-btn" type="primary" @click="onSearch">
<img src="@/assets/images/global/search.png" alt="" />
Search
{{$t('m.system.search')}}
</a-button>
<slot name="additional"></slot>
</a-row>
@ -69,15 +66,9 @@ export default {
}
},
watch: {
value: {
handler(val) {
this.formModel = val
},
deep: true
value(val) {
this.formModel = val
},
// value(val) {
// this.formModel = val
// },
formModel: {
handler(val) {
this.$emit('input', val)
@ -96,7 +87,6 @@ export default {
border-bottom: 1px solid rgba(12, 235, 201, 0.3);
margin-bottom: 18px;
background-color: rgba(12, 235, 201, 0.05);
&-item {
margin-bottom: 10px;
}

View File

@ -1,33 +1,16 @@
<template>
<a-radio-group v-if="tagType == 'radio'" @change="handleInput" :value="getValueSting" :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-radio-group
v-else-if="tagType == 'radioButton'"
buttonStyle="solid"
@change="handleInput"
:value="getValueSting"
:disabled="disabled"
>
<a-radio-group v-else-if="tagType=='radioButton'" buttonStyle="solid" @change="handleInput" :value="getValueSting" :disabled="disabled">
<a-radio-button v-for="(item, key) in dictOptions" :key="key" :value="item.value">{{ item.text }}</a-radio-button>
</a-radio-group>
<a-select
v-else-if="tagType == 'select'"
:getPopupContainer="getPopupContainer"
:placeholder="placeholder"
:disabled="disabled"
:value="getValueSting"
:allowClear="allowClear"
show-arrow
:mode="modeType"
:maxTagCount="1"
@change="handleInput"
>
<a-select v-else-if="tagType=='select'" :getPopupContainer = "getPopupContainer" :placeholder="placeholder" :disabled="disabled" :value="getValueSting" :allowClear="allowClear" @change="handleInput">
<img slot="suffixIcon" src="@/assets/images/global/select-down.png" alt="" />
<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">
<span style="display: inline-block;width: 100%" :title=" item.text || item.label ">
{{ item.text || item.label }}
</span>
</a-select-option>
@ -35,98 +18,97 @@
</template>
<script>
import { ajaxGetDictItems, getDictItemsFromCache } from '@/api/api'
import {ajaxGetDictItems,getDictItemsFromCache} from '@/api/api'
export default {
name: 'JDictSelectTag',
props: {
modeType: String,
dictCode: String,
placeholder: String,
disabled: Boolean,
value: [String, Number, Array],
type: String,
getPopupContainer: {
type: Function,
default: (node) => node.parentNode,
export default {
name: "JDictSelectTag",
props: {
dictCode: String,
placeholder: String,
disabled: Boolean,
value: [String, Number],
type: String,
getPopupContainer:{
type: Function,
default: (node) => node.parentNode
},
allowClear: {
type: Boolean,
default: true
}
},
allowClear: {
type: Boolean,
default: true,
data() {
return {
dictOptions: [],
tagType:""
}
},
},
data() {
return {
dictOptions: [],
tagType: '',
}
},
watch: {
dictCode: {
immediate: true,
handler() {
this.initDictData()
watch:{
dictCode:{
immediate:true,
handler() {
this.initDictData()
},
}
},
created() {
// console.log(this.dictCode);
if(!this.type || this.type==="list"){
this.tagType = "select"
}else{
this.tagType = this.type
}
//
// this.initDictData();
},
computed: {
getValueSting(){
// update-begin author:wangshuai date:20200601 for: placeholder ------
// null placeholder
return this.value != null ? this.value.toString() : undefined;
// update-end author:wangshuai date:20200601 for: placeholder ------
},
},
},
created() {
// console.log(this.dictCode);
if (!this.type || this.type === 'list') {
this.tagType = 'select'
} else {
this.tagType = this.type
}
//
// this.initDictData();
},
computed: {
getValueSting() {
// update-begin author:wangshuai date:20200601 for: placeholder ------
// null placeholder
// return this.value != null ? this.value.toString() : undefined
return Array.isArray(this.value) ? this.value : this.value != null ? this.value.toString() : undefined
// update-end author:wangshuai date:20200601 for: placeholder ------
},
},
methods: {
initDictData() {
//
if (getDictItemsFromCache(this.dictCode)) {
this.dictOptions = getDictItemsFromCache(this.dictCode)
return
}
//Code,
ajaxGetDictItems(this.dictCode, null).then((res) => {
if (res.success) {
// console.log(res.result);
this.dictOptions = res.result
methods: {
initDictData() {
//
if(getDictItemsFromCache(this.dictCode)){
this.dictOptions = getDictItemsFromCache(this.dictCode);
return
}
})
},
handleInput(e = '') {
let val
if (Object.keys(e).includes('target')) {
val = e.target.value
} else {
val = e
//Code,
ajaxGetDictItems(this.dictCode, null).then((res) => {
if (res.success) {
// console.log(res.result);
this.dictOptions = res.result;
}
})
},
handleInput(e='') {
let val;
if(Object.keys(e).includes('target')){
val = e.target.value
}else{
val = e
}
console.log(val);
this.$emit('change', val? val: undefined);
//LOWCOD-2146 SQL
this.$emit('input', val? val: undefined);
},
setCurrentDictOptions(dictOptions){
this.dictOptions = dictOptions
},
getCurrentDictOptions(){
return this.dictOptions
}
this.$emit('change', val ? val : undefined)
//LOWCOD-2146 SQL
this.$emit('input', val ? val : undefined)
},
setCurrentDictOptions(dictOptions) {
this.dictOptions = dictOptions
},
getCurrentDictOptions() {
return this.dictOptions
},
},
model: {
prop: 'value',
event: 'change',
},
}
model:{
prop: 'value',
event: 'change'
}
}
</script>
<style scoped>

View File

@ -3,7 +3,7 @@
<a-input :placeholder="placeholder" v-model="editCronValue" :disabled="disabled">
<a slot="addonAfter" @click="showConfigDlg" class="config-btn" :disabled="disabled">
<a-icon type="setting"></a-icon>
Select
选择
</a>
</a-input>
<j-modal :visible.sync="show" title="Cron表达式" width="800px">
@ -24,44 +24,44 @@ import EasyCron from './EasyCron.vue'
export default {
name: 'input-cron',
components: { EasyCron },
components: {EasyCron},
model: {
prop: 'cronValue',
event: 'change',
event: 'change'
},
props: {
cronValue: {
type: String,
default: '',
default: ''
},
width: {
type: String,
default: '800px',
default: '800px'
},
placeholder: {
type: String,
default: '请输入cron表达式',
default: '请输入cron表达式'
},
disabled: {
type: Boolean,
default: false,
default: false
},
exeStartTime: {
type: [Number, String, Object],
default: 0,
default: 0
},
hideSecond: {
type: Boolean,
default: false,
default: false
},
hideYear: {
type: Boolean,
default: false,
default: false
},
remote: {
type: Function,
default: null,
},
default: null
}
},
data() {
return {
@ -78,20 +78,22 @@ export default {
},
editCronValue(newVal, oldVal) {
this.$emit('change', newVal)
},
}
},
methods: {
showConfigDlg() {
if (!this.disabled) {
this.show = true
}
},
},
}
}
}
</script>
<style scoped>
.config-btn {
cursor: pointer;
}
.config-btn {
cursor: pointer;
}
</style>

View File

@ -2,11 +2,11 @@
<div>
<a-input-search
v-model="textVals"
placeholder="Please select the user first"
placeholder="请先选择用户"
readOnly
unselectable="on"
@search="onSearchDepUser">
<a-button slot="enterButton" :disabled="disabled">Select user</a-button>
<a-button slot="enterButton" :disabled="disabled">选择用户</a-button>
</a-input-search>
<j-select-user-by-dep-modal
ref="selectModal"
@ -120,7 +120,7 @@
this.$refs.selectModal.showModal()
},
selectOK(rows) {
console.log("Currently selected user", rows)
console.log("当前选中用户", rows)
if (!rows) {
this.storeVals = ''
this.textVals = ''

View File

@ -1,9 +1,10 @@
<template>
<global-layout>
<transition name="page-transition">
<keep-alive>
<keep-alive v-if="keepAlive">
<router-view />
</keep-alive>
<router-view v-else />
</transition>
</global-layout>
</template>
@ -21,6 +22,14 @@
}
},
computed: {
keepAlive () {
return this.$route.meta.keepAlive
}
},
methods: {
},
}
</script>

View File

@ -1,8 +1,9 @@
<template>
<div class="main">
<keep-alive>
<router-view />
<keep-alive :include="includedComponents">
<router-view v-if="keepAlive" />
</keep-alive>
<router-view v-if="!keepAlive" />
</div>
</template>

View File

@ -1,7 +1,7 @@
<template>
<div class="custom-top-menu">
<a-menu mode="horizontal" v-model="selectedKeys" @click="onMenuSelect">
<a-menu-item v-for="(menu, index) in menus" :key="menu.name" :class="{ 'is-last': index === menus.length - 1 }">
<a-menu-item v-for="(menu, index) in menus" :key="menu.name" :class="{ 'is-last': index === menus.length - 1}">
<img
v-show="menu.name === selectedKeys[0]"
class="menu-logo"
@ -15,7 +15,7 @@
alt=""
/>
<span v-html="menu.meta.title.split(' ').join('<br>')"></span>
<img v-if="index !== menus.length - 1" class="split-line" src="@/assets/images/header/split-line.png" alt="" />
<img v-if="index !== menus.length - 1" class="split-line" src="@/assets/images/header/split-line.png" alt="">
</a-menu-item>
</a-menu>
</div>
@ -26,12 +26,12 @@ export default {
props: {
menus: {
type: Array,
default: () => [],
},
default: () => []
}
},
data() {
return {
selectedKeys: [],
selectedKeys: []
}
},
created() {
@ -40,24 +40,8 @@ export default {
},
methods: {
onMenuSelect({ key }) {
const childPath = this.getChildrenPath(this.menuItems.find((menu) => menu.name === key))
if (key == 'abnormal-alarm') {
const selectedKeys = window.sessionStorage.getItem('currMenu_alarm')
if (selectedKeys) {
this.$router.push(selectedKeys)
} else {
this.$router.push(childPath)
}
} else if (key == 'istatistics') {
const selectedKeys = window.sessionStorage.getItem('currMenu_web')
if (selectedKeys) {
this.$router.push(selectedKeys)
} else {
this.$router.push(childPath)
}
} else {
this.$router.push(childPath)
}
const childPath = this.getChildrenPath(this.menuItems.find(menu => menu.name === key))
this.$router.push(childPath)
},
getChildrenPath(menuItem) {
if (menuItem.children) {
@ -82,19 +66,19 @@ export default {
}
}
}
},
}
},
watch: {
$route(route) {
const currTopMenu = this.findTopMenuByRouteName(this.menuItems, route.name)
this.selectedKeys = [currTopMenu.name]
},
}
},
computed: {
menuItems() {
return this.menus.filter((item) => !item.hidden)
},
},
return this.menus.filter(item => !item.hidden)
}
}
}
</script>

File diff suppressed because it is too large Load Diff

View File

@ -6,8 +6,7 @@
:arrowPointAtCenter="true"
overlayClassName="header-notice-wrapper"
@visibleChange="handleHoverChange"
:overlayStyle="{ width: '300px', top: '50px' }"
>
:overlayStyle="{ width: '300px', top: '50px' }">
<template slot="content">
<a-spin :spinning="loadding">
<a-tabs>
@ -31,21 +30,17 @@
</a-list>-->
<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 style="color: #c9f6f6; margin-bottom: 0px">{{ record.createTime }} 发布</p>
<div style="margin-left: 5%;width: 80%">
<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">
<a-tag @click="showAnnouncement(record)" v-if="record.priority === 'L'" color="blue">一般消息</a-tag>
<a-tag @click="showAnnouncement(record)" v-if="record.priority === 'M'" color="orange"
>重要消息</a-tag
>
<a-tag @click="showAnnouncement(record)" v-if="record.priority === 'M'" color="orange">重要消息</a-tag>
<a-tag @click="showAnnouncement(record)" v-if="record.priority === 'H'" color="red">紧急消息</a-tag>
</div>
</a-list-item>
<div style="margin-top: 5px; text-align: center">
<div style="margin-top: 5px;text-align: center">
<a-button @click="toMyAnnouncement()" type="dashed" block>查看更多</a-button>
</div>
</a-list>
@ -53,21 +48,17 @@
<a-tab-pane :tab="msg2Title" key="2">
<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 style="color: #c9f6f6; margin-bottom: 0px">{{ record.createTime }} 发布</p>
<div style="margin-left: 5%;width: 80%">
<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">
<a-tag @click="showAnnouncement(record)" v-if="record.priority === 'L'" color="blue">一般消息</a-tag>
<a-tag @click="showAnnouncement(record)" v-if="record.priority === 'M'" color="orange"
>重要消息</a-tag
>
<a-tag @click="showAnnouncement(record)" v-if="record.priority === 'M'" color="orange">重要消息</a-tag>
<a-tag @click="showAnnouncement(record)" v-if="record.priority === 'H'" color="red">紧急消息</a-tag>
</div>
</a-list-item>
<div style="margin-top: 5px; text-align: center">
<div style="margin-top: 5px;text-align: center">
<a-button @click="toMyAnnouncement()" type="dashed" block>查看更多</a-button>
</div>
</a-list>
@ -77,297 +68,291 @@
</template>
<span @click="fetchNotice" class="header-notice">
<a-badge :count="msgTotal">
<img src="@/assets/images/header/notice.png" alt="" />
<img src="@/assets/images/header/notice.png" alt="">
</a-badge>
</span>
<show-announcement ref="ShowAnnouncement" @ok="modalFormOk"></show-announcement>
<dynamic-notice ref="showDynamNotice" :path="openPath" :formData="formData" />
<dynamic-notice ref="showDynamNotice" :path="openPath" :formData="formData"/>
</a-popover>
</template>
<script>
import { getAction, putAction } from '@/api/manage'
import ShowAnnouncement from './ShowAnnouncement'
import store from '@/store/'
import DynamicNotice from './DynamicNotice'
import Vue from 'vue'
import { ACCESS_TOKEN } from '@/store/mutation-types'
import { getAction,putAction } from '@/api/manage'
import ShowAnnouncement from './ShowAnnouncement'
import store from '@/store/'
import DynamicNotice from './DynamicNotice'
import Vue from 'vue'
import { ACCESS_TOKEN } from '@/store/mutation-types'
export default {
name: 'HeaderNotice',
components: {
DynamicNotice,
ShowAnnouncement,
},
data() {
return {
loadding: false,
url: {
listCementByUser: '/sys/annountCement/listByUser',
editCementSend: '/sys/sysAnnouncementSend/editByAnntIdAndUserId',
queryById: '/sys/annountCement/queryById',
},
hovered: false,
announcement1: [],
announcement2: [],
msg1Count: '0',
msg2Count: '0',
msg1Title: '通知(0)',
msg2Title: '',
stopTimer: false,
websock: null,
lockReconnect: false,
//websocket
wsConnectErrorTime: 1,
heartCheck: null,
formData: {},
openPath: '',
}
},
computed: {
msgTotal() {
return parseInt(this.msg1Count) + parseInt(this.msg2Count)
export default {
name: "HeaderNotice",
components: {
DynamicNotice,
ShowAnnouncement,
},
},
mounted() {
this.loadData()
//this.timerFun();
this.initWebSocket()
// this.heartCheckFun();
},
destroyed: function () {
//
this.websocketOnclose()
},
methods: {
timerFun() {
this.stopTimer = false
let myTimer = setInterval(() => {
//
if (this.stopTimer == true) {
clearInterval(myTimer)
data () {
return {
loadding: false,
url:{
listCementByUser:"/sys/annountCement/listByUser",
editCementSend:"/sys/sysAnnouncementSend/editByAnntIdAndUserId",
queryById:"/sys/annountCement/queryById",
},
hovered: false,
announcement1:[],
announcement2:[],
msg1Count:"0",
msg2Count:"0",
msg1Title:"通知(0)",
msg2Title:"",
stopTimer:false,
websock: null,
lockReconnect:false,
//websocket
wsConnectErrorTime:1,
heartCheck:null,
formData:{},
openPath:''
}
},
computed:{
msgTotal () {
return parseInt(this.msg1Count)+parseInt(this.msg2Count);
}
},
mounted() {
this.loadData();
//this.timerFun();
this.initWebSocket();
// this.heartCheckFun();
},
destroyed: function () { //
this.websocketOnclose();
},
methods: {
timerFun() {
this.stopTimer = false;
let myTimer = setInterval(()=>{
//
if (this.stopTimer == true) {
clearInterval(myTimer);
return;
}
this.loadData()
},6000)
},
loadData (){
try {
//
getAction(this.url.listCementByUser).then((res) => {
if (res.success) {
this.announcement1 = res.result.anntMsgList;
this.msg1Count = res.result.anntMsgTotal;
this.msg1Title = "通知(" + res.result.anntMsgTotal + ")";
this.announcement2 = res.result.sysMsgList;
this.msg2Count = res.result.sysMsgTotal;
this.msg2Title = "系统消息(" + res.result.sysMsgTotal + ")";
}
}).catch(error => {
console.log("系统消息通知异常",error);//permissionName is undefined
this.stopTimer = true;
console.log("清理timer");
});
} catch (err) {
this.stopTimer = true;
console.log("通知异常",err);
}
},
fetchNotice () {
if (this.loadding) {
this.loadding = false
return
}
this.loadData()
}, 6000)
},
loadData() {
try {
//
getAction(this.url.listCementByUser)
.then((res) => {
if (res.success) {
this.announcement1 = res.result.anntMsgList
this.msg1Count = res.result.anntMsgTotal
this.msg1Title = '通知(' + res.result.anntMsgTotal + ')'
this.announcement2 = res.result.sysMsgList
this.msg2Count = res.result.sysMsgTotal
this.msg2Title = '系统消息(' + res.result.sysMsgTotal + ')'
}
})
.catch((error) => {
console.log('系统消息通知异常', error) //permissionName is undefined
this.stopTimer = true
console.log('清理timer')
})
} catch (err) {
this.stopTimer = true
console.log('通知异常', err)
}
},
fetchNotice() {
if (this.loadding) {
this.loadding = false
return
}
this.loadding = true
setTimeout(() => {
this.loadding = false
}, 200)
},
showAnnouncement(record) {
putAction(this.url.editCementSend, { anntId: record.id }).then((res) => {
if (res.success) {
this.loadData()
this.loadding = true
setTimeout(() => {
this.loadding = false
}, 200)
},
showAnnouncement(record){
putAction(this.url.editCementSend,{anntId:record.id}).then((res)=>{
if(res.success){
this.loadData();
}
});
this.hovered = false;
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);
}
})
this.hovered = false
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() {
this.$router.push({
path: '/isystem/userAnnouncement',
})
},
modalFormOk() {},
handleHoverChange(visible) {
this.hovered = visible
},
},
toMyAnnouncement(){
this.$router.push({
path: '/isps/userAnnouncement'
});
},
modalFormOk(){
},
handleHoverChange (visible) {
this.hovered = visible;
},
initWebSocket: function () {
// WebSocketwshttpwsshttps
var userId = store.getters.userInfo.id
var url =
window._CONFIG['domianURL'].replace('https://', 'wss://').replace('http://', 'ws://') + '/websocket/' + userId
//console.log(url);
//update-begin-author:taoyan date:2022-4-22 for: v2.4.6 websocket #3278
let token = Vue.ls.get(ACCESS_TOKEN)
this.websock = new WebSocket(url, [token])
//update-end-author:taoyan date:2022-4-22 for: v2.4.6 websocket #3278
this.websock.onopen = this.websocketOnopen
this.websock.onerror = this.websocketOnerror
this.websock.onmessage = this.websocketOnmessage
this.websock.onclose = this.websocketOnclose
},
websocketOnopen: function () {
console.log('WebSocket连接成功')
//
//this.heartCheck.reset().start();
},
websocketOnerror: function (e) {
console.log('WebSocket连接发生错误第%s次', this.wsConnectErrorTime)
initWebSocket: function () {
// WebSocketwshttpwsshttps
var userId = store.getters.userInfo.id;
var url = window._CONFIG['domianURL'].replace("https://","wss://").replace("http://","ws://")+"/websocket/"+userId;
//console.log(url);
//update-begin-author:taoyan date:2022-4-22 for: v2.4.6 websocket #3278
let token = Vue.ls.get(ACCESS_TOKEN)
this.websock = new WebSocket(url, [token]);
//update-end-author:taoyan date:2022-4-22 for: v2.4.6 websocket #3278
this.websock.onopen = this.websocketOnopen;
this.websock.onerror = this.websocketOnerror;
this.websock.onmessage = this.websocketOnmessage;
this.websock.onclose = this.websocketOnclose;
},
websocketOnopen: function () {
console.log("WebSocket连接成功");
//
//this.heartCheck.reset().start();
},
websocketOnerror: function (e) {
console.log("WebSocket连接发生错误第%s次",this.wsConnectErrorTime);
this.wsConnectErrorTime = this.wsConnectErrorTime + 1
if (this.wsConnectErrorTime > 5) {
console.log('WebSocket连接错误超过5次就不再重新连了')
this.lockReconnect = true
return
}
this.wsConnectErrorTime = this.wsConnectErrorTime + 1;
if(this.wsConnectErrorTime>5){
console.log("WebSocket连接错误超过5次就不再重新连了");
this.lockReconnect = true
return;
}
this.reconnect()
},
websocketOnmessage: function (e) {
console.log('-----接收消息-------', e.data)
var data = eval('(' + e.data + ')') //
this.voiceBroadcast(data.msgTxt)
if (data.cmd == 'topic') {
//
this.loadData()
} else if (data.cmd == 'user') {
//
this.loadData()
}
//
//this.heartCheck.reset().start();
},
websocketOnclose: function (e) {
console.log('connection closed (' + e + ')')
if (e) {
console.log('connection closed (' + e.code + ')')
}
this.reconnect()
},
websocketSend(text) {
//
try {
this.websock.send(text)
} catch (err) {
console.log('send failed (' + err.code + ')')
}
},
//
voiceBroadcast(text) {
var url = 'http://tts.baidu.com/text2audio?lan=zh&ie=UTF-8&text=' + encodeURI(text) // baidu
var voiceContent = new Audio(url)
voiceContent.src = url
voiceContent.play()
},
openNotification(data) {
var text = data.msgTxt
const key = `open${Date.now()}`
this.$notification.open({
message: '消息提醒',
placement: 'bottomRight',
description: text,
key,
btn: (h) => {
return h(
'a-button',
{
this.reconnect();
},
websocketOnmessage: function (e) {
console.log("-----接收消息-------",e.data);
var data = eval("(" + e.data + ")"); //
this.voiceBroadcast(data.msgTxt)
if(data.cmd == "topic"){
//
this.loadData();
}else if(data.cmd == "user"){
//
this.loadData();
}
//
//this.heartCheck.reset().start();
},
websocketOnclose: function (e) {
console.log("connection closed (" + e + ")");
if(e){
console.log("connection closed (" + e.code + ")");
}
this.reconnect();
},
websocketSend(text) { //
try {
this.websock.send(text);
} catch (err) {
console.log("send failed (" + err.code + ")");
}
},
//
voiceBroadcast(text){
var url = "http://tts.baidu.com/text2audio?lan=zh&ie=UTF-8&text=" + encodeURI(text); // baidu
var voiceContent = new Audio(url);
voiceContent.src = url;
voiceContent.play();
},
openNotification (data) {
var text = data.msgTxt;
const key = `open${Date.now()}`;
this.$notification.open({
message: '消息提醒',
placement:'bottomRight',
description: text,
key,
btn: (h)=>{
return h('a-button', {
props: {
type: 'primary',
size: 'small',
},
on: {
click: () => this.showDetail(key, data),
},
},
'查看详情'
)
},
})
},
click: () => this.showDetail(key,data)
}
}, '查看详情')
},
});
},
reconnect() {
var that = this
if (that.lockReconnect) return
that.lockReconnect = true
//
setTimeout(function () {
console.info('尝试重连...')
that.initWebSocket()
that.lockReconnect = false
}, 20000)
},
heartCheckFun() {
var that = this
//,20s
that.heartCheck = {
timeout: 20000,
timeoutObj: null,
serverTimeoutObj: null,
reset: function () {
clearTimeout(this.timeoutObj)
//clearTimeout(this.serverTimeoutObj);
return this
},
start: function () {
var self = this
this.timeoutObj = setTimeout(function () {
//
//onmessage
that.websocketSend('HeartBeat')
console.info('客户端发送心跳')
//self.serverTimeoutObj = setTimeout(function(){//
// that.websock.close();//onclosereconnectws.close().reconnect onclose
//}, self.timeout)
}, this.timeout)
},
}
},
showDetail(key, data) {
this.$notification.close(key)
var id = data.msgId
getAction(this.url.queryById, { id: id }).then((res) => {
if (res.success) {
var record = res.result
this.showAnnouncement(record)
reconnect() {
var that = this;
if(that.lockReconnect) return;
that.lockReconnect = true;
//
setTimeout(function () {
console.info("尝试重连...");
that.initWebSocket();
that.lockReconnect = false;
}, 20000);
},
heartCheckFun(){
var that = this;
//,20s
that.heartCheck = {
timeout: 20000,
timeoutObj: null,
serverTimeoutObj: null,
reset: function(){
clearTimeout(this.timeoutObj);
//clearTimeout(this.serverTimeoutObj);
return this;
},
start: function(){
var self = this;
this.timeoutObj = setTimeout(function(){
//
//onmessage
that.websocketSend("HeartBeat");
console.info("客户端发送心跳");
//self.serverTimeoutObj = setTimeout(function(){//
// that.websock.close();//onclosereconnectws.close().reconnect onclose
//}, self.timeout)
}, this.timeout)
}
}
})
},
},
}
},
showDetail(key,data){
this.$notification.close(key);
var id = data.msgId;
getAction(this.url.queryById,{id:id}).then((res) => {
if (res.success) {
var record = res.result;
this.showAnnouncement(record);
}
})
},
}
}
</script>
<style lang="css">
.header-notice-wrapper {
top: 50px !important;
}
.header-notice-wrapper {
top: 50px !important;
}
</style>
<style lang="less" scoped>
.header-notice {
display: inline-block;
transition: all 0.3s;
.header-notice{
display: inline-block;
transition: all 0.3s;
span {
vertical-align: initial;
span {
vertical-align: initial;
}
}
}
</style>

View File

@ -4,19 +4,18 @@ import xss from "xss"
:title="title"
:width="modelStyle.width"
:visible="visible"
:bodyStyle="bodyStyle"
:bodyStyle ="bodyStyle"
:switchFullscreen="switchFullscreen"
@cancel="handleCancel"
>
>
<template slot="footer">
<a-button key="back" @click="handleCancel">Cancel</a-button>
<a-button v-if="record.openType === 'url'" type="primary" @click="toHandle">去处理</a-button>
<a-button key="back" @click="handleCancel">关闭</a-button>
<a-button v-if="record.openType==='url'" type="primary" @click="toHandle">去处理</a-button>
</template>
<a-card class="daily-article" :loading="loading">
<a-card-meta
:title="record.titile"
:description="'Sender' + record.sender + ' Send Time ' + record.sendTime"
>
:description="'发布人:'+record.sender + ' 发布时间: ' + record.sendTime">
</a-card-meta>
<a-divider />
<span v-html="record.msgContent" class="article-content"></span>
@ -25,141 +24,133 @@ import xss from "xss"
</template>
<script>
import { getUserList } from '@/api/api'
import xss from 'xss'
export default {
name: 'SysAnnouncementModal',
components: {},
data() {
return {
title: 'Notification Message',
record: {},
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
import {getUserList} from '@/api/api'
import xss from 'xss'
export default {
name: "SysAnnouncementModal",
components: {
},
data () {
return {
title:"通知消息",
record: {},
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
visible: false,
switchFullscreen: true,
loading: false,
bodyStyle:{
padding: "0",
height:(window.innerHeight*0.8)+"px",
"overflow-y":"auto",
},
modelStyle:{
width: '60%',
style: { top: '20px' },
fullScreen: false
}
}
},
created () {
},
methods: {
detail (record) {
//update-begin---author:wangshuai ---date:20220107 for
if(record.sender){
getUserList({"username":record.sender}).then((res) =>{
if(res.success && res.result.records.length>0){
record.sender = res.result.records[0].realname
}
})
}
//update-end---author:wangshuai ---date:20220107 for
this.visible = true;
//update-begin-author:taoyan date:2022-7-14 for: VUEN-1702 sql
if(record.msgContent){
record.msgContent = xss(record.msgContent)
}
//update-end-author:taoyan date:2022-7-14 for: VUEN-1702 sql
this.record = record;
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
handleCancel () {
this.visible = false;
},
visible: false,
switchFullscreen: true,
loading: false,
bodyStyle: {
padding: '0',
height: window.innerHeight * 0.8 + 'px',
'overflow-y': 'auto',
/** 切换全屏显示 */
handleClickToggleFullScreen() {
let mode = !this.modelStyle.fullScreen
if (mode) {
this.modelStyle.width = '100%'
this.modelStyle.style.top = '20px'
} else {
this.modelStyle.width = '60%'
this.modelStyle.style.top = '50px'
}
this.modelStyle.fullScreen = mode
},
modelStyle: {
width: '60%',
style: { top: '20px' },
fullScreen: false,
toHandle(){
if(this.record.openType==='url'){
this.visible = false;
//
this.$router.push({path: this.record.openPage})
}
},
}
},
created() {},
methods: {
detail(record) {
//update-begin---author:wangshuai ---date:20220107 for
if (record.sender) {
getUserList({ username: record.sender }).then((res) => {
if (res.success && res.result.records.length > 0) {
record.sender = res.result.records[0].realname
}
})
}
//update-end---author:wangshuai ---date:20220107 for
this.visible = true
//update-begin-author:taoyan date:2022-7-14 for: VUEN-1702 sql
if (record.msgContent) {
record.msgContent = xss(record.msgContent)
}
//update-end-author:taoyan date:2022-7-14 for: VUEN-1702 sql
this.record = record
},
handleCancel() {
this.visible = false
},
/** 切换全屏显示 */
handleClickToggleFullScreen() {
let mode = !this.modelStyle.fullScreen
if (mode) {
this.modelStyle.width = '100%'
this.modelStyle.style.top = '20px'
} else {
this.modelStyle.width = '60%'
this.modelStyle.style.top = '50px'
}
this.modelStyle.fullScreen = mode
},
toHandle() {
if (this.record.openType === 'url') {
this.visible = false
//
this.$router.push({ path: this.record.openPage })
}
},
},
}
}
</script>
<style lang="less">
.announcementCustomModal {
.ant-modal-header {
border: none;
display: inline-block;
position: absolute;
z-index: 1;
right: 56px;
padding: 0;
.ant-modal-title {
.custom-btn {
width: 56px;
height: 56px;
border: none;
box-shadow: none;
.announcementCustomModal{
.ant-modal-header {
border: none;
display: inline-block;
position: absolute;
z-index: 1;
right: 56px;
padding: 0;
.ant-modal-title{
.custom-btn{
width: 56px;
height: 56px;
border: none;
box-shadow: none;
}
}
}
.daily-article{
border-bottom: 0;
}
}
</style>
<style scoped lang="less">
.daily-article {
.article-button {
font-size: 1.2rem !important;
}
.ant-card-body {
padding: 18px !important;
}
.ant-card-head {
padding: 0 1rem;
}
.ant-card-meta {
margin-bottom: 1rem;
}
.article-content {
p {
word-wrap: break-word;
word-break: break-all;
text-overflow: initial;
white-space: normal;
font-size: .9rem !important;
margin-bottom: .8rem;
}
}
}
.daily-article {
border-bottom: 0;
}
}
.ant-card-meta-description {
color: #fff !important;
}
</style>
<style scoped lang="less">
.daily-article {
.article-button {
font-size: 1.2rem !important;
}
.ant-card-body {
padding: 18px !important;
}
.ant-card-head {
padding: 0 1rem;
}
.ant-card-meta {
margin-bottom: 1rem;
}
.article-content {
p {
word-wrap: break-word;
word-break: break-all;
text-overflow: initial;
white-space: normal;
font-size: 0.9rem !important;
margin-bottom: 0.8rem;
}
}
}
.ant-card-bordered {
border: none;
padding: 20px;
}
/deep/.ant-card-meta-title {
font-weight: 700;
font-size: 18px;
}
</style>

View File

@ -1,12 +1,18 @@
<template>
<div class="user-wrapper" :class="theme">
<header-notice class="action" />
<span class="language" @click="changeLang">
<img :src="$i18n.locale=='zh-CN'?langIcon_en:langIcon_zh" alt="">
<!-- <img :src=langIcon_zh alt=""> -->
</span>
<!-- <span @click="changeLang('zh-CN')">zh</span>
<span style="margin-left: 10px;" @click="changeLang('en-US')">en</span> -->
<header-notice class="action"/>
<a-dropdown>
<span class="action action-full ant-dropdown-link user-dropdown-menu">
<img src="@/assets/images/header/avatar.png" alt="" />
<img src="@/assets/images/header/avatar.png" alt="">
</span>
<a-menu slot="overlay" class="user-dropdown-menu-wrapper">
<!-- <a-menu-item key="0">
<a-menu-item key="0">
<router-link :to="{ name: 'account-center' }">
<a-icon type="user"/>
<span>个人中心</span>
@ -21,29 +27,24 @@
<a-menu-item key="3" @click="systemSetting">
<a-icon type="tool"/>
<span>系统设置</span>
</a-menu-item> -->
<a-menu-item key="3">
<a-icon type="user" />
<span>{{ this.userInfo().username }}</span>
</a-menu-item>
<a-menu-divider />
<a-menu-item key="4" @click="updatePassword">
<a-icon type="setting" />
<span>Change Password</span>
<a-icon type="setting"/>
<span>密码修改</span>
</a-menu-item>
<!-- <a-menu-item key="5" @click="updateCurrentDepart">
<a-menu-item key="5" @click="updateCurrentDepart">
<a-icon type="cluster"/>
<span>切换部门</span>
</a-menu-item>
<a-menu-item key="6" @click="clearCache">
<a-icon type="sync"/>
<span>清理缓存</span>
</a-menu-item> -->
</a-menu-item>
</a-menu>
</a-dropdown>
<span class="action">
<a class="logout_title" href="javascript:;" @click="handleLogout">
<img src="@/assets/images/header/close.png" alt="" />
<img src="@/assets/images/header/close.png" alt="">
</a>
</span>
<user-password ref="userPassword"></user-password>
@ -53,205 +54,221 @@
</template>
<script>
import HeaderNotice from './HeaderNotice'
import UserPassword from './UserPassword'
import SettingDrawer from '@/components/setting/SettingDrawer'
import DepartSelect from './DepartSelect'
import { mapActions, mapGetters, mapState } from 'vuex'
import { mixinDevice } from '@/utils/mixin.js'
import { getFileAccessHttpUrl, getAction } from '@/api/manage'
import Vue from 'vue'
import { UI_CACHE_DB_DICT_DATA } from '@/store/mutation-types'
import HeaderNotice from './HeaderNotice'
import UserPassword from './UserPassword'
import SettingDrawer from "@/components/setting/SettingDrawer";
import DepartSelect from './DepartSelect'
import { mapActions, mapGetters,mapState } from 'vuex'
import { mixinDevice } from '@/utils/mixin.js'
import { getFileAccessHttpUrl,getAction } from "@/api/manage"
import Vue from 'vue'
import { UI_CACHE_DB_DICT_DATA } from "@/store/mutation-types"
import i18nMixin from '@/store/i18n-mixin'
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,
DepartSelect,
SettingDrawer,
},
props: {
theme: {
type: String,
required: false,
default: 'dark',
},
},
/* update_begin author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
created() {
let lists = []
this.searchMenus(lists, this.permissionMenuList)
this.searchMenuOptions = [...lists]
},
mounted() {
//
if (process.env.VUE_APP_SSO == 'true') {
let depart = this.userInfo().orgCode
if (!depart) {
this.updateCurrentDepart()
export default {
name: "UserMenu",
mixins: [mixinDevice,i18nMixin],
data(){
return {
langIcon_zh:require('@/assets/images/header/zh.png'),
langIcon_en:require('@/assets/images/header/en.png'),
// update-begin author:sunjianlei date:20200219 for: --------------
searchMenuOptions:[],
searchMenuComp: 'span',
searchMenuVisible: false,
// update-begin author:sunjianlei date:20200219 for: --------------
}
},
components: {
HeaderNotice,
UserPassword,
DepartSelect,
SettingDrawer
},
props: {
theme: {
type: String,
required: false,
default: 'dark'
}
}
},
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
created() {
let lists = []
this.searchMenus(lists,this.permissionMenuList)
this.searchMenuOptions = [...lists]
},
hiddenClick() {
this.shows = false
mounted() {
console.log(this.$i18n.locale);
//
if (process.env.VUE_APP_SSO == 'true') {
let depart = this.userInfo().orgCode
if (!depart) {
this.updateCurrentDepart()
}
}
},
computed: {
...mapState({
//
permissionMenuList: state => state.user.permissionList
})
},
/* update_end author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
...mapActions(['Logout']),
...mapGetters(['nickname', 'avatar', 'userInfo']),
getAvatar() {
return getFileAccessHttpUrl(this.avatar())
},
handleLogout() {
const that = this
this.$confirm({
title: 'Prompt',
content: 'Ensure Log Out?',
cancelButtonProps: {
props: {
type: 'warn',
},
watch: {
// update-begin author:sunjianlei date:20200219 for:
device: {
immediate: true,
handler() {
this.searchMenuVisible = false
this.searchMenuComp = this.isMobile() ? 'a-modal' : 'span'
},
onOk() {
return that
.Logout({})
.then(() => {
},
// update-end author:sunjianlei date:20200219 for:
},
methods: {
changeLang() {
let lang = this.$i18n.locale == "zh-CN" ? "en-US" : "zh-CN"
this.$i18n.locale = lang
this.setLang(lang)
},
/* 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(){
return getFileAccessHttpUrl(this.avatar())
},
handleLogout() {
const that = this
this.$confirm({
title: 'Prompt',
content: 'Ensure Log Out?',
cancelButtonProps: {
props: {
type: 'warn'
}
},
onOk() {
return that.Logout({}).then(() => {
// update-begin author:scott date:20211223 for:JTC-198退
//that.$router.push({ path: '/user/login' });
window.location.reload()
// update-end author:scott date:20211223 for:JTC-198退
})
.catch((err) => {
}).catch(err => {
that.$message.error({
title: 'Error',
description: err.message,
description: err.message
})
})
},
onCancel() {},
})
},
updatePassword() {
let username = this.userInfo().username
this.$refs.userPassword.show(username)
},
updateCurrentDepart() {
this.$refs.departSelect.show()
},
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)
},
onCancel() {
},
});
},
updatePassword(){
let username = this.userInfo().username
this.$refs.userPassword.show(username)
},
updateCurrentDepart(){
this.$refs.departSelect.show()
},
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)
}
}
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]
//update-begin-author:sunjianlei date:20220111 for: JTC-702Token
if(route.component.includes('layouts/IframePageView')){
this.$router.push(route)
}else{
this.$router.push({ path: route.path })
}
}
},
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]
//update-begin-author:sunjianlei date:20220111 for: JTC-702Token
if (route.component.includes('layouts/IframePageView')) {
this.$router.push(route)
} else {
this.$router.push({ path: route.path })
}
//update-end-author:sunjianlei date:20220111 for: JTC-702Token
this.searchMenuVisible = false
},
// update_end author:sunjianlei date:20191230 for:
/*update_end author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
/*update_begin author:liushaoqian date:20200507 for: 刷新缓存*/
clearCache() {
getAction('sys/dict/refleshCache')
.then((res) => {
//update-end-author:sunjianlei date:20220111 for: JTC-702Token
this.searchMenuVisible = false
},
// update_end author:sunjianlei date:20191230 for:
/*update_end author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
/*update_begin author:liushaoqian date:20200507 for: 刷新缓存*/
clearCache(){
getAction("sys/dict/refleshCache").then((res) => {
if (res.success) {
//
getAction('sys/dict/queryAllDictItems').then((res) => {
getAction("sys/dict/queryAllDictItems").then((res) => {
if (res.success) {
Vue.ls.remove(UI_CACHE_DB_DICT_DATA)
Vue.ls.set(UI_CACHE_DB_DICT_DATA, res.result, 7 * 24 * 60 * 60 * 1000)
}
})
this.$message.success('刷新缓存完成!')
this.$message.success("刷新缓存完成!");
}
}).catch(e=>{
this.$message.warn("刷新缓存失败!");
console.log("刷新失败",e)
})
.catch((e) => {
this.$message.warn('刷新缓存失败!')
console.log('刷新失败', e)
})
},
/*update_end author:liushaoqian date:20200507 for: 刷新缓存*/
},
}
}
/*update_end author:liushaoqian date:20200507 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;
/* 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;
/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: 让搜索框颜色能随主题颜色变换*/
.language{
display: inline-block;
width: 21px;
height: 21px;
cursor: pointer;
margin-right: 5px;
img{
width: 100%;
height: 100%;
}
}
/* update-end author:sunjianlei date:20191220 for: 解决全局样式冲突问题 */
/* update_end author:zhaoxin date:20191129 for: 让搜索框颜色能随主题颜色变换*/
</style>
<style scoped>
.logout_title {
color: inherit;
text-decoration: none;
}
.logout_title {
color: inherit;
text-decoration: none;
}
</style>

View File

@ -6,164 +6,152 @@
:confirmLoading="confirmLoading"
@ok="handleOk"
@cancel="handleCancel"
cancelText="Cancel"
cancelText="关闭"
>
<a-spin :spinning="confirmLoading">
<a-form :form="form">
<a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="Old Password">
<a-input
type="password"
placeholder="Please enter your old password"
v-decorator="['oldpassword', validatorRules.oldpassword]"
/>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="旧密码">
<a-input type="password" placeholder="请输入旧密码" v-decorator="[ 'oldpassword', validatorRules.oldpassword]" />
</a-form-item>
<a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="New Password">
<a-input
type="password"
placeholder="Please enter your new password"
v-decorator="['password', validatorRules.password]"
/>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="新密码">
<a-input type="password" placeholder="请输入新密码" v-decorator="[ 'password', validatorRules.password]" />
</a-form-item>
<a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="Confirm New Password">
<a-input
type="password"
@blur="handleConfirmBlur"
placeholder="Please enter your new password"
v-decorator="['confirmpassword', validatorRules.confirmpassword]"
/>
<a-form-item
:labelCol="labelCol"
:wrapperCol="wrapperCol"
label="确认新密码">
<a-input type="password" @blur="handleConfirmBlur" placeholder="请确认新密码" v-decorator="[ 'confirmpassword', validatorRules.confirmpassword]"/>
</a-form-item>
</a-form>
</a-spin>
</a-modal>
</template>
<script>
import { putAction } from '@/api/manage'
export default {
name: 'UserPassword',
data() {
return {
title: 'Change Password',
modalWidth: 800,
visible: false,
confirmLoading: false,
validatorRules: {
oldpassword: {
rules: [
{
required: true,
message: '请输入旧密码!',
},
],
},
password: {
rules: [
{
required: true,
message: '请输入新密码!',
},
{
import { putAction } from '@/api/manage'
export default {
name: "UserPassword",
data () {
return {
title:"修改密码",
modalWidth:800,
visible: false,
confirmLoading: false,
validatorRules:{
oldpassword:{
rules: [{
required: true, message: '请输入旧密码!',
}],
},
password:{
rules: [{
required: true, message: '请输入新密码!',
}, {
validator: this.validateToNextPassword,
},
],
},
confirmpassword: {
rules: [
{
required: true,
message: '请确认新密码!',
},
{
}],
},
confirmpassword:{
rules: [{
required: true, message: '请确认新密码!',
}, {
validator: this.compareToFirstPassword,
},
],
}],
}
},
confirmDirty:false,
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
},
confirmDirty: false,
labelCol: {
xs: { span: 24 },
sm: { span: 6 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
form: this.$form.createForm(this),
url: 'sys/user/updatePassword',
username: '',
}
},
methods: {
show(uname) {
if (!uname) {
this.$message.warning('当前系统无登录用户!')
return
} else {
this.username = uname
this.form.resetFields()
this.visible = true
form:this.$form.createForm(this),
url: "sys/user/updatePassword",
username:"",
}
},
handleCancel() {
this.close()
},
close() {
this.$emit('close')
this.visible = false
this.disableSubmit = false
this.selectedRole = []
},
handleOk() {
const that = this
//
this.form.validateFields((err, values) => {
if (!err) {
that.confirmLoading = true
let params = Object.assign({ username: this.username }, values)
console.log('修改密码提交数据', params)
putAction(this.url, params)
.then((res) => {
if (res.success) {
console.log(res)
that.$message.success(res.message)
that.close()
} else {
that.$message.warning(res.message)
}
})
.finally(() => {
that.confirmLoading = false
})
methods: {
show(uname){
if(!uname){
this.$message.warning("当前系统无登录用户!");
return
}else{
this.username = uname
this.form.resetFields();
this.visible = true;
}
})
},
validateToNextPassword(rule, value, callback) {
const form = this.form
if (value && this.confirmDirty) {
form.validateFields(['confirm'], { force: true })
},
handleCancel () {
this.close()
},
close () {
this.$emit('close');
this.visible = false;
this.disableSubmit = false;
this.selectedRole = [];
},
handleOk () {
const that = this;
//
this.form.validateFields((err, values) => {
if (!err) {
that.confirmLoading = true;
let params = Object.assign({username:this.username},values)
console.log("修改密码提交数据",params)
putAction(this.url,params).then((res)=>{
if(res.success){
console.log(res)
that.$message.success(res.message);
that.close();
}else{
that.$message.warning(res.message);
}
}).finally(() => {
that.confirmLoading = false;
})
}
})
},
validateToNextPassword (rule, value, callback) {
const form = this.form;
if (value && this.confirmDirty) {
form.validateFields(['confirm'], { force: true })
}
callback();
},
compareToFirstPassword (rule, value, callback) {
const form = this.form;
if (value && value !== form.getFieldValue('password')) {
callback('两次输入的密码不一样!');
} else {
callback()
}
},
handleConfirmBlur (e) {
const value = e.target.value
this.confirmDirty = this.confirmDirty || !!value
}
callback()
},
compareToFirstPassword(rule, value, callback) {
const form = this.form
if (value && value !== form.getFieldValue('password')) {
callback('两次输入的密码不一样!')
} else {
callback()
}
},
handleConfirmBlur(e) {
const value = e.target.value
this.confirmDirty = this.confirmDirty || !!value
},
},
}
}
}
</script>
<style scoped>
</style>

View File

@ -1,4 +1,4 @@
import { TabLayout, RouteView, BlankLayout, PageView, BasicLayout } from '@/components/layouts'
import { TabLayout, RouteView, BlankLayout, PageView } from '@/components/layouts'
import Login from '@/views/user/Login'
/**
@ -10,7 +10,7 @@ export const asyncRouterMap = [
{
path: '/',
name: 'dashboard',
component: BasicLayout,
component: TabLayout,
meta: { title: '首页' },
redirect: '/station-operation',
children: [

15
src/locales/index.js Normal file
View File

@ -0,0 +1,15 @@
import Vue from 'vue'
import VueI18n from 'vue-i18n'
Vue.use(VueI18n)
const i18n = new VueI18n({
locale: localStorage.getItem('APP_LANGUAGE') || 'en-US',
//this.$i18n.locale // 通过切换locale的值来实现语言切换
messages: {
'zh-CN': require('./lang/zh'), // 中文语言包
'en-US': require('./lang/en') // 英文语言包
}
})
export default i18n

15
src/locales/lang/en.js Normal file
View File

@ -0,0 +1,15 @@
export const m = {
common: {
search: "Search",
},
system: {
user: "User",
name: "Name",
role: "Role",
search: "Search",
add: "Add",
edit: "Edit",
delete: "Delete",
num: "NO"
}
}

15
src/locales/lang/zh.js Normal file
View File

@ -0,0 +1,15 @@
export const m = {
common: {
search: "搜索",
},
system: {
user: "用户",
name: "名称",
role: "角色",
search: "搜索",
add: "添加",
edit: "编辑",
delete: "删除",
num: "序号"
}
}

View File

@ -7,6 +7,7 @@ import Storage from 'vue-ls'
import router from './router'
import store from './store/'
import { VueAxios } from "@/utils/request"
import i18n from './locales'
require('@jeecg/antd-online-mini')
require('@jeecg/antd-online-mini/dist/OnlineForm.css')
@ -52,7 +53,6 @@ import { rules } from '@/utils/rules'
import SearchForm from '@/components/SearchForm'
import CustomSelect from '@/components/CustomSelect'
import CustomAllSelect from '@/components/CustomAllSelect'
import CustomTable from '@/components/CustomTable'
import CustomModal from '@/components/CustomModal'
import CustomDatePicker from '@/components/CustomDatePicker'
@ -83,7 +83,6 @@ Vue.use(JeecgComponents);
Vue.use(VueAreaLinkage);
Vue.component('search-form', SearchForm)
Vue.component('custom-select', CustomSelect)
Vue.component('custom-all-select', CustomAllSelect)
Vue.component('custom-table', CustomTable)
Vue.component('custom-modal', CustomModal)
Vue.component('custom-date-picker', CustomDatePicker)
@ -97,6 +96,7 @@ function main() {
new Vue({
router,
store,
i18n,
mounted () {
store.commit('SET_SIDEBAR_TYPE', Vue.ls.get(SIDEBAR_TYPE, true))
store.commit('TOGGLE_THEME', Vue.ls.get(DEFAULT_THEME, config.navTheme))

View File

@ -4,20 +4,20 @@
* data中url定义 list为查询列表 delete为删除单条记录 deleteBatch为批量删除
*/
import { filterObj } from '@/utils/util';
import { deleteAction, getAction, downFile, getFileAccessHttpUrl } from '@/api/manage'
import { deleteAction, getAction,downFile,getFileAccessHttpUrl } from '@/api/manage'
import Vue from 'vue'
import { ACCESS_TOKEN, TENANT_ID } from "@/store/mutation-types"
import store from '@/store'
export const JeecgListMixin = {
data() {
data(){
return {
/* 查询条件-请不要在queryParam中声明非字符串值的属性 */
queryParam: {},
/* 数据源 */
dataSource: [],
dataSource:[],
/* 分页参数 */
ipagination: {
ipagination:{
current: 1,
pageSize: 10,
pageSizeOptions: ['10', '20', '30'],
@ -30,22 +30,22 @@ export const JeecgListMixin = {
total: 0
},
/* 排序参数 */
isorter: {
isorter:{
column: 'createTime',
order: 'desc',
},
/* 筛选参数 */
filters: {},
/* table加载状态 */
loading: false,
loading:false,
/* table选中keys*/
selectedRowKeys: [],
/* table选中records*/
selectionRows: [],
/* 查询折叠 */
toggleSearchStatus: false,
toggleSearchStatus:false,
/* 高级查询条件生效状态 */
superQueryFlag: false,
superQueryFlag:false,
/* 高级查询条件 */
superQueryParams: '',
/** 高级查询拼接方式 */
@ -53,27 +53,27 @@ export const JeecgListMixin = {
}
},
created() {
if (!this.disableMixinCreated) {
console.log(' -- mixin created -- ')
this.loadData();
//初始化字典配置 在自己页面定义
this.initDictConfig();
}
if(!this.disableMixinCreated){
console.log(' -- mixin created -- ')
this.loadData();
//初始化字典配置 在自己页面定义
this.initDictConfig();
}
},
computed: {
//token header
tokenHeader() {
let head = { 'X-Access-Token': Vue.ls.get(ACCESS_TOKEN) }
tokenHeader(){
let head = {'X-Access-Token': Vue.ls.get(ACCESS_TOKEN)}
let tenantid = Vue.ls.get(TENANT_ID)
if (tenantid) {
if(tenantid){
head['tenant-id'] = tenantid
}
return head;
}
},
methods: {
methods:{
loadData(arg) {
if (!this.url.list) {
if(!this.url.list){
this.$message.error("请设置url.list属性!")
return
}
@ -82,51 +82,51 @@ export const JeecgListMixin = {
this.ipagination.current = 1;
}
this.onClearSelected()
var params = this.getQueryParams();//查询条件
this.loading = true;
getAction(this.url.list, params).then((res) => {
if (res.success) {
//update-begin---author:zhangyafei Date:20201118 for适配不分页的数据列表------------
this.dataSource = res.result.records || res.result;
if (res.result.total) {
this.dataSource = res.result.records||res.result;
if(res.result.total)
{
this.ipagination.total = res.result.total;
} else {
}else{
this.ipagination.total = 0;
}
//update-end---author:zhangyafei Date:20201118 for适配不分页的数据列表------------
} else {
}else{
this.$message.warning(res.message)
}
}).finally(() => {
this.loading = false
})
},
initDictConfig() {
initDictConfig(){
console.log("--这是一个假的方法!")
},
handleSuperQuery(params, matchType) {
//高级查询方法
if (!params) {
this.superQueryParams = ''
if(!params){
this.superQueryParams=''
this.superQueryFlag = false
} else {
}else{
this.superQueryFlag = true
this.superQueryParams = JSON.stringify(params)
this.superQueryParams=JSON.stringify(params)
this.superQueryMatchType = matchType
}
this.loadData(1)
},
getQueryParams() {
//获取查询条件
console.log("this.queryParamthis.queryParam", this.queryParam);
let sqp = {}
if (this.superQueryParams) {
sqp['superQueryParams'] = encodeURI(this.superQueryParams)
if(this.superQueryParams){
sqp['superQueryParams']=encodeURI(this.superQueryParams)
sqp['superQueryMatchType'] = this.superQueryMatchType
}
var param = Object.assign(sqp, this.queryParam, this.isorter, this.filters);
// param.field = this.getQueryField();
param.field = this.isorter.column;
var param = Object.assign(sqp, this.queryParam, this.isorter ,this.filters);
param.field = this.getQueryField();
param.pageNo = this.ipagination.current;
param.pageSize = this.ipagination.pageSize;
return filterObj(param);
@ -163,7 +163,7 @@ export const JeecgListMixin = {
this.loadData(1);
},
batchDel: function () {
if (!this.url.deleteBatch) {
if(!this.url.deleteBatch){
this.$message.error("请设置url.deleteBatch属性!")
return
}
@ -181,7 +181,7 @@ export const JeecgListMixin = {
content: "Do You Want To Delete This Item?",
onOk: function () {
that.loading = true;
deleteAction(that.url.deleteBatch, { ids: ids }).then((res) => {
deleteAction(that.url.deleteBatch, {ids: ids}).then((res) => {
if (res.success) {
//重新计算分页问题
that.reCalculatePage(that.selectedRowKeys.length)
@ -199,12 +199,12 @@ export const JeecgListMixin = {
}
},
handleDelete: function (id, propertyName) {
if (!this.url.delete) {
if(!this.url.delete){
this.$message.error("请设置url.delete属性!")
return
}
var that = this;
deleteAction(that.url.delete, { [propertyName || 'id']: id }).then((res) => {
deleteAction(that.url.delete, {[propertyName || 'id']: id}).then((res) => {
if (res.success) {
//重新计算分页问题
that.reCalculatePage(1)
@ -215,16 +215,16 @@ export const JeecgListMixin = {
}
});
},
reCalculatePage(count) {
reCalculatePage(count){
//总数量-count
let total = this.ipagination.total - count;
let total=this.ipagination.total-count;
//获取删除后的分页数
let currentIndex = Math.ceil(total / this.ipagination.pageSize);
let currentIndex=Math.ceil(total/this.ipagination.pageSize);
//删除后的分页数<所在当前页
if (currentIndex < this.ipagination.current) {
this.ipagination.current = currentIndex;
if(currentIndex<this.ipagination.current){
this.ipagination.current=currentIndex;
}
console.log('currentIndex', currentIndex)
console.log('currentIndex',currentIndex)
},
handleEdit: function (record) {
this.$refs.modalForm.edit(record);
@ -237,7 +237,6 @@ export const JeecgListMixin = {
this.$refs.modalForm.disableSubmit = false;
},
handleTableChange(pagination, filters, sorter) {
console.log("sortersorter", sorter);
//分页、排序、筛选变化时触发
//TODO 筛选
console.log(pagination)
@ -248,11 +247,11 @@ export const JeecgListMixin = {
this.ipagination = pagination;
this.loadData();
},
handleToggleSearch() {
handleToggleSearch(){
this.toggleSearchStatus = !this.toggleSearchStatus;
},
// 给popup查询使用(查询区域不支持回填多个字段,限制只返回一个字段)
getPopupField(fields) {
getPopupField(fields){
return fields.split(',')[0]
},
modalFormOk() {
@ -261,39 +260,39 @@ export const JeecgListMixin = {
//清空列表选中
this.onClearSelected()
},
handleDetail: function (record) {
handleDetail:function(record){
this.$refs.modalForm.edit(record);
this.$refs.modalForm.title = "Detail";
this.$refs.modalForm.title="Detail";
this.$refs.modalForm.disableSubmit = true;
},
/* 导出 */
handleExportXls2() {
handleExportXls2(){
let paramsStr = encodeURI(JSON.stringify(this.getQueryParams()));
let url = `${window._CONFIG['domianURL']}/${this.url.exportXlsUrl}?paramsStr=${paramsStr}`;
window.location.href = url;
},
handleExportXls(fileName) {
if (!fileName || typeof fileName != "string") {
handleExportXls(fileName){
if(!fileName || typeof fileName != "string"){
fileName = "导出文件"
}
let param = this.getQueryParams();
if (this.selectedRowKeys && this.selectedRowKeys.length > 0) {
if(this.selectedRowKeys && this.selectedRowKeys.length>0){
param['selections'] = this.selectedRowKeys.join(",")
}
console.log("导出参数", param)
downFile(this.url.exportXlsUrl, param).then((data) => {
console.log("导出参数",param)
downFile(this.url.exportXlsUrl,param).then((data)=>{
if (!data) {
this.$message.warning("文件下载失败")
return
}
if (typeof window.navigator.msSaveBlob !== 'undefined') {
window.navigator.msSaveBlob(new Blob([data], { type: 'application/vnd.ms-excel' }), fileName + '.xls')
} else {
let url = window.URL.createObjectURL(new Blob([data], { type: 'application/vnd.ms-excel' }))
window.navigator.msSaveBlob(new Blob([data],{type: 'application/vnd.ms-excel'}), fileName+'.xls')
}else{
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
link.setAttribute('download', fileName + '.xls')
link.setAttribute('download', fileName+'.xls')
document.body.appendChild(link)
link.click()
document.body.removeChild(link); //下载完成移除元素
@ -302,7 +301,7 @@ export const JeecgListMixin = {
})
},
/* 导入 */
handleImportExcel(info) {
handleImportExcel(info){
this.loading = true;
if (info.file.status !== 'uploading') {
console.log(info.file, info.fileList);
@ -317,9 +316,9 @@ export const JeecgListMixin = {
this.$warning({
title: message,
content: (<div>
<span>{msg}</span><br />
<span>具体详情请 <a href={href} target="_blank" download={fileName}>点击下载</a> </span>
</div>
<span>{msg}</span><br/>
<span>具体详情请 <a href={href} target="_blank" download={fileName}>点击下载</a> </span>
</div>
)
})
} else {
@ -354,21 +353,21 @@ export const JeecgListMixin = {
}
},
/* 图片预览 */
getImgView(text) {
if (text && text.indexOf(",") > 0) {
text = text.substring(0, text.indexOf(","))
getImgView(text){
if(text && text.indexOf(",")>0){
text = text.substring(0,text.indexOf(","))
}
return getFileAccessHttpUrl(text)
},
/* 文件下载 */
// update--autor:lvdandan-----date:20200630------for修改下载文件方法名uploadFile改为downloadFile------
downloadFile(text) {
if (!text) {
downloadFile(text){
if(!text){
this.$message.warning("未知的文件")
return;
}
if (text.indexOf(",") > 0) {
text = text.substring(0, text.indexOf(","))
if(text.indexOf(",")>0){
text = text.substring(0,text.indexOf(","))
}
let url = getFileAccessHttpUrl(text)
window.open(url);

View File

@ -1,29 +1,17 @@
export default {
props: {
value: {
type: Boolean
}
},
data() {
return {
isLoading: false
}
},
methods: {
beforeModalOpen() {}
},
computed: {
visible: {
get() {
return this.value
},
set(val) {
if (val && this.beforeModalOpen && typeof this.beforeModalOpen == 'function') {
this.beforeModalOpen()
props: {
value: {
type: Boolean
}
},
computed: {
visible: {
get() {
return this.value
},
set(val) {
this.$emit('input', val)
}
}
this.$emit('input', val)
}
}
}
}
}

16
src/store/i18n-mixin.js Normal file
View File

@ -0,0 +1,16 @@
import { mapState } from 'vuex'
const i18nMixin = {
computed: {
...mapState({
currentLang: state => state.app.lang
})
},
methods: {
setLang (lang) {
this.$store.dispatch('setLang', lang)
}
}
}
export default i18nMixin

View File

@ -21,6 +21,7 @@ const app = {
device: 'desktop',
theme: '',
layout: '',
lang: 'zh-CN',
contentWidth: '',
fixedHeader: false,
fixSiderbar: false,
@ -78,9 +79,19 @@ const app = {
SET_MULTI_PAGE (state, multipageFlag) {
Vue.ls.set(DEFAULT_MULTI_PAGE, multipageFlag)
state.multipage = multipageFlag
},
APP_LANGUAGE: (state, lang, antd = {}) => {
state.lang = lang
state._antLocale = antd
Vue.ls.set("APP_LANGUAGE", lang)
}
},
actions: {
setLang ({ commit }, lang) {
// return new Promise((resolve, reject) => {
commit('APP_LANGUAGE', lang)
// })
},
setSidebar: ({ commit }, type) => {
commit('SET_SIDEBAR_TYPE', type)
},

View File

@ -18,17 +18,18 @@
@modal-footer-border-color-split: @formInputBorderColor;
@disabled-color: rgba(255, 255, 255, 0.25);
@disabled-color: rgba(255, 255, 255, .25);
@background-color-base: darken(@primary-color, 20);
@border-color-base: darken(@primary-color, 20);
@text-color: #fff;
@component-background: @modalBg;
@heading-color: #fff;
@input-bg: @formInputBgColor;
@input-border-color: @formInputBorderColor;
.ant-btn:hover,
.ant-btn:active,
.ant-btn:focus {
color: #fff !important;
border-color: transparent;
}
@font-face {
font-family: MicrogrammaD-MediExte;
@ -64,29 +65,19 @@ body {
}
// 表格样式
@table-border-radius-base: 0;
@table-padding-vertical-sm: 2px;
@table-padding-vertical: 6px;
@table-padding-horizontal: 8px;
@table-row-hover-bg: #0e505f;
.ant-table {
color: #ade6ee;
font-size: 16px;
border: 1px solid rgba(65, 111, 127, 0.5);
&-header {
background: #126b82 !important;
box-sizing: border-box !important;
table {
width: calc(100% + 11px) !important;
}
}
border: 1px solid rgba(65,111,127, .5);
&-thead {
> tr {
th {
background-color: #126b82 !important;
color: #fff;
padding: 6px 8px !important;
border-bottom: none;
border-radius: 0 !important;
}
}
}
@ -96,12 +87,15 @@ body {
&:nth-child(2n) {
background-color: #08373a;
}
td {
padding: 10px 8px !important;
border-bottom: none;
}
&:hover {
td {
background-color: #0e505f !important;
}
}
&.ant-table-row-selected {
td {
background-color: #0d4e5c !important;
@ -123,29 +117,6 @@ body {
border-color: @formInputBorderColor;
color: @formInputBorderColor;
}
&-small {
font-size: 14px;
.ant-table {
&-tbody {
tr td {
padding-top: 6px !important;
padding-bottom: 6px !important;
}
}
&-placeholder {
.ant-empty-image {
height: 60px;
}
.ant-empty-description {
font-size: 14px;
}
}
}
}
}
// 表格下的分页器
@ -168,7 +139,7 @@ body {
width: 100%;
}
&-required::before {
// display: none !important;
display: none !important;
}
}
&-horizontal {
@ -189,13 +160,6 @@ body {
&-time-picker-inner {
background-color: @modalBg;
}
&-time-picker {
background: none;
}
&-time-picker-combobox {
background-color: @modalBg !important;
border-color: @formInputBorderColor !important;
}
&-picker {
width: 100%;
@ -206,13 +170,10 @@ body {
background-color: @formInputBgColor;
color: #00e9fe !important;
}
&-select {
background-color: @formInputBgColor !important;
}
}
&-input {
background-color: red;
background-color: transparent;
&-wrap {
border-color: @formInputBorderColor;
height: 32px;
@ -280,9 +241,6 @@ body {
}
}
}
.ant-calendar-range .ant-calendar-in-range-cell::before {
background: #1397a3;
}
// 日历
.ant-fullcalendar {
@ -346,8 +304,7 @@ body {
&-selected-day &-date,
&-date:hover {
background-color: #0b4f54 !important;
// background-color: #072f32 !important;
background-color: #072f32 !important;
}
}
@ -355,19 +312,18 @@ body {
@time-picker-selected-bg: @primary-color;
@item-hover-bg: @primary-color;
.ant-time-picker {
width: 100%;
&-input {
background: @modalBg;
border-radius: 0;
&::placeholder {
color: #ccc;
color: #fff;
}
}
&-clear,
&-clock-icon {
color: #01b6e3 !important;
background-color: @modalBg !important;
color: #01B6E3 !important;
}
&-panel {
@ -388,17 +344,13 @@ body {
}
// 输入框样式
.ant-calendar-input {
background-color: transparent !important;
}
.ant-calendar-range-middle {
color: #fff;
}
.ant-input {
background-color: @formInputBgColor !important;
border-color: @formInputBorderColor !important;
border-radius: 0;
color: #fff;
&::placeholder {
color: #ccc;
color: #fff;
}
&:focus {
box-shadow: none;
@ -563,7 +515,7 @@ input[type='number']::-webkit-outer-spin-button {
&.ant-select-dropdown-placement-topLeft {
padding-top: 0;
padding-bottom: 7px;
.ant-select-dropdown-content {
&::before {
top: auto;
@ -645,9 +597,6 @@ input[type='number']::-webkit-outer-spin-button {
}
}
}
.ant-select-selection--multiple .ant-select-selection__choice {
max-width: 60%;
}
// 下拉菜单
.ant-dropdown {

View File

@ -1,55 +0,0 @@
/**
* 本地文件选择
*/
export class FilePicker {
/**
* 接口是否可用
* @returns { Boolean }
*/
static canUse() {
return !!(window.showDirectoryPicker && window.showOpenFilePicker)
}
/**
* 选择一个目录
* @returns { Promise<FileSystemDirectoryHandle> }
*/
static chooseDirectory() {
if (!this.canUse()) {
throw new Error('Not Support showDirectoryPicker')
}
return window.showDirectoryPicker()
}
/**
* 选择一个文件
* @param { Boolean } multiple
* @param { { description?: string; accept?: { [key: string]: string[]; } } } types
* @returns { Promise<FileSystemFileHandle[]> }
*/
static chooseFile(multiple, types) {
if (!this.canUse()) {
throw new Error('Not Support showOpenFilePicker')
}
const pickerOpts = {
multiple,
types,
excludeAcceptAllOption: true
}
return window.showOpenFilePicker(pickerOpts)
}
/**
* 判断一个文件是否在某个目录下
* @param {FileSystemDirectoryHandle} directoryHandle
* @param {FileSystemFileHandle} fileHandle
*/
static async isFileInDirectory(directoryHandle, fileHandle) {
const relativePaths = await directoryHandle.resolve(fileHandle)
if (relativePaths === null || relativePaths.length > 1) {
return false
} else {
return true
}
}
}

View File

@ -1,84 +0,0 @@
// 所有缓存的谱
let sampleList = []
/**
* 重新设置缓存的谱
* @param {Array} list
*/
const setSampleList = list => {
sampleList = list
}
/**
* 缓存一条谱数据
* @param {*} sampleData
*/
const addSampleData = sampleData => {
const find = sampleList.find(item => item.inputFileName == sampleData.inputFileName)
if (find) {
find.data = sampleData.data
} else {
sampleList.push(sampleData)
}
}
/**
* 更新谱数据
* @param {{ inputFileName: string; key: string; data: any; }} param0
*/
const updateSampleData = ({ inputFileName, key, data }) => {
const find = sampleList.find(item => item.inputFileName == inputFileName)
if (find) {
find.data[key] = data
}
}
/**
* 移除谱数据
* @param {string} inputFileName
*/
const removeSampleData = inputFileName => {
const findIndex = sampleList.findIndex(item => item.inputFileName == inputFileName)
if (-1 !== findIndex) {
sampleList.splice(findIndex, 1)
}
}
/**
* 更新分析数据
* @param {{ inputFileName: string; data: any; }} param0
*/
const updateSampleDataAnaly = ({ inputFileName, data }) => {
const find = sampleList.find(item => item.inputFileName == inputFileName)
if (find) {
data.DetailedInformation = find.data.DetailedInformation
find.data = data
}
}
/**
* 清理缓存列表
*/
const clearSampleData = () => {
sampleList = []
}
/**
* 根据文件名获取谱
* @param {string} inputFileName
*/
const getSampleData = inputFileName => {
const find = sampleList.find(item => item.inputFileName == inputFileName)
return find ? find : null
}
export {
sampleList,
setSampleList,
addSampleData,
updateSampleData,
removeSampleData,
updateSampleDataAnaly,
clearSampleData,
getSampleData
}

View File

@ -1,2 +0,0 @@
const { UpdateBaseLine } = Module;
export { UpdateBaseLine as updateBaseLine };

View File

@ -8,7 +8,7 @@ export function getXAxisAndYAxisByPosition(chart, offsetX, offsetY, seriesIndex
if (
chart.containPixel(
{
seriesIndex
seriesIndex: 0
},
pointInPixel
)
@ -17,102 +17,4 @@ export function getXAxisAndYAxisByPosition(chart, offsetX, offsetY, seriesIndex
return [xAxis, yAxis]
}
return null
}
/**
* 将图表导出为图片
* @param {import("echarts").ECharts} chartInstance
* @param {'png' | 'jpeg' | 'svg'} type
*/
export function exportEchartImg(chartInstance, type = 'png', backgroundColor = '#022024') {
const dataURL = chartInstance.getDataURL({
type,
pixelRatio: 2,
backgroundColor
});
const link = document.createElement('a')
link.style.display = 'none'
link.href = dataURL
link.setAttribute('download', 'export.png')
document.body.appendChild(link)
link.click()
document.body.removeChild(link) //下载完成移除元素
}
/**
* 按份数分割轴线
* @param {Number} max
* @param {Number} min
* @param {Number} cnt
* @param {Number} maxBoundaryGap
*/
export function splitAxis(max, min, cnt, maxBoundaryGap = 1.1) {
const _min = Math.floor(min)
const interval = Math.ceil((Math.ceil(max * maxBoundaryGap) - _min) / cnt)
const _max = _min + interval * cnt
return {
min: _min,
interval,
max: _max
}
}
/**
* 构建线形series
* @param {*} name
* @param {*} data
* @param {*} color
* @param {*} extra
* @returns
*/
export function buildLineSeries(name, data, color, extra = {}) {
return {
name,
type: 'line',
data,
itemStyle: {
color
},
lineStyle: {
width: 1
},
symbol: 'none',
symbolSize: 1,
emphasis: {
disabled: true
},
animation: false,
...extra
}
}
// 根据name查找series
export function findSeriesByName(series, seriesName) {
return series.find(item => item.name == seriesName)
}
/**
* 限定数字在一定范围
* @param {Number} min
* @param {Number} max
* @returns {(num: number) => number }
*/
export function rangeNumber(min, max) {
return num => {
return num > max ? max : num < min ? min : num
}
}
/**
* 获取图表某条轴线的最大值
* @param {import("echarts").ECharts} chartInstance
* @param {'xAxis' | 'yAxis'} axis
* @returns
*/
export function getAxisMax(chartInstance, axis) {
return chartInstance.getModel().getComponent(axis).axis.scale.rawExtentInfo._dataMax
}

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