Commit 288d689a by 潘际乾

页面多页签切换,增加首页、待办任务

parent bce4577e
......@@ -2338,6 +2338,15 @@
"es5-ext": "~0.10.46"
}
},
"echarts": {
"version": "5.2.2",
"resolved": "https://registry.npmmirror.com/echarts/download/echarts-5.2.2.tgz",
"integrity": "sha1-7DyLKhUcu6cbo8LHz5svIEfOQ3A=",
"requires": {
"tslib": "2.3.0",
"zrender": "5.2.1"
}
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
......@@ -6926,6 +6935,11 @@
"integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=",
"dev": true
},
"tslib": {
"version": "2.3.0",
"resolved": "https://registry.nlark.com/tslib/download/tslib-2.3.0.tgz",
"integrity": "sha1-gDuM2rPhK6WBpMpByIObuw2ssJ4="
},
"tty-browserify": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
......@@ -8129,6 +8143,14 @@
"dev": true
}
}
},
"zrender": {
"version": "5.2.1",
"resolved": "https://registry.nlark.com/zrender/download/zrender-5.2.1.tgz",
"integrity": "sha1-X0u9qRW6bUErCxncJDG+qtBUF7s=",
"requires": {
"tslib": "2.3.0"
}
}
}
}
......@@ -10,14 +10,15 @@
"dependencies": {
"async-validator": "^3.5.2",
"axios": "^0.19.2",
"bignumber.js": "^9.0.1",
"cluster": "^0.7.7",
"echarts": "^5.2.2",
"element-ui": "^2.13.2",
"es6-promise": "^4.2.8",
"lodash": "^4.17.21",
"vue": "^2.6.11",
"vue-router": "^3.2.0",
"vuex": "^3.4.0",
"bignumber.js": "^9.0.1"
"vuex": "^3.4.0"
},
"engines": {
"node": ">=6"
......
......@@ -56,7 +56,7 @@
background-color: var(--color);
} */
.m-app-main {
background-color: var(--bgcolor);
/* background-color: var(--bgcolor); */
}
.m-app {
background-color: var(--darkbgcolor);
......@@ -219,13 +219,22 @@
.el-dialog__body {
padding: 10px 20px 20px;
}
/* form 必填项的内容区域颜色突出显示 */
.el-form-item.is-required .el-form-item__content .el-input__inner,
.el-form-item.is-required .el-form-item__content .el-textarea__inner,
.el-form-item.is-required .el-form-item__content .el-checkbox__inner,
.el-form-item.is-required .el-form-item__content .el-radio__inner,
.el-form-item.is-required .el-form-item__content .el-input__count {
background-color: #f3f3bf87;
}
/* form 必填项红星星靠右 */
.el-form-item.is-required:not(.is-no-asterisk) .el-form-item__label-wrap>.el-form-item__label:after, .el-form-item.is-required:not(.is-no-asterisk)>.el-form-item__label:after {
.el-form-item.is-required:not(.is-no-asterisk) .el-form-item__label-wrap>.el-form-item__label:before, .el-form-item.is-required:not(.is-no-asterisk)>.el-form-item__label:before {
content: '*';
color: #F56C6C;
margin-left: 4px;
}
.el-form-item.is-required:not(.is-no-asterisk) .el-form-item__label-wrap>.el-form-item__label:before, .el-form-item.is-required:not(.is-no-asterisk)>.el-form-item__label:before {
.el-form-item.is-required:not(.is-no-asterisk) .el-form-item__label-wrap>.el-form-item__label:after, .el-form-item.is-required:not(.is-no-asterisk)>.el-form-item__label:after {
content: none;
}
......
......@@ -10,7 +10,7 @@
height: {
type: Number,
require: false,
default: 220
default: 275
}
},
data() {
......
<template>
<div class="c-page-container">
<div class="title">
<!-- <div class="title">
<i class="el-icon-location" style="color: #409eff;"></i>
<span>{{ title }}</span>
</div>
</div> -->
<div style="flex: 1; padding: 10px 20px; position: relative">
<slot></slot>
</div>
......
......@@ -194,6 +194,24 @@ export default {
*/
changeFormItemRequired(property, required) {
this.pattern[property][0].required = required
},
/**
* 在 A 交易中打开 B 交易视图(详情、开立...)。
*
* 路由视图跳转,例:
* this.gotoView("Ditopn", {inr: "001021021"}, {name: "lisi"}) 实际请求的 url 为 /business/ditopn/001021021?name=lisi
* params, query按需传入(得提前配置好 Router ),在对应的vue页面做好处理
* @param {String} name 路由的name
* @param {Object} params 路由的params
* @param {Object} query 路由的query
*/
gotoView(name, params, query) {
params = params || {}
query = query || {}
this.$router.push({name, params, query})
},
gotoUrl(url) {
this.$router.push(url)
}
},
computed: {
......
import Vue from 'vue'
import VueRouter from 'vue-router'
import Vue from "vue";
import VueRouter from "vue-router";
import Display from "../views/Display"
import Login from "../views/Login"
import Layout from "../views/Layout"
import BusRouter from '../views/Business/BusRouter'
import DocRouter from '../views/Docpan/DocRouter'
import Display from "../views/Display";
import Login from "../views/Login";
import Layout from "../views/Layout";
import BusRouter from "../views/Business/BusRouter";
import DocRouter from "../views/Docpan/DocRouter";
Vue.use(VueRouter)
Vue.use(VueRouter);
const rootRouter = new VueRouter({
routes: [
{path:"/display",component:Display,children:BusRouter},
{path:"/login",component:Login},
{path:"/business",component:Layout,children:BusRouter},
{path:"/docpan",component: () => import('../views/Docpan'), children:DocRouter}
]
const DisplayRouter = BusRouter.map(route => {
const newRoute = Object.assign({}, route)
newRoute.name = newRoute.name + 'Display'
return newRoute;
})
export default rootRouter
/**
* Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
*
* name:'router-name' name 必填 <keep-alive>使用这个
* meta : {
* title: 'title' title
* icon: 'svg-name'/'el-icon-x' 图标
* noCache: true 无需缓存起来的页面
* affix: true 固定的页面视图
* activeMenu: '/example/list' if set path, the sidebar will highlight the path you set
* }
*/
export const routes = [
// 刷新时使用
{
path: '/redirect',
component: Layout,
hidden: true,
children: [
{
path: '/redirect/:path(.*)',
component: () => import('~/views/Redirect/index')
}
]
},
{
path: "/",
component: Layout,
redirect: "/home",
children: [
{ path: 'home', component: () => import('~/views/Home'), name: 'Home', meta: { title: '首页', icon: 'el-icon-s-home', affix: true} },
{ path: 'todo', component: () => import('~/views/Todo'), name: 'Todo', meta: { title: '任务列表', icon: 'el-icon-s-claim', affix: true} },
],
},
{ path: "/display", component: Display, children: DisplayRouter },
{ path: "/business", component: Layout, children: BusRouter },
{ path: "/login", component: Login },
{ path: "/docpan", component: () => import("../views/Docpan"), children: DocRouter },
];
const rootRouter = new VueRouter({
routes,
});
// 解决ElementUI导航栏中的vue-router在3.0版本以上重复点菜单报错问题
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err)
}
export default rootRouter;
const state = {
visitedViews: [],
cachedViews: []
}
const mutations = {
ADD_VISITED_VIEW: (state, view) => {
if (state.visitedViews.some(v => v.path === view.path)) return
state.visitedViews.push(
Object.assign({}, view, {
title: view.meta.title || 'no-name'
})
)
},
ADD_CACHED_VIEW: (state, view) => {
if (state.cachedViews.includes(view.name)) return
if (!view.meta.noCache) {
state.cachedViews.push(view.name)
}
},
DEL_VISITED_VIEW: (state, view) => {
for (const [i, v] of state.visitedViews.entries()) {
if (v.path === view.path) {
state.visitedViews.splice(i, 1)
break
}
}
},
DEL_CACHED_VIEW: (state, view) => {
const index = state.cachedViews.indexOf(view.name)
index > -1 && state.cachedViews.splice(index, 1)
},
DEL_OTHERS_VISITED_VIEWS: (state, view) => {
state.visitedViews = state.visitedViews.filter(v => {
return v.meta.affix || v.path === view.path
})
},
DEL_OTHERS_CACHED_VIEWS: (state, view) => {
const index = state.cachedViews.indexOf(view.name)
if (index > -1) {
state.cachedViews = state.cachedViews.slice(index, index + 1)
} else {
// if index = -1, there is no cached tags
state.cachedViews = []
}
},
DEL_ALL_VISITED_VIEWS: state => {
// keep affix tags
const affixTags = state.visitedViews.filter(tag => tag.meta.affix)
state.visitedViews = affixTags
},
DEL_ALL_CACHED_VIEWS: state => {
state.cachedViews = []
},
UPDATE_VISITED_VIEW: (state, view) => {
for (let v of state.visitedViews) {
if (v.path === view.path) {
v = Object.assign(v, view)
break
}
}
}
}
const actions = {
addView({ dispatch }, view) {
dispatch('addVisitedView', view)
dispatch('addCachedView', view)
},
addVisitedView({ commit }, view) {
commit('ADD_VISITED_VIEW', view)
},
addCachedView({ commit }, view) {
commit('ADD_CACHED_VIEW', view)
},
delView({ dispatch, state }, view) {
return new Promise(resolve => {
dispatch('delVisitedView', view)
dispatch('delCachedView', view)
resolve({
visitedViews: [...state.visitedViews],
cachedViews: [...state.cachedViews]
})
})
},
delVisitedView({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_VISITED_VIEW', view)
resolve([...state.visitedViews])
})
},
delCachedView({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_CACHED_VIEW', view)
resolve([...state.cachedViews])
})
},
delOthersViews({ dispatch, state }, view) {
return new Promise(resolve => {
dispatch('delOthersVisitedViews', view)
dispatch('delOthersCachedViews', view)
resolve({
visitedViews: [...state.visitedViews],
cachedViews: [...state.cachedViews]
})
})
},
delOthersVisitedViews({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_OTHERS_VISITED_VIEWS', view)
resolve([...state.visitedViews])
})
},
delOthersCachedViews({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_OTHERS_CACHED_VIEWS', view)
resolve([...state.cachedViews])
})
},
delAllViews({ dispatch, state }, view) {
return new Promise(resolve => {
dispatch('delAllVisitedViews', view)
dispatch('delAllCachedViews', view)
resolve({
visitedViews: [...state.visitedViews],
cachedViews: [...state.cachedViews]
})
})
},
delAllVisitedViews({ commit, state }) {
return new Promise(resolve => {
commit('DEL_ALL_VISITED_VIEWS')
resolve([...state.visitedViews])
})
},
delAllCachedViews({ commit, state }) {
return new Promise(resolve => {
commit('DEL_ALL_CACHED_VIEWS')
resolve([...state.cachedViews])
})
},
updateVisitedView({ commit }, view) {
commit('UPDATE_VISITED_VIEW', view)
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
......@@ -2,6 +2,7 @@ import I18NStore from "./I18NStore"
import UserContext from "./UserContext"
import Status from "./Status"
import Swift from "./Swift"
import TagsView from "./TagsView"
import Vuex from 'vuex'
import Vue from 'vue'
......@@ -12,7 +13,8 @@ const store = new Vuex.Store({
I18n: I18NStore,
UserContext: UserContext,
Status: Status,
Swift: Swift
Swift: Swift,
TagsView: TagsView
}
})
......
......@@ -21,30 +21,34 @@ import Switsk from "./Switsk"
import Infusr from "./Infusr"
import Infcpd from "./Infcpd"
/**
* 带有name的才会被添加进顶部的标签页里
*/
const BusRouter = [
{ path: 'bdtudp', component: Bdtudp },
{ path: 'cptadv', component: Cptadv },
{ path: 'cptopn', component: Cptopn },
{ path: 'diasel', component: Diasel },
{ path: 'ditame', component: Ditame },
{ path: 'ditsel', component: Ditsel },
{ path: 'ditopn', component: Ditopn },
{ path: 'office', component: Office },
{ path: 'sptsel', component: Sptsel },
{ path: 'trnrel', component: Trnrel },
{ path: 'trndtl', query: 'inr', component: Trndtl },
{ path: 'tstopn', component: Tstopn },
{ path: 'infpta', component: Infpta },
{ path: 'letopn', component: Letopn },
{ path: 'sptrel', component: Sptrel },
{ path: 'sptrou', component: Sptrou },
{ path: 'bddsel', component: Bddsel },
{ path: 'infbdd', component: Infbdd },
{ path: 'mgrtsk', component: Mgrtsk },
{ path: 'switsk', component: Switsk },
{ path: 'infusr', component: Infusr },
{ path: 'infcpd', component: Infcpd },
{ path: 'bdtudp', component: Bdtudp, name: 'Bdtudp', meta: {title: '国内证承兑'} },
{ path: 'cptadv', component: Cptadv, name: 'Cptadv', meta: {title: '汇入汇款'} },
{ path: 'cptopn', component: Cptopn, name: 'Cptopn', meta: {title: '汇出汇款'} },
{ path: 'diasel', component: Diasel, name: 'Diasel', meta: {title: '备忘录选择交易'} },
{ path: 'ditame', component: Ditame, name: 'Ditame', meta: {title: '信用证修改'} },
{ path: 'ditsel', component: Ditsel, name: 'Ditsel', meta: {title: '信用证查询'} },
{ path: 'ditopn', component: Ditopn, name: 'Ditopn', meta: {title: '买方信用证开立'} },
// 例
{ path: 'ditopn/:inr', component: Ditopn, name: 'DitopnInr', meta: {title: (params) => {return '买方信用证开立-' + params.inr}} },
{ path: 'office', component: Office, name: 'Office', meta: {title: 'Office'} },
{ path: 'sptsel', component: Sptsel, name: 'Sptsel', meta: {title: '待办任务'} },
{ path: 'trnrel', component: Trnrel, name: 'Trnrel', meta: {title: '复核任务'} },
{ path: 'trndtl', query: 'inr', component: Trndtl, name: 'Trndtl', meta: {title: 'Trndtl'} },
{ path: 'tstopn', component: Tstopn, name: 'Tstopn', meta: {title: 'Tstopn'} },
{ path: 'infpta', component: Infpta, name: 'Infpta', meta: {title: 'Infpta'} },
{ path: 'letopn', component: Letopn, name: 'Letopn', meta: {title: '出口信用证通知'} },
{ path: 'sptrel', component: Sptrel, name: 'Sptrel', meta: {title: 'Sptrel'} },
{ path: 'sptrou', component: Sptrou, name: 'Sptrou', meta: {title: 'Sptrou'} },
{ path: 'bddsel', component: Bddsel, name: 'Bddsel', meta: {title: 'Bddsel'} },
{ path: 'infbdd', component: Infbdd, name: 'Infbdd', meta: {title: 'Infbdd'} },
{ path: 'mgrtsk', component: Mgrtsk, name: 'Mgrtsk', meta: {title: 'Mgrtsk'} },
{ path: 'switsk', component: Switsk, name: 'Switsk', meta: {title: 'Switsk'} },
{ path: 'infusr', component: Infusr, name: 'Infusr', meta: {title: '用户信息'} },
{ path: 'infcpd', component: Infcpd, name: 'Infcpd', meta: {title: '汇款查询'} },
]
export default BusRouter
\ No newline at end of file
......@@ -20,7 +20,7 @@
:rules="rules"
ref="modelForm"
label-width="150px"
label-position="left"
label-position="right"
size="small"
:validate-on-rule-change="false"
>
......@@ -46,7 +46,9 @@
-->
<el-tab-pane label="银行明细" name="detp1">
<!--PD000452 -->
<m-detp1 :model="model" :codes="codes" />
<c-content>
<m-detp1 :model="model" :codes="codes" />
</c-content>
</el-tab-pane>
<el-tab-pane label="明细" name="detp">
<!--PD000077 -->
......@@ -149,6 +151,7 @@ import Setpan from "~/views/Public/Setpan";
import Docpan from "~/views/Public/Docpan";
export default {
name: 'Ditopn',
components: {
"m-ovwp": Ovwp,
"m-revp": Revp,
......
......@@ -38,6 +38,7 @@ import Event from "~/model/Trnrel/Event";
export default {
name: 'Trnrel',
components:{
"m-inftrnps" : Inftrnps,
},
......
<template>
<div id="business_container">
<router-view></router-view>
</div>
<section id="business_container">
<transition name="fade-transform" mode="out-in">
<keep-alive :include="cachedViews">
<router-view :key="key" />
</keep-alive>
</transition>
</section>
</template>
<script>
export default {
created:()=>{
console.log("进入业务交易界面")
}
}
created: () => {
console.log("进入业务交易界面");
},
computed: {
cachedViews() {
return this.$store.state.TagsView.cachedViews;
},
key() {
return this.$route.path;
},
},
};
</script>
<style>
#business_container{
height: 100%;
position: absolute;
width: 100%;
}
#business_container {
/* height: 100%; */
height: calc(100% - 55px);
position: absolute;
width: 100%;
}
</style>
<template>
<div class="home-item" id="customerAnalyse">
<ItemHeaderVue title="大客户分析">
<span class="el-icon-refresh-right" title="刷新"></span>
</ItemHeaderVue>
<div class="item-content">
<div class="chart-operate">
<i class="el-icon-arrow-up"></i>
<i class="el-icon-arrow-down"></i>
</div>
<div id="chart"></div>
</div>
</div>
</template>
<script>
import ItemHeaderVue from "./ItemHeader.vue";
import * as echarts from "echarts";
export default {
name: "CustomerAnalyse",
components: { ItemHeaderVue },
data() {
return {};
},
mounted() {
const echartInstance = echarts.init(document.getElementById("chart"));
const option = {
title: {
// text: "Test Demo",
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
},
legend: {
bottom: "2%",
},
grid: {
left: "1%",
right: "6%",
top: "1%",
containLabel: true,
},
xAxis: {
type: "value",
boundaryGap: [0, 0.01],
},
yAxis: {
type: "category",
data: [
"总行国际业务中心",
"盛世饮料",
"中国华润总公司",
"东风汽车公司",
"恒大集团",
"万康食品",
],
},
series: [
{
name: "业务量(万美元)",
type: "bar",
data: [18203, 23489, 29034, 104970, 131744, 230230],
},
{
name: "融资量(万美元)",
type: "bar",
data: [19325, 23438, 31000, 121594, 134141, 381807],
},
{
name: "中欧贡献(千美元)",
type: "bar",
data: [49325, 53438, 11000, 221594, 43241, 455807],
},
],
};
echartInstance.setOption(option);
},
};
</script>
<style scoped>
#customerAnalyse .item-content .chart-operate {
margin-left: 20px;
height: 20px;
}
#customerAnalyse .item-content .chart-operate i {
cursor: pointer;
}
#customerAnalyse .item-content #chart {
width: 98%;
height: calc(100% - 20px);
margin: 0 auto;
}
</style>
<template>
<div class="home-item" id="hall">
<ItemHeaderVue title="电子大厅">
<span class="el-icon-refresh-right" title="刷新"></span>
</ItemHeaderVue>
<div class="item-content">
<div class="card-item" v-for="(item, idx) in itemList" :key="idx">
<div class="dept-name">
<div class="first-word" :style="{ 'background-image': item.backImg }">
{{ item.title.substr(0, 1) }}
</div>
<div class="dz-title">{{ item.title }}</div>
</div>
<div class="type-count">
<div class="count-item">
操作处理类 <span class="count-number">26</span>
</div>
<div class="count-item">
提示信息类 <span class="count-number">3</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import ItemHeaderVue from "./ItemHeader.vue";
export default {
name: "Hall",
components: { ItemHeaderVue },
data() {
return {
itemList: [
{ title: "资产管理大厅", backImg: "linear-gradient(#2073ef, #bec2f3" },
{
title: "我行发布资产大厅",
backImg: "linear-gradient(rgb(28 190 241), rgb(201 229 237))",
},
{
title: "他行发布资产大厅",
backImg: "linear-gradient(rgb(243, 195, 12), rgb(239 228 197))",
},
{
title: "资金发布大厅",
backImg: "linear-gradient(#ff9800, rgb(251 234 210))",
},
],
};
},
};
</script>
<style scoped>
#hall .item-content {
display: flex;
flex-wrap: wrap;
}
#hall .item-content {
justify-content: space-around;
align-items: center;
}
#hall .item-content .card-item {
width: 45%;
height: 45%;
background-color: #e6e8ef;
border-radius: 12px;
padding: 20px 20px;
box-sizing: border-box;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.dept-name {
display: flex;
align-items: center;
}
.first-word {
width: 40px;
height: 40px;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
font-weight: bolder;
font-family: emoji;
border-radius: 8px;
}
.dz-title {
margin-left: 20px;
margin-left: 20px;
font-weight: bold;
}
.type-count .count-item {
display: flex;
align-items: center;
font-weight: 400;
color: #6c6f72;
}
.type-count .count-number {
font-size: 25px;
margin-left: 20px;
color: #000;
}
</style>
<template>
<div class="item-header">
<div class="item-header_title">{{ title }}</div>
<div>
<slot></slot>
</div>
</div>
</template>
<script>
export default {
props: {
title: {
type: String,
required: true,
},
},
};
</script>
<style scoped>
.item-header {
margin: 10px 20px;
height: 30px;
display: flex;
justify-content: space-between;
border-bottom: 2px solid #f7f7f7;
}
.item-header_title {
font-weight: bold;
font-size: 15px;
}
.item-header_title::before {
content: "";
border-left: 5px solid #647092;
margin-right: 10px;
}
.item-header [class^="el-icon-"] {
font-weight: bold;
cursor: pointer;
color: #95979b;
}
.item-header [class^="el-icon-"]:hover {
color: #000;
}
.item-header >>> .el-icon-more {
transform: rotate(90deg);
}
</style>
<template>
<div class="home-item" id="noticeAnnouncement">
<ItemHeaderVue title="通知公告">
<span class="el-icon-refresh-right" title="刷新"></span>
<span class="el-icon-more" title="操作"></span>
</ItemHeaderVue>
<div class="item-content">
<div class="notice-item" v-for="(item, idx) in noticeList" :key="idx">
<div class="notice-title" :class="{ active: idx === 0 }">
{{ item.title }}
</div>
<div class="notice-date">
{{ item.date }}
</div>
</div>
</div>
</div>
</template>
<script>
import ItemHeaderVue from "./ItemHeader.vue";
export default {
name: "NoticeAnnouncement",
components: { ItemHeaderVue },
data() {
return {
noticeList: [
{
title:
"国务院关于同意在澳门特别行政区维护国家安全委员会设立国家安全事务顾问和国家安全技术顾问的批复",
date: "2021-12-03",
},
{ title: '国务院批复同意《"十四五"公共服务规划》', date: "2021-11-30" },
{ title: "学习六中全会精神 这些表述要精读", date: "2021-11-08" },
{ title: "十九届六中全会有何特殊意义", date: "2021-11-08" },
{ title: "部署开展科技成果评价改革试点", date: "2021-11-08" },
{ title: "印发供电企业信息公开实施办法", date: "2021-11-08" },
{ title: "公布2020年全国海水利用报告", date: "2021-11-08" },
{ title: "制造业中小微企业缓缴税费超15亿元", date: "2021-11-08" },
{ title: "完成审计事项整改1882项", date: "2021-11-08" },
{ title: "完成审计事项整改1882项", date: "2021-11-08" },
{ title: "完成审计事项整改1882项", date: "2021-11-08" },
{ title: "探索企业信用监管“一张网”显成效", date: "2021-11-08" },
{ title: "探索企业信用监管“一张网”显成效", date: "2021-11-08" },
],
};
},
};
</script>
<style scoped>
/* 通知公告 */
#noticeAnnouncement .item-content {
display: flex;
flex-wrap: wrap;
margin: 0 20px;
}
#noticeAnnouncement .item-content .notice-item {
width: 100%;
display: flex;
justify-content: space-between;
margin-bottom: 5px;
font-size: 15px;
}
#noticeAnnouncement .item-content .notice-item .notice-title {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 75%;
}
#noticeAnnouncement .item-content .notice-item .notice-title::before {
content: "";
display: inline-block;
width: 8px;
}
#noticeAnnouncement .item-content .notice-item .notice-title.active::before {
content: "";
background: rgb(255, 0, 0);
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
position: relative;
margin-right: 2px;
margin-bottom: 2px;
}
#noticeAnnouncement .item-content .notice-item .notice-date {
/* width: 20%; */
margin-right: 6px;
}
</style>
<template>
<div class="home-item" id="quickSearch">
<ItemHeaderVue title="快速查询"> </ItemHeaderVue>
<div class="item-content">
<div
class="search-item"
v-for="(item, index) in options"
:key="index"
>
<i class="el-icon-set-up"></i>
<span>{{ item.name }}</span>
</div>
</div>
</div>
</template>
<script>
import ItemHeaderVue from "./ItemHeader.vue";
export default {
name: 'QuickSearch',
components: { ItemHeaderVue },
data() {
return {
options: [
{name: '报文查询', img: '', url: ''},
{name: '银行查询', img: '', url: ''},
{name: '公司查询', img: '', url: ''},
{name: '交易查询', img: '', url: ''},
{name: '序号查询', img: '', url: ''},
{name: '企业分类信息查询', img: '', url: ''},
{name: '电子数据查询', img: '', url: ''},
{name: '账务查看', img: '', url: ''},
]
}
}
};
</script>
<style scoped>
#quickSearch .item-content {
display: flex;
flex-wrap: wrap;
}
#quickSearch .item-content .search-item {
display: flex;
display: flex;
width: 150px;
/* height: 80px; */
flex-direction: column;
align-items: center;
margin: 0 15px 15px;
cursor: pointer;
}
#quickSearch .item-content .search-item i {
color: #0088ff;
font-size: 36px;
}
#quickSearch .item-content .search-item span {
color: #303133;
font-size: 15px;
margin-top: 10px;
}
/* #quickSearch .item-content .search-item:hover i {
color: var(--themecolor);
} */
#quickSearch .item-content .search-item:hover span {
color: var(--themecolor);
}
</style>
<template>
<div class="home-item" id="quickVisit">
<ItemHeaderVue title="快速访问">
<span class="el-icon-refresh-right" title="刷新"></span>
<span class="el-icon-more" title="操作"></span>
</ItemHeaderVue>
<div class="item-content">
<div
class="visit-item"
v-for="(item, index) in quickVisitItem"
:key="index"
>
<i class="el-icon-set-up"></i>
<span>{{ item.name }}</span>
</div>
<div class="visit-item">
<i class="el-icon-circle-plus-outline"></i>
<span>添加</span>
</div>
</div>
</div>
</template>
<script>
import ItemHeaderVue from "./ItemHeader.vue";
export default {
name: 'QuickVisit',
components: { ItemHeaderVue },
data() {
return {
quickVisitItem: [
{ name: "用户权限", url: "" },
{ name: "银行信息管理", url: "" },
{ name: "财务费用管理", url: "" },
{ name: "风险提示参数", url: "" },
{ name: "业务公共参数", url: "" },
{ name: "国内证开立", url: "" },
{ name: "国内证通知", url: "" },
{ name: "进口信用证开立", url: "" },
{ name: "转让信用证开立", url: "" },
{ name: "国内证通知", url: "" },
{ name: "国内证通知", url: "" },
{ name: "国内证通知", url: "" },
{ name: "国内证通知", url: "" },
{ name: "国内证通知", url: "" },
{ name: "国内证通知", url: "" },
{ name: "国内证通知", url: "" },
{ name: "国内证通知", url: "" },
{ name: "国内证通知", url: "" },
{ name: "国内证通知", url: "" },
{ name: "国内证通知", url: "" },
],
};
},
};
</script>
<style scoped>
/* 快速访问 */
#quickVisit .item-content {
display: flex;
flex-wrap: wrap;
}
#quickVisit .item-content .visit-item {
display: flex;
display: flex;
width: 150px;
/* height: 80px; */
flex-direction: column;
align-items: center;
margin: 0 15px 15px;
cursor: pointer;
}
#quickVisit .item-content .visit-item i {
color: #0088ff;
font-size: 36px;
}
#quickVisit .item-content .visit-item span {
color: #303133;
font-size: 15px;
margin-top: 10px;
}
/* #quickVisit .item-content .visit-item:hover i {
color: var(--themecolor);
} */
#quickVisit .item-content .visit-item:hover span {
color: var(--themecolor);
}
</style>
<template>
<div class="eContainer-home">
<QuickVisitVue></QuickVisitVue>
<NoticeAnnouncementVue></NoticeAnnouncementVue>
<HallVue></HallVue>
<CustomerAnalyseVue></CustomerAnalyseVue>
<QuickSearchVue></QuickSearchVue>
</div>
</template>
<script>
import QuickVisitVue from "./QuickVisit.vue";
import NoticeAnnouncementVue from "./NoticeAnnouncement.vue";
import HallVue from "./Hall.vue";
import CustomerAnalyseVue from "./CustomerAnalyse.vue";
import QuickSearchVue from "./QuickSearch.vue";
export default {
name: "Home",
components: {
QuickVisitVue,
NoticeAnnouncementVue,
HallVue,
CustomerAnalyseVue,
QuickSearchVue,
},
data() {
return {};
},
};
</script>
<style scoped>
.eContainer-home {
height: 100%;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
align-items: center;
}
.home-item {
height: 47%;
background-color: #ffffff;
box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
border-radius: 8px;
}
#quickVisit {
width: 65.3%;
}
#noticeAnnouncement,
#hall,
#customerAnalyse,
#quickSearch {
width: 32%;
}
.home-item >>> .item-content {
/* max-height: calc(100% - 52px); */
height: calc(100% - 52px);
overflow: auto;
}
</style>
......@@ -4,16 +4,16 @@
<c-button icon="el-icon-s-fold" v-if="menuOpen" @click="closeMenu"></c-button>
<c-button icon="el-icon-s-unfold" v-else @click="openMenu"></c-button>
<c-input prefix-icon="el-icon-search" v-if="menuOpen" v-model="searchContent"
@keyup.enter.native="searchMenuEvent"></c-input>
@keyup.enter.native="searchMenuEvent" placeholder="全局搜索"></c-input>
</div>
<c-content :height="250">
<img src="../../assets/menu_bottom.png" style="position: fixed; width: 200px; bottom: 0" />
<el-menu default-active="2" class="el-menu-vertical-demo" v-bind:router="true" :unique-opened="true"
<el-menu :default-active="activeMenu" class="el-menu-vertical-demo" v-bind:router="true"
@open="handleOpen" @close="handleClose" :collapse="!menuOpen">
<el-menu-item index="/business/office">
<!-- <el-menu-item index="/business/office">
<i class="el-icon-menu"></i>
<span slot="title">主页</span>
</el-menu-item>
</el-menu-item> -->
<SubMenu :subMenuList="menus"></SubMenu>
</el-menu>
</c-content>
......@@ -52,6 +52,11 @@
menus: [],
};
},
computed: {
activeMenu() {
return this.$route.path
},
},
mounted() {
const arr = [];
this.generateMenuTree(arr);
......
<template>
<el-scrollbar ref="scrollContainer" :vertical="false" class="scroll-container" @wheel.native.prevent="handleScroll">
<slot />
</el-scrollbar>
</template>
<script>
const tagAndTagSpacing = 4 // tagAndTagSpacing
export default {
name: 'ScrollPane',
data() {
return {
left: 0
}
},
computed: {
scrollWrapper() {
return this.$refs.scrollContainer.$refs.wrap
}
},
mounted() {
this.scrollWrapper.addEventListener('scroll', this.emitScroll, true)
},
beforeDestroy() {
this.scrollWrapper.removeEventListener('scroll', this.emitScroll)
},
methods: {
handleScroll(e) {
const eventDelta = e.wheelDelta || -e.deltaY * 40
const $scrollWrapper = this.scrollWrapper
$scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4
},
emitScroll() {
this.$emit('scroll')
},
moveToTarget(currentTag) {
const $container = this.$refs.scrollContainer.$el
const $containerWidth = $container.offsetWidth
const $scrollWrapper = this.scrollWrapper
const tagList = this.$parent.$refs.tag
let firstTag = null
let lastTag = null
// find first tag and last tag
if (tagList.length > 0) {
firstTag = tagList[0]
lastTag = tagList[tagList.length - 1]
}
if (firstTag === currentTag) {
$scrollWrapper.scrollLeft = 0
} else if (lastTag === currentTag) {
$scrollWrapper.scrollLeft = $scrollWrapper.scrollWidth - $containerWidth
} else {
// find preTag and nextTag
const currentIndex = tagList.findIndex(item => item === currentTag)
const prevTag = tagList[currentIndex - 1]
const nextTag = tagList[currentIndex + 1]
// the tag's offsetLeft after of nextTag
const afterNextTagOffsetLeft = nextTag.$el.offsetLeft + nextTag.$el.offsetWidth + tagAndTagSpacing
// the tag's offsetLeft before of prevTag
const beforePrevTagOffsetLeft = prevTag.$el.offsetLeft - tagAndTagSpacing
if (afterNextTagOffsetLeft > $scrollWrapper.scrollLeft + $containerWidth) {
$scrollWrapper.scrollLeft = afterNextTagOffsetLeft - $containerWidth
} else if (beforePrevTagOffsetLeft < $scrollWrapper.scrollLeft) {
$scrollWrapper.scrollLeft = beforePrevTagOffsetLeft
}
}
}
}
}
</script>
<style scoped>
.scroll-container {
white-space: nowrap;
position: relative;
overflow: hidden;
width: 100%;
}
.scroll-container >>> .el-scrollbar__bar {
bottom: 0px;
}
.scroll-container >>> .el-scrollbar__wrap {
height: 49px;
}
</style>
<template>
<div id="tags-view-container" class="tags-view-container">
<scroll-pane
ref="scrollPane"
class="tags-view-wrapper"
@scroll="handleScroll"
>
<router-link
v-for="tag in visitedViews"
ref="tag"
:key="tag.path"
:class="{'active': isActive(tag), activeIcon: !isAffix(tag)}"
:to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"
tag="span"
class="tags-view-item"
@click.middle.native="!isAffix(tag) ? closeSelectedTag(tag) : ''"
@contextmenu.prevent.native="openMenu(tag, $event)"
>
<span v-if="isAffix(tag) && tag.meta.icon" :class="tag.meta.icon"></span>
{{ typeof tag.title === 'function' ? tag.title(tag.params) : tag.title }}
<span
v-if="!isAffix(tag)"
class="el-icon-close"
@click.prevent.stop="closeSelectedTag(tag)"
/>
</router-link>
</scroll-pane>
<ul
v-show="visible"
:style="{ left: left + 'px', top: top + 'px' }"
class="contextmenu"
>
<li @click="refreshSelectedTag(selectedTag)">刷新</li>
<li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)">
关闭
</li>
<li @click="closeOthersTags">关闭其他</li>
<li @click="closeAllTags(selectedTag)">关闭所有</li>
</ul>
</div>
</template>
<script>
import ScrollPane from "./ScrollPane";
import path from "path";
import { routes as allRoute } from "~/routers"
export default {
components: { ScrollPane },
data() {
return {
visible: false,
top: 0,
left: 0,
selectedTag: {},
affixTags: [],
};
},
computed: {
visitedViews() {
return this.$store.state.TagsView.visitedViews;
},
routes() {
return allRoute;
},
},
watch: {
$route() {
this.addTags();
this.moveToCurrentTag();
},
visible(value) {
if (value) {
document.body.addEventListener("click", this.closeMenu);
} else {
document.body.removeEventListener("click", this.closeMenu);
}
},
},
mounted() {
this.initTags();
this.addTags();
},
methods: {
isActive(route) {
return route.path === this.$route.path;
},
isAffix(tag) {
return tag.meta && tag.meta.affix;
},
filterAffixTags(routes, basePath = "/") {
let tags = [];
routes.forEach((route) => {
if (route.meta && route.meta.affix) {
const tagPath = path.resolve(basePath, route.path);
tags.push({
fullPath: tagPath,
path: tagPath,
name: route.name,
meta: { ...route.meta },
});
}
if (route.children) {
const tempTags = this.filterAffixTags(route.children, route.path);
if (tempTags.length >= 1) {
tags = [...tags, ...tempTags];
}
}
});
return tags;
},
initTags() {
const affixTags = (this.affixTags = this.filterAffixTags(this.routes));
for (const tag of affixTags) {
// Must have tag name
if (tag.name) {
this.$store.dispatch("TagsView/addVisitedView", tag);
}
}
},
addTags() {
const { name } = this.$route;
if (name) {
this.$store.dispatch("TagsView/addView", this.$route);
}
return false;
},
moveToCurrentTag() {
const tags = this.$refs.tag;
this.$nextTick(() => {
for (const tag of tags) {
if (tag.to.path === this.$route.path) {
this.$refs.scrollPane.moveToTarget(tag);
// when query is different then update
if (tag.to.fullPath !== this.$route.fullPath) {
this.$store.dispatch("TagsView/updateVisitedView", this.$route);
}
break;
}
}
});
},
refreshSelectedTag(view) {
this.$store.dispatch("TagsView/delCachedView", view).then(() => {
const { fullPath } = view;
this.$nextTick(() => {
this.$router.replace({
path: "/redirect" + fullPath,
});
});
});
},
closeSelectedTag(view) {
this.$store
.dispatch("TagsView/delView", view)
.then(({ visitedViews }) => {
if (this.isActive(view)) {
this.toLastView(visitedViews, view);
}
});
},
closeOthersTags() {
this.$router.push(this.selectedTag);
this.$store
.dispatch("TagsView/delOthersViews", this.selectedTag)
.then(() => {
this.moveToCurrentTag();
});
},
closeAllTags(view) {
this.$store.dispatch("TagsView/delAllViews").then(({ visitedViews }) => {
if (this.affixTags.some((tag) => tag.path === view.path)) {
return;
}
this.toLastView(visitedViews, view);
});
},
toLastView(visitedViews, view) {
const latestView = visitedViews.slice(-1)[0];
if (latestView) {
this.$router.push(latestView.fullPath);
} else {
// now the default is to redirect to the home page if there is no tags-view,
// you can adjust it according to your needs.
if (view.name === "Home") {
// to reload home page
this.$router.replace({ path: "/redirect" + view.fullPath });
} else {
this.$router.push("/");
}
}
},
openMenu(tag, e) {
const menuMinWidth = 105;
const offsetLeft = this.$el.getBoundingClientRect().left; // container margin left
const offsetWidth = this.$el.offsetWidth; // container width
const maxLeft = offsetWidth - menuMinWidth; // left boundary
const left = e.clientX - offsetLeft + 15; // 15: margin right
if (left > maxLeft) {
this.left = maxLeft;
} else {
this.left = left;
}
this.top = e.clientY - 68;
this.visible = true;
this.selectedTag = tag;
},
closeMenu() {
this.visible = false;
},
handleScroll() {
this.closeMenu();
},
},
};
</script>
<style scoped>
.tags-view-container {
height: 34px;
width: 100%;
background: #f5f4f9;
border-bottom: 1px solid #d8dce5;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 3px 0 rgba(0, 0, 0, 0.04);
/* box-sizing: inherit; */
padding-top: 5px;
padding-bottom: 5px;
}
.tags-view-container .tags-view-wrapper .tags-view-item {
display: inline-block;
position: relative;
cursor: pointer;
height: 26px;
line-height: 26px;
border: 1px solid #d8dce5;
color: #495060;
background: #fff;
padding: 0 8px;
font-size: 12px;
margin-left: 5px;
margin-top: 4px;
}
.tags-view-container .tags-view-wrapper .tags-view-item:first-of-type {
margin-left: 15px;
}
.tags-view-container .tags-view-wrapper .tags-view-item:last-of-type {
margin-right: 15px;
}
.tags-view-container .tags-view-wrapper .tags-view-item.active {
background-color: var(--themecolor);
color: #fff;
border-color: var(--themecolor);
}
.tags-view-container .tags-view-wrapper .tags-view-item.active.activeIcon::before {
content: "";
background: #fff;
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
position: relative;
margin-right: 2px;
}
.tags-view-container .tags-view-wrapper .tags-view-item [class^=el-icon-] {
font-size: 15px;
}
.tags-view-container .tags-view-wrapper .tags-view-item .el-icon-close {
font-size: 12px;
}
.tags-view-container .contextmenu {
margin: 0;
background: #fff;
z-index: 3000;
position: absolute;
list-style-type: none;
padding: 5px 0;
border-radius: 4px;
font-size: 12px;
font-weight: 400;
color: #333;
box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.3);
}
.tags-view-container .contextmenu li {
margin: 0;
padding: 7px 16px;
cursor: pointer;
}
.tags-view-container .contextmenu li:hover {
background: #eee;
}
</style>
<style>
/* reset element css of el-icon-close */
.tags-view-wrapper .tags-view-item .el-icon-close {
width: 16px;
height: 16px;
vertical-align: 2px;
border-radius: 50%;
text-align: center;
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
transform-origin: 100% 50%;
}
.tags-view-wrapper .tags-view-item .el-icon-close::before {
transform: scale(0.6);
display: inline-block;
vertical-align: -3px;
}
.tags-view-wrapper .tags-view-item .el-icon-close:hover {
background-color: #989ca5;
color: #fff;
}
</style>
......@@ -11,8 +11,10 @@
<sideMenu></sideMenu>
</el-aside>
<div style="width: 8px"></div>
<el-main class="m-app-main" style="background-color: var(--bgcolor)">
<business></business>
<el-main class="m-app-main">
<tagViews></tagViews>
<div style="height: 10px"></div>
<business style="background-color: var(--bgcolor)"></business>
<toolbars></toolbars>
</el-main>
</el-container>
......@@ -22,11 +24,12 @@
<script>
import headerCom from "./Header";
import sideMenu from "./SideMenu";
import tagViews from "./components/TagsView"
import business from "../Business";
import toolbars from "~/components/Toolbars"
export default {
components: { headerCom, sideMenu, business, toolbars }
components: { headerCom, sideMenu, tagViews, business, toolbars }
};
</script>
......
<script>
export default {
created() {
const { params, query } = this.$route
const { path } = params
this.$router.replace({ path: '/' + path, query })
},
render: function(h) {
return h() // avoid warning message
}
}
</script>
<template>
<div class="eContainer-todo">
<c-tabs :value="tabVal" type="card" @tab-click="tabClick">
<el-tab-pane label="待办列表" name="todoList">
<c-table :columnsConfig="tableColumns" :list="tableData"></c-table>
</el-tab-pane>
<el-tab-pane label="未完成列表" name="unfinishedList">
<c-table :columnsConfig="tableColumns" :list="tableData"></c-table>
</el-tab-pane>
<el-tab-pane label="已完成列表" name="finishedList">
<c-table :columnsConfig="tableColumns" :list="tableData"></c-table>
</el-tab-pane>
<el-tab-pane label="带申报列表" name="dsbList">
<c-table :columnsConfig="tableColumns" :list="tableData"></c-table>
</el-tab-pane>
</c-tabs>
</div>
</template>
<script>
export default {
name: "Todo",
data() {
return {
tabVal: "todoList",
tableColumns: [
{ label: "业务编号", prop: "" },
{ label: "交易名称", prop: "" },
{ label: "客户名称", prop: "" },
{ label: "币种", prop: "" },
{ label: "金额", prop: "" },
{ label: "交易创建时间", prop: "" },
{ label: "任务分配时间", prop: "" },
{ label: "机构类型", prop: "" },
{ label: "交易优先级别", prop: "" },
],
tableData: [],
};
},
methods: {
tabClick() {},
},
};
</script>
<style scoped>
.eContainer-todo {
padding: 20px;
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment