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

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',
@ -29,38 +28,6 @@ export function postAction(url, parameter) {
})
}
//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) {
let sign = signMd5Utils.getSign(url, parameter);
@ -87,41 +54,21 @@ export function putAction(url, 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()};
// 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) {
return axios({
@ -256,7 +203,7 @@ export function getFileAccessHttpUrl(avatar, subStr) {
if(avatar && avatar.startsWith(subStr)){
return avatar;
}else{
if (avatar && avatar.length > 0 && avatar.indexOf('[') == -1) {
if(avatar && avatar.length>0 && avatar.indexOf('[')==-1){
return window._CONFIG['staticDomainURL'] + "/" + avatar;
}
}

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

@ -2,13 +2,11 @@
* 列表查询通用样式,移动端自适应
*/
.search{
/**
margin-bottom: 54px;
*/
}
.fold{
width: calc(100% - 216px);
display: inline-block;
display: inline-block
}
.operator{
margin-bottom: 18px;

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,21 +1,11 @@
<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-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>
@ -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) {
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' : '']"
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,68 +23,50 @@ 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
})
innerSelectedRows: []
}
},
methods: {
// /
customRow(record, index) {
customRow(record) {
const key = record[this.rowKey]
return {
class: this.innerSelectedRowKeys.includes(key) ? 'ant-table-row-selected' : '',
@ -95,70 +75,24 @@ export default {
if(!this.canSelect) {
return
}
//
if (this.innerSelectedRowKeys.includes(key)) {
if (this.multiple || this.canDeselect) {
const findIndex = this.innerSelectedRowKeys.findIndex((k) => k == key)
const findIndex = this.innerSelectedRowKeys.findIndex(k => k == key)
this.innerSelectedRowKeys.splice(findIndex, 1)
}
}
//
else {
} 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) {
@ -167,32 +101,20 @@ export default {
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 {
<style lang="less">
.custom-table-row {
cursor: pointer;
}
}
.mouse-move-select {
user-select: none;
::v-deep {
td {
transition: none !important;
}
}
}
</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) {
value(val) {
this.formModel = val
},
deep: true
},
// 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

@ -3,28 +3,11 @@
<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 ">
@ -38,27 +21,26 @@
import {ajaxGetDictItems,getDictItemsFromCache} from '@/api/api'
export default {
name: 'JDictSelectTag',
name: "JDictSelectTag",
props: {
modeType: String,
dictCode: String,
placeholder: String,
disabled: Boolean,
value: [String, Number, Array],
value: [String, Number],
type: String,
getPopupContainer:{
type: Function,
default: (node) => node.parentNode,
default: (node) => node.parentNode
},
allowClear: {
type: Boolean,
default: true,
},
default: true
}
},
data() {
return {
dictOptions: [],
tagType: '',
tagType:""
}
},
watch:{
@ -67,12 +49,12 @@ export default {
handler() {
this.initDictData()
},
},
}
},
created() {
// console.log(this.dictCode);
if (!this.type || this.type === 'list') {
this.tagType = 'select'
if(!this.type || this.type==="list"){
this.tagType = "select"
}else{
this.tagType = this.type
}
@ -83,8 +65,7 @@ export default {
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
return this.value != null ? this.value.toString() : undefined;
// update-end author:wangshuai date:20200601 for: placeholder ------
},
},
@ -92,7 +73,7 @@ export default {
initDictData() {
//
if(getDictItemsFromCache(this.dictCode)){
this.dictOptions = getDictItemsFromCache(this.dictCode)
this.dictOptions = getDictItemsFromCache(this.dictCode);
return
}
@ -100,32 +81,33 @@ export default {
ajaxGetDictItems(this.dictCode, null).then((res) => {
if (res.success) {
// console.log(res.result);
this.dictOptions = res.result
this.dictOptions = res.result;
}
})
},
handleInput(e='') {
let val
let val;
if(Object.keys(e).includes('target')){
val = e.target.value
}else{
val = e
}
this.$emit('change', val ? val : undefined)
console.log(val);
this.$emit('change', val? val: undefined);
//LOWCOD-2146 SQL
this.$emit('input', val ? val : undefined)
this.$emit('input', val? val: undefined);
},
setCurrentDictOptions(dictOptions){
this.dictOptions = dictOptions
},
getCurrentDictOptions(){
return this.dictOptions
},
}
},
model:{
prop: 'value',
event: 'change',
},
event: 'change'
}
}
</script>

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">
@ -27,41 +27,41 @@ export default {
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;
}
</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

@ -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 {
const childPath = this.getChildrenPath(this.menuItems.find(menu => menu.name === key))
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)
}
},
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>

View File

@ -2,8 +2,7 @@
<a-layout class="layout" :class="[device]">
<a-layout
:class="[layoutMode, `content-width-${contentWidth}`]"
:style="{ paddingLeft: fixSiderbar && isDesktop() ? `${sidebarOpened ? 200 : 80}px` : '0' }"
>
:style="{ paddingLeft: fixSiderbar && isDesktop() ? `${sidebarOpened ? 200 : 80}px` : '0' }">
<!-- layout header -->
<global-header
:mode="layoutMode"
@ -16,11 +15,11 @@
/>
<div class="global-content">
<div class="content-top-border">
<img src="@/assets/images/content/top.png" alt="" />
<img src="@/assets/images/content/top.png" alt="">
</div>
<div class="content-main">
<div class="content-left-border">
<img src="@/assets/images/content/left.png" alt="" />
<img src="@/assets/images/content/left.png" alt="">
</div>
<!-- layout content -->
<a-layout-content>
@ -32,11 +31,11 @@
</div>
</a-layout-content>
<div class="content-right-border">
<img src="@/assets/images/content/left.png" alt="" />
<img src="@/assets/images/content/left.png" alt="">
</div>
</div>
<div class="content-bottom-border">
<img src="@/assets/images/content/bottom.png" alt="" />
<img src="@/assets/images/content/bottom.png" alt="">
</div>
</div>
</a-layout>
@ -66,39 +65,38 @@ export default {
SideMenu,
GlobalHeader,
GlobalFooter,
SMenu,
SMenu
// update-start---- author:os_chengtgen -- date:20190830 -- for:issues/463 - ------
// // SettingDrawer
// SettingDrawer
// update-end ---- author:os_chengtgen -- date:20190830 -- for:issues/463 - ------
},
mixins: [mixin, mixinDevice],
data() {
return {
collapsed: false,
activeMenu:{},
menus: [],
menus: []
}
},
computed: {
...mapState({
//
mainRouters: (state) => state.permission.addRouters,
mainRouters: state => state.permission.addRouters,
//
permissionMenuList: (state) => state.user.permissionList,
permissionMenuList: state => state.user.permissionList
}),
//
currentChildrenMenus () {
const hasSubmenuPathList = ['/isystem', '/system'] //
const hasSubMenu = hasSubmenuPathList.some((item) => this.$route.path.indexOf(item) == 0)
return hasSubMenu ? this.findSubMenus(this.$route.name) : []
},
return this.findSubMenus(this.$route.name)
}
},
watch: {
sidebarOpened(val) {
this.collapsed = !val
},
}
},
created() {
//--update-begin----author:scott---date:20190320------for:URL------
@ -106,7 +104,7 @@ export default {
this.menus = this.permissionMenuList
//--update-begin----author:liusq---date:20210223------for: #2255
this.collapsed = !this.sidebarOpened
this.collapsed=!this.sidebarOpened;
//--update-begin----author:liusq---date:20210223------for: #2255
//
@ -126,10 +124,7 @@ export default {
findSubMenus(routeName) {
for (const menu of this.menus) {
if (menu.children) {
const find = menu.children.find(
(child) =>
child.name === routeName || (child.children && child.children.find((item) => item.name === routeName))
)
const find = menu.children.find(child => child.name === routeName || child.children && child.children.find(item => item.name === routeName))
if (find) {
return menu.children
}
@ -151,7 +146,7 @@ export default {
myMenuSelect(value){
//
this.findMenuBykey(this.menus,value.key)
this.$emit('dynamicRouterShow', value.key, this.activeMenu.meta.title)
this.$emit("dynamicRouterShow",value.key,this.activeMenu.meta.title)
},
findMenuBykey(menus,key){
for(let i of menus){
@ -171,8 +166,10 @@ export default {
this.$emit('dynamicRouterShow', value.path, this.activeMenu.meta.title)
},
// update-end-author:sunjianlei date:20210409 for:
},
}
}
</script>
<style lang="less">
@ -191,7 +188,9 @@ body {
overflow-x: hidden;
&.mobile {
.ant-layout-content {
.content {
margin: 24px 0 0;
}
@ -213,9 +212,9 @@ body {
}
.sidemenu {
.ant-header-fixedHeader {
&.ant-header-side-opened,
&.ant-header-side-closed {
width: 100%;
&.ant-header-side-opened, &.ant-header-side-closed {
width: 100%
}
}
}
@ -228,8 +227,7 @@ body {
}
}
}
.header,
.top-nav-header-index {
.header, .top-nav-header-index {
.user-wrapper .action {
padding: 0 12px;
}
@ -259,7 +257,7 @@ body {
right: 0;
z-index: 9;
width: 100%;
transition: width 0.2s;
transition: width .2s;
&.ant-header-side-opened {
width: 100%;
@ -280,6 +278,7 @@ body {
max-width: unset;
}
}
}
.sidemenu {
@ -289,14 +288,14 @@ body {
right: 0;
z-index: 9;
width: 100%;
transition: width 0.2s;
transition: width .2s;
&.ant-header-side-opened {
width: calc(100% - 200px);
width: calc(100% - 200px)
}
&.ant-header-side-closed {
width: calc(100% - 80px);
width: calc(100% - 80px)
}
}
}
@ -305,12 +304,12 @@ body {
height: 64px;
padding: 0 12px 0 0;
background: #fff;
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
box-shadow: 0 1px 4px rgba(0, 21, 41, .08);
position: relative;
}
.header,
.top-nav-header-index {
.header, .top-nav-header-index {
.user-wrapper {
width: 140px;
height: 100%;
@ -326,7 +325,7 @@ body {
.avatar {
margin: 20px 10px 20px 0;
color: #1890ff;
background: hsla(0, 0%, 100%, 0.85);
background: hsla(0, 0%, 100%, .85);
vertical-align: middle;
}
@ -343,6 +342,7 @@ body {
&.dark {
.user-wrapper {
.action {
color: black;
@ -360,8 +360,11 @@ body {
&.mobile {
.top-nav-header-index {
.header-index-wide {
.header-index-left {
.trigger {
color: rgba(255, 255, 255, 0.85);
padding: 0 12px;
@ -380,7 +383,9 @@ body {
}
&.light {
.header-index-wide {
.header-index-left {
.trigger {
color: rgba(0, 0, 0, 0.65);
@ -395,7 +400,9 @@ body {
&.tablet {
// overflow: hidden; text-overflow:ellipsis; white-space: nowrap;
.top-nav-header-index {
.header-index-wide {
.header-index-left {
.logo > a {
overflow: hidden;
@ -405,12 +412,13 @@ body {
}
}
}
}
.top-nav-header-index {
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
box-shadow: 0 1px 4px rgba(0, 21, 41, .08);
position: relative;
transition: background 0.3s, width 0.2s;
transition: background .3s, width .2s;
.header-index-wide {
width: 100%;
@ -469,7 +477,9 @@ body {
}
&.dark {
.user-wrapper {
.action {
color: white;
@ -482,6 +492,7 @@ body {
background: rgba(255, 255, 255, 0.3);
}
}
}
//
@ -490,6 +501,7 @@ body {
height: 64px;
padding: 0 12px 0 0;
}
}
.topmenu {
@ -518,13 +530,13 @@ body {
}
.ant-drawer-body {
padding: 0;
padding: 0
}
}
//
.sider {
box-shadow: 2px 116px 6px 0 rgba(0, 21, 41, 0.35);
box-shadow: 2px 116px 6px 0 rgba(0, 21, 41, .35);
position: relative;
z-index: 10;
@ -538,13 +550,12 @@ body {
position: relative;
line-height: 64px;
padding-left: 24px;
-webkit-transition: all 0.3s;
transition: all 0.3s;
-webkit-transition: all .3s;
transition: all .3s;
background: #002140;
overflow: hidden;
img,
h1 {
img, h1 {
display: inline-block;
vertical-align: middle;
}
@ -557,9 +568,7 @@ body {
color: #fff;
font-size: 18px;
margin: 0 0 0 8px;
font-family: 'Chinese Quote', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB',
'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
'Segoe UI Symbol';
font-family: "Chinese Quote", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-weight: 600;
}
}
@ -581,6 +590,7 @@ body {
border-right-color: transparent;
}
}
}
//
@ -593,10 +603,12 @@ body {
.ant-dropdown-menu-item > .anticon:first-child,
.ant-dropdown-menu-item > a > .anticon:first-child,
.ant-dropdown-menu-submenu-title > .anticon:first-child .ant-dropdown-menu-submenu-title > a > .anticon:first-child {
.ant-dropdown-menu-submenu-title > .anticon:first-child
.ant-dropdown-menu-submenu-title > a > .anticon:first-child {
min-width: 12px;
margin-right: 8px;
}
}
//
@ -605,7 +617,9 @@ body {
}
.table-page-search-wrapper {
.ant-form-inline {
.ant-form-item {
display: flex;
margin-bottom: 24px;
@ -634,9 +648,11 @@ body {
margin-bottom: 24px;
white-space: nowrap;
}
}
.content {
.table-operator {
margin-bottom: 18px;
@ -647,11 +663,11 @@ body {
}
.sub-menus {
border-top: 1px solid rgba(12, 235, 201, 0.3);
border-bottom: 1px solid rgba(12, 235, 201, 0.3);
border-top: 1px solid rgba(12, 235, 201, .3);
border-bottom: 1px solid rgba(12, 235, 201, .3);
margin-bottom: 16px;
padding: 5px 10px 8px;
background-color: rgba(12, 235, 201, 0.05);
background-color: rgba(12, 235, 201, .05);
overflow: auto;
.ant-menu {
border-bottom: none;
@ -659,7 +675,7 @@ body {
line-height: normal;
background-color: transparent;
.ant-menu-item {
background: rgba(58, 236, 240, 0.22) !important;
background: rgba(58, 236, 240, .22) !important;
border-bottom: none !important;
margin-right: 10px;
height: 30px;
@ -702,50 +718,6 @@ body {
border-left: 0;
}
}
.ant-menu-submenu {
background: rgba(58, 236, 240, 0.22) !important;
border-bottom: none !important;
margin-right: 10px;
height: 30px;
line-height: 30px;
padding: 0 16px;
letter-spacing: 2px;
position: relative;
&-title {
color: #c9f6f6;
font-weight: bold;
font-family: BookmanOldStyle;
padding: 0;
}
&-active,
&-selected {
> a {
color: #2affdf !important;
}
&::before,
&::after {
border-color: #0cecca !important;
}
}
&::before,
&::after {
content: '';
position: absolute;
border: 2px solid #569e9e;
width: 7px;
height: 30px;
top: 0;
}
&::before {
left: 0;
border-right: 0;
}
&::after {
right: 0;
border-left: 0;
}
}
}
}
.global-content {
@ -811,34 +783,4 @@ body {
}
}
}
.ant-menu-submenu-popup .ant-menu-item {
display: block !important;
width: 100%;
padding: 0 16px !important;
height: 32px !important;
line-height: 32px !important;
color: #fff;
font-family: Arial;
margin-bottom: 0 !important;
}
.ant-menu-submenu-popup .ant-menu {
height: auto;
width: 220px;
position: absolute;
left: -16px;
a {
color: white;
&:hover {
color: white;
}
}
}
.ant-menu-submenu-popup {
position: relative;
}
</style>
<style lang="less" scoped>
.ant-menu {
max-width: calc(100% - 200px);
}
</style>

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>
@ -32,16 +31,12 @@
<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>
<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>
@ -54,16 +49,12 @@
<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>
<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>
@ -77,7 +68,7 @@
</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>
@ -94,7 +85,7 @@ import Vue from 'vue'
import { ACCESS_TOKEN } from '@/store/mutation-types'
export default {
name: 'HeaderNotice',
name: "HeaderNotice",
components: {
DynamicNotice,
ShowAnnouncement,
@ -103,17 +94,17 @@ export default {
return {
loadding: false,
url:{
listCementByUser: '/sys/annountCement/listByUser',
editCementSend: '/sys/sysAnnouncementSend/editByAnntIdAndUserId',
queryById: '/sys/annountCement/queryById',
listCementByUser:"/sys/annountCement/listByUser",
editCementSend:"/sys/sysAnnouncementSend/editByAnntIdAndUserId",
queryById:"/sys/annountCement/queryById",
},
hovered: false,
announcement1:[],
announcement2:[],
msg1Count: '0',
msg2Count: '0',
msg1Title: '通知(0)',
msg2Title: '',
msg1Count:"0",
msg2Count:"0",
msg1Title:"通知(0)",
msg2Title:"",
stopTimer:false,
websock: null,
lockReconnect:false,
@ -121,32 +112,31 @@ export default {
wsConnectErrorTime:1,
heartCheck:null,
formData:{},
openPath: '',
openPath:''
}
},
computed:{
msgTotal () {
return parseInt(this.msg1Count) + parseInt(this.msg2Count)
},
return parseInt(this.msg1Count)+parseInt(this.msg2Count);
}
},
mounted() {
this.loadData()
this.loadData();
//this.timerFun();
this.initWebSocket()
this.initWebSocket();
// this.heartCheckFun();
},
destroyed: function () {
//
this.websocketOnclose()
destroyed: function () { //
this.websocketOnclose();
},
methods: {
timerFun() {
this.stopTimer = false
this.stopTimer = false;
let myTimer = setInterval(()=>{
//
if (this.stopTimer == true) {
clearInterval(myTimer)
return
clearInterval(myTimer);
return;
}
this.loadData()
},6000)
@ -154,25 +144,23 @@ export default {
loadData (){
try {
//
getAction(this.url.listCementByUser)
.then((res) => {
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 + ')'
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(error => {
console.log("系统消息通知异常",error);//permissionName is undefined
this.stopTimer = true;
console.log("清理timer");
});
} catch (err) {
this.stopTimer = true
console.log('通知异常', err)
this.stopTimer = true;
console.log("通知异常",err);
}
},
fetchNotice () {
@ -188,171 +176,168 @@ export default {
showAnnouncement(record){
putAction(this.url.editCementSend,{anntId:record.id}).then((res)=>{
if(res.success){
this.loadData()
this.loadData();
}
})
this.hovered = false
});
this.hovered = false;
if(record.openType==='component'){
this.openPath = record.openPage
this.formData = { id: record.busId }
this.$refs.showDynamNotice.detail(record.openPage)
this.openPath = record.openPage;
this.formData = {id:record.busId};
this.$refs.showDynamNotice.detail(record.openPage);
}else{
this.$refs.ShowAnnouncement.detail(record)
this.$refs.ShowAnnouncement.detail(record);
}
},
toMyAnnouncement(){
this.$router.push({
path: '/isystem/userAnnouncement',
})
path: '/isps/userAnnouncement'
});
},
modalFormOk(){
},
modalFormOk() {},
handleHoverChange (visible) {
this.hovered = 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
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])
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
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连接成功')
console.log("WebSocket连接成功");
//
//this.heartCheck.reset().start();
},
websocketOnerror: function (e) {
console.log('WebSocket连接发生错误第%s次', this.wsConnectErrorTime)
console.log("WebSocket连接发生错误第%s次",this.wsConnectErrorTime);
this.wsConnectErrorTime = this.wsConnectErrorTime + 1
this.wsConnectErrorTime = this.wsConnectErrorTime + 1;
if(this.wsConnectErrorTime>5){
console.log('WebSocket连接错误超过5次就不再重新连了')
console.log("WebSocket连接错误超过5次就不再重新连了");
this.lockReconnect = true
return
return;
}
this.reconnect()
this.reconnect();
},
websocketOnmessage: function (e) {
console.log('-----接收消息-------', e.data)
var data = eval('(' + e.data + ')') //
console.log("-----接收消息-------",e.data);
var data = eval("(" + e.data + ")"); //
this.voiceBroadcast(data.msgTxt)
if (data.cmd == 'topic') {
if(data.cmd == "topic"){
//
this.loadData()
} else if (data.cmd == 'user') {
this.loadData();
}else if(data.cmd == "user"){
//
this.loadData()
this.loadData();
}
//
//this.heartCheck.reset().start();
},
websocketOnclose: function (e) {
console.log('connection closed (' + e + ')')
console.log("connection closed (" + e + ")");
if(e){
console.log('connection closed (' + e.code + ')')
console.log("connection closed (" + e.code + ")");
}
this.reconnect()
this.reconnect();
},
websocketSend(text) {
//
websocketSend(text) { //
try {
this.websock.send(text)
this.websock.send(text);
} catch (err) {
console.log('send failed (' + err.code + ')')
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()
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()}`
var text = data.msgTxt;
const key = `open${Date.now()}`;
this.$notification.open({
message: '消息提醒',
placement:'bottomRight',
description: text,
key,
btn: (h)=>{
return h(
'a-button',
{
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
var that = this;
if(that.lockReconnect) return;
that.lockReconnect = true;
//
setTimeout(function () {
console.info('尝试重连...')
that.initWebSocket()
that.lockReconnect = false
}, 20000)
console.info("尝试重连...");
that.initWebSocket();
that.lockReconnect = false;
}, 20000);
},
heartCheckFun(){
var that = this
var that = this;
//,20s
that.heartCheck = {
timeout: 20000,
timeoutObj: null,
serverTimeoutObj: null,
reset: function(){
clearTimeout(this.timeoutObj)
clearTimeout(this.timeoutObj);
//clearTimeout(this.serverTimeoutObj);
return this
return this;
},
start: function(){
var self = this
var self = this;
this.timeoutObj = setTimeout(function(){
//
//onmessage
that.websocketSend('HeartBeat')
console.info('客户端发送心跳')
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
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)
var record = res.result;
this.showAnnouncement(record);
}
})
},
},
}
}
</script>

View File

@ -9,14 +9,13 @@ import xss from "xss"
@cancel="handleCancel"
>
<template slot="footer">
<a-button key="back" @click="handleCancel">Cancel</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>
@ -28,11 +27,12 @@ import xss from "xss"
import {getUserList} from '@/api/api'
import xss from 'xss'
export default {
name: 'SysAnnouncementModal',
components: {},
name: "SysAnnouncementModal",
components: {
},
data () {
return {
title: 'Notification Message',
title:"通知消息",
record: {},
labelCol: {
xs: { span: 24 },
@ -46,39 +46,41 @@ export default {
switchFullscreen: true,
loading: false,
bodyStyle:{
padding: '0',
height: window.innerHeight * 0.8 + 'px',
'overflow-y': 'auto',
padding: "0",
height:(window.innerHeight*0.8)+"px",
"overflow-y":"auto",
},
modelStyle:{
width: '60%',
style: { top: '20px' },
fullScreen: false,
},
fullScreen: false
}
}
},
created() {},
created () {
},
methods: {
detail (record) {
//update-begin---author:wangshuai ---date:20220107 for
if(record.sender){
getUserList({ username: record.sender }).then((res) => {
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
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
this.record = record;
},
handleCancel () {
this.visible = false
this.visible = false;
},
/** 切换全屏显示 */
handleClickToggleFullScreen() {
@ -94,12 +96,12 @@ export default {
},
toHandle(){
if(this.record.openType==='url'){
this.visible = false
this.visible = false;
//
this.$router.push({path: this.record.openPage})
}
},
},
}
}
</script>
@ -125,9 +127,6 @@ export default {
border-bottom: 0;
}
}
.ant-card-meta-description {
color: #fff !important;
}
</style>
<style scoped lang="less">
.daily-article {
@ -149,17 +148,9 @@ export default {
word-break: break-all;
text-overflow: initial;
white-space: normal;
font-size: 0.9rem !important;
margin-bottom: 0.8rem;
font-size: .9rem !important;
margin-bottom: .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">
<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>
<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>
@ -55,19 +56,22 @@
<script>
import HeaderNotice from './HeaderNotice'
import UserPassword from './UserPassword'
import SettingDrawer from '@/components/setting/SettingDrawer'
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 { getFileAccessHttpUrl,getAction } from "@/api/manage"
import Vue from 'vue'
import { UI_CACHE_DB_DICT_DATA } from '@/store/mutation-types'
import { UI_CACHE_DB_DICT_DATA } from "@/store/mutation-types"
import i18nMixin from '@/store/i18n-mixin'
export default {
name: 'UserMenu',
mixins: [mixinDevice],
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',
@ -79,14 +83,14 @@ export default {
HeaderNotice,
UserPassword,
DepartSelect,
SettingDrawer,
SettingDrawer
},
props: {
theme: {
type: String,
required: false,
default: 'dark',
},
default: 'dark'
}
},
/* update_begin author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
created() {
@ -95,6 +99,7 @@ export default {
this.searchMenuOptions = [...lists]
},
mounted() {
console.log(this.$i18n.locale);
//
if (process.env.VUE_APP_SSO == 'true') {
let depart = this.userInfo().orgCode
@ -106,8 +111,9 @@ export default {
computed: {
...mapState({
//
permissionMenuList: (state) => state.user.permissionList,
}),
permissionMenuList: state => state.user.permissionList
})
},
/* update_end author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
watch: {
@ -122,6 +128,11 @@ export default {
// 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
@ -130,8 +141,8 @@ export default {
this.shows = false
},
/* update_end author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
...mapActions(['Logout']),
...mapGetters(['nickname', 'avatar', 'userInfo']),
...mapActions(["Logout"]),
...mapGetters(["nickname", "avatar","userInfo"]),
getAvatar(){
return getFileAccessHttpUrl(this.avatar())
},
@ -143,27 +154,25 @@ export default {
content: 'Ensure Log Out?',
cancelButtonProps: {
props: {
type: 'warn',
},
type: 'warn'
}
},
onOk() {
return that
.Logout({})
.then(() => {
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() {},
})
onCancel() {
},
});
},
updatePassword(){
let username = this.userInfo().username
@ -178,7 +187,7 @@ export default {
/* update_begin author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
searchMenus(arr,menus){
for(let i of menus){
if (!i.hidden && 'layouts/RouteView' !== i.component) {
if(!i.hidden && "layouts/RouteView"!==i.component){
arr.push(i)
}
if(i.children&& i.children.length>0){
@ -191,7 +200,7 @@ export default {
},
// update_begin author:sunjianlei date:20191230 for:
searchMethods(value) {
let route = this.searchMenuOptions.filter((item) => item.id === value)[0]
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)
@ -205,26 +214,24 @@ export default {
/*update_end author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
/*update_begin author:liushaoqian date:20200507 for: 刷新缓存*/
clearCache(){
getAction('sys/dict/refleshCache')
.then((res) => {
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: 刷新缓存*/
},
}
}
</script>
@ -239,12 +246,22 @@ export default {
background-color: inherit;
border: 0;
border-bottom: 1px solid white;
&__placeholder,
&__field__placeholder {
&__placeholder, &__field__placeholder {
color: inherit;
}
}
}
.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>

View File

@ -6,86 +6,74 @@
: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',
name: "UserPassword",
data () {
return {
title: 'Change Password',
title:"修改密码",
modalWidth:800,
visible: false,
confirmLoading: false,
validatorRules:{
oldpassword:{
rules: [
{
required: true,
message: '请输入旧密码!',
},
],
rules: [{
required: true, message: '请输入旧密码!',
}],
},
password:{
rules: [
{
required: true,
message: '请输入新密码!',
},
{
rules: [{
required: true, message: '请输入新密码!',
}, {
validator: this.validateToNextPassword,
},
],
}],
},
confirmpassword:{
rules: [
{
required: true,
message: '请确认新密码!',
},
{
rules: [{
required: true, message: '请确认新密码!',
}, {
validator: this.compareToFirstPassword,
},
],
},
}],
}
},
confirmDirty:false,
labelCol: {
xs: { span: 24 },
sm: { span: 6 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
@ -93,65 +81,63 @@ export default {
},
form:this.$form.createForm(this),
url: 'sys/user/updatePassword',
username: '',
url: "sys/user/updatePassword",
username:"",
}
},
methods: {
show(uname){
if(!uname){
this.$message.warning('当前系统无登录用户!')
this.$message.warning("当前系统无登录用户!");
return
}else{
this.username = uname
this.form.resetFields()
this.visible = true
this.form.resetFields();
this.visible = true;
}
},
handleCancel () {
this.close()
},
close () {
this.$emit('close')
this.visible = false
this.disableSubmit = false
this.selectedRole = []
this.$emit('close');
this.visible = false;
this.disableSubmit = false;
this.selectedRole = [];
},
handleOk () {
const that = this
const that = this;
//
this.form.validateFields((err, values) => {
if (!err) {
that.confirmLoading = true
that.confirmLoading = true;
let params = Object.assign({username:this.username},values)
console.log('修改密码提交数据', params)
putAction(this.url, params)
.then((res) => {
console.log("修改密码提交数据",params)
putAction(this.url,params).then((res)=>{
if(res.success){
console.log(res)
that.$message.success(res.message)
that.close()
that.$message.success(res.message);
that.close();
}else{
that.$message.warning(res.message)
that.$message.warning(res.message);
}
})
.finally(() => {
that.confirmLoading = false
}).finally(() => {
that.confirmLoading = false;
})
}
})
},
validateToNextPassword (rule, value, callback) {
const form = this.form
const form = this.form;
if (value && this.confirmDirty) {
form.validateFields(['confirm'], { force: true })
}
callback()
callback();
},
compareToFirstPassword (rule, value, callback) {
const form = this.form
const form = this.form;
if (value && value !== form.getFieldValue('password')) {
callback('两次输入的密码不一样!')
callback('两次输入的密码不一样!');
} else {
callback()
}
@ -159,11 +145,13 @@ export default {
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

@ -82,13 +82,15 @@ 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) {
if(res.result.total)
{
this.ipagination.total = res.result.total;
}else{
this.ipagination.total = 0;
@ -118,15 +120,13 @@ export const JeecgListMixin = {
},
getQueryParams() {
//获取查询条件
console.log("this.queryParamthis.queryParam", this.queryParam);
let sqp = {}
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;
param.field = this.getQueryField();
param.pageNo = this.ipagination.current;
param.pageSize = this.ipagination.pageSize;
return filterObj(param);
@ -237,7 +237,6 @@ export const JeecgListMixin = {
this.$refs.modalForm.disableSubmit = false;
},
handleTableChange(pagination, filters, sorter) {
console.log("sortersorter", sorter);
//分页、排序、筛选变化时触发
//TODO 筛选
console.log(pagination)

View File

@ -4,24 +4,12 @@ export default {
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()
}
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;
@ -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
)
@ -18,101 +18,3 @@ export function getXAxisAndYAxisByPosition(chart, offsetX, offsetY, seriesIndex
}
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