Commit e79b6265 authored by MyName's avatar MyName
parents 9409cb8f f0f0904b
......@@ -10,10 +10,7 @@ import com.dsk.system.domain.customer.dto.CustomerSearchDto;
import com.dsk.system.service.ICustomerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
/**
* 客户相关
......@@ -44,7 +41,7 @@ public class CustomerController extends BaseController {
@PreAuthorize("@ss.hasPermi('customer:add')")
@PostMapping()
@RepeatSubmit
public AjaxResult add(Customer customer){
public AjaxResult add(@RequestBody Customer customer){
return AjaxResult.success(baseService.add(customer));
}
......@@ -52,9 +49,9 @@ public class CustomerController extends BaseController {
* 编辑客户
*/
@PreAuthorize("@ss.hasPermi('customer:edit')")
@PostMapping()
@PutMapping()
@RepeatSubmit
public AjaxResult edit(Customer customer){
public AjaxResult edit(@RequestBody Customer customer){
return AjaxResult.success(baseService.edit(customer));
}
......
package com.dsk.web.controller.customer;
import com.dsk.common.annotation.RepeatSubmit;
import com.dsk.common.core.controller.BaseController;
import com.dsk.common.core.domain.AjaxResult;
import com.dsk.common.core.page.TableDataInfo;
import com.dsk.system.domain.customer.Customer;
import com.dsk.system.domain.customer.CustomerFollowRecord;
import com.dsk.system.domain.customer.dto.CustomerFollowRecordSearchDto;
import com.dsk.system.domain.customer.dto.CustomerSearchDto;
import com.dsk.system.service.ICustomerFollowRecordService;
import com.dsk.system.service.ICustomerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
/**
* 客户跟进记录相关
*
* @author lcl
* @create 2023/5/18
*/
@RestController
@RequestMapping("/customer/follow/record")
public class CustomerFollowRecordController extends BaseController {
@Autowired
private ICustomerFollowRecordService baseService;
/**
* 查询客户跟进记录列表
*/
// @PreAuthorize("@ss.hasPermi('customer:follow:record:list')")
@GetMapping("/list")
public TableDataInfo selectPageList(CustomerFollowRecordSearchDto dto){
startPage();
return getDataTable(baseService.selectList(dto));
}
/**
* 添加客户跟进记录
*/
// @PreAuthorize("@ss.hasPermi('customer:follow:record:add')")
@PostMapping()
@RepeatSubmit
public AjaxResult add(@RequestBody CustomerFollowRecord followRecord){
return AjaxResult.success(baseService.add(followRecord));
}
}
......@@ -20,4 +20,6 @@ npm run dev
4* 组件引用:公用组件存放目录src/components;单独引用的组件存放目录可在页面同级目录下建component文件夹存。
5* 表格小样例:src/views/macro/nationalEconomies/index.vue
\ No newline at end of file
5* 表格小样例:src/views/macro/nationalEconomies/index.vue。
6* 页面上能使用栅栏布局的就用栅栏布局,拉伸收缩能达到适当的自适应效果。
\ No newline at end of file
......@@ -41,6 +41,7 @@
"clipboard": "2.0.8",
"core-js": "3.25.3",
"echarts": "5.4.0",
"element-resize-detector": "^1.2.4",
"element-ui": "2.15.12",
"file-saver": "2.0.5",
"fuse.js": "6.4.3",
......
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1684392363345" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4078" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><path d="M300.8 202.666667l-12.8 64h-42.666667v640h533.333334v-640h-42.666667l-12.8-64h119.466667v768h-661.333334v-768h119.466667zM554.666667 640v64H320v-64h234.666667z m149.333333-170.666667v64H320v-64h384zM512 53.333333A96 96 0 0 1 608 149.333333v10.666667h58.24l34.133333 170.666667H323.626667l34.133333-170.666667h58.24V149.333333A96 96 0 0 1 512 53.333333z m0 64A32 32 0 0 0 480 149.333333v74.666667h-69.76l-8.533333 42.666667h220.586666l-8.533333-42.666667H544V149.333333A32 32 0 0 0 512 117.333333z" fill="#979797" p-id="4079"></path></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1684392363345" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4078" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><path d="M300.8 202.666667l-12.8 64h-42.666667v640h533.333334v-640h-42.666667l-12.8-64h119.466667v768h-661.333334v-768h119.466667zM554.666667 640v64H320v-64h234.666667z m149.333333-170.666667v64H320v-64h384zM512 53.333333A96 96 0 0 1 608 149.333333v10.666667h58.24l34.133333 170.666667H323.626667l34.133333-170.666667h58.24V149.333333A96 96 0 0 1 512 53.333333z m0 64A32 32 0 0 0 480 149.333333v74.666667h-69.76l-8.533333 42.666667h220.586666l-8.533333-42.666667H544V149.333333A32 32 0 0 0 512 117.333333z" fill="#58637B" p-id="4079"></path></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="2" height="2" viewBox="0 0 2 2"><g style="mix-blend-mode:passthrough"><ellipse cx="1" cy="1" rx="1" ry="1" fill="#344062" fill-opacity="1"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="2" height="2" viewBox="0 0 2 2"><g style="mix-blend-mode:passthrough"><ellipse cx="1" cy="1" rx="1" ry="1" fill="#FFFFFF" fill-opacity="1"/></g></svg>
\ No newline at end of file
......@@ -23,10 +23,26 @@
bottom: 0;
left: 0;
z-index: 1001;
overflow: hidden;
// overflow: hidden;
-webkit-box-shadow: 2px 0 6px rgba(0,21,41,.35);
box-shadow: 2px 0 6px rgba(0,21,41,.35);
//展开、收起箭头
.side-expand{
position: absolute;
top: 180px;
width: 21px;
height: 62px;
cursor: pointer;
animation: left-right .2s;
animation-fill-mode: forwards;
z-index: 1002;
}
@keyframes left-right{
0%{right: 0;}
100%{right: -21px;}
}
// reset element-ui css
.horizontal-collapse-transition {
transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
......@@ -43,6 +59,7 @@
.el-scrollbar {
height: 100%;
}
......@@ -84,7 +101,12 @@
.el-menu--inline .nest-menu .el-menu-item{
width: 100%!important;
min-width: 128px;
font-size: 12px;
color: #fff!important;
padding-left: 23px!important;
}
.el-menu--inline .nest-menu .el-menu-item .svg-icon{
display: none;
}
.el-menu-item, .el-submenu__title {
......@@ -112,6 +134,9 @@
color: #fff!important;
border: 1px solid #2b3f69;
}
&:before{
background: #fff!important;
}
}
......@@ -135,6 +160,27 @@
border-radius: 10px;
border: 1px solid #2b3f69;
}
.sidebar-container .el-submenu .el-menu-item:before, .sidebar-container .nest-menu .el-submenu>.el-submenu__title:before {
position: absolute;
width: 2px;
height: 2px;
border-radius: 50%;
background: #344062;
left: 16px;
top: 50%;
content: "";
}
.sidebar-container .el-submenu .el-menu-item:hover:before, .sidebar-container .nest-menu .el-submenu>.el-submenu__title:hover:before{
position: absolute;
width: 2px;
height: 2px;
border-radius: 50%;
background: #fff;
left: 16px;
top: 50%;
content: "";
}
.hideSidebar {
.sidebar-container {
......@@ -276,3 +322,79 @@
}
}
}
.side-popover{
min-width: 80px;
font-size: 12px;
color: #232323;
padding: 0 8px 32px 8px;
margin-left: 16px !important;
.side-title{
font-size: 16px;
height: 54px;
line-height: 58px;
padding: 0 6px;
border-bottom: 1px solid #F0F0F0;
}
.side-list{
li{
padding: 24px 6px 0 6px;
&:hover{
color: #3D3D3D;
}
}
}
}
.side-retract {
height: 40px;
line-height: 48px;
border: 1px solid #141B2F;
margin-bottom: 6px;
padding: 0 6px !important;
text-align: center;
cursor: pointer;
&:hover {
background-color: #1E2C4C !important;
border-radius: 10px;
border: 1px solid #2B3F69;
}
.svg-icon {
margin-right: 0 !important;
}
}
.side-one-popover{
min-width: 52px;
padding-bottom: 0;
.side-title{
font-size: 12px;
height: 24px;
line-height: 24px;
border-bottom: 0;
}
}
.side-logo-popover{
width: 120px;
padding-top: 16px;
padding-bottom: 0;
margin-left: 16px !important;
.sidebar-logo{
width: 24px;
height: 24px;
background: #F5F5F5;
margin: 0 auto;
text-align: center;
img{
width: 16px;
height: 23px;
}
}
.side-title{
text-align: center;
font-size: 12px;
height: auto;
line-height: 18px;
border-bottom: 0;
padding-top: 6px;
padding-bottom: 10px;
}
}
\ No newline at end of file
......@@ -40,9 +40,18 @@ $base-sub-menu-hover:#001528;
$base-menu-background:#141b2f;
$base-menu-light-background: #fff; // 选中菜单的字体颜色
$base-logo-light-title-color: #fff; // 对应base-logo-title-color
$menuText:#FFFFFF;
$menuActiveText:#FFFFFF;
$subMenuActiveText:#f4f4f5; //https://github.com/ElemeFE/element/issues/12951
$menuBg:#141B2F;
$menuHover:#263445;
$subMenuBg:#1f2d3d;
$subMenuHover:#001528;
$base-sidebar-width: 144px;
$sideBarWidth: 144px;
//系统默认颜色
$systemColor:#0081FF;
......@@ -50,14 +59,23 @@ $systemColor:#0081FF;
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export {
menuText: $menuText;
menuActiveText: $menuActiveText;
subMenuActiveText: $subMenuActiveText;
menuBg: $menuBg;
menuHover: $menuHover;
subMenuBg: $subMenuBg;
subMenuHover: $subMenuHover;
sideBarWidth: $sideBarWidth;
menuColor: $base-menu-color;
menuLightColor: $base-menu-light-color;
menuColorActive: $base-menu-color-active;
menuBackground: $base-menu-background;
menuLightBackground: $base-menu-light-background;
subMenuBackground: $base-sub-menu-background;
subMenuHover: $base-sub-menu-hover;
sideBarWidth: $base-sidebar-width;
// subMenuHover: $base-sub-menu-hover;
// sideBarWidth: $base-sidebar-width;
logoTitleColor: $base-logo-title-color;
logoLightTitleColor: $base-logo-light-title-color;
systemColor: $systemColor
......
<template>
<div class="navbar">
<hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
<breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!topNav"/>
<top-nav id="topmenu-container" class="topmenu-container" v-if="topNav"/>
<div class="right-menu">
<template v-if="device!=='mobile'">
<search id="header-search" class="right-menu-item" />
<el-tooltip content="源码地址" effect="dark" placement="bottom">
<ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />
</el-tooltip>
<el-tooltip content="文档地址" effect="dark" placement="bottom">
<ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" />
</el-tooltip>
<screenfull id="screenfull" class="right-menu-item hover-effect" />
<el-tooltip content="布局大小" effect="dark" placement="bottom">
<size-select id="size-select" class="right-menu-item hover-effect" />
</el-tooltip>
</template>
<el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click">
<div class="avatar-wrapper">
<img :src="avatar" class="user-avatar">
<i class="el-icon-caret-bottom" />
<div id="navBar" class="navbar">
<div class="left-menu" :style="{width: scrollerWidth}">
<tags-view />
</div>
<div ref="rightMenu" class="flex-box right-menu">
<div class="menu-bells"><img src="@/assets/images/message.png"><i /></div>
<i class="menu-line" />
<el-dropdown class="avatar-container" trigger="hover">
<div class="flex-box avatar-wrapper">
<img v-if="avatar" class="pic-avatar" src="@/assets/images/avatar.png">
<span v-else class="user-avatar">{{ name&&name.slice(0, 1) }}</span>
{{ name }}
</div>
<el-dropdown-menu slot="dropdown">
<el-dropdown-menu slot="dropdown" class="user-dropdown">
<router-link to="/user/profile">
<el-dropdown-item>个人中心</el-dropdown-item>
<el-dropdown-item>用户中心</el-dropdown-item>
</router-link>
<el-dropdown-item @click.native="setting = true">
<span>布局设置</span>
</el-dropdown-item>
<el-dropdown-item divided @click.native="logout">
<span>退出登录</span>
<span>退出</span>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
......@@ -48,53 +27,36 @@
<script>
import { mapGetters } from 'vuex'
import Breadcrumb from '@/components/Breadcrumb'
import TopNav from '@/components/TopNav'
import Hamburger from '@/components/Hamburger'
import Screenfull from '@/components/Screenfull'
import SizeSelect from '@/components/SizeSelect'
import Search from '@/components/HeaderSearch'
import RuoYiGit from '@/components/RuoYi/Git'
import RuoYiDoc from '@/components/RuoYi/Doc'
import elementResizeDetectorMaker from "element-resize-detector"
import TagsView from './TagsView'
export default {
components: {
Breadcrumb,
TopNav,
Hamburger,
Screenfull,
SizeSelect,
Search,
RuoYiGit,
RuoYiDoc
TagsView
},
data() {
return {
scrollerWidth: null
}
},
computed: {
...mapGetters([
'sidebar',
'avatar',
'device'
]),
setting: {
get() {
return this.$store.state.settings.showSettings
},
set(val) {
this.$store.dispatch('settings/changeSetting', {
key: 'showSettings',
value: val
})
}
},
topNav: {
get() {
return this.$store.state.settings.topNav
}
}
'name'
])
},
mounted() {
const _this = this, erd = elementResizeDetectorMaker(), navBar = document.getElementById("navBar")
erd.listenTo(navBar, element => {
_this.$nextTick(() => {
const nvWidth = navBar.offsetWidth
const rtWidth = _this.$refs.rightMenu.offsetWidth
this.scrollerWidth = (nvWidth - rtWidth - 100)+'px' || '800px'
})
})
},
methods: {
toggleSideBar() {
this.$store.dispatch('app/toggleSideBar')
},
async logout() {
this.$confirm('确定注销并退出系统吗?', '提示', {
confirmButtonText: '确定',
......@@ -112,89 +74,94 @@ export default {
<style lang="scss" scoped>
.navbar {
height: 50px;
overflow: hidden;
height: 56px;
overflow: inherit;
position: relative;
background: #fff;
box-shadow: 0 1px 4px rgba(0,21,41,.08);
.hamburger-container {
line-height: 46px;
height: 100%;
float: left;
cursor: pointer;
transition: background .3s;
-webkit-tap-highlight-color:transparent;
&:hover {
background: rgba(0, 0, 0, .025)
}
}
.breadcrumb-container {
.left-menu{
float: left;
}
.topmenu-container {
position: absolute;
left: 50px;
}
.errLog-container {
display: inline-block;
vertical-align: top;
}
.right-menu {
float: right;
height: 100%;
line-height: 50px;
&:focus {
outline: none;
}
.right-menu-item {
display: inline-block;
padding: 0 8px;
height: 100%;
font-size: 18px;
color: #5a5e66;
vertical-align: text-bottom;
&.hover-effect {
cursor: pointer;
transition: background .3s;
&:hover {
background: rgba(0, 0, 0, .025)
}
.menu-bells{
position: relative;
margin-right: 16px;
cursor: pointer;
img{
width: 24px;
height: 24px;
}
i{
width: 6px;
height: 6px;
background: #FF4545;
border-radius: 50%;
position: absolute;
right: 0;
top: 0;
}
}
.menu-line{
display: inline-block;
width: 1px;
height: 24px;
background: #EEEEEE;
margin-right: 16px;
}
.avatar-container {
margin-right: 30px;
margin-right: 24px;
margin-top: -5px;
.avatar-wrapper {
margin-top: 5px;
position: relative;
.user-avatar {
cursor: pointer;
width: 40px;
height: 40px;
border-radius: 10px;
font-size: 12px;
color: #232323;
line-height: 20px;
cursor: pointer;
.pic-avatar{
width: 20px;
height: 20px;
border-radius: 50%;
margin-right: 4px;
overflow: hidden;
}
.el-icon-caret-bottom {
.user-avatar {
display: inline-block;
cursor: pointer;
position: absolute;
right: -20px;
top: 25px;
font-size: 12px;
width: 20px;
height: 20px;
line-height: 20px;
text-align: center;
background: #E3EEF9;
color: #0081FF;
border-radius: 50%;
margin-right: 4px;
}
}
}
}
}
.user-dropdown {
.el-dropdown-menu__item{
font-size: 12px;
color: #232323;
line-height: 24px;
border-top: 0;
margin-top: 0;
padding: 0 12px;
&:focus, &:not(.is-disabled):hover{
background: #E3EEF9;
}
&:before{
height: 0;
margin: 0;
}
}
}
</style>
......@@ -15,8 +15,7 @@ export default {
render(h, context) {
const { icon, title } = context.props
const vnodes = []
if (icon) {
if (icon&&icon!='#') {
vnodes.push(<svg-icon icon-class={icon}/>)
}
......
<template>
<div v-if="!item.hidden">
<template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path, onlyOneChild.query)">
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
<item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="onlyOneChild.meta.title" />
</el-menu-item>
</app-link>
</template>
<el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
<template slot="title">
<item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
<!-- 展开 -->
<template v-if="!isCollapse">
<template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.alwaysShow">
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
<item :icon="sideIcon(item, onlyOneChild)" :title="onlyOneChild.meta.title" />
</el-menu-item>
</app-link>
</template>
<sidebar-item
v-for="child in item.children"
:key="child.path"
:is-nest="true"
:item="child"
:base-path="resolvePath(child.path)"
class="nest-menu"
/>
</el-submenu>
<el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
<template slot="title">
<item v-if="item.meta" :icon="sideIcon(item)" :title="item.meta.title" />
</template>
<sidebar-item
v-for="child in item.children"
:key="child.path"
:is-nest="true"
:item="child"
:base-path="resolvePath(child.path)"
:active-menu="activeMenu"
class="nest-menu"
/>
</el-submenu>
</template>
<!-- 收起 -->
<template v-else>
<div v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.alwaysShow" class="side-retract">
<el-popover
placement="right-start"
popper-class="side-popover side-one-popover"
:visible-arrow="true"
trigger="hover"
:disabled="onlyOneChild.meta||item.meta?false:true"
>
<div class="side-container">
<div class="side-title">
<app-link v-if="onlyOneChild.meta || item.meta" :to="resolvePath(onlyOneChild.path || item.path)">
{{ onlyOneChild.meta.title || item.meta.title }}
</app-link>
</div>
</div>
<item v-if="onlyOneChild.meta" slot="reference" :icon="sideIcon(item, onlyOneChild)" />
</el-popover>
</div>
<div v-else class="side-retract">
<el-popover
placement="right-start"
popper-class="side-popover"
:visible-arrow="true"
trigger="hover"
:disabled="item.meta?false:true"
>
<div class="side-container">
<div class="side-title">{{ item.meta.title }}</div>
<ul class="side-list">
<li v-for="child in item.children" :key="child.path">
<app-link v-if="child.meta" :to="resolvePath(child.path)">
{{ child.meta.title }}
</app-link>
</li>
</ul>
</div>
<item v-if="item.meta" slot="reference" :icon="sideIcon(item)" />
</el-popover>
</div>
</template>
</div>
</template>
......@@ -36,24 +81,68 @@ export default {
components: { Item, AppLink },
mixins: [FixiOSBug],
props: {
// route object
item: {
type: Object,
required: true
},
isNest: {
type: Boolean,
default: false
},
basePath: {
type: String,
default: ''
}
// route object
item: {
type: Object,
required: true
},
isCollapse: {
type: Boolean,
default: false
},
isNest: {
type: Boolean,
default: false
},
basePath: {
type: String,
default: ''
},
activeMenu: {
type: String,
default: ''
}
},
data() {
this.onlyOneChild = null
return {}
},
computed: {
sideIcon() {
return function(item, onlyOneChild) {
let icon = ''
if (onlyOneChild) {
if(onlyOneChild.meta.icon || (item.meta && item.meta.icon&&item.meta.icon!='#')){
icon = onlyOneChild.meta.icon || (item.meta && item.meta.icon)
}
let tempPath = ''
if (onlyOneChild.path) {
tempPath = this.resolvePath(onlyOneChild.path)
console.log(tempPath);
console.log(this.activeMenu);
if (this.activeMenu === tempPath&&onlyOneChild.meta.icon!='#') {
icon = onlyOneChild.meta.icon+'s'
}
} else {
tempPath = this.resolvePath(item.path).substring(0, this.resolvePath(item.path).lastIndexOf('/'))
if (this.activeMenu === tempPath&&item.meta.icon!='#') {
icon = item.meta.icon+'s'
}
}
} else {
if(item.meta && item.meta.icon&&item.meta.icon!='#'){
icon = item.meta.icon
}
const tempPath = this.activeMenu.substring(0, this.activeMenu.indexOf('/', this.activeMenu.indexOf('/') + 1))
if (this.resolvePath(item.path) === tempPath&&item.meta.icon!='#') {
icon = item.meta.icon+'s'
}
}
console.log(icon);
return icon
}
}
},
methods: {
hasOneShowingChild(children = [], parent) {
if (!children) {
......
<template>
<div :class="{'has-logo':showLogo}" :style="{ backgroundColor: settings.sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }">
<div :class="{'has-logo':showLogo}" @mouseenter="sideEnter" @mouseleave="sideLeave" :style="{ backgroundColor: settings.sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }">
<logo v-if="showLogo" :collapse="isCollapse" />
<el-scrollbar :class="settings.sideTheme" wrap-class="scrollbar-wrapper">
<el-menu
:default-active="activeMenu"
:collapse="isCollapse"
:background-color="settings.sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground"
:text-color="settings.sideTheme === 'theme-dark' ? variables.menuColor : variables.menuLightColor"
:background-color="variables.menuBg"
:text-color="variables.menuText"
:unique-opened="true"
:active-text-color="settings.theme"
:collapse-transition="false"
......@@ -14,12 +14,21 @@
>
<sidebar-item
v-for="(route, index) in sidebarRouters"
:key="route.path + index"
:is-collapse="isCollapse"
:active-menu="activeMenu"
:item="route"
:base-path="route.path"
:class="route.fixed&&route.fixed.isFixed?'sideFoot':''"
:style="route.fixed&&route.fixed.isFixed?{'bottom': route.fixed.number*50+'px'}: bottomMenu&&index==routes.length-bottomMenu-2?{'padding-bottom': bottomMenu*50+'px'}:''"
/>
</el-menu>
</el-scrollbar>
<div v-show="isExpand" class="side-expand" @click="toggleSideBar">
<img :src="isCollapse?require('@/assets/images/sidebar_right.png'):require('@/assets/images/sidebar_left.png')">
</div>
</div>
</template>
......@@ -30,7 +39,13 @@ import SidebarItem from "./SidebarItem";
import variables from "@/assets/styles/variables.scss";
export default {
components: { SidebarItem, Logo },
data() {
return {
isExpand: false
}
},
computed: {
...mapState(["settings"]),
...mapGetters(["sidebarRouters", "sidebar"]),
......@@ -43,6 +58,14 @@ export default {
}
return path;
},
device() {
return this.$store.state.app.device
},
bottomMenu() {
const routeArr = this.$router.options.routes
const navFixed = routeArr.filter(item => item.fixed && item.fixed.isFixed)
return navFixed.length
},
showLogo() {
return this.$store.state.settings.sidebarLogo;
},
......@@ -51,7 +74,23 @@ export default {
},
isCollapse() {
return !this.sidebar.opened;
}
}
},
},
methods: {
toggleSideBar(){
this.$emit('handleBar', this.isCollapse ? '-96' : '96'); // 96为展开宽度和收起宽度之差
this.$store.dispatch('app/toggleSideBar');
},
sideEnter(){
if (this.device !== 'mobile') {
this.isExpand = true;
}
},
sideLeave(){
if (this.device !== 'mobile') {
this.isExpand = false;
}
},
},
};
</script>
......@@ -87,7 +87,17 @@ export default {
bottom: 0px;
}
.el-scrollbar__wrap {
height: 39px;
height: 100%;
padding-top: 24px;
margin-bottom: 0 !important;
}
.is-horizontal{
width: 0;
height: 0;
}
.is-vertical{
width: 0;
height: 0;
}
}
}
......
......@@ -2,19 +2,22 @@
<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"
v-for="(tag, index) in visitedViews"
ref="tag"
:key="tag.path"
:class="isActive(tag)?'active':''"
:to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"
tag="span"
class="tags-view-item"
:style="activeStyle(tag)"
@click.middle.native="!isAffix(tag)?closeSelectedTag(tag):''"
@contextmenu.prevent.native="openMenu(tag,$event)"
>
<svg :class="isActive(tag)?'tags-icon tags-icon-active':'tags-icon'" aria-hidden="true">
<use :xlink:href="iconName(tag)" />
</svg>
{{ tag.title }}
<span v-if="!isAffix(tag)" class="el-icon-close" @click.prevent.stop="closeSelectedTag(tag)" />
<i :class="index!=visitedViews.length-1 && index != isActiveIndex() && index != isActiveIndex()-1?'tags-item-line':'tags-item-line item-color'" />
</router-link>
</scroll-pane>
<ul v-show="visible" :style="{left:left+'px',top:top+'px'}" class="contextmenu">
......@@ -47,6 +50,21 @@ export default {
visitedViews() {
return this.$store.state.tagsView.visitedViews
},
iconName() {
return function(val) {
let svgIcon = val.meta.icon, currentIcon = ''
let icon = this.isActive(val) ? svgIcon+'Tags' : svgIcon+'Tag'
if (!svgIcon) {
const index = val.path.indexOf('/', val.path.indexOf('/') + 1)
const parentPath = val.path.slice(0, index)
const currentRoute = this.$router.options.routes.find(item => item.path === parentPath)
currentIcon = currentRoute.meta.icon
icon = this.isActive(val) ? currentIcon+'Tags' : currentIcon+'Tag'
}
icon = (svgIcon && svgIcon != '#') || (currentIcon && svgIcon != '#') ? icon : this.isActive(val) ? 'defaultTags' : 'defaultTag'
return `#icon-${icon}`
}
},
routes() {
return this.$store.state.permission.routes
},
......@@ -75,16 +93,13 @@ export default {
isActive(route) {
return route.path === this.$route.path
},
activeStyle(tag) {
if (!this.isActive(tag)) return {};
return {
"background-color": this.theme,
"border-color": this.theme
};
},
isAffix(tag) {
return tag.meta && tag.meta.affix
},
isActiveIndex() {
const idx = this.visitedViews.findIndex(item => item.path === this.$route.path) || 0
return idx
},
isFirstView() {
try {
return this.selectedTag.fullPath === '/index' || this.selectedTag.fullPath === this.visitedViews[1].fullPath
......@@ -239,44 +254,63 @@ export default {
<style lang="scss" scoped>
.tags-view-container {
height: 34px;
height: 56px;
width: 100%;
background: #fff;
border-bottom: 1px solid #d8dce5;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04);
.tags-view-wrapper {
.tags-view-item {
display: inline-block;
position: relative;
cursor: pointer;
height: 26px;
line-height: 26px;
border: 1px solid #d8dce5;
min-width: 128px;
height: 32px;
line-height: 32px;
color: #495060;
background: #fff;
padding: 0 8px;
padding: 0 20px 0 8px;
font-size: 12px;
margin-left: 5px;
margin-top: 4px;
.tags-icon{
width: 16px;
height: 16px;
fill: currentColor;
color: #5a5e66;
margin: 8px 4px -3px 4px;
&.tags-icon-active{
color: pink;
}
}
.tags-item-line{
display: block;
width: 1px;
height: 24px;
background: #D0D1D9;
position: absolute;
right: 0;
top: 4px;
z-index: 2;
&.item-color{
background: #FFFFFF;
}
}
&:first-of-type {
margin-left: 15px;
margin-left: 24px;
}
&:last-of-type {
margin-right: 15px;
&:hover {
.el-icon-close{
background-color: rgba(153,153,153,0.3);
color: #999999;
}
}
&.active {
background-color: #42b983;
color: #fff;
border-color: #42b983;
&::before {
content: '';
background: #fff;
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
position: relative;
margin-right: 2px;
background-color: #F5F5F5;
color: #232323;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
&:hover {
.el-icon-close{
background-color: initial;
color: initial;
}
}
}
}
......@@ -310,6 +344,9 @@ export default {
.tags-view-wrapper {
.tags-view-item {
.el-icon-close {
position: absolute;
right: 5px;
top: 8px;
width: 16px;
height: 16px;
vertical-align: 2px;
......@@ -322,10 +359,6 @@ export default {
display: inline-block;
vertical-align: -3px;
}
&:hover {
background-color: #b4bccc;
color: #fff;
}
}
}
}
......
<template>
<div :class="classObj" class="app-wrapper" :style="{'--current-color': theme}">
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
<sidebar v-if="!sidebar.hide" class="sidebar-container"/>
<sidebar v-if="!sidebar.hide" class="sidebar-container" @handleBar="handleSideBar"/>
<div :class="{hasTagsView:needTagsView,sidebarHide:sidebar.hide}" class="main-container">
<div :class="{'fixed-header':fixedHeader}">
<navbar/>
<tags-view v-if="needTagsView"/>
<navbar :is-side-bar="isSideBar"/>
</div>
<app-main/>
<right-panel>
......@@ -33,6 +33,11 @@ export default {
TagsView
},
mixins: [ResizeMixin],
data() {
return {
isSideBar: ''
}
},
computed: {
...mapState({
theme: state => state.settings.theme,
......@@ -57,7 +62,10 @@ export default {
methods: {
handleClickOutside() {
this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
}
},
handleSideBar(val) {
this.isSideBar = val
}
}
}
</script>
......
......@@ -70,7 +70,7 @@ export const constantRoutes = [
path: 'index',
component: () => import('@/views/index'),
name: 'Index',
meta: { title: '首页', icon: 'dashboard', affix: true }
meta: { title: '首页', icon: 'index', }
}
]
},
......@@ -87,6 +87,39 @@ export const constantRoutes = [
meta: { title: '个人中心', icon: 'user' }
}
]
},
{
path: '/party',
component: Layout,
hidden: true,
redirect: 'noredirect',
children: [
{
path: 'party-a',
component: () => import('@/views/detail/party-a/index'),
name: 'PartyA',
meta: { title: '甲方详情', icon: 'custom' }
},
{
path: 'party-b',
component: () => import('@/views/detail/party-b/index'),
name: 'PartyB',
meta: { title: '已方详情', icon: 'user' }
}
]
},
{
path: '/financing',
component: Layout,
hidden: true,
children: [
{
path: '/macro/financing/details/:id(\\d+)',
component: () => import('@/views/macro/financing/details'),
name: 'financingDetails',
meta: { title: '区域专项债详情' }
}
]
}
]
......
<template>
<div class="app-container part-container">
<div class="bread-crumb">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">企业数据</el-breadcrumb-item>
<el-breadcrumb-item><a href="/">查企业</a></el-breadcrumb-item>
<el-breadcrumb-item>中铁一建</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="flex-box part-header">
<img class="header-logo" src="@/assets/images/avatar.png">
中交第二航务工程局有限公司
</div>
</div>
</template>
<script>
export default {
name: 'PartyA',
data() {
return {
}
},
created() {
},
methods: {
}
}
</script>
<style lang="scss" scoped>
.part-container{
padding: 0;
}
.bread-crumb{
.el-breadcrumb{
font-size: 12px;
::v-deep .el-breadcrumb__separator{
margin: 0 5px;
}
::v-deep .el-breadcrumb__inner.is-link, .el-breadcrumb__inner a{
color: rgba(35,35,35,0.4);
&:hover{
color: #1890ff;
}
}
::v-deep .el-breadcrumb__item{
&:last-child .el-breadcrumb__inner{
color: #232323;
}
&:nth-last-child(2){
.el-breadcrumb__separator{
color: #232323;
}
}
}
}
}
.part-header{
font-size: 16px;
font-weight: bold;
color: #232323;
background: #FFFFFF;
padding: 14px 16px;
margin-top: 12px;
.header-logo{
width: 28px;
height: 28px;
margin-right: 16px;
}
}
</style>
<template>
<div v-loading="loading" class="app-container">
<iframe ref="companyIframe" marginwidth="0" marginheight="0" frameborder="0" scrolling="no" width="100%" :height="iframeHight" :src="src" />
</div>
</template>
<script>
export default {
name: 'PartyB',
components: {
},
data() {
return {
loading: false, // 是否加载中
companyId: null, // 企业ID
iframeHight: window.innerHeight, // iframe高度
scrollTop: 0, // 滚动条距离内部页面顶部距离
token: this.$store.getters.token // 需要携带的token
}
},
created() {
if (this.$route.query.companyId) { // 获取companyId
this.loading = true
this.companyId = this.encodeStr(window.atob(this.$route.query.companyId))
this.src = `https://pre-plug.jiansheku.com/enterprise/${this.companyId}?token=${this.token}`
}
// 示例传参:?companyId=window.btoa('6034')
},
mounted() {
this.getInframeHight() // 实时控制iframe高度
window.addEventListener('scroll', this.scrolling) // 监听页面滚动事件
},
beforeDestroy() {
window.removeEventListener('scroll', this.scrolling) // 销毁页面滚动事件
},
methods: {
getInframeHight() {
const _this = this
window.addEventListener('message', function(e) {
const data = e.data
const sc = document && document.documentElement.scrollTop || document && document.body.scrollTop
if (data && typeof data === 'object') {
// 动态设置iFrame高度
if (data.height) {
_this.iframeHight = data.height
_this.loading = false
}
// 点击栏目名及子标签动态设置滚动高度
if (data.scrollHeight) {
window.scrollTo(sc, parseInt(data.scrollHeight) + 83)
}
// 点击下拉子标签动态设置滚动高度
if (data.clientHeight) {
window.scrollTo(sc, sc - 30)
}
}
})
},
scrolling() {
// 滚动条距文档顶部的距离
const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
this.scrollTop = scrollTop
// 准备传值
this.$nextTick(() => {
const ifa = this.$refs.companyIframe
ifa.contentWindow.postMessage({ 'scrollTop': this.scrollTop }, '*')
})
},
// companyId加密
encodeStr(str, secondary) {
const table = 'VyB2Kz79QWYjpiD5lRCIMwJEhqFSx0GN1cveZfU4gs6rk8dPbLtAomOnT3'
const ss = [2, 7, 5, 1, 4, 8, 3, 0, 6]
const xor = 177451812
const add = 8728348608
const mp2 = new Map()
let content = secondary ? str : ' '
let result = '' // 最终加密id
if (!secondary) {
let s = parseInt(str)
s = (s ^ xor) + add
for (let i = 0; i < table.length; i++) {
const s1 = table.substring(i, i + 1)
mp2.set(i, s1)
}
for (let i = 0; i < 9; i++) {
const r = mp2.get(parseInt(s / this.power(58, i) % 58))
content = this.changeStr(content, ss[i], r)
}
}
// 二次加密
const idArr = content.split('')
for (var i = 0; i < idArr.length; i++) {
const hex = idArr[i].charCodeAt().toString(16)
result = result + hex
}
return result
},
power(a, b) {
let power = 1
for (let c = 0; c < b; c++) {
power *= a
}
return power
},
changeStr(str, index, changeStr) {
return str.substr(0, index) + changeStr + str.substr(index + changeStr.length)
}
}
}
</script>
<style lang="scss" scoped>
.app-container{
padding: 0;
}
</style>
<template>
<div class="app-container">
<iframe ref="companyIframe" marginwidth="0" marginheight="0" frameborder="0" scrolling="no" width="100%" :height="iframeHight" src="https://pre.jiansheku.com/enterprise/56546856314e567a69/" />
</div>
</template>
<script>
export default {
name: 'EnterpriseData',
components: {
},
data() {
return {
iframeHight: null,
iframeWin: {}
}
},
computed: {
},
created() {
},
mounted() {
this.getInframeHight()
},
methods: {
getInframeHight() {
const _this = this
window.addEventListener('message', function(e) {
const data = e.data
if (data && typeof data === 'object' && data.height) {
_this.iframeHight = data.height
}
})
}
}
}
</script>
<style lang="scss" scoped>
</style>
<template>
<div class="app-container qyzx-details">
<p class="tab">区域专项债 <span>/ 专项债项目详情{{id}}</span></p>
<div class="content main1">
<div class="title"><img src="@/assets/images/financing/head_icon.png" />重庆至黔江高速铁路项目一项目详情</div>
<p>本项目是厦渝高铁通道的重要组成部分,是成渝地区、海西经济区间高速客运交流的主通道;是成渝地区与华南、华东地区间客运交流的辅助通道;是以重庆主城为核心的城际客流的快速客运通道;
是整合区域旅游资源,促进沿线旅游资源开发的黄金旅游通道。线路起自重庆站,经巴南、南川、武隆、彭水,终至江,正线全长265公里,设8座,其中新建6座。
同步建设重庆东动车所动车出入段,重庆枢纽东环联络线。</p>
</div>
<div class="content main2">
<div class="common-title">项目筹资</div>
<div class="main2-box">
<div class="list">
<div class="item color1">
<div class="item-left">
<h4>535.00<span>亿</span></h4>
<p>项目总投资额</p>
</div>
<img class="img" src="@/assets/images/financing/icon1.png" />
</div>
<div class="item color2">
<div class="item-left">
<h4>535.00<span>亿</span></h4>
<p>项目资本金</p>
</div>
<img class="img" src="@/assets/images/financing/icon2.png" />
</div>
<div class="item color3">
<div class="item-left">
<h4>535.00<span>亿</span></h4>
<p>专项债融资</p>
</div>
<img class="img" src="@/assets/images/financing/icon3.png" />
</div>
<div class="item color4">
<div class="item-left">
<h4>535.00<span>亿</span></h4>
<p>专项债用作资本金</p>
</div>
<img class="img" src="@/assets/images/financing/icon4.png" />
</div>
</div>
<div class="list">
<div class="item color4">
<div class="item-left">
<h4>535.00<span>亿</span></h4>
<p>其他资金</p>
</div>
<img class="img" src="@/assets/images/financing/icon5.png" />
</div>
<div class="item color3">
<div class="item-left">
<h4>535.00<span>亿 / 10只</span></h4>
<p>专项债融资额/专项债只数</p>
</div>
<img class="img" src="@/assets/images/financing/icon6.png" />
</div>
<div class="item color4">
<div class="item-left">
<h4>535.00<span>亿</span></h4>
<p>其他融资</p>
</div>
<img class="img" src="@/assets/images/financing/icon7.png" />
</div>
<div class="item color2">
<div class="item-left">
<h4>535.00<span>亿</span></h4>
<p>政府安排资金</p>
</div>
<img class="img" src="@/assets/images/financing/icon8.png" />
</div>
</div>
</div>
</div>
<div class="content main3">
<div class="common-title">项目保障</div>
</div>
<div class="content main4">
<div class="common-title">项目当事人</div>
<div class="main4-box">
<label class="label">项目主体</label>
<span>重庆铁路投资集团有限公司</span>
<label class="label">主管部门</label>
<span>-</span>
<label class="label">实施单位</label>
<span>重庆铁路投资集团有限公司</span>
</div>
</div>
<div class="content main5">
<div class="common-title">专项债</div>
<div class="table-item">
<el-table
:data="tableData"
element-loading-text="Loading"
border
fit
highlight-current-row
>
<el-table-column prop="name" label="债券简称">
<template slot-scope="scope">
<router-link :to="'/macro/financing/details/'+ scope.row.id" tag="a" class="a-link">{{ scope.row.name}}</router-link>
</template>
</el-table-column>
<el-table-column prop="name" label="招标日期" width="220" />
<el-table-column prop="gm" label="专项债规模(亿)" width="260" />
<el-table-column prop="gm" label="用于项目规模(亿)" width="260" />
<el-table-column prop="zj" label="是否资本金" width="200" />
</el-table>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'financingDetails',
data() {
return {
id:'',
tableData:[
{
id:0,
name:'20重庆债14(2005938)',
time:'2020-09-18',
gm:'285.24',
zj:'否',
}
]
}
},
created() {
console.log(this.$route.params)
this.id=this.$route.params.id
},
methods: {
}
}
</script>
<style lang="scss" scoped>
.app-container{
padding: 0;
}
.qyzx-details{
.tab{
font-size: 12px;
color:#A1A1A1;
span{
color:#232323;
}
}
.content{
margin-top: 16px;
background: #FFFFFF;
padding: 16px;
}
.common-title{
margin-bottom: 8px;
}
.main1{
.title{
color: #232323;
font-size: 16px;
line-height: 28px;
font-weight: bold;
margin-bottom: 8px;
text-align: left;
img{
width: 28px;
height: 28px;
margin-bottom: -9px;
margin-right: 17px;
}
}
p{
color: #3D3D3D;
font-size: 14px;
margin: 0;
}
}
.main2{
.list{
display: flex;
margin: 16px 0;
}
.item{
width: 24.5%;
margin-right: 16px;
height: 100px;
display: flex;
justify-content: space-between;
border-radius: 8px;
.item-left{
margin-left: 16px;
margin-top: 24px;
h4{
color: #232323;
font-size: 22px;
line-height: 22px;
font-weight: bold;
margin: 0;
span{
font-weight: 400;
margin-left: 4px;
font-size: 18px;
}
}
p{
margin: 0;
color: #3D3D3D;
font-size: 14px;
padding-top: 8px;
}
}
.img{
width: 56px;
height: 56px;
margin-top: 22px;
margin-right: 12px;
}
}
.color1{
background: rgba(246,190,59,0.08);
border: 1px solid rgba(246,190,59,0.2);
}
.color2{
background: rgba(148,216,196,0.102);
border: 1px solid rgba(73,187,154,0.1);
}
.color3{
background: rgba(57,100,199,0.06);
border: 1px solid rgba(57,100,199,0.1);
}
.color4{
background: rgba(0,129,255,0.04);
border: 1px solid rgba(0,129,255,0.1);
}
}
.main4{
.main4-box{
margin-top: 22px;
.label{
width: 14%;
background: #F0F3FA;
border: 1px solid #E6E9F0;
display: inline-block;
height: 40px;
line-height: 40px;
font-size: 12px;
color: rgba(35,35,35,0.8);
padding-left: 12px;
}
span{
width: 19%;
display: inline-block;
height: 40px;
line-height: 40px;
border-top: 1px solid #E6E9F0;
border-bottom: 1px solid #E6E9F0;
padding-left: 12px;
font-size: 12px;
}
span:last-child{
width: 20%;
border-right: 1px solid #E6E9F0;
}
}
}
}
</style>
<template>
<div class="app-container">
<div>
专项债项目
<div class="app-container qyzx">
<div class="content">
<div class="common-title">专项债项目</div>
<div class="content-box">
<div class="box-left">
<div id="echarts" style="height: 400px"></div>
</div>
<div class="box-right">
<el-table
:data="tableData"
element-loading-text="Loading"
border
height="360"
fit
highlight-current-row
>
<el-table-column prop="name" label="项目关系" width="150" />
<el-table-column prop="value" label="项目个数" width="140" />
<el-table-column prop="tz" label="投资额(亿元)" width="140" />
<el-table-column prop="bl" label="比例" width="140" />
</el-table>
</div>
</div>
</div>
<div>
项目明细
<div class="content">
<div class="common-title flex-box">
<div class="flex-box">项目明细</div>
<div class="flex-box query-ability">
<span class="flex-box">{{tableDataTotal}}</span>
<span class="flex-box"><img src="@/assets/images/ability_excel.png">导出EXCEL</span>
</div>
</div>
<div class="table-item">
<el-table
:data="listData"
element-loading-text="Loading"
border
fit
highlight-current-row
>
<el-table-column label="序号" width="55" align="left" fixed>
<template slot-scope="scope">{{ pageIndex * pageSize - pageSize + scope.$index + 1 }}</template>
</el-table-column>
<el-table-column prop="name" label="项目名称" width="290">
<template slot-scope="scope">
<router-link :to="'/macro/financing/details/'+ scope.row.id" tag="a" class="a-link">{{ scope.row.name}}</router-link>
</template>
</el-table-column>
<el-table-column prop="tz" label="项目总投资(亿)" sortable width="155" />
<el-table-column prop="bj" label="项目资本金(亿)" sortable width="155" />
<el-table-column prop="sy" label="项目收益倍数(倍)" width="150" />
<el-table-column prop="zxz" label="专项债金额(亿)" width="150" />
<el-table-column prop="zxzzj" label="专项债用作资本金(亿)" width="170" />
<el-table-column prop="xmzt" label="项目主体"/>
</el-table>
</div>
</div>
</div>
</template>
<script>
import * as echarts from 'echarts';
export default {
name: 'Financing',
data() {
return {
tableData:[
{
name:'农业农村',
value:'2',
tz:'50.01',
bl:'0.19%'
},
{
name:'乡村振兴',
value:'2',
tz:'50.01',
bl:'0.19%'
},
{
name:'农林水利',
value:'2',
tz:'50.01',
bl:'0.19%'
},
{
name:'交通',
value:'2',
tz:'50.01',
bl:'0.19%'
},
{
name:'轨道交通',
value:'2',
tz:'50.01',
bl:'0.19%'
},
{
name:'政府收费公路',
value:'2',
tz:'50.01',
bl:'0.19%'
},
{
name:'其他交通基础设施',
value:'2',
tz:'50.01',
bl:'0.19%'
},
{
name:'铁路',
value:'2',
tz:'50.01',
bl:'0.19%'
},
{
name:'养老',
value:'2',
tz:'50.01',
bl:'0.19%'
},
{
name:'生态环保',
value:'2',
tz:'50.01',
bl:'0.19%'
},
{
name:'职业教育',
value:'2',
tz:'50.01',
bl:'0.19%'
},
{
name:'能源',
value:'2',
tz:'50.01',
bl:'0.19%'
},
],
listData:[
{
id:1,
name:'涪陵高新产业园区总和配套项目',
tz:'535.00',
bj:'235.00',
sy:'3',
zxz:'230',
zxzzj:'423',
xmzt:'重庆市涪陵区新城区开发 (集团) 有限公司',
},
{
id:2,
name:'涪陵高新产业园区总和配套项目',
tz:'235.00',
bj:'435.00',
sy:'6',
zxz:'530',
zxzzj:'323',
xmzt:'重庆市涪陵区新城区开发 (集团) 有限公司',
}
],
tableLoading: false,
pageIndex: 1,
pageSize: 10,
tableDataTotal: 120
}
},
created() {
this.$nextTick(()=>{
this.initChart()
})
},
methods: {
initChart() {
let myChart = echarts.init(document.getElementById("echarts"))
let option ={
tooltip: {
trigger: 'item',
borderWidth:0,
backgroundColor:"rgba(255, 255, 255, 0.8)",
formatter: function (params) {
var result = ''
result+='<h3 style="color: #232226;padding: 0 0 5px 0;margin: 0;">'+ params.data.name +'</h3>'
result+='<p style="color: rgba(35,35,35,0.8);padding: 0;margin: 0;">'+ params.data.value +'个</p>'
result+='<p style="color: rgba(35,35,35,0.8);padding: 0;margin: 0;">'+ params.data.tz +'亿元</p>'
result+='<p style="color: rgba(35,35,35,0.8);padding: 0;margin: 0;">'+ params.data.bl +'%</p>'
return result;
},
extraCssText:'width:150px!important;',
},
legend: {
type: 'scroll',
orient: 'horizontal',
bottom: 20,
data: this.tableData,
pageButtonPosition: 'end',
},
series: [
{
type: 'pie',
radius: '55%',
center: ['50%', '40%'],
data: this.tableData,
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
}
myChart.setOption(option);
}
}
}
</script>
<style lang="scss" scoped>
.app-container{
padding: 0;
}
.qyzx{
.content{
background: #ffffff;
padding: 16px;
margin-bottom: 16px;
}
.common-title{
justify-content: space-between;
}
.content-box{
height: 422px;
display: flex;
justify-content: space-between;
.box-left{
width: 55%;
}
.box-right{
float: right;
::v-deep .el-table{
.el-table__cell{
height: 40px;
padding: 0;
line-height: 40px;
}
}
}
}
.table-item{
margin-top: 22px;
}
}
</style>
<template>
<div class="child-container">
<div class="child-container ndmx-detail">
<el-drawer
:visible.sync="dialogVisible"
direction="rtl"
size="50%"
>
<div slot="title" class="common-title">年度明细</div>
<div slot="title" class="ndmx-title"><img src="@/assets/images/economies/icon.png" class="icon">年度明细</div>
<!--<div class="content">-->
<!--<div class="main-title">-->
<!--<span class="label-200">指标</span>-->
<!--<span>2022年</span>-->
<!--<span>2021年</span>-->
<!--<span>2020年</span>-->
<!--<span>2019年</span>-->
<!--<span>2018年</span>-->
<!--</div>-->
<!--<div class="main-list">-->
<!--<div class="item">-->
<!--<h3></h3>-->
<!--<div class="item-cont">-->
<!--<span>指标</span>-->
<!--<span>2022年</span>-->
<!--<span>2021年</span>-->
<!--<span>2020年</span>-->
<!--<span>2019年</span>-->
<!--<span>2018年</span>-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
<div class="table-item">
<el-table
:data="tableData"
element-loading-text="Loading"
:data="getValues"
:show-header="false"
border
fit
highlight-current-row
>
<el-table-column prop="date" label="指标" width="150" />
<el-table-column prop="name" label="2022年" width="200" />
<el-table-column prop="name" label="2021年" />
<el-table-column prop="name" label="2020年" />
<el-table-column prop="name" label="2019年" />
<el-table-column prop="name" label="2018年" />
<el-table-column
v-for="(item, index) in getHeaders"
:key="index"
:prop="item"
>
</el-table-column>
</el-table>
</div>
</el-drawer>
......@@ -36,28 +57,62 @@ export default {
data() {
return {
dialogVisible: false,
tableData: [{
date: '2016-05-02',
name: '大司空'
}, {
date: '2016-05-04',
name: '大司空'
}, {
date: '2016-05-01',
name: '大司空'
}, {
date: '2016-05-03',
name: '大司空'
}, {
date: '2016-05-03',
name: '大司空'
}, {
date: '2016-05-03',
name: '大司空'
}]
tableData: [
{
zb:"2022年",
gdp:'129,118.58',
gdpzs:'124,369.67',
rjgdp:'134,369.67',
},
{
zb:"2021年",
gdp:'129,118.58',
gdpzs:'124,369.67',
rjgdp:'134,369.67',
},
{
zb:"2020年",
gdp:'129,118.58',
gdpzs:'124,369.67',
rjgdp:'134,369.67',
},
],
headers: [
{
prop: 'zb',
label: '指标',
},
{
prop: 'name',
label: '国民经济核算',
},
{
prop: 'gdp',
label: 'GDP(亿元)',
},
{
prop: 'gdpzs',
label: 'GDP增速',
},
{
prop: 'rjgdp',
label: '人均GDP(元)',
},
],
}
},
created() {
},
computed: {
getHeaders() {
return this.tableData.reduce((pre, cur, index) => pre.concat(`value${index}`), ['title'])
},
getValues() {
return this.headers.map(item => {
return this.tableData.reduce((pre, cur, index) => Object.assign(pre, {['value' + index]: cur[item.prop]}), {'title': item.label,});
});
}
},
methods: {
open(row) {
......@@ -74,6 +129,28 @@ export default {
</script>
<style lang="scss" scoped>
.ndmx-detail{
::v-deep .el-drawer{
.el-drawer__header{
padding:0 0 0 13px;
line-height: 48px;
}
}
.content{
height: 100%;
padding: 0 12px;
}
}
.ndmx-title{
color: #232323;
font-weight: bold;
font-size: 16px;
.icon{
width: 17px;
height: 17px;
margin-right: 8px;
}
}
.table-item{
padding: 16px 10px 16px 16px;
}
......
......@@ -39,7 +39,7 @@
<el-table-column label="序号" width="50" align="left" fixed>
<template slot-scope="scope">{{ pageIndex * pageSize - pageSize + scope.$index + 1 }}</template>
</el-table-column>
<el-table-column label="地区" min-width="60" align="left" fixed>
<el-table-column label="地区" min-width="70" align="left" fixed>
<template slot-scope="scope">
<router-link to="" tag="a" class="a-link">{{ scope.row.address || '广东省' }}</router-link>
</template>
......@@ -72,12 +72,13 @@
<el-table-column label="专项债余额(亿元)" prop="cgfs" width="160" align="left" />
<el-table-column label="地方政府债务限额(亿元)" prop="cgfs" width="160" align="left" />
<el-table-column label="城投平台有息债务??(亿元)" prop="cgfs" width="160" align="left" >
<!--<template slot="header" slot-scope="scope">-->
<!--<el-input-->
<!--v-model="search"-->
<!--size="mini"-->
<!--placeholder="输入关键字搜索"/>-->
<!--</template>-->
<template slot="header" slot-scope="scope">
<span>城投平台有息债务(亿元)
<el-tooltip popper-class="tips" effect="light" content="城投平台有息债务是该地区行政区划下所有的城投公司的短期债务与长期债务合计。其中,短期债务=短期借款+一年内到期的非流动负债+应付短期债券,长期债务=长期借款+应付长期债券。" placement="top">
<i class="el-icon-warning-outline"></i>
</el-tooltip>
</span>
</template>
</el-table-column>
<el-table-column label="负债率(%)" prop="cgfs" width="160" align="left" />
<el-table-column label="负债率(宽口径)(%)" prop="cgfs" width="160" align="left" />
......@@ -128,7 +129,13 @@ export default {
multiple: true,
},
addressList: [],
tableData: [],
tableData: [
{
dataId:'1',
cgrssqy:'100',
cgfs:'200'
}
],
tableLoading: false,
pageIndex: 1,
pageSize: 10,
......@@ -250,8 +257,24 @@ export default {
}
}
</script>
<style lang="scss">
.tips.is-light{
padding: 12px;
width: 318px;
box-sizing: border-box;
font-size: 14px;
line-height: 20px;
color: #333333;
border-color: rgba(0, 0, 0, 0.08);
box-shadow: 0px 0px 0px 0px rgba(0, 0, 0, 0.08);
.popper__arrow {
border-bottom-color: rgba(0, 0, 0, 0.08) !important;
border-top-color: rgba(0, 0, 0, 0.08) !important;
}
}
</style>
<style lang="scss" scoped>
.query-box{
margin: -8px 0 8px 0;
.query-params{
......
......@@ -135,7 +135,7 @@
@show="$refs['iconSelect'].reset()"
>
<IconSelect ref="iconSelect" @selected="selected" :active-icon="form.icon" />
<el-input slot="reference" v-model="form.icon" placeholder="点击选择图标" readonly>
<el-input slot="reference" v-model="form.icon" placeholder="点击选择图标" >
<svg-icon
v-if="form.icon"
slot="prefix"
......
package com.dsk.system.domain.customer;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* 客户跟进记录(CustomerFollowRecord)实体类
*
* @author makejava
* @since 2023-05-18 15:07:59
*/
@Data
@NoArgsConstructor
@Accessors(chain = true)
@TableName("customer_follow_record")
public class CustomerFollowRecord implements Serializable {
private static final long serialVersionUID = -17639570424991398L;
@TableId(value = "id",type = IdType.AUTO)
private Long id;
/**
* 客户id
*/
private String customerId;
/**
* 用户id
*/
private Long userId;
/**
* 拜访方式(visit_mode_type)
*/
private String visitMode;
/**
* 下次拜访时间
*/
private Date nextVisitTime;
/**
* 拜访对象姓名
*/
private String name;
/**
* 拜访对象职务
*/
private String position;
/**
* 拜访内容
*/
private String content;
@TableField(fill = FieldFill.INSERT)
private Date createTime;
}
package com.dsk.system.domain.customer.dto;
import lombok.Data;
import java.io.Serializable;
/**
* 客户跟进记录筛选对象
*
* @author lcl
* @create 2023/5/18
*/
@Data
public class CustomerFollowRecordSearchDto implements Serializable {
/**
* 客户id
*/
private String customerId;
/**
* 用户id
*/
private Long userId;
}
package com.dsk.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dsk.system.domain.customer.CustomerFollowRecord;
import org.apache.ibatis.annotations.Mapper;
/**
* 客户跟进记录(CustomerFollowRecord)表数据库访问层
*
* @author makejava
* @since 2023-05-18 15:07:59
*/
@Mapper
public interface CustomerFollowRecordMapper extends BaseMapper<CustomerFollowRecord> {
}
package com.dsk.system.service;
import com.dsk.system.domain.customer.CustomerFollowRecord;
import com.dsk.system.domain.customer.dto.CustomerFollowRecordSearchDto;
import java.util.List;
/**
* 客户跟进记录(CustomerFollowRecord)表服务接口
*
* @author makejava
* @since 2023-05-18 15:07:59
*/
public interface ICustomerFollowRecordService {
List<CustomerFollowRecord> selectList(CustomerFollowRecordSearchDto dto);
boolean add(CustomerFollowRecord followRecord);
}
package com.dsk.system.service.impl;
import cn.hutool.core.bean.BeanException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.dsk.common.utils.SecurityUtils;
import com.dsk.system.domain.customer.CustomerFollowRecord;
import com.dsk.system.domain.customer.dto.CustomerFollowRecordSearchDto;
import com.dsk.system.mapper.CustomerFollowRecordMapper;
import com.dsk.system.service.ICustomerFollowRecordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import javax.annotation.Resource;
import java.util.List;
/**
* 客户跟进记录(CustomerFollowRecord)表服务实现类
*
* @author makejava
* @since 2023-05-18 15:07:59
*/
@Slf4j
@Service
public class CustomerFollowRecordServiceImpl implements ICustomerFollowRecordService {
@Resource
private CustomerFollowRecordMapper baseMapper;
@Override
public List<CustomerFollowRecord> selectList(CustomerFollowRecordSearchDto dto) {
LambdaQueryWrapper<CustomerFollowRecord> wrapper = Wrappers.lambdaQuery();
if (!ObjectUtils.isEmpty(dto.getCustomerId())) {
wrapper.eq(CustomerFollowRecord::getCustomerId, dto.getCustomerId());
}
wrapper.eq(CustomerFollowRecord::getUserId, SecurityUtils.getUserId())
.orderByDesc(CustomerFollowRecord::getCreateTime);
return baseMapper.selectList(wrapper);
}
@Override
public boolean add(CustomerFollowRecord followRecord) {
if (ObjectUtils.isEmpty(followRecord.getContent())) throw new BeanException("跟进内容不能为空");
if (ObjectUtils.isEmpty(followRecord.getCustomerId())) throw new BeanException("跟进客户不能为空");
followRecord.setUserId(SecurityUtils.getUserId());
return baseMapper.insert(followRecord) != 0;
}
}
......@@ -69,7 +69,7 @@ public class CustomerServiceImpl implements ICustomerService {
@Override
@Transactional(rollbackFor = Exception.class)
public boolean edit(Customer customer) {
if (ObjectUtils.isEmpty(customer.getCompanyId())) throw new BeanException("客户id不能为空");
if (ObjectUtils.isEmpty(customer.getCustomerId())) throw new BeanException("客户id不能为空");
customer.setUpdateId(SecurityUtils.getUserId());
int u = baseMapper.updateById(customer);
return u != 0;
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dsk.system.mapper.CustomerFollowRecordMapper">
</mapper>
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