Compare commits
21 Commits
projects/l
...
projects/l
| Author | SHA1 | Date | |
|---|---|---|---|
| f208c3c744 | |||
| b05d42cfc8 | |||
| 9b0a768216 | |||
| ee4fdbd45b | |||
| 5465a43bcc | |||
| 2465f89d26 | |||
| 09c7fd1f63 | |||
| 195979b3e0 | |||
| 0e6caec8d8 | |||
| acc327212e | |||
| dd1f639c77 | |||
| b36acbf1e6 | |||
| 660bc4b58b | |||
| 2a316f89c6 | |||
| 4d3b2b13b8 | |||
| 1d5af53e1a | |||
| d379d7bb5b | |||
| 418c29095b | |||
| ef230b3836 | |||
| 9f2f7036fd | |||
| 2f3586e2f2 |
7
.env.dev
@@ -9,7 +9,12 @@ VUE_APP_TITLE = 洛玻集团驾驶舱
|
||||
# VUE_APP_BASE_API = 'http://172.16.32.95:7070'
|
||||
# VUE_APP_BASE_API = 'http://172.16.33.83:7070'
|
||||
|
||||
VUE_APP_BASE_API = 'http://192.168.0.35:7070'
|
||||
# 杨姗姗
|
||||
# VUE_APP_BASE_API = 'http://172.16.20.218:7070'
|
||||
# 小田
|
||||
VUE_APP_BASE_API = 'http://172.16.19.232:7070'
|
||||
# 测试
|
||||
# VUE_APP_BASE_API = 'http://192.168.0.35:8080'
|
||||
|
||||
|
||||
# 路由懒加载
|
||||
|
||||
1
.gitignore
vendored
@@ -20,3 +20,4 @@ selenium-debug.log
|
||||
*.local
|
||||
|
||||
package-lock.json
|
||||
sync_luobo.bat
|
||||
@@ -117,6 +117,22 @@ export function updateDataBackUpDetail(data) {
|
||||
});
|
||||
}
|
||||
|
||||
export function copyLastMonthData(data) {
|
||||
return request({
|
||||
url: "/lb/index-target-month/copyLastMonth",
|
||||
method: "post",
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
export function copyLastYearData(data) {
|
||||
return request({
|
||||
url: "/lb/index-target-year/copyLastYear",
|
||||
method: "post",
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export function getSalesRevenueGroupData(data) {
|
||||
return request({
|
||||
@@ -254,6 +270,13 @@ export function getCalendar(data) {
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
export function getCalendarYear(data) {
|
||||
return request({
|
||||
url: "lb/index-target-year/getCalendarYear",
|
||||
method: "post",
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
export function getLevelStruc(data) {
|
||||
return request({
|
||||
url: "/lb/index-target-month/getLevelStruc",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="32px" height="32px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>切片</title>
|
||||
<title>全屏</title>
|
||||
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="01-运营驾驶舱" transform="translate(-1864.000000, -12.000000)" fill="#0B58FF">
|
||||
<g id="icon/可视化/全屏" transform="translate(1864.000000, 12.000000)">
|
||||
|
||||
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
11
src/assets/icons/svg/logout.svg
Normal file
@@ -0,0 +1,11 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g id="组_1" data-name="组 1" transform="translate(-970 -281.875)">
|
||||
<g id="编辑备份" transform="translate(970 281.5)">
|
||||
<rect id="矩形" width="16" height="16" transform="translate(0 0.375)" opacity="0"/>
|
||||
<path id="形状" d="M12.281,5.406a.512.512,0,0,0,1.023,0V2.559A2.559,2.559,0,0,0,10.746,0H2.559A2.559,2.559,0,0,0,0,2.559v8.188A2.559,2.559,0,0,0,2.559,13.3H5.415a.512.512,0,1,0,0-1.023H2.559a1.535,1.535,0,0,1-1.535-1.535V2.559A1.535,1.535,0,0,1,2.559,1.023h8.188a1.535,1.535,0,0,1,1.535,1.535Z" transform="translate(1.535 1.535)" fill="#3d7aff"/>
|
||||
</g>
|
||||
<g id="移出" transform="translate(978 290.608)">
|
||||
<path id="形状结合" d="M0,2.821a.746.746,0,0,0,.529.73l.118.011,3.68-.011L3.459,4.4a.656.656,0,0,0,.816,1.02l.1-.083L6.146,3.6a1.107,1.107,0,0,0,.321-.634l.012-.2,0-.026a.61.61,0,0,0-.015-.125,1.106,1.106,0,0,0-.189-.455l-.107-.129L4.39.2a.656.656,0,0,0-1.022.814L4.23,2.108.654,2.1l-.125.011A.88.88,0,0,0,0,2.821Z" transform="translate(0 0)" fill="#3d7aff"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="32px" height="32px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>展开备份</title>
|
||||
<title>展开菜单</title>
|
||||
<g id="12-月修改-2-版" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="01-运营驾驶舱展开" transform="translate(-1818.000000, -12.000000)" fill="#0B58FF">
|
||||
<g id="展开备份" transform="translate(1818.000000, 12.000000)">
|
||||
<g id="展开菜单" transform="translate(1818.000000, 12.000000)">
|
||||
<rect id="矩形" stroke="#0B58FF" opacity="0" x="0.5" y="0.5" width="31" height="31"></rect>
|
||||
<path d="M26.9054416,1.26315789 L27.1627614,1.2715785 C27.589262,1.29963047 28.0033877,1.39768715 28.3969525,1.56449606 C28.853625,1.75530116 29.2618455,2.03033772 29.6157539,2.38424612 C29.967102,2.73559426 30.2434779,3.1465945 30.4352441,3.6024321 C30.6356746,4.07532525 30.7368421,4.57721075 30.7368421,5.09455843 L30.7368421,26.9054416 L30.7284215,27.1627614 C30.7003695,27.589262 30.6023129,28.0033877 30.4355039,28.3969525 C30.2446988,28.853625 29.9696623,29.2618455 29.6157539,29.6157539 C29.2644057,29.967102 28.8534055,30.2434779 28.3975679,30.4352441 C27.9246748,30.6356746 27.4227892,30.7368421 26.9054416,30.7368421 L5.09455843,30.7368421 L4.83723859,30.7284215 C4.41073802,30.7003695 3.99661229,30.6023129 3.60304751,30.4355039 C3.14637497,30.2446988 2.73815452,29.9696623 2.38424612,29.6157539 C2.03289798,29.2644057 1.75652209,28.8534055 1.56475593,28.3975679 C1.36432537,27.9246748 1.26315789,27.4227892 1.26315789,26.9054416 L1.26315789,5.09455843 L1.2715785,4.83723859 C1.29963047,4.41073802 1.39768715,3.99661229 1.56449606,3.60304751 C1.75530116,3.14637497 2.03033772,2.73815452 2.38424612,2.38424612 C2.73559426,2.03289798 3.1465945,1.75652209 3.6024321,1.56475593 C4.07532525,1.36432537 4.57721075,1.26315789 5.09455843,1.26315789 L26.9054416,1.26315789 Z M26.9054416,3.17216771 L5.09455843,3.17216771 L4.94438644,3.17795455 C3.95326514,3.25463661 3.17216771,4.08386243 3.17216771,5.09455843 L3.17216771,26.9054416 L3.17795455,27.0556136 C3.25463661,28.0467349 4.08386243,28.8278323 5.09455843,28.8278323 L26.9054416,28.8278323 L27.0556136,28.8220454 C28.0467349,28.7453634 28.8278323,27.9161376 28.8278323,26.9054416 L28.8278323,5.09455843 L28.8220454,4.94438644 C28.7453634,3.95326514 27.9161376,3.17216771 26.9054416,3.17216771 Z M29.2015182,9.76714413 L29.2015182,11.8615014 L2.12281432,11.8615014 L2.12281432,9.76714413 L29.2015182,9.76714413 Z" id="形状结合" fill-rule="nonzero" opacity="0.79078311"></path>
|
||||
</g>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
@@ -1,6 +1,6 @@
|
||||
<!--?xml version="1.0" encoding="UTF-8"?-->
|
||||
<svg width="100%" height="100%" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet">
|
||||
<title>icon/可视化/退出全屏</title>
|
||||
<title>退出全屏</title>
|
||||
<g id="00首页" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g transform="translate(-1802.000000, -40.000000)" fill="#0B58FF" id="icon/可视化/退出全屏">
|
||||
<g transform="translate(1802.000000, 40.000000)">
|
||||
|
||||
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
BIN
src/assets/images/avatar.png
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
@@ -143,7 +143,7 @@ h6 {
|
||||
|
||||
.pagination-container .el-pagination {
|
||||
right: 0;
|
||||
position: absolute;
|
||||
position: absolute !important;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
<el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click">
|
||||
<div class="avatar-wrapper">
|
||||
<img :src="avatar" class="user-avatar">
|
||||
<img :src="require(`../../assets/images/choicepart/avatar.png`)" class="user-avatar">
|
||||
<span v-if="nickname" class="user-nickname">{{ nickname }}</span>
|
||||
<i class="el-icon-caret-bottom" />
|
||||
</div>
|
||||
@@ -188,7 +188,7 @@ export default {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: -20px;
|
||||
top: 25px;
|
||||
top: 18px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<template>
|
||||
<div class="sidebar-logo-container" :class="{'collapse':collapse}" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }">
|
||||
<transition name="sidebarLogoFade">
|
||||
<router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
|
||||
<div v-if="collapse" key="collapse" class="sidebar-logo-link">
|
||||
<img v-if="logo" :src="logo" class="sidebar-logo" />
|
||||
<h1 v-else class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }} </h1>
|
||||
</router-link>
|
||||
<router-link v-else key="expand" class="sidebar-logo-link" to="/">
|
||||
</div>
|
||||
<div v-else key="expand" class="sidebar-logo-link">
|
||||
<img v-if="logo" :src="logo" class="sidebar-logo" />
|
||||
<h1 class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }} </h1>
|
||||
</router-link>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -8,6 +8,46 @@ import { isRelogin } from '@/utils/request'
|
||||
|
||||
NProgress.configure({ showSpinner: false })
|
||||
|
||||
// 从菜单树中查找第一个可见叶子菜单路径(按接口返回顺序)
|
||||
function findFirstLeafPathFromMenus(menus) {
|
||||
if (!Array.isArray(menus) || menus.length === 0) return null
|
||||
|
||||
function dfs(list, parentPath = '') {
|
||||
for (const item of list) {
|
||||
if (item.visible === false) continue
|
||||
const rawPath = item.path || ''
|
||||
const currentPath = rawPath.startsWith('/')
|
||||
? rawPath
|
||||
: `${parentPath}/${rawPath}`.replace(/\/+/g, '/')
|
||||
if (item.children && item.children.length > 0) {
|
||||
const found = dfs(item.children, currentPath)
|
||||
if (found != null) return found
|
||||
} else {
|
||||
return currentPath
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
return dfs(menus)
|
||||
}
|
||||
function findFirstLeafPathFromRoutes(routes) {
|
||||
if (!Array.isArray(routes) || routes.length === 0) return null
|
||||
const stack = [...routes]
|
||||
while (stack.length) {
|
||||
const route = stack.shift()
|
||||
if (!route || route.hidden === true) continue
|
||||
if (Array.isArray(route.children) && route.children.length > 0) {
|
||||
stack.unshift(...route.children)
|
||||
continue
|
||||
}
|
||||
const p = route.path || ''
|
||||
if (typeof p === 'string' && p.startsWith('/') && p !== '/404') {
|
||||
return p
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// 增加三方登陆 update by 芋艿
|
||||
const whiteList = ['/login', '/social-login', '/auth-redirect', '/bind', '/register', '/oauthLogin/gitee']
|
||||
|
||||
@@ -17,21 +57,35 @@ router.beforeEach((to, from, next) => {
|
||||
to.meta.title && store.dispatch('settings/setTitle', to.meta.title)
|
||||
/* has token*/
|
||||
if (to.path === '/login') {
|
||||
next({ path: '/' })
|
||||
next({ path: store.getters.defaultPath || '/' })
|
||||
NProgress.done()
|
||||
} else {
|
||||
if (store.getters.roles.length === 0) {
|
||||
isRelogin.show = true
|
||||
// 获取字典数据 add by 芋艿
|
||||
store.dispatch('dict/loadDictDatas')
|
||||
// 获取部门权限
|
||||
store.dispatch('GetLevel')
|
||||
// 判断当前用户是否已拉取完 user_info 信息
|
||||
store.dispatch('GetInfo').then(userInfo => {
|
||||
isRelogin.show = false
|
||||
// 触发 GenerateRoutes 事件时,将 menus 菜单树传递进去
|
||||
store.dispatch('GenerateRoutes', userInfo.menus).then(accessRoutes => {
|
||||
store.dispatch('GenerateRoutes', userInfo.menus).then(accessRoutes => {
|
||||
// 根据 roles 权限生成可访问的路由表
|
||||
router.addRoutes(accessRoutes) // 动态添加可访问路由表
|
||||
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
|
||||
const menuDefaultPath = findFirstLeafPathFromMenus(userInfo.menus)
|
||||
const routeFallbackPath = findFirstLeafPathFromRoutes(accessRoutes)
|
||||
const defaultPath = menuDefaultPath || routeFallbackPath || '/'
|
||||
store.dispatch('SetDefaultPath', defaultPath)
|
||||
// 仅当目标为根路径 '/' 时跳默认页;否则保持当前路径(含刷新场景),避免刷新被误判为“未匹配”而跳到默认页
|
||||
if (to.path === '/') {
|
||||
const matched = router.match(defaultPath)
|
||||
const hasMatch = matched && Array.isArray(matched.matched) && matched.matched.length > 0
|
||||
const safePath = hasMatch ? defaultPath : (routeFallbackPath || '/')
|
||||
next({ path: safePath, replace: true })
|
||||
} else {
|
||||
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成,当前页刷新时保留 to 的路径
|
||||
}
|
||||
})
|
||||
}).catch(err => {
|
||||
store.dispatch('LogOut').then(() => {
|
||||
@@ -40,7 +94,12 @@ router.beforeEach((to, from, next) => {
|
||||
})
|
||||
})
|
||||
} else {
|
||||
next()
|
||||
if (to.path === '/') {
|
||||
const defaultPath = store.getters.defaultPath || '/'
|
||||
next({ path: defaultPath, replace: true })
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -64,13 +64,13 @@ export const constantRoutes = [
|
||||
component: (resolve) => require(["@/views/error/401"], resolve),
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
path: "/",
|
||||
// component: () => import('@/views/choicePart'),
|
||||
component: () => import("@/views/home"),
|
||||
hidden: true,
|
||||
meta: { requireToken: true },
|
||||
},
|
||||
// {
|
||||
// path: "/",
|
||||
// // component: () => import('@/views/choicePart'),
|
||||
// component: () => import("@/views/home"),
|
||||
// hidden: true,
|
||||
// meta: { requireToken: true },
|
||||
// },
|
||||
// {
|
||||
// path: "/operatingRevenue",
|
||||
// // component: () => import('@/views/choicePart'),
|
||||
|
||||
@@ -17,7 +17,10 @@ const getters = {
|
||||
topbarRouters:state => state.permission.topbarRouters,
|
||||
defaultRoutes:state => state.permission.defaultRoutes,
|
||||
sidebarRouters:state => state.permission.sidebarRouters,
|
||||
defaultPath: state => state.permission.defaultPath,
|
||||
// 数据字典
|
||||
dict_datas: state => state.dict.dictDatas
|
||||
dict_datas: state => state.dict.dictDatas,
|
||||
// 部门层级
|
||||
levelList: state => state.user.levelList
|
||||
}
|
||||
export default getters
|
||||
|
||||
@@ -11,8 +11,12 @@ const permission = {
|
||||
addRoutes: [],
|
||||
sidebarRouters: [], // 左侧边菜单的路由,被 Sidebar/index.vue 使用
|
||||
topbarRouters: [], // 顶部菜单的路由,被 TopNav/index.vue 使用
|
||||
defaultPath: '/', // 登录后默认跳转路径(由菜单 jumpFlag===1 决定)
|
||||
},
|
||||
mutations: {
|
||||
SET_DEFAULT_PATH: (state, path) => {
|
||||
state.defaultPath = path || '/'
|
||||
},
|
||||
SET_ROUTES: (state, routes) => {
|
||||
state.addRoutes = routes
|
||||
state.routes = constantRoutes.concat(routes)
|
||||
@@ -48,6 +52,9 @@ const permission = {
|
||||
commit('SET_TOPBAR_ROUTES', sidebarRoutes)
|
||||
resolve(rewriteRoutes)
|
||||
})
|
||||
},
|
||||
SetDefaultPath({commit}, path) {
|
||||
commit('SET_DEFAULT_PATH', path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {login, logout, getInfo, socialLogin, smsLogin} from '@/api/login'
|
||||
import {setToken, removeToken} from '@/utils/auth'
|
||||
import {getLevelStruc} from '@/api/cockpit'
|
||||
|
||||
const user = {
|
||||
state: {
|
||||
@@ -7,7 +8,8 @@ const user = {
|
||||
name: '',
|
||||
avatar: '',
|
||||
roles: [],
|
||||
permissions: []
|
||||
permissions: [],
|
||||
levelList:[]
|
||||
},
|
||||
|
||||
mutations: {
|
||||
@@ -28,6 +30,9 @@ const user = {
|
||||
},
|
||||
SET_PERMISSIONS: (state, permissions) => {
|
||||
state.permissions = permissions
|
||||
},
|
||||
SET_LEVEL_LIST: (state, levelList) => {
|
||||
state.levelList = levelList
|
||||
}
|
||||
},
|
||||
|
||||
@@ -122,7 +127,21 @@ const user = {
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
// 获取层级
|
||||
GetLevel({ commit, state }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
getLevelStruc().then(res => {
|
||||
// 如果未加载到数据,则直接返回
|
||||
if (!res || !res.data) {
|
||||
return;
|
||||
}
|
||||
commit('SET_LEVEL_LIST', res.data)
|
||||
resolve()
|
||||
})
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
},
|
||||
// 退出系统
|
||||
LogOut({ commit, state }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
@@ -81,6 +81,9 @@ export const DICT_TYPE = {
|
||||
PROMOTION_COUPON_TAKE_TYPE: 'promotion_coupon_take_type', // 优惠劵的领取方式
|
||||
PROMOTION_ACTIVITY_STATUS: 'promotion_activity_status', // 优惠活动的状态
|
||||
PROMOTION_CONDITION_TYPE: 'promotion_condition_type', // 营销的条件类型枚举
|
||||
|
||||
// ========== 模块 ==========
|
||||
LB_DW: 'lb_dw'
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,3 +142,15 @@ export function getDictDataLabel(dictType, value) {
|
||||
const dict = getDictData(dictType, value);
|
||||
return dict ? dict.label : '';
|
||||
}
|
||||
|
||||
// table中用来过滤字典
|
||||
export function publicFormatter(dictTable) {
|
||||
const dictDatas = getDictDatas(dictTable)
|
||||
return function (val) {
|
||||
const arr = {}
|
||||
dictDatas.map((item) => {
|
||||
arr[item.value] = item.label
|
||||
})
|
||||
return arr?.[val]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import axios from 'axios'
|
||||
import {Message, MessageBox, Notification} from 'element-ui'
|
||||
import {Message, MessageBox, Notification, Loading} from 'element-ui'
|
||||
import store from '@/store'
|
||||
import {getAccessToken, getRefreshToken, getTenantId, setToken, getVisitTenantId} from '@/utils/auth'
|
||||
import errorCode from '@/utils/errorCode'
|
||||
@@ -31,8 +31,36 @@ const service = axios.create({
|
||||
// 禁用 Cookie 等信息
|
||||
withCredentials: false,
|
||||
})
|
||||
|
||||
|
||||
let loadingInstance = null
|
||||
function startLoading() {
|
||||
loadingInstance = Loading.service({
|
||||
fullscreen: false,
|
||||
text: '拼命加载中...',
|
||||
background: 'rgba(0, 0, 0, 0.1)'
|
||||
})
|
||||
}
|
||||
function endLoading() {
|
||||
loadingInstance.close()
|
||||
}
|
||||
let needLoadingRequestCount = 0
|
||||
function showFullScreenLoading() {
|
||||
if (needLoadingRequestCount === 0) {
|
||||
startLoading()
|
||||
}
|
||||
needLoadingRequestCount++
|
||||
}
|
||||
function tryHideFullScreenLoading() {
|
||||
if (needLoadingRequestCount <= 0) return
|
||||
needLoadingRequestCount--
|
||||
if (needLoadingRequestCount === 0) {
|
||||
endLoading()
|
||||
}
|
||||
}
|
||||
// request拦截器
|
||||
service.interceptors.request.use(config => {
|
||||
showFullScreenLoading()
|
||||
// 是否需要设置 token
|
||||
const isToken = (config.headers || {}).isToken === false
|
||||
if (getAccessToken() && !isToken) {
|
||||
@@ -88,12 +116,14 @@ service.interceptors.request.use(config => {
|
||||
}
|
||||
return config
|
||||
}, error => {
|
||||
tryHideFullScreenLoading()
|
||||
console.log(error)
|
||||
Promise.reject(error)
|
||||
})
|
||||
|
||||
// 响应拦截器
|
||||
service.interceptors.response.use(async res => {
|
||||
tryHideFullScreenLoading()
|
||||
let { data } = res
|
||||
// 未设置状态码则默认成功状态
|
||||
// 二进制数据则直接返回,例如说 Excel 导出
|
||||
@@ -202,6 +232,7 @@ service.interceptors.response.use(async res => {
|
||||
}
|
||||
}, error => {
|
||||
console.log('err' + error)
|
||||
tryHideFullScreenLoading()
|
||||
let {message} = error;
|
||||
if (message === "Network Error") {
|
||||
message = "后端接口连接异常";
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
gap: 12px;
|
||||
grid-template-columns:416px 1192px;
|
||||
">
|
||||
<indicatorCalendar :calendarList="calendarList" />
|
||||
<indicatorDetails :timeType="timeType" />
|
||||
<indicatorCalendar :timeType="timeType" :calendarObj='calendarObj'/>
|
||||
<indicatorDetails :timeType="timeType" @updateLeft='getData' @updateLevel='getLevel'/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="top" style="margin-top: -20px; display: flex; gap: 16px">
|
||||
@@ -53,8 +53,9 @@ import { mapState } from "vuex";
|
||||
// import operatingLineChart from "../operatingComponents/operatingLineChart";
|
||||
// import operatingLineChartCumulative from "../operatingComponents/operatingLineChartCumulative.vue";
|
||||
|
||||
import { getSalesRevenueGroupData, getCalendar } from '@/api/cockpit'
|
||||
import { getSalesRevenueGroupData } from '@/api/cockpit'
|
||||
import moment from "moment";
|
||||
import {getCalendar, getCalendarYear} from '@/api/cockpit';
|
||||
export default {
|
||||
name: "DayReport",
|
||||
components: {
|
||||
@@ -78,7 +79,8 @@ export default {
|
||||
selectDate:{},
|
||||
monthData: {},
|
||||
ytdData: {},
|
||||
calendarList:{},
|
||||
calendarObj:{},
|
||||
levelId: null
|
||||
};
|
||||
},
|
||||
|
||||
@@ -144,37 +146,29 @@ export default {
|
||||
this.beilv = _this.clientWidth / 1920;
|
||||
})();
|
||||
};
|
||||
this.getData()
|
||||
// this.getData()
|
||||
},
|
||||
methods: {
|
||||
// sortChange(value) {
|
||||
// this.sort = value
|
||||
// this.getData()
|
||||
// },
|
||||
getData() {
|
||||
getCalendar().then((res) => {
|
||||
console.log(res, 'res');
|
||||
this.calendarList = res.data
|
||||
// this.monthData = res.data.month
|
||||
// this.ytdData = res.data.ytd
|
||||
})
|
||||
// getSalesRevenueGroupData({
|
||||
// startTime: this.dateData.startTime,
|
||||
// endTime: this.dateData.endTime,
|
||||
// sort: this.sort,
|
||||
// index: undefined,
|
||||
// factory: undefined
|
||||
// // timeDim: obj.mode
|
||||
// }).then((res) => {
|
||||
// console.log(res);
|
||||
// this.monthData= res.data.month
|
||||
// this.ytdData = res.data.ytd
|
||||
// })
|
||||
if(this.timeType == 'month'){
|
||||
getCalendar({levelId: this.levelId}).then((res) => {
|
||||
this.calendarObj = res.data
|
||||
})
|
||||
}else{
|
||||
getCalendarYear({levelId: this.levelId}).then((res) => {
|
||||
this.calendarObj = res.data
|
||||
})
|
||||
}
|
||||
},
|
||||
// 层级变动
|
||||
getLevel(id) {
|
||||
this.levelId = id
|
||||
this.getData()
|
||||
},
|
||||
handleTimeChange(obj) {
|
||||
console.log(obj, 'obj');
|
||||
this.timeType = obj
|
||||
// this.getData()
|
||||
this.getData()
|
||||
},
|
||||
handleClickOutside() {
|
||||
this.$store.dispatch("app/closeSideBar", { withoutAnimation: false });
|
||||
|
||||
@@ -8,6 +8,15 @@
|
||||
|
||||
<!-- 右侧区域:全屏按钮 -->
|
||||
<div class="right-content">
|
||||
<el-dropdown trigger="click">
|
||||
<el-button type="text" class="logout-btn" :title="'退出'">
|
||||
<svg-icon style="color: #0B58FF;" icon-class="logout" />
|
||||
</el-button>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item @click.native='logout'>退出登录</el-dropdown-item>
|
||||
<el-dropdown-item @click.native='handleToggle'>切换账号</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<el-button type="text" class="screen-btn" @click="changeHomeSider">
|
||||
<svg-icon style="color: #0B58FF;" v-if="openSider" icon-class="closeSider" />
|
||||
<svg-icon style="color: #0B58FF;" v-else icon-class="openSider" />
|
||||
@@ -36,6 +45,7 @@
|
||||
|
||||
<script>
|
||||
import moment from 'moment'
|
||||
import {getPath} from "@/utils/ruoyi";
|
||||
export default {
|
||||
name: 'Header',
|
||||
props: {
|
||||
@@ -139,6 +149,19 @@ export default {
|
||||
const timeRange = this.calculateTimeRange();
|
||||
this.$emit('timeRangeChange', timeRange);
|
||||
console.log('触发时间范围变化:', timeRange);
|
||||
},
|
||||
|
||||
async logout() {
|
||||
this.$modal.confirm('确定注销并退出系统吗?', '提示').then(() => {
|
||||
this.$store.dispatch('LogOut').then(() => {
|
||||
location.href = getPath('/index');
|
||||
})
|
||||
}).catch(() => {});
|
||||
},
|
||||
handleToggle() {
|
||||
this.$store.dispatch('LogOut').then(() => {
|
||||
location.href = getPath('/index');
|
||||
})
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -325,10 +348,11 @@ export default {
|
||||
|
||||
.right-content {
|
||||
display: flex;
|
||||
margin-bottom: 60px;
|
||||
margin-top: 12px;
|
||||
margin-right: 16px;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
gap: 21px;
|
||||
height: 35px;
|
||||
}
|
||||
|
||||
.current-time {
|
||||
@@ -345,6 +369,15 @@ export default {
|
||||
color: #00fff0;
|
||||
font-size: 26px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.logout-btn {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
font-size: 30px;
|
||||
padding: 0;
|
||||
margin-top: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
style="display: flex; gap: 16px; flex-wrap: wrap; align-content: flex-start; row-gap: 8px;">
|
||||
<!-- 循环生成12个月:通过判断当前月份索引,添加current类 -->
|
||||
<div class="monthItem" :class="{
|
||||
'has-data': month.haveData,
|
||||
'current': index === currentMonthIndex // 本月匹配current样式
|
||||
}" v-for="(month, index) in monthList" :key="index">
|
||||
{{ month.name }}
|
||||
'has-data': calendar.haveData,
|
||||
'current': calendar.isActive // 本月匹配current样式
|
||||
}" v-for="(calendar, index) in calendarList" :key="index">
|
||||
{{ calendar.name }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -25,49 +25,35 @@
|
||||
|
||||
<script>
|
||||
import Container from './container.vue'
|
||||
// import * as echarts from 'echarts'
|
||||
// import topItem from './operating-item.vue'
|
||||
|
||||
export default {
|
||||
name: 'ProductionStatus',
|
||||
components: { Container },
|
||||
// mixins: [resize],
|
||||
props: {
|
||||
calendarList: { // 接收父组件传递的年月状态对象
|
||||
timeType: {
|
||||
type: String,
|
||||
default: 'month', // 默认月份维度
|
||||
},
|
||||
calendarObj: { // 接收父组件传递的年月状态对象
|
||||
type: Object, // 注意:父组件传递的是对象,不是数组,修正props类型
|
||||
default: () => ({}) // 默认空对象,避免报错
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
chart: null,
|
||||
// 初始化12个月的列表,可根据实际需求修改haveData默认值
|
||||
monthList: [
|
||||
{ name: '1月', haveData: false, isActive: false },
|
||||
{ name: '2月', haveData: false, isActive: false },
|
||||
{ name: '3月', haveData: false, isActive: false },
|
||||
{ name: '4月', haveData: false, isActive: false },
|
||||
{ name: '5月', haveData: false, isActive: false },
|
||||
{ name: '6月', haveData: false, isActive: false },
|
||||
{ name: '7月', haveData: false, isActive: false },
|
||||
{ name: '8月', haveData: false, isActive: false },
|
||||
{ name: '9月', haveData: false, isActive: false },
|
||||
{ name: '10月', haveData: false, isActive: false },
|
||||
{ name: '11月', haveData: false, isActive: false },
|
||||
{ name: '12月', haveData: false, isActive: false }
|
||||
],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 计算属性:获取当前月份对应的索引(0-11,对应1月-12月)
|
||||
currentMonthIndex() {
|
||||
// new Date().getMonth() 返回 0(1月) - 11(12月),正好匹配monthList索引
|
||||
return new Date().getMonth();
|
||||
calendarList:[],// 日历列表
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 监听calendarList变化,实时更新monthList的haveData状态
|
||||
calendarList: {
|
||||
// timeType: {
|
||||
// immediate: true, // 组件挂载时立即执行一次
|
||||
// deep: true, // 深度监听对象内部属性变化
|
||||
// handler() {
|
||||
// this.updateMonthHaveData();
|
||||
// }
|
||||
// },
|
||||
calendarObj:{
|
||||
immediate: true, // 组件挂载时立即执行一次
|
||||
deep: true, // 深度监听对象内部属性变化
|
||||
handler(newVal) {
|
||||
@@ -75,28 +61,24 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 初始化图表(若需展示图表,需在模板中添加对应 DOM)
|
||||
// this.$nextTick(() => this.updateChart())
|
||||
},
|
||||
mounted() {},
|
||||
methods: {
|
||||
// 根据calendarList更新monthList的haveData状态
|
||||
// 根据月或者年维度,获取不同的接口,拿到数据,更新左侧日历框
|
||||
updateMonthHaveData(calendarObj) {
|
||||
if (!calendarObj || typeof calendarObj !== 'object') return;
|
||||
|
||||
// 遍历12个月,匹配对应年月
|
||||
this.monthList.forEach((month, index) => {
|
||||
// 获取月份数字(索引+1,补两位,如1→01,10→10)
|
||||
const monthNum = (index + 1).toString().padStart(2, '0');
|
||||
// 拼接成calendarList中的键格式(如2025-01)
|
||||
const yearMonthKey = `2025-${monthNum}`; // 若年份不固定,可改为props传递年份
|
||||
|
||||
// 判断calendarObj中该键对应的值:1→true,0→false,无该键则保持默认false
|
||||
if (calendarObj.hasOwnProperty(yearMonthKey)) {
|
||||
month.haveData = calendarObj[yearMonthKey] === 1;
|
||||
if(this.timeType == 'month'){
|
||||
const keys = Object.keys(calendarObj);
|
||||
this.calendarList = []
|
||||
for(let i = 0; i < keys.length; i++) {
|
||||
this.calendarList.push({name:i+1+'月',haveData:calendarObj[keys[i]],isActive:i==new Date().getMonth()})
|
||||
}
|
||||
});
|
||||
},
|
||||
}else{
|
||||
const keys = Object.keys(calendarObj);
|
||||
this.calendarList = []
|
||||
for(let i = 0; i < keys.length; i++) {
|
||||
this.calendarList.push({name:keys[i]+'年',haveData:calendarObj[keys[i]],isActive:keys[i]==new Date().getFullYear()})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -119,7 +101,6 @@ export default {
|
||||
line-height: 42px;
|
||||
text-align: center;
|
||||
font-style: normal;
|
||||
cursor: pointer; // 鼠标悬浮手型
|
||||
transition: all 0.2s ease; // 过渡效果,样式切换更平滑
|
||||
border: 2px solid transparent; // 透明边框,避免选中时布局偏移
|
||||
margin: 0; // 清除默认外边距,进一步缩小缝隙
|
||||
@@ -140,5 +121,3 @@ export default {
|
||||
border: 2px solid #0B58FF !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style></style>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<div style="width: 4px;height: 16px;background: #0B58FF;border-radius: 1px;margin-top: 10px;"></div>
|
||||
<el-form :inline="true" :model="form" class="demo-form-inline">
|
||||
<el-form-item label="所属层级">
|
||||
<el-select v-model="form.levelId" placeholder="请选择">
|
||||
<el-select v-model="form.levelId" placeholder="请选择" @change='handleLevelChange'>
|
||||
<el-option v-for="item in levelLList" :key="item.id" :label="item.name" :value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
@@ -22,7 +22,7 @@
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button style="background-color: #0B58FF;" type="primary" @click="onSubmit">查询</el-button>
|
||||
<!-- <el-button type="primary" plain size="medium">导入</el-button> -->
|
||||
<el-button type="primary" plain size="medium" @click='importExcel'>导入</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
@@ -35,14 +35,14 @@
|
||||
<div v-if="!isDetail" style="display: flex;gap: 8px;align-items: center;height: 32px;">
|
||||
<div style="width: 4px;height: 16px;background: #0B58FF;border-radius: 1px;"></div>
|
||||
<div style="width: 58px;
|
||||
height: 16px;
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: rgba(0,0,0,0.85);
|
||||
line-height: 16px;
|
||||
text-align: right;
|
||||
font-style: normal;">指标详情</div>
|
||||
height: 16px;
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: rgba(0,0,0,0.85);
|
||||
line-height: 16px;
|
||||
text-align: right;
|
||||
font-style: normal;">指标详情</div>
|
||||
<el-button style="background-color: #0B58FF;height: 32px;line-height: 10px;" type="primary"
|
||||
@click="handleEdit">编辑</el-button>
|
||||
</div>
|
||||
@@ -53,12 +53,12 @@ font-style: normal;">指标详情</div>
|
||||
<div
|
||||
style="width: 58px;height: 16px;font-family: PingFangSC, PingFang SC;font-weight: 400;font-size: 14px;color: rgba(0,0,0,0.85);line-height: 16px;text-align: right;font-style: normal;">
|
||||
快捷操作</div>
|
||||
<!-- <el-button style="height: 32px;line-height: 10px;" type="primary" plain size="medium"
|
||||
@click="onSubmit">复制上月</el-button>
|
||||
<el-button style="height: 32px;line-height: 10px;" type="primary" plain size="medium"
|
||||
@click="onSubmit">全部上调5%</el-button>
|
||||
@click="copyLastMonth">复制上月/年</el-button>
|
||||
<el-button style="height: 32px;line-height: 10px;" type="primary" plain size="medium"
|
||||
@click="onSubmit">全部下调5%</el-button> -->
|
||||
@click="allUp">全部上调5%</el-button>
|
||||
<el-button style="height: 32px;line-height: 10px;" type="primary" plain size="medium"
|
||||
@click="allDown">全部下调5%</el-button>
|
||||
<el-button style="height: 32px;line-height: 10px;" type="primary" plain size="medium"
|
||||
@click="handleClear">清空配置</el-button>
|
||||
<el-button style="background-color: #0B58FF;height: 32px;line-height: 10px;" type="primary"
|
||||
@@ -69,28 +69,28 @@ font-style: normal;">指标详情</div>
|
||||
|
||||
<!-- 表格组件:添加key属性强制刷新,绑定所有必要属性 -->
|
||||
<base-table style="height: 700px;" :maxHeight=" '700' " @emitFun="inputChange" class="right-aside"
|
||||
:table-props="tableProps" :page="form.pageNo" :limit="form.pageSize" :table-data="tableData" ref="baseTable"
|
||||
:key="`base-table-${isDetail}-${timeType}`"></base-table>
|
||||
:table-props="tableProps" :page="form.pageNo" :limit="form.pageSize" :table-data="tableData" ref="baseTable" id='calendarTable'
|
||||
:key="tableKey"></base-table>
|
||||
</div>
|
||||
</div>
|
||||
<el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
|
||||
<el-upload ref="upload" :limit="1" accept=".xlsx, .xls" :headers="upload.headers"
|
||||
:action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading"
|
||||
:on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
|
||||
<el-upload ref="upload" :limit="1" accept=".xlsx, .xls" action="#" :disabled="upload.isUploading"
|
||||
:on-change="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||
<div class="el-upload__tip text-center" slot="tip">
|
||||
<div class="el-upload__tip" slot="tip">
|
||||
<el-checkbox v-model="upload.updateSupport" /> 是否更新已经存在的用户数据
|
||||
</div>
|
||||
<span>仅允许导入xls、xlsx格式文件。</span>
|
||||
<el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;"
|
||||
@click="importTemplate">下载模板</el-link>
|
||||
</div>
|
||||
<div class="el-upload__tip" slot="tip">
|
||||
<el-radio-group v-model="upload.timeDim">
|
||||
<el-radio :label="2">月预算</el-radio>
|
||||
<el-radio :label="3">年预算</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</el-upload>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitFileForm">确 定</el-button>
|
||||
<el-button @click="upload.open = false">取 消</el-button>
|
||||
<el-button @click="cancelBtn">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</Container>
|
||||
@@ -99,9 +99,11 @@ font-style: normal;">指标详情</div>
|
||||
|
||||
<script>
|
||||
import Container from './container.vue'
|
||||
import { getLevelStruc, getTargetMonthPage, updateTargetMonthData, getTargetYearPage, updateTargetYearData, getDictListData } from '@/api/cockpit'
|
||||
import { getLevelStruc, getTargetMonthPage, updateTargetMonthData, getTargetYearPage, updateTargetYearData,copyLastMonthData, copyLastYearData} from '@/api/cockpit'
|
||||
import inputArea from './inputArea.vue' // 导入输入组件
|
||||
import { getBaseHeader } from "@/utils/request";
|
||||
import { publicFormatter } from '@/utils/dict';
|
||||
import {getAccessToken, getTenantId} from '@/utils/auth'
|
||||
import axios from 'axios';
|
||||
export default {
|
||||
name: 'ProductionStatus',
|
||||
components: {
|
||||
@@ -118,34 +120,33 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
levelId: 1,
|
||||
levelId: undefined,
|
||||
pageNo: 1,
|
||||
pageSize: 100,
|
||||
date: undefined, // 统一存储日期(月份/年份)
|
||||
startTime: undefined, // 起始时间戳
|
||||
endTime: undefined // 结束时间戳
|
||||
},
|
||||
dictData: [],
|
||||
upload: {
|
||||
// 是否显示弹出层(用户导入)
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 弹出层标题(用户导入)
|
||||
title: "",
|
||||
// 弹出层标题
|
||||
title: "预算填报导入",
|
||||
// 是否禁用上传
|
||||
isUploading: false,
|
||||
// 是否更新已经存在的用户数据
|
||||
updateSupport: 0,
|
||||
// 设置上传的请求头部
|
||||
headers: getBaseHeader(),
|
||||
// 上传的地址
|
||||
url: process.env.VUE_APP_BASE_API + '/admin-api/system/user/import'
|
||||
fileList:[],
|
||||
currentFile:null,
|
||||
timeDim: 2
|
||||
},
|
||||
getDataList: null, // 动态切换的查询接口
|
||||
updateData: null, // 动态切换的更新接口
|
||||
isDetail: false, // 编辑状态标识:false=只读,true=编辑
|
||||
tableData: [], // 表格数据
|
||||
levelLList: [], // 所属层级下拉数据
|
||||
tableProps: [] // 表格列配置
|
||||
tableProps: [], // 表格列配置
|
||||
tableKey:0,// 强制表格更新
|
||||
allUpBtn: false, // 全部上调按钮状态
|
||||
allDownBtn: false // 全部下调按钮状态
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -182,7 +183,6 @@ export default {
|
||||
this.initDefaultDate();
|
||||
// 2. 计算对应时间戳
|
||||
this.calculateTimeStamp();
|
||||
this.getDictData()
|
||||
// 3. 先初始化表格配置(优先于数据请求,避免表格空配置渲染)
|
||||
this.initTableProps(this.isDetail);
|
||||
// 4. 等待配置就绪后,再请求数据,避免异步冲突
|
||||
@@ -191,14 +191,178 @@ export default {
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
getDictData() {
|
||||
getDictListData({ pageNo: 1, pageSize: 100, dictType: 'lb_dw' }).then((res) => {
|
||||
this.dictData = res.data.list
|
||||
// 清空配置
|
||||
handleClear() {
|
||||
// 清空target
|
||||
this.tableData.forEach(item => {
|
||||
item.target = null;
|
||||
})
|
||||
this.tableKey++;
|
||||
this.allDownBtn = false;
|
||||
this.allUpBtn = false;
|
||||
},
|
||||
//复制上月/上年数据(调用接口不同)
|
||||
copyLastMonth() {
|
||||
if(this.timeType === 'month') {
|
||||
this.$modal.confirm('是否确认复制上月数据?').then(() => {
|
||||
this.copyLastMonthDataPage()
|
||||
}).then(() => {
|
||||
this.$modal.msgSuccess("复制成功");
|
||||
}).catch(() => { });
|
||||
}else{
|
||||
this.$modal.confirm('是否确认复制上年数据?').then(() => {
|
||||
this.copyLastYearDataPage()
|
||||
}).then(() => {
|
||||
this.$modal.msgSuccess("复制成功");
|
||||
}).catch(() => { });
|
||||
}
|
||||
},
|
||||
copyLastMonthDataPage() {
|
||||
copyLastMonthData({
|
||||
levelId: this.form.levelId,
|
||||
startTime: this.form.startTime,
|
||||
endTime: this.form.endTime,
|
||||
pageSize: this.form.pageSize,
|
||||
pageNo: this.form.pageNo
|
||||
}).then((res) => {
|
||||
this.tableData = res.data.map(item => {
|
||||
// 新增unitLabel字段,存储匹配后的显示名称
|
||||
return {
|
||||
...item
|
||||
};
|
||||
});
|
||||
this.tableKey++;
|
||||
this.allDownBtn = false;
|
||||
this.allUpBtn = false;
|
||||
}).catch(err => {
|
||||
console.error('获取表格数据失败:', err);
|
||||
this.tableData = [];
|
||||
});
|
||||
},
|
||||
copyLastYearDataPage() {
|
||||
copyLastYearData({
|
||||
levelId: this.form.levelId,
|
||||
startTime: this.form.startTime,
|
||||
endTime: this.form.endTime,
|
||||
pageSize: this.form.pageSize,
|
||||
pageNo: this.form.pageNo
|
||||
}).then((res) => {
|
||||
this.tableData = res.data.map(item => {
|
||||
// 新增unitLabel字段,存储匹配后的显示名称
|
||||
return {
|
||||
...item
|
||||
};
|
||||
});
|
||||
this.tableKey++;
|
||||
this.allDownBtn = false;
|
||||
this.allUpBtn = false;
|
||||
}).catch(err => {
|
||||
console.error('获取表格数据失败:', err);
|
||||
this.tableData = [];
|
||||
});
|
||||
},
|
||||
//全部上调5%
|
||||
allUp() {
|
||||
if(this.allUpBtn || this.allDownBtn) {
|
||||
this.$modal.msgWarning("数据已调整,请先保存数据");
|
||||
return
|
||||
}
|
||||
for(let i = 0; i < this.tableData.length; i++) {
|
||||
this.tableData[i].target = (this.tableData[i].target * 1.05).toFixed(2)
|
||||
}
|
||||
// 强制表格组件刷新
|
||||
this.tableKey++;
|
||||
this.allUpBtn = true;
|
||||
},
|
||||
// 全部下调5%
|
||||
allDown() {
|
||||
if(this.allUpBtn || this.allDownBtn) {
|
||||
this.$modal.msgWarning("数据已调整,请先保存数据");
|
||||
return;
|
||||
}
|
||||
for(let i = 0; i < this.tableData.length; i++) {
|
||||
this.tableData[i].target = (this.tableData[i].target * 0.95).toFixed(2)
|
||||
}
|
||||
// 强制表格组件刷新
|
||||
this.tableKey++;
|
||||
this.allDownBtn = true;
|
||||
},
|
||||
// 查询按钮
|
||||
onSubmit() {
|
||||
// 清空原有表格数据,重新请求
|
||||
this.tableData = [];
|
||||
this.$nextTick(() => {
|
||||
this.getDataPage();
|
||||
});
|
||||
},
|
||||
// 切换到编辑模式
|
||||
handleEdit() {
|
||||
this.isDetail = true;
|
||||
// 先更新表格配置,再强制表格刷新
|
||||
this.initTableProps(this.isDetail);
|
||||
this.tableKey++;
|
||||
},
|
||||
// 保存数据(使用动态切换的updateData接口)
|
||||
handleSave() {
|
||||
this.$modal.confirm('是否确认保存数据?').then(() => {
|
||||
return this.updateData(this.tableData)
|
||||
}).then(() => {
|
||||
this.isDetail = false;
|
||||
// 重置表格配置
|
||||
this.initTableProps(this.isDetail);
|
||||
// 清空并重新请求数据,恢复原始状态
|
||||
this.$nextTick(() => {
|
||||
this.tableData = [];
|
||||
this.getDataPage();
|
||||
});
|
||||
this.$modal.msgSuccess("保存成功");
|
||||
this.$emit('updateLeft')
|
||||
}).catch(() => { });
|
||||
},
|
||||
// 请求下拉数据和表格数据(使用动态切换的getDataList接口)
|
||||
getData() {
|
||||
if (!this.getDataList) {
|
||||
console.warn('当前时间维度异常,无法获取数据');
|
||||
return;
|
||||
}
|
||||
// 1. 请求所属层级下拉数据
|
||||
getLevelStruc().then((res) => {
|
||||
this.levelLList = res.data || [];
|
||||
this.form.levelId = this.levelLList[0].id;
|
||||
this.$emit('updateLevel', this.levelLList[0].id)
|
||||
this.getDataPage()
|
||||
}).catch(err => {
|
||||
console.error('获取所属层级失败:', err);
|
||||
this.levelLList = [];
|
||||
});
|
||||
this.$emit('updateLeft')
|
||||
},
|
||||
getDataPage() {
|
||||
// 2. 请求表格分页数据(使用动态接口)
|
||||
this.getDataList({
|
||||
levelId: this.form.levelId,
|
||||
startTime: this.form.startTime,
|
||||
endTime: this.form.endTime,
|
||||
pageSize: this.form.pageSize,
|
||||
pageNo: this.form.pageNo
|
||||
}).then((res) => {
|
||||
console.log('表格数据:', res);
|
||||
this.tableData = res.data.map(item => {
|
||||
// 新增unitLabel字段,存储匹配后的显示名称
|
||||
return {
|
||||
...item
|
||||
};
|
||||
});
|
||||
}).catch(err => {
|
||||
console.error('获取表格数据失败:', err);
|
||||
this.tableData = [];
|
||||
});
|
||||
},
|
||||
handleLevelChange(id) {
|
||||
this.$emit('updateLevel', id)
|
||||
},
|
||||
// 表格单元格数据变更回调
|
||||
inputChange(val) {
|
||||
console.log('修改的数据:', val);
|
||||
// 安全修改:判断索引是否存在,避免数组越界
|
||||
if (this.tableData[val._pageIndex - 1]) {
|
||||
this.tableData[val._pageIndex - 1][val.prop] = val[val.prop];
|
||||
@@ -206,21 +370,31 @@ export default {
|
||||
this.tableData[val._pageIndex - 1].status = 1;
|
||||
}
|
||||
},
|
||||
|
||||
// 取消编辑,恢复只读模式
|
||||
handleCancel() {
|
||||
this.isDetail = false;
|
||||
this.allUpBtn = false;
|
||||
this.allDownBtn = false;
|
||||
// 重置表格配置
|
||||
this.initTableProps(this.isDetail);
|
||||
// 清空并重新请求数据,恢复原始状态
|
||||
this.$nextTick(() => {
|
||||
this.tableData = [];
|
||||
this.getDataPage();
|
||||
});
|
||||
},
|
||||
// 初始化表格列配置(核心:精准控制inputArea挂载)
|
||||
initTableProps(isEdit) {
|
||||
console.log('当前编辑状态:', isEdit, '当前时间维度:', this.timeType);
|
||||
|
||||
// 基础表格列配置(只读模式使用)
|
||||
const baseTableProps = [
|
||||
{ prop: 'type', label: '指标类型', align: 'center' },
|
||||
// { prop: 'type', label: '指标类型', align: 'center' },
|
||||
{ prop: 'name', label: '指标名称', align: 'center' },
|
||||
{ prop: 'unit', label: '单位', align: 'center' },
|
||||
{ prop: 'target', label: '预估值', align: 'center' },
|
||||
{ prop: 'unit', label: '单位', align: 'center', filter: publicFormatter('lb_dw') },
|
||||
{ prop: 'target', label: '预算值', align: 'center' },
|
||||
];
|
||||
|
||||
if (isEdit) {
|
||||
// 编辑模式:仅给「预估值」列添加inputArea(精准挂载,避免无效配置)
|
||||
// 编辑模式:仅给「预算值」列添加inputArea(精准挂载,避免无效配置)
|
||||
this.tableProps = baseTableProps.map(item => {
|
||||
if (item.prop === 'target') { // 只给需要编辑的列添加子组件
|
||||
return {
|
||||
@@ -232,75 +406,16 @@ export default {
|
||||
});
|
||||
} else {
|
||||
// 只读模式:深拷贝基础配置,避免引用污染
|
||||
this.tableProps = JSON.parse(JSON.stringify(baseTableProps));
|
||||
// this.tableProps = JSON.parse(JSON.stringify(baseTableProps));
|
||||
this.tableProps = baseTableProps;
|
||||
}
|
||||
console.log('表格配置:', this.tableProps);
|
||||
},
|
||||
|
||||
// 切换到编辑模式
|
||||
handleEdit() {
|
||||
this.isDetail = true;
|
||||
// 先更新表格配置,再强制表格刷新(双重保障)
|
||||
this.initTableProps(this.isDetail);
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.baseTable) {
|
||||
this.$refs.baseTable.$forceUpdate(); // 强制表格组件刷新
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 保存数据(使用动态切换的updateData接口)
|
||||
handleSave() {
|
||||
// if (!this.updateData) {
|
||||
// this.$modal.msgWarning('当前时间维度异常,无法保存');
|
||||
// return;
|
||||
// }
|
||||
this.$modal.confirm('是否确认保存数据?').then(() => {
|
||||
return this.updateData(this.tableData)
|
||||
}).then(() => {
|
||||
this.isDetail = false;
|
||||
// 重置表格配置
|
||||
this.initTableProps(this.isDetail);
|
||||
// 清空并重新请求数据,恢复原始状态
|
||||
this.$nextTick(() => {
|
||||
this.tableData = [];
|
||||
this.getData();
|
||||
});
|
||||
this.$modal.msgSuccess("保存成功");
|
||||
}).catch(() => { });
|
||||
},
|
||||
|
||||
// 取消编辑,恢复只读模式
|
||||
handleCancel() {
|
||||
this.isDetail = false;
|
||||
// 重置表格配置
|
||||
this.initTableProps(this.isDetail);
|
||||
// 清空并重新请求数据,恢复原始状态
|
||||
this.$nextTick(() => {
|
||||
this.tableData = [];
|
||||
this.getData();
|
||||
});
|
||||
console.log('已取消编辑,恢复原始数据');
|
||||
},
|
||||
|
||||
// 清空配置
|
||||
handleClear() {
|
||||
this.isDetail = false;
|
||||
// 重置表格配置
|
||||
this.initTableProps(this.isDetail);
|
||||
// 清空并重新请求数据,恢复原始状态
|
||||
this.$nextTick(() => {
|
||||
this.tableData = [];
|
||||
this.getData();
|
||||
});
|
||||
},
|
||||
|
||||
// 初始化默认日期(根据timeType)
|
||||
initDefaultDate() {
|
||||
const currentDate = new Date();
|
||||
this.form.date = currentDate;
|
||||
},
|
||||
|
||||
// 计算时间戳(根据timeType切换:月/年)
|
||||
calculateTimeStamp(selectDate) {
|
||||
let targetDate = selectDate || this.form.date;
|
||||
@@ -330,7 +445,6 @@ export default {
|
||||
this.form.endTime = endDatePrecise.getTime();
|
||||
}
|
||||
},
|
||||
|
||||
// 日期选择器变更事件(统一处理月/年变更)
|
||||
handleDateChange(val) {
|
||||
if (!val) {
|
||||
@@ -342,61 +456,65 @@ export default {
|
||||
// 计算选中日期对应的时间戳
|
||||
this.calculateTimeStamp(val);
|
||||
},
|
||||
getUnitLabel(unitCode) {
|
||||
// 若字典为空或无匹配编码,返回原编码或空字符串
|
||||
if (!this.dictData || this.dictData.length === 0) {
|
||||
return unitCode || '';
|
||||
}
|
||||
// 查找匹配的字典项
|
||||
const matchItem = this.dictData.find(item => item.value == unitCode);
|
||||
// 返回匹配的label,无匹配则返回原unit编码
|
||||
return matchItem ? matchItem.label : (unitCode || '');
|
||||
// 导入
|
||||
importExcel() {
|
||||
this.upload.open = true
|
||||
},
|
||||
// 请求下拉数据和表格数据(使用动态切换的getDataList接口)
|
||||
getData() {
|
||||
if (!this.getDataList) {
|
||||
console.warn('当前时间维度异常,无法获取数据');
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 请求所属层级下拉数据
|
||||
getLevelStruc().then((res) => {
|
||||
console.log('所属层级数据:', res);
|
||||
this.levelLList = res.data || [];
|
||||
}).catch(err => {
|
||||
console.error('获取所属层级失败:', err);
|
||||
this.levelLList = [];
|
||||
});
|
||||
|
||||
// 2. 请求表格分页数据(使用动态接口)
|
||||
this.getDataList({
|
||||
levelId: this.form.levelId,
|
||||
startTime: this.form.startTime,
|
||||
endTime: this.form.endTime,
|
||||
pageSize: this.form.pageSize,
|
||||
pageNo: this.form.pageNo
|
||||
}).then((res) => {
|
||||
console.log('表格数据:', res);
|
||||
this.tableData = res.data.map(item => {
|
||||
// 新增unitLabel字段,存储匹配后的显示名称
|
||||
return {
|
||||
...item,
|
||||
unitLabel: this.getUnitLabel(item.unit)
|
||||
};
|
||||
});
|
||||
}).catch(err => {
|
||||
console.error('获取表格数据失败:', err);
|
||||
this.tableData = [];
|
||||
});
|
||||
// 文件上传中处理
|
||||
handleFileUploadProgress(file, fileList) {
|
||||
console.log('文件上传中:',file, fileList)
|
||||
this.upload.isUploading = true;
|
||||
this.upload.fileList = fileList;
|
||||
this.upload.currentFile = file.raw;
|
||||
},
|
||||
|
||||
// 查询按钮点击事件(可根据需求扩展逻辑)
|
||||
onSubmit() {
|
||||
// 清空原有表格数据,重新请求
|
||||
this.tableData = [];
|
||||
this.$nextTick(() => {
|
||||
this.getData();
|
||||
});
|
||||
handleFileSuccess() {},
|
||||
importTemplate() {},
|
||||
// 提交上传文件
|
||||
async submitFileForm() {
|
||||
try {
|
||||
if (!this.upload.currentFile) {
|
||||
return this.$message.error('请先选择要上传的文件!')
|
||||
}
|
||||
const formData = new FormData()
|
||||
formData.append('file', this.upload.currentFile) // 文件字段
|
||||
formData.append('timeDim', this.upload.timeDim) // 年月维度字段
|
||||
formData.append('reportDate', this.form.endTime) // 时间维度字段
|
||||
formData.append('levelId', this.form.levelId) // 层级维度字段
|
||||
const response = await axios({
|
||||
url: process.env.VUE_APP_BASE_API + '/admin-api/lb/index-target-month/import',
|
||||
method: 'post',
|
||||
data: formData,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
'Authorization': "Bearer " + getAccessToken(),
|
||||
'tenant-id': getTenantId(),
|
||||
},
|
||||
timeout: 30000
|
||||
})
|
||||
// 4. 处理响应结果
|
||||
if (response.data.code === 0) {
|
||||
this.$message.success('文件上传成功!')
|
||||
// 重置表单
|
||||
this.upload.fileList = []
|
||||
this.upload.timeDim = 2
|
||||
this.upload.currentFile = null
|
||||
this.upload.open = false
|
||||
this.upload.isUploading = false
|
||||
this.$refs.upload.clearFiles();
|
||||
this.getDataPage();
|
||||
this.$emit('updateLeft')
|
||||
} else {
|
||||
this.$message.error(`上传失败:${response.data.msg || '未知错误'}`)
|
||||
}
|
||||
} catch (error) {
|
||||
// 5. 异常处理
|
||||
console.error('文件上传出错:', error)
|
||||
this.$message.error('上传失败!')
|
||||
}
|
||||
},
|
||||
cancelBtn() {
|
||||
this.upload.open = false
|
||||
this.$refs.upload.clearFiles();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,15 @@
|
||||
|
||||
<!-- 右侧区域:全屏按钮 -->
|
||||
<div class="right-content">
|
||||
<el-dropdown trigger="click">
|
||||
<el-button type="text" class="logout-btn" :title="'退出'">
|
||||
<svg-icon style="color: #0B58FF;" icon-class="logout" />
|
||||
</el-button>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item @click.native='logout'>退出登录</el-dropdown-item>
|
||||
<el-dropdown-item @click.native='handleToggle'>切换账号</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<el-button type="text" class="return-btn" :title="'返回'" @click="handleReturn">
|
||||
<svg-icon style="color: #0B58FF;" icon-class="returnIcon" />
|
||||
</el-button>
|
||||
@@ -35,7 +44,7 @@
|
||||
|
||||
<script>
|
||||
import moment from 'moment'; // 引入moment
|
||||
|
||||
import {getPath} from "@/utils/ruoyi";
|
||||
export default {
|
||||
name: 'Header',
|
||||
props: {
|
||||
@@ -75,6 +84,18 @@ export default {
|
||||
handleReturn() {
|
||||
this.$router.go(-1);
|
||||
},
|
||||
async logout() {
|
||||
this.$modal.confirm('确定注销并退出系统吗?', '提示').then(() => {
|
||||
this.$store.dispatch('LogOut').then(() => {
|
||||
location.href = getPath('/index');
|
||||
})
|
||||
}).catch(() => {});
|
||||
},
|
||||
handleToggle() {
|
||||
this.$store.dispatch('LogOut').then(() => {
|
||||
location.href = getPath('/index');
|
||||
})
|
||||
},
|
||||
exportPDF() {
|
||||
this.$emit('exportPDF');
|
||||
},
|
||||
@@ -300,6 +321,7 @@ export default {
|
||||
margin-top: 12px;
|
||||
margin-right: 10px;
|
||||
gap: 21px;
|
||||
height: 35px;
|
||||
}
|
||||
|
||||
// .current-time {
|
||||
@@ -326,6 +348,7 @@ export default {
|
||||
color: #00fff0;
|
||||
font-size: 26px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.return-btn {
|
||||
@@ -336,6 +359,13 @@ export default {
|
||||
font-size: 26px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.logout-btn {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
font-size: 28px;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* 自定义下拉框样式(替换原有日期选择器样式) */
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div class="changeBase">
|
||||
<div class="base-item" @click="handleClick(index)" v-for="(item, index) in buttonList" :key="item"
|
||||
:style="{ zIndex: activeButton === index ? 10 : 1 }">
|
||||
<img :src="activeButton === index ? imgMap.bgBase[item] : imgMap.base[item]" :alt="`${item}基地`" :title="item">
|
||||
<div class="base-item" @click="handleClick(item.id)" v-for="(item) in buttonLevelList" :key="item.id"
|
||||
:style="{ zIndex: activeButton === item.id ? 10 : 1 }">
|
||||
<img :src="activeButton === item.id ? item.bgImg : item.img" :alt="`${item.name}基地`" :title="item.name">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -33,80 +33,69 @@ export default {
|
||||
props: {
|
||||
factory: {
|
||||
type: [String, Number],
|
||||
default: 5, // 新映射中“宜兴”对应序号7
|
||||
validator: (val) => [5, 2, 7, 3, 8, 9, 10].includes(val) // 校验序号范围(匹配新的baseNameToIndexMap)
|
||||
default: undefined,
|
||||
validator: (val) => [5, 2, 7, 3, 8, 9, 10, 6].includes(val) // 校验序号范围(匹配新的baseNameToIndexMap)
|
||||
}
|
||||
},
|
||||
// 计算属性(响应式,levelList变化时会自动更新)
|
||||
computed: {
|
||||
buttonLevelList() {
|
||||
// 核心:通过$store.getters获取定义的getter
|
||||
let arr = []
|
||||
this.$store.getters.levelList.forEach(item => {
|
||||
this.buttonList.forEach(item2 => {
|
||||
if (item2.id === item.id) {
|
||||
arr.push(item2)
|
||||
}
|
||||
})
|
||||
})
|
||||
this.activeButton = arr[0].id
|
||||
return arr
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeButton: 5, // 初始化默认选中索引2(对应buttonList中的“宜兴”)
|
||||
buttonList: ['合肥', '桐城', '宜兴', '自贡', '漳州', '洛阳', '秦皇岛', '宿迁'], // 匹配截图顺序
|
||||
imgMap: {
|
||||
base: {
|
||||
合肥: baseHefei,
|
||||
桐城: baseTongcheng,
|
||||
宜兴: baseYixing,
|
||||
自贡: baseZigong,
|
||||
漳州: baseZhangzhou,
|
||||
洛阳: baseLuoyang,
|
||||
秦皇岛: baseQinhuangdao,
|
||||
宿迁: baseSuqian
|
||||
},
|
||||
bgBase: {
|
||||
合肥: bgBaseHefei,
|
||||
桐城: bgBaseTongcheng,
|
||||
宜兴: bgBaseYixing,
|
||||
自贡: bgBaseZigong,
|
||||
漳州: bgBaseZhangzhou,
|
||||
洛阳: bgBaseLuoyang,
|
||||
秦皇岛: bgBaseQinhuangdao,
|
||||
宿迁: bgBaseSuqian
|
||||
}
|
||||
},
|
||||
baseNameToIndexMap: { // 新的名称→序号映射
|
||||
宜兴: 7,
|
||||
漳州: 8,
|
||||
自贡: 3,
|
||||
桐城: 2,
|
||||
洛阳: 9,
|
||||
合肥: 5,
|
||||
秦皇岛: 10, // 补充
|
||||
宿迁: 6 // 补充
|
||||
}
|
||||
activeButton: undefined,
|
||||
buttonList:[
|
||||
{id: 5, name: '合肥', img: baseHefei, bgImg: bgBaseHefei},
|
||||
{id: 2, name: '桐城', img: baseTongcheng, bgImg: bgBaseTongcheng},
|
||||
{id: 7, name: '宜兴', img: baseYixing, bgImg: bgBaseYixing},
|
||||
{id: 3, name: '自贡', img: baseZigong, bgImg: bgBaseZigong},
|
||||
{id: 8, name: '漳州', img: baseZhangzhou, bgImg: bgBaseZhangzhou},
|
||||
{id: 9, name: '洛阳', img: baseLuoyang, bgImg: bgBaseLuoyang},
|
||||
{id: 10, name: '秦皇岛', img: baseQinhuangdao, bgImg: bgBaseQinhuangdao},
|
||||
{id: 6, name: '宿迁', img: baseSuqian, bgImg: bgBaseSuqian}
|
||||
],
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
// 监听父组件传递的factory变化,同步本地选中索引
|
||||
factory: {
|
||||
handler(newVal) {
|
||||
// 根据新的baseNameToIndexMap,找到对应的基地名称
|
||||
const targetName = Object.keys(this.baseNameToIndexMap).find(name => this.baseNameToIndexMap[name] === newVal);
|
||||
// 根据名称找到buttonList中的索引
|
||||
const targetIndex = this.buttonList.indexOf(targetName);
|
||||
// 合法索引则更新,否则默认选中宜兴
|
||||
this.activeButton = targetIndex > -1 ? targetIndex : 2;
|
||||
console.log('当前选中基地:', this.buttonList[this.activeButton], '序号:', newVal);
|
||||
console.log('watch factory=======================:', newVal);
|
||||
if (newVal) {
|
||||
this.activeButton = newVal;
|
||||
}
|
||||
// // 根据新的baseNameToIndexMap,找到对应的基地名称
|
||||
// const targetName = Object.keys(this.baseNameToIndexMap).find(name => this.baseNameToIndexMap[name] === newVal);
|
||||
// // 根据名称找到buttonList中的索引
|
||||
// const targetIndex = this.buttonList.indexOf(targetName);
|
||||
// // 合法索引则更新,否则默认选中宜兴
|
||||
// this.activeButton = targetIndex > -1 ? targetIndex : 2;
|
||||
// console.log('当前选中基地:', this.buttonList[this.activeButton], '序号:', newVal);
|
||||
},
|
||||
immediate: true // 初始化立即执行
|
||||
},
|
||||
// 监听本地选中索引变化,向父组件发送事件
|
||||
activeButton(newVal) {
|
||||
const selectedName = this.buttonList[newVal];
|
||||
const selectedIndex = this.baseNameToIndexMap[selectedName] || 5; // 默认返回宜兴的序号7
|
||||
this.$emit('baseChange', selectedIndex);
|
||||
// immediate: true // 初始化立即执行
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClick(index) {
|
||||
this.activeButton = index;
|
||||
},
|
||||
getIndexByName(name) {
|
||||
return this.baseNameToIndexMap[name] || 5;
|
||||
handleClick(id) {
|
||||
this.activeButton = id;
|
||||
this.$emit('baseChange', id);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 初始化时触发事件,传递默认选中的宜兴序号(7)
|
||||
this.$emit('baseChange', 5);
|
||||
// this.$emit('baseChange', 5);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -84,7 +84,7 @@ export default {
|
||||
|
||||
return dataMap.map(itemInfo => {
|
||||
const rawItem = rawData[itemInfo.key] || {};
|
||||
const progress = Math.max(0, Math.round((rawItem.rate || 0)));
|
||||
const progress = rawItem.rate || 0;
|
||||
|
||||
return {
|
||||
unit: itemInfo.unit,
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<div class="monthItem" :class="{
|
||||
'has-data': month.haveData,
|
||||
'current': index === currentMonthIndex // 本月匹配current样式
|
||||
}" v-for="(month, index) in monthList" :key="index">
|
||||
}" v-for="(month, index) in list" :key="index">
|
||||
{{ month.name }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -41,21 +41,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
chart: null,
|
||||
// 初始化12个月的列表,可根据实际需求修改haveData默认值
|
||||
monthList: [
|
||||
{ name: '1月', haveData: false, isActive: false },
|
||||
{ name: '2月', haveData: false, isActive: false },
|
||||
{ name: '3月', haveData: false, isActive: false },
|
||||
{ name: '4月', haveData: false, isActive: false },
|
||||
{ name: '5月', haveData: false, isActive: false },
|
||||
{ name: '6月', haveData: false, isActive: false },
|
||||
{ name: '7月', haveData: false, isActive: false },
|
||||
{ name: '8月', haveData: false, isActive: false },
|
||||
{ name: '9月', haveData: false, isActive: false },
|
||||
{ name: '10月', haveData: false, isActive: false },
|
||||
{ name: '11月', haveData: false, isActive: false },
|
||||
{ name: '12月', haveData: false, isActive: false }
|
||||
],
|
||||
list:[]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -83,19 +69,15 @@ export default {
|
||||
// 根据calendarList更新monthList的haveData状态
|
||||
updateMonthHaveData(calendarObj) {
|
||||
if (!calendarObj || typeof calendarObj !== 'object') return;
|
||||
|
||||
// 遍历12个月,匹配对应年月
|
||||
this.monthList.forEach((month, index) => {
|
||||
// 获取月份数字(索引+1,补两位,如1→01,10→10)
|
||||
const monthNum = (index + 1).toString().padStart(2, '0');
|
||||
// 拼接成calendarList中的键格式(如2025-01)
|
||||
const yearMonthKey = `2025-${monthNum}`; // 若年份不固定,可改为props传递年份
|
||||
|
||||
// 判断calendarObj中该键对应的值:1→true,0→false,无该键则保持默认false
|
||||
if (calendarObj.hasOwnProperty(yearMonthKey)) {
|
||||
month.haveData = calendarObj[yearMonthKey] === 1;
|
||||
}
|
||||
});
|
||||
const keys = Object.keys(calendarObj);
|
||||
if(keys.length == 0){
|
||||
return
|
||||
}
|
||||
console.log('calendarObj',calendarObj)
|
||||
this.list = []
|
||||
for(let i = 0; i < keys.length; i++) {
|
||||
this.list.push({name:i+1+'月',haveData:calendarObj[keys[i]],isActive:i==new Date().getMonth()})
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<div style="width: 4px;height: 16px;background: #0B58FF;border-radius: 1px;margin-top: 10px;"></div>
|
||||
<el-form :inline="true" :model="form" class="demo-form-inline">
|
||||
<el-form-item label="所属层级">
|
||||
<el-select v-model="form.levelId" placeholder="请选择">
|
||||
<el-select v-model="form.levelId" placeholder="请选择" @change='handleLevelChange'>
|
||||
<el-option v-for="item in levelLList" :key="item.id" :label="item.name" :value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
@@ -20,7 +20,7 @@
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button style="background-color: #0B58FF;" type="primary" @click="onSubmit">查询</el-button>
|
||||
<!-- <el-button type="primary" plain size="medium">导入</el-button> -->
|
||||
<el-button type="primary" plain size="medium" @click='importExcel'>导入</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
@@ -64,6 +64,22 @@ font-style: normal;">指标详情</div>
|
||||
></base-table>
|
||||
</div>
|
||||
</div>
|
||||
<el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
|
||||
<el-upload ref="upload" :limit="1" accept=".xlsx, .xls" action="#" :disabled="upload.isUploading"
|
||||
:on-change="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||
<div class="el-upload__tip text-center" slot="tip">
|
||||
<span>仅允许导入xls、xlsx格式文件。</span>
|
||||
</div>
|
||||
<div class="el-upload__tip" slot="tip">
|
||||
</div>
|
||||
</el-upload>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitFileForm">确 定</el-button>
|
||||
<el-button @click="cancelBtn">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</Container>
|
||||
</div>
|
||||
</template>
|
||||
@@ -72,7 +88,8 @@ font-style: normal;">指标详情</div>
|
||||
import Container from './container.vue'
|
||||
import { getLevelStruc, getRealMonthPage, updateRealMonthData, getDictListData, } from '@/api/cockpit'
|
||||
import inputArea from './inputArea.vue' // 导入输入组件
|
||||
|
||||
import {getAccessToken, getTenantId} from '@/utils/auth'
|
||||
import axios from 'axios';
|
||||
export default {
|
||||
name: 'ProductionStatus',
|
||||
components: {
|
||||
@@ -85,7 +102,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
levelId: 1,
|
||||
levelId: undefined,
|
||||
pageNo: 1,
|
||||
pageSize: 100,
|
||||
month: undefined,
|
||||
@@ -96,7 +113,17 @@ export default {
|
||||
isDetail: false, // 编辑状态标识:false=只读,true=编辑
|
||||
tableData: [], // 表格数据
|
||||
levelLList: [], // 所属层级下拉数据
|
||||
tableProps: [] // 表格列配置
|
||||
tableProps: [], // 表格列配置
|
||||
upload: {
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 弹出层标题
|
||||
title: "指标填报导入",
|
||||
// 是否禁用上传
|
||||
isUploading: false,
|
||||
fileList:[],
|
||||
currentFile:null
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -142,7 +169,7 @@ export default {
|
||||
|
||||
// 基础表格列配置(只读模式使用)
|
||||
const baseTableProps = [
|
||||
{ prop: 'type', label: '指标类型', align: 'center' },
|
||||
// { prop: 'type', label: '指标类型', align: 'center' },
|
||||
{ prop: 'name', label: '指标名称', align: 'center' },
|
||||
{ prop: 'unitLabel', label: '单位', align: 'center' },
|
||||
{ prop: 'value', label: '实际值', align: 'center' },
|
||||
@@ -187,9 +214,10 @@ export default {
|
||||
// 清空并重新请求数据,恢复原始状态
|
||||
this.$nextTick(() => {
|
||||
this.tableData = [];
|
||||
this.getData();
|
||||
this.getDataPage();
|
||||
});
|
||||
this.$modal.msgSuccess("保存成功");
|
||||
this.$emit('updateLeft')
|
||||
}).catch(() => { });
|
||||
},
|
||||
// 取消编辑,恢复只读模式
|
||||
@@ -200,7 +228,7 @@ export default {
|
||||
// 清空并重新请求数据,恢复原始状态
|
||||
this.$nextTick(() => {
|
||||
this.tableData = [];
|
||||
this.getData();
|
||||
this.getDataPage();
|
||||
});
|
||||
console.log('已取消编辑,恢复原始数据');
|
||||
},
|
||||
@@ -211,7 +239,7 @@ export default {
|
||||
// 清空并重新请求数据,恢复原始状态
|
||||
this.$nextTick(() => {
|
||||
this.tableData = [];
|
||||
this.getData();
|
||||
this.getDataPage();
|
||||
});
|
||||
},
|
||||
|
||||
@@ -261,13 +289,17 @@ export default {
|
||||
getData() {
|
||||
// 1. 请求所属层级下拉数据
|
||||
getLevelStruc().then((res) => {
|
||||
console.log('所属层级数据:', res);
|
||||
this.levelLList = res.data || [];
|
||||
this.form.levelId = this.levelLList[0].id;
|
||||
this.$emit('updateLevel', this.levelLList[0].id)
|
||||
this.getDataPage()
|
||||
}).catch(err => {
|
||||
console.error('获取所属层级失败:', err);
|
||||
this.levelLList = [];
|
||||
});
|
||||
|
||||
this.$emit('updateLeft')
|
||||
},
|
||||
getDataPage() {
|
||||
// 2. 请求表格分页数据
|
||||
getRealMonthPage({
|
||||
levelId: this.form.levelId,
|
||||
@@ -288,6 +320,10 @@ export default {
|
||||
console.error('获取表格数据失败:', err);
|
||||
this.tableData = [];
|
||||
});
|
||||
|
||||
},
|
||||
handleLevelChange(id) {
|
||||
this.$emit('updateLevel', id)
|
||||
},
|
||||
|
||||
// 查询按钮点击事件(可根据需求扩展逻辑)
|
||||
@@ -295,8 +331,66 @@ export default {
|
||||
// 清空原有表格数据,重新请求
|
||||
this.tableData = [];
|
||||
this.$nextTick(() => {
|
||||
this.getData();
|
||||
this.getDataPage();
|
||||
});
|
||||
},
|
||||
// 导入
|
||||
importExcel() {
|
||||
this.upload.open = true
|
||||
},
|
||||
// 文件上传中处理
|
||||
handleFileUploadProgress(file, fileList) {
|
||||
console.log('文件上传中:',file, fileList)
|
||||
this.upload.isUploading = true;
|
||||
this.upload.fileList = fileList;
|
||||
this.upload.currentFile = file.raw;
|
||||
},
|
||||
handleFileSuccess() {},
|
||||
importTemplate() {},
|
||||
// 提交上传文件
|
||||
async submitFileForm() {
|
||||
try {
|
||||
if (!this.upload.currentFile) {
|
||||
return this.$message.error('请先选择要上传的文件!')
|
||||
}
|
||||
const formData = new FormData()
|
||||
formData.append('file', this.upload.currentFile) // 文件字段
|
||||
formData.append('reportDate', this.form.endTime) // 时间维度字段
|
||||
formData.append('levelId', this.form.levelId) // 层级维度字段
|
||||
const response = await axios({
|
||||
url: process.env.VUE_APP_BASE_API + '/admin-api/lb/index-real-month/actualIndicatorImport',
|
||||
method: 'post',
|
||||
data: formData,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
'Authorization': "Bearer " + getAccessToken(),
|
||||
'tenant-id': getTenantId(),
|
||||
},
|
||||
timeout: 30000
|
||||
})
|
||||
// 4. 处理响应结果
|
||||
if (response.data.code === 0) {
|
||||
this.$message.success('文件上传成功!')
|
||||
// 重置表单
|
||||
this.upload.fileList = []
|
||||
this.upload.currentFile = null
|
||||
this.upload.open = false
|
||||
this.upload.isUploading = false
|
||||
this.$refs.upload.clearFiles();
|
||||
this.getDataPage();
|
||||
this.$emit('updateLeft')
|
||||
} else {
|
||||
this.$message.error(`上传失败:${response.data.msg || '未知错误'}`)
|
||||
}
|
||||
} catch (error) {
|
||||
// 5. 异常处理
|
||||
console.error('文件上传出错:', error)
|
||||
this.$message.error('上传失败!')
|
||||
}
|
||||
},
|
||||
cancelBtn(){
|
||||
this.upload.open = false
|
||||
this.$refs.upload.clearFiles();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,15 @@
|
||||
|
||||
<!-- 右侧区域:全屏按钮 -->
|
||||
<div class="right-content">
|
||||
<el-dropdown trigger="click">
|
||||
<el-button type="text" class="logout-btn" :title="'退出'">
|
||||
<svg-icon style="color: #0B58FF;" icon-class="logout" />
|
||||
</el-button>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item @click.native='logout'>退出登录</el-dropdown-item>
|
||||
<el-dropdown-item @click.native='handleToggle'>切换账号</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<el-button type="text" class="return-btn" :title="'返回'" @click="handleReturn">
|
||||
<svg-icon style="color: #0B58FF;" icon-class="returnIcon" />
|
||||
</el-button>
|
||||
@@ -31,7 +40,7 @@
|
||||
|
||||
<script>
|
||||
import moment from 'moment'; // 引入moment
|
||||
|
||||
import {getPath} from "@/utils/ruoyi";
|
||||
export default {
|
||||
name: 'Header',
|
||||
props: {
|
||||
@@ -100,6 +109,18 @@ export default {
|
||||
this.$router.go(-1);
|
||||
}
|
||||
},
|
||||
async logout() {
|
||||
this.$modal.confirm('确定注销并退出系统吗?', '提示').then(() => {
|
||||
this.$store.dispatch('LogOut').then(() => {
|
||||
location.href = getPath('/index');
|
||||
})
|
||||
}).catch(() => {});
|
||||
},
|
||||
handleToggle() {
|
||||
this.$store.dispatch('LogOut').then(() => {
|
||||
location.href = getPath('/index');
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 计算时间范围(时间戳格式)
|
||||
* 固定为月维度:当月1日00:00:00 → 当月最后一天23:59:59
|
||||
@@ -297,6 +318,7 @@ export default {
|
||||
margin-top: 12px;
|
||||
margin-right: 10px;
|
||||
gap: 21px;
|
||||
height: 35px;
|
||||
}
|
||||
|
||||
.screen-btn {
|
||||
@@ -305,6 +327,7 @@ export default {
|
||||
color: #00fff0;
|
||||
font-size: 26px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.home-btn {
|
||||
@@ -322,6 +345,14 @@ export default {
|
||||
font-size: 26px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.logout-btn {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
font-size: 28px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* 日期选择器自定义样式 */
|
||||
|
||||
@@ -99,7 +99,7 @@ export default {
|
||||
grid: {
|
||||
top: 35,
|
||||
bottom: 20,
|
||||
right: 25,
|
||||
right: 13,
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
@@ -222,11 +222,11 @@ export default {
|
||||
/* (你的样式代码保持不变) */
|
||||
.legend {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: -5px;
|
||||
right: 12px;
|
||||
top: 0px;
|
||||
display: flex;
|
||||
/* 使用 flex 布局让两个图例项并排且对齐 */
|
||||
gap: 20px;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.legend-item-line {
|
||||
@@ -237,7 +237,7 @@ export default {
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
position: relative;
|
||||
padding-left: 20px;
|
||||
padding-left: 24px;
|
||||
/* 为圆点和线条留出空间 */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -121,7 +121,7 @@ export default {
|
||||
|
||||
.lineFour {
|
||||
top: 5px;
|
||||
left: 268px;
|
||||
left: 252px;
|
||||
}
|
||||
|
||||
.item-button {
|
||||
|
||||
@@ -89,7 +89,7 @@ export default {
|
||||
unit: mappingItem.unit,
|
||||
targetValue: indicatorData.target, // 目标值
|
||||
currentValue: indicatorData.real, // 实际值
|
||||
progress: indicatorData.rate ? Math.round(indicatorData.rate) : 0, // 完成率(百分比,四舍五入)
|
||||
progress: indicatorData.rate || 0, // 完成率
|
||||
path: mappingItem.path // 路由路径
|
||||
};
|
||||
});
|
||||
|
||||
@@ -71,7 +71,7 @@ export default {
|
||||
// 定义一个映射关系,将后端字段名与前端显示信息关联起来
|
||||
const dataMap = [
|
||||
{
|
||||
key: 'processCost',
|
||||
key: 'totalCost',
|
||||
unit: '制造成本·元/㎡',
|
||||
route: '/productionCostAnalysis/productionCostAnalysis'
|
||||
},
|
||||
@@ -101,7 +101,7 @@ export default {
|
||||
return dataMap.map(itemInfo => {
|
||||
const rawItem = rawData[itemInfo.key] || {};
|
||||
// 计算进度百分比,确保不小于0
|
||||
const progress = Math.max(0, Math.round((rawItem.rate || 0)));
|
||||
const progress = rawItem.rate || 0;
|
||||
|
||||
return {
|
||||
unit: itemInfo.unit,
|
||||
|
||||
@@ -27,7 +27,7 @@ export default {
|
||||
chart: null,
|
||||
// 固定3条默认数据,作为展示模板
|
||||
parentItemList: [
|
||||
{ name: "总制造成本", targetValue: 0, value: 0, proportion: 0, flag: 0 },
|
||||
{ name: "制造成本", targetValue: 0, value: 0, proportion: 0, flag: 0 },
|
||||
{ name: "原片成本", targetValue: 0, value: 0, proportion: 0, flag: 0 },
|
||||
{ name: "加工成本", targetValue: 0, value: 0, proportion: 0, flag: 0 },
|
||||
]
|
||||
|
||||
@@ -114,6 +114,7 @@ export default {
|
||||
monthAnalysis: [],
|
||||
ytdAnalysis: [],
|
||||
trend: [],
|
||||
factory:null
|
||||
};
|
||||
},
|
||||
|
||||
@@ -185,7 +186,13 @@ export default {
|
||||
this.beilv = _this.clientWidth / 1920;
|
||||
})();
|
||||
};
|
||||
this.factory = this.$route.query.factory ? Number(this.$route.query.factory) : 5
|
||||
if(this.$route.query.factory){
|
||||
this.factory =Number(this.$route.query.factory)
|
||||
}else if(this.$store.getters.levelList.length > 0 && this.$store.getters.levelList[0].id !== 1) {
|
||||
this.factory = this.$store.getters.levelList[0].id
|
||||
}else{
|
||||
this.factory = this.$store.getters.levelList[1].id
|
||||
}
|
||||
this.dateData = this.$route.query.dateData ? this.$route.query.dateData : undefined
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -61,7 +61,7 @@ export default {
|
||||
return {
|
||||
activeButton: 0,
|
||||
isDropdownShow: false,
|
||||
selectedProfit: null, // 选中的名称,初始为null
|
||||
selectedProfit: '总费用', // 选中的名称,初始为null
|
||||
profitOptions: [
|
||||
'总费用',
|
||||
'管理费用',
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div :id="id" style="width: 100%; height:100%;"></div>
|
||||
<div class="bottomTip">
|
||||
<div class="precent">
|
||||
<span class="precentNum">{{ detailData.rate || 0 }} </span>
|
||||
<span class="precentNum">{{ detailData.rate || 0 }}% </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -125,7 +125,7 @@ export default {
|
||||
width: 264px;
|
||||
height: 205px;
|
||||
background: #F9FCFF;
|
||||
padding: 16px 0 0 16px;
|
||||
padding: 16px 0 0 10px;
|
||||
|
||||
.title {
|
||||
// width: 190px;
|
||||
@@ -144,7 +144,7 @@ export default {
|
||||
.number {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 30px;
|
||||
gap: 6px;
|
||||
// width: 190px;
|
||||
height: 32px;
|
||||
font-family: YouSheBiaoTiHei;
|
||||
@@ -154,6 +154,7 @@ export default {
|
||||
letter-spacing: 2px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mom {
|
||||
@@ -167,6 +168,7 @@ export default {
|
||||
letter-spacing: 1px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ getRateFlag(rate, real, target) {
|
||||
max-width: 300px; // 最大宽度,限制过宽
|
||||
height: 205px;
|
||||
background: #F9FCFF;
|
||||
padding: 16px 16px 0;
|
||||
padding: 16px 0 0 10px;
|
||||
margin: 0 4px;
|
||||
|
||||
.title {
|
||||
@@ -201,6 +201,7 @@ getRateFlag(rate, real, target) {
|
||||
line-height: 18px;
|
||||
letter-spacing: 1px;
|
||||
text-align: left;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -57,8 +57,8 @@ export default {
|
||||
return {
|
||||
activeButton: 0,
|
||||
isDropdownShow: false,
|
||||
selectedSort: null, // 选中的label
|
||||
selectedSortValue: null, // 选中的value,用于排序逻辑
|
||||
selectedSort: '实际值:高~低', // 选中的label
|
||||
selectedSortValue: 1, // 选中的value,用于排序逻辑
|
||||
profitOptions: [
|
||||
{ label: '实际值:高~低', value: 1 },
|
||||
{ label: '实际值:低~高', value: 2 },
|
||||
|
||||
@@ -89,7 +89,9 @@ export default {
|
||||
const baseIndex = this.baseNameToIndexMap[itemName] || 0;
|
||||
|
||||
console.log(`你点击了【${itemName}】(序号:${baseIndex})`);
|
||||
|
||||
if (itemName === undefined) {
|
||||
return;
|
||||
}
|
||||
this.$router.push({
|
||||
path: 'expenseAnalysisBase',
|
||||
query: { // 使用query传递参数(推荐),也可使用params
|
||||
|
||||
@@ -85,9 +85,10 @@ export default {
|
||||
},
|
||||
grid: {
|
||||
top: 30,
|
||||
bottom: 30,
|
||||
right: 20,
|
||||
left: 60,
|
||||
bottom: 5,
|
||||
right: 10,
|
||||
left: 25,
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
|
||||
@@ -84,10 +84,11 @@ export default {
|
||||
// }
|
||||
},
|
||||
grid: {
|
||||
top: 30,
|
||||
bottom: 50,
|
||||
right: 20,
|
||||
left: 40,
|
||||
top: 25,
|
||||
bottom: 30,
|
||||
right: 0,
|
||||
left: 2,
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
|
||||
@@ -95,7 +95,7 @@ export default {
|
||||
if (rate >= 100) return 1;
|
||||
|
||||
// 2. 完成率 = 0 且 (目标值=0 或 实际值=目标值=0) => 达标
|
||||
if (rate === 0 && target === 0) return 1;
|
||||
if (real <= target) return 1;
|
||||
|
||||
// 其他情况 => 未达标
|
||||
return 0;
|
||||
|
||||
@@ -90,7 +90,7 @@ export default {
|
||||
if (rate >= 100) return 1;
|
||||
|
||||
// 2. 完成率 = 0 且 (目标值=0 或 实际值=目标值=0) => 达标
|
||||
if (rate === 0 && target === 0) return 1;
|
||||
if (real <= target) return 1;
|
||||
|
||||
// 其他情况 => 未达标
|
||||
return 0;
|
||||
|
||||
@@ -125,7 +125,7 @@ export default {
|
||||
width: 264px;
|
||||
height: 205px;
|
||||
background: #F9FCFF;
|
||||
padding: 16px 0 0 16px;
|
||||
padding: 16px 0 0 10px;
|
||||
|
||||
.title {
|
||||
// width: 190px;
|
||||
@@ -167,6 +167,7 @@ export default {
|
||||
letter-spacing: 1px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ getRateFlag(rate, real, target) {
|
||||
grid: {
|
||||
top: 10,
|
||||
bottom: 30,
|
||||
right: 50,
|
||||
right: 80,
|
||||
left: 30,
|
||||
containLabel: true,
|
||||
show: false // 隐藏grid背景,避免干扰
|
||||
|
||||
@@ -158,7 +158,7 @@ getRateFlag(rate, real, target) {
|
||||
max-width: 300px; // 最大宽度,限制过宽
|
||||
height: 205px;
|
||||
background: #F9FCFF;
|
||||
padding: 16px 16px 0;
|
||||
padding: 16px 0 0 10px;
|
||||
margin: 0 4px;
|
||||
|
||||
.title {
|
||||
@@ -202,6 +202,7 @@ getRateFlag(rate, real, target) {
|
||||
line-height: 18px;
|
||||
letter-spacing: 1px;
|
||||
text-align: left;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -102,7 +102,7 @@ export default {
|
||||
beilv: 1,
|
||||
month: '',
|
||||
value: 100,
|
||||
factory: 5,
|
||||
factory: null,
|
||||
dateData: {},
|
||||
monData: {},
|
||||
totalData: {},
|
||||
@@ -174,7 +174,13 @@ export default {
|
||||
this.beilv = _this.clientWidth / 1920;
|
||||
})();
|
||||
};
|
||||
this.factory = this.$route.query.factory ? Number(this.$route.query.factory) : 5
|
||||
if(this.$route.query.factory){
|
||||
this.factory =Number(this.$route.query.factory)
|
||||
}else if(this.$store.getters.levelList.length > 0 && this.$store.getters.levelList[0].id !== 1) {
|
||||
this.factory = this.$store.getters.levelList[0].id
|
||||
}else{
|
||||
this.factory = this.$store.getters.levelList[1].id
|
||||
}
|
||||
this.dateData = this.$route.query.dateData ? this.$route.query.dateData : undefined
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div :id="id" style="width: 100%; height:100%;"></div>
|
||||
<div class="bottomTip">
|
||||
<div class="precent">
|
||||
<span class="precentNum">{{ detailData.completeRate || 0 }} </span>
|
||||
<span class="precentNum">{{ detailData.completeRate || 0 }}% </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -142,7 +142,7 @@ getRateFlag(rate, real, target) {
|
||||
width: 264px;
|
||||
height: 205px;
|
||||
background: #F9FCFF;
|
||||
padding: 16px 0 0 16px;
|
||||
padding: 16px 0 0 10px;
|
||||
|
||||
.title {
|
||||
height: 18px;
|
||||
@@ -157,13 +157,14 @@ getRateFlag(rate, real, target) {
|
||||
.number {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 30px;
|
||||
gap: 6px;
|
||||
height: 32px;
|
||||
font-family: YouSheBiaoTiHei;
|
||||
font-size: 32px;
|
||||
color: #0B58FF;
|
||||
line-height: 32px;
|
||||
letter-spacing: 2px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mom {
|
||||
@@ -178,6 +179,7 @@ getRateFlag(rate, real, target) {
|
||||
display: flex;
|
||||
align-items: center; // 箭头和文字垂直居中
|
||||
gap: 4px; // 文字和箭头间距
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
// 箭头样式优化
|
||||
|
||||
@@ -118,7 +118,7 @@ export default {
|
||||
width: 382px;
|
||||
height: 205px;
|
||||
background: #F9FCFF;
|
||||
padding: 16px 0 0 16px;
|
||||
padding: 16px 0 0 10px;
|
||||
|
||||
.title {
|
||||
// width: 190px;
|
||||
@@ -137,7 +137,7 @@ export default {
|
||||
.number {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 30px;
|
||||
gap: 6px;
|
||||
// width: 190px;
|
||||
height: 32px;
|
||||
font-family: YouSheBiaoTiHei;
|
||||
@@ -147,10 +147,11 @@ export default {
|
||||
letter-spacing: 2px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mom {
|
||||
width: 97px;
|
||||
width: 120px;
|
||||
height: 18px;
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
@@ -160,6 +161,7 @@ export default {
|
||||
letter-spacing: 1px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,8 +57,8 @@ export default {
|
||||
return {
|
||||
activeButton: 0,
|
||||
isDropdownShow: false,
|
||||
selectedSort: null, // 选中的label
|
||||
selectedSortValue: null, // 选中的value,用于排序逻辑
|
||||
selectedSort: '实际值:高~低', // 选中的label
|
||||
selectedSortValue: 1, // 选中的value,用于排序逻辑
|
||||
profitOptions: [
|
||||
{ label: '实际值:高~低', value: 1 },
|
||||
{ label: '实际值:低~高', value: 2 },
|
||||
|
||||
@@ -91,7 +91,9 @@ export default {
|
||||
const baseIndex = this.baseNameToIndexMap[itemName] || 0;
|
||||
|
||||
console.log(`你点击了【${itemName}】(序号:${baseIndex})`);
|
||||
|
||||
if (itemName === undefined) {
|
||||
return;
|
||||
}
|
||||
// 路由跳转时携带序号(或名称+序号)
|
||||
this.$router.push({
|
||||
path: 'fullCostAnalysisBase',
|
||||
|
||||
@@ -85,9 +85,10 @@ export default {
|
||||
},
|
||||
grid: {
|
||||
top: 30,
|
||||
bottom: 30,
|
||||
right: 20,
|
||||
left: 60,
|
||||
bottom: 5,
|
||||
right: 10,
|
||||
left: 25,
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
|
||||
@@ -83,11 +83,12 @@ export default {
|
||||
// return html;
|
||||
// }
|
||||
},
|
||||
grid: {
|
||||
top: 30,
|
||||
bottom: 60,
|
||||
right: 30,
|
||||
left: 50,
|
||||
grid: {
|
||||
top: 25,
|
||||
bottom: 20,
|
||||
right: 10,
|
||||
left: 2,
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
|
||||
@@ -88,8 +88,8 @@ getRateFlag(rate, real, target) {
|
||||
// 1. 完成率 >= 100 => 达标
|
||||
if (rate >= 100) return 1;
|
||||
|
||||
// 2. 完成率 = 0 且 (目标值=0 或 实际值=目标值=0) => 达标
|
||||
if (rate === 0 && target === 0) return 1;
|
||||
// 2. 实际小于等于目标) => 达标
|
||||
if (real <= target) return 1;
|
||||
|
||||
// 其他情况 => 未达标
|
||||
return 0;
|
||||
|
||||
@@ -163,7 +163,7 @@ export default {
|
||||
|
||||
// const flags = flags || [];
|
||||
const currentDiff = diff || 0;
|
||||
const currentFlag = flags[0] || 0;
|
||||
const currentFlag = data?.flags[0] || 0;
|
||||
// const prefix = currentFlag === 1 ? '+' : '';
|
||||
// 根据标志位选择不同的样式类
|
||||
if (currentFlag === 1) {
|
||||
|
||||
@@ -202,8 +202,7 @@ getRateFlag(rate, real, target) {
|
||||
width: 310px;
|
||||
height: 205px;
|
||||
background: #F9FCFF;
|
||||
padding: 16px 0 0 16px;
|
||||
|
||||
padding: 16px 0 0 10px;
|
||||
.title {
|
||||
// width: 190px;
|
||||
height: 18px;
|
||||
@@ -221,7 +220,7 @@ getRateFlag(rate, real, target) {
|
||||
.number {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 30px;
|
||||
gap: 6px;
|
||||
// width: 190px;
|
||||
height: 32px;
|
||||
font-family: YouSheBiaoTiHei;
|
||||
@@ -231,10 +230,11 @@ getRateFlag(rate, real, target) {
|
||||
letter-spacing: 2px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mom {
|
||||
width: 97px;
|
||||
width: 120px;
|
||||
height: 18px;
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
@@ -244,6 +244,7 @@ getRateFlag(rate, real, target) {
|
||||
letter-spacing: 1px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ getRateFlag(rate, real, target) {
|
||||
width: 264px;
|
||||
height: 205px;
|
||||
background: #F9FCFF;
|
||||
padding: 16px 0 0 16px;
|
||||
padding: 16px 0 0 10px;
|
||||
|
||||
.title {
|
||||
// width: 190px;
|
||||
@@ -172,7 +172,7 @@ getRateFlag(rate, real, target) {
|
||||
.number {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 30px;
|
||||
gap: 6px;
|
||||
// width: 190px;
|
||||
height: 32px;
|
||||
font-family: YouSheBiaoTiHei;
|
||||
@@ -182,6 +182,7 @@ getRateFlag(rate, real, target) {
|
||||
letter-spacing: 2px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mom {
|
||||
@@ -195,6 +196,7 @@ getRateFlag(rate, real, target) {
|
||||
letter-spacing: 1px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ export default {
|
||||
grid: {
|
||||
top: 10,
|
||||
bottom: 30,
|
||||
right: 50,
|
||||
right: 80,
|
||||
left: 30,
|
||||
containLabel: true,
|
||||
show: false
|
||||
|
||||
@@ -118,8 +118,7 @@ export default {
|
||||
width: 382px;
|
||||
height: 205px;
|
||||
background: #F9FCFF;
|
||||
padding: 16px 0 0 16px;
|
||||
|
||||
padding: 16px 0 0 10px;
|
||||
.title {
|
||||
// width: 190px;
|
||||
height: 18px;
|
||||
@@ -137,7 +136,7 @@ export default {
|
||||
.number {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 30px;
|
||||
gap: 6px;
|
||||
// width: 190px;
|
||||
height: 32px;
|
||||
font-family: YouSheBiaoTiHei;
|
||||
@@ -147,10 +146,11 @@ export default {
|
||||
letter-spacing: 2px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mom {
|
||||
width: 97px;
|
||||
width: 120px;
|
||||
height: 18px;
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
@@ -160,6 +160,7 @@ export default {
|
||||
letter-spacing: 1px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ export default {
|
||||
dateData:{},
|
||||
levelId:undefined,
|
||||
index: '毛利率',
|
||||
factory: 1,
|
||||
factory: null,
|
||||
monthData: {},
|
||||
ytdData: {},
|
||||
monthAnalysis: [],
|
||||
@@ -188,7 +188,13 @@ export default {
|
||||
this.beilv = _this.clientWidth / 1920;
|
||||
})();
|
||||
};
|
||||
this.factory = this.$route.query.factory ? Number(this.$route.query.factory) : 5
|
||||
if(this.$route.query.factory){
|
||||
this.factory =Number(this.$route.query.factory)
|
||||
}else if(this.$store.getters.levelList.length > 0 && this.$store.getters.levelList[0].id !== 1) {
|
||||
this.factory = this.$store.getters.levelList[0].id
|
||||
}else{
|
||||
this.factory = this.$store.getters.levelList[1].id
|
||||
}
|
||||
this.dateData = this.$route.query.dateData ? this.$route.query.dateData : undefined
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -61,7 +61,7 @@ export default {
|
||||
return {
|
||||
activeButton: 0,
|
||||
isDropdownShow: false,
|
||||
selectedProfit: null, // 选中的名称,初始为null
|
||||
selectedProfit: '毛利率', // 选中的名称,初始为null
|
||||
profitOptions: [
|
||||
'毛利率',
|
||||
'营业收入',
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div :id="id" style="width: 100%; height:100%;"></div>
|
||||
<div class="bottomTip">
|
||||
<div class="precent">
|
||||
<span class="precentNum">{{ detailData.rate || 0 }} </span>
|
||||
<span class="precentNum">{{ detailData.rate || 0 }}% </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -126,7 +126,7 @@ export default {
|
||||
width: 264px;
|
||||
height: 205px;
|
||||
background: #F9FCFF;
|
||||
padding: 16px 0 0 16px;
|
||||
padding: 16px 0 0 10px;
|
||||
|
||||
.title {
|
||||
// width: 190px;
|
||||
@@ -145,7 +145,7 @@ export default {
|
||||
.number {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 30px;
|
||||
gap: 6px;
|
||||
// width: 190px;
|
||||
height: 32px;
|
||||
font-family: YouSheBiaoTiHei;
|
||||
@@ -155,6 +155,7 @@ export default {
|
||||
letter-spacing: 2px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mom {
|
||||
@@ -168,6 +169,7 @@ export default {
|
||||
letter-spacing: 1px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ getRateFlag(rate, real, target) {
|
||||
min-width: 300px;
|
||||
height: 205px;
|
||||
background: #F9FCFF;
|
||||
padding: 16px 16px 0;
|
||||
padding: 16px 0 0 10px;
|
||||
margin: 0 4px;
|
||||
|
||||
.title {
|
||||
@@ -196,6 +196,7 @@ getRateFlag(rate, real, target) {
|
||||
line-height: 18px;
|
||||
letter-spacing: 1px;
|
||||
text-align: left;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,8 +57,8 @@ export default {
|
||||
return {
|
||||
activeButton: 0,
|
||||
isDropdownShow: false,
|
||||
selectedSort: null, // 选中的label
|
||||
selectedSortValue: null, // 选中的value,用于排序逻辑
|
||||
selectedSort: '实际值:高~低', // 选中的label
|
||||
selectedSortValue: 1, // 选中的value,用于排序逻辑
|
||||
profitOptions: [
|
||||
{ label: '实际值:高~低', value: 1 },
|
||||
{ label: '实际值:低~高', value: 2 },
|
||||
|
||||
@@ -102,7 +102,9 @@ export default {
|
||||
const baseIndex = this.baseNameToIndexMap[itemName] || 0;
|
||||
|
||||
console.log(`你点击了【${itemName}】(序号:${baseIndex})`);
|
||||
|
||||
if (itemName === undefined) {
|
||||
return;
|
||||
}
|
||||
// 路由跳转时携带序号(或名称+序号)
|
||||
this.$router.push({
|
||||
path: 'grossMarginBase',
|
||||
|
||||
@@ -85,9 +85,10 @@ export default {
|
||||
},
|
||||
grid: {
|
||||
top: 30,
|
||||
bottom: 30,
|
||||
right: 20,
|
||||
left: 60,
|
||||
bottom: 5,
|
||||
right: 10,
|
||||
left: 25,
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
|
||||
@@ -83,11 +83,12 @@ export default {
|
||||
// return html;
|
||||
// }
|
||||
},
|
||||
grid: {
|
||||
top: 30,
|
||||
bottom: 60,
|
||||
right: 30,
|
||||
left: 50,
|
||||
grid: {
|
||||
top: 25,
|
||||
bottom: 30,
|
||||
right: 0,
|
||||
left: 2,
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
|
||||
@@ -125,7 +125,7 @@ export default {
|
||||
width: 264px;
|
||||
height: 205px;
|
||||
background: #F9FCFF;
|
||||
padding: 16px 0 0 16px;
|
||||
padding: 16px 0 0 10px;
|
||||
|
||||
.title {
|
||||
// width: 190px;
|
||||
@@ -167,6 +167,7 @@ export default {
|
||||
letter-spacing: 1px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ getRateFlag(rate, real, target) {
|
||||
grid: {
|
||||
top: 10,
|
||||
bottom: 30,
|
||||
right: 50,
|
||||
right: 80,
|
||||
left: 30,
|
||||
containLabel: true,
|
||||
show: false // 隐藏grid背景,避免干扰
|
||||
|
||||
@@ -157,7 +157,7 @@ export default {
|
||||
min-width: 300px; // 最小宽度,防止挤压
|
||||
height: 205px;
|
||||
background: #F9FCFF;
|
||||
padding: 16px 16px 0; // 左右内边距一致
|
||||
padding: 16px 0 0 10px;// 左右内边距一致
|
||||
margin: 0 4px; // 左右间距
|
||||
|
||||
.title {
|
||||
@@ -201,6 +201,7 @@ export default {
|
||||
line-height: 18px;
|
||||
letter-spacing: 1px;
|
||||
text-align: left;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ import { getOperateCockpit, getOrderDetail } from '@/api/cockpit'
|
||||
import { Sidebar } from "../../layout/components";
|
||||
import { mapState } from "vuex";
|
||||
export default {
|
||||
name: 'DayReport',
|
||||
name: 'JtHome',
|
||||
components: { ReportHeader, coreSalesKPIs, keyProductionIndicators, coreBottomLeft, keyWork, orderProgress, financeCosts, Sidebar },
|
||||
data() {
|
||||
return {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
grid-template-columns:416px 1192px;
|
||||
">
|
||||
<indicatorCalendar :calendarList="calendarList" />
|
||||
<indicatorDetails />
|
||||
<indicatorDetails @updateLeft='getData' @updateLevel='getLevel'/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="top" style="margin-top: -20px; display: flex; gap: 16px">
|
||||
@@ -78,6 +78,7 @@ export default {
|
||||
monthData: {},
|
||||
ytdData: {},
|
||||
calendarList:{},
|
||||
levelId:null
|
||||
};
|
||||
},
|
||||
|
||||
@@ -143,35 +144,20 @@ export default {
|
||||
this.beilv = _this.clientWidth / 1920;
|
||||
})();
|
||||
};
|
||||
this.getData()
|
||||
},
|
||||
methods: {
|
||||
// sortChange(value) {
|
||||
// this.sort = value
|
||||
// this.getData()
|
||||
// },
|
||||
// 层级变动
|
||||
getLevel(id) {
|
||||
this.levelId = id
|
||||
this.getData()
|
||||
},
|
||||
getData() {
|
||||
getRealMonthCalendar().then((res) => {
|
||||
getRealMonthCalendar({
|
||||
levelId: this.levelId
|
||||
}).then((res) => {
|
||||
console.log(res, 'res');
|
||||
this.calendarList = res.data
|
||||
})
|
||||
// getSalesRevenueGroupData({
|
||||
// startTime: this.dateData.startTime,
|
||||
// endTime: this.dateData.endTime,
|
||||
// sort: this.sort,
|
||||
// index: undefined,
|
||||
// factory: undefined
|
||||
// // timeDim: obj.mode
|
||||
// }).then((res) => {
|
||||
// console.log(res);
|
||||
// this.monthData= res.data.month
|
||||
// this.ytdData = res.data.ytd
|
||||
// })
|
||||
},
|
||||
handleTimeChange(obj) {
|
||||
console.log(obj, 'obj');
|
||||
this.dateData= obj
|
||||
this.getData()
|
||||
},
|
||||
handleClickOutside() {
|
||||
this.$store.dispatch("app/closeSideBar", { withoutAnimation: false });
|
||||
|
||||
@@ -104,7 +104,7 @@ export default {
|
||||
beilv: 1,
|
||||
month: '',
|
||||
value: 100,
|
||||
factory: 5,
|
||||
factory: null,
|
||||
dateData: {},
|
||||
index: '加工成品率',
|
||||
monthData: undefined,
|
||||
@@ -184,7 +184,13 @@ export default {
|
||||
this.beilv = _this.clientWidth / 1920;
|
||||
})();
|
||||
};
|
||||
this.factory = this.$route.query.factory ? Number(this.$route.query.factory) : 5
|
||||
if(this.$route.query.factory){
|
||||
this.factory =Number(this.$route.query.factory)
|
||||
}else if(this.$store.getters.levelList.length > 0 && this.$store.getters.levelList[0].id !== 1) {
|
||||
this.factory = this.$store.getters.levelList[0].id
|
||||
}else{
|
||||
this.factory = this.$store.getters.levelList[1].id
|
||||
}
|
||||
this.dateData = this.$route.query.dateData ? this.$route.query.dateData : undefined
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -61,7 +61,7 @@ export default {
|
||||
return {
|
||||
activeButton: 0,
|
||||
isDropdownShow: false,
|
||||
selectedProfit: null, // 选中的名称,初始为null
|
||||
selectedProfit: '加工成品率', // 选中的名称,初始为null
|
||||
profitOptions: [
|
||||
'加工成品率',
|
||||
'领用量',
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div :id="id" style="width: 100%; height:100%;"></div>
|
||||
<div class="bottomTip">
|
||||
<div class="precent">
|
||||
<span class="precentNum">{{ detailData.rate || 0 }} </span>
|
||||
<span class="precentNum">{{ detailData.rate || 0 }}% </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -125,7 +125,7 @@ export default {
|
||||
width: 264px;
|
||||
height: 205px;
|
||||
background: #F9FCFF;
|
||||
padding: 16px 0 0 16px;
|
||||
padding: 16px 0 0 10px;
|
||||
|
||||
.title {
|
||||
// width: 190px;
|
||||
@@ -144,7 +144,7 @@ export default {
|
||||
.number {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 30px;
|
||||
gap: 6px;
|
||||
// width: 190px;
|
||||
height: 32px;
|
||||
font-family: YouSheBiaoTiHei;
|
||||
@@ -154,6 +154,7 @@ export default {
|
||||
letter-spacing: 2px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mom {
|
||||
@@ -167,6 +168,7 @@ export default {
|
||||
letter-spacing: 1px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ getRateFlag(rate, real, target) {
|
||||
min-width: 300px; // 最小宽度限制
|
||||
height: 205px;
|
||||
background: #F9FCFF;
|
||||
padding: 16px 16px 0;
|
||||
padding: 16px 0 0 10px;
|
||||
margin: 0 4px;
|
||||
|
||||
.title {
|
||||
@@ -187,6 +187,7 @@ getRateFlag(rate, real, target) {
|
||||
line-height: 18px;
|
||||
letter-spacing: 1px;
|
||||
text-align: left;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,8 +57,8 @@ export default {
|
||||
return {
|
||||
activeButton: 0,
|
||||
isDropdownShow: false,
|
||||
selectedSort: null, // 选中的label
|
||||
selectedSortValue: null, // 选中的value,用于排序逻辑
|
||||
selectedSort: '实际值:高~低', // 选中的label
|
||||
selectedSortValue: 1, // 选中的value,用于排序逻辑
|
||||
profitOptions: [
|
||||
{ label: '实际值:高~低', value: 1 },
|
||||
{ label: '实际值:低~高', value: 2 },
|
||||
|
||||
@@ -90,7 +90,9 @@ export default {
|
||||
const baseIndex = this.baseNameToIndexMap[itemName] || 0;
|
||||
|
||||
console.log(`你点击了【${itemName}】(序号:${baseIndex})`);
|
||||
|
||||
if (itemName === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 路由跳转时携带序号(或名称+序号)
|
||||
this.$router.push({
|
||||
|
||||
@@ -85,9 +85,10 @@ export default {
|
||||
},
|
||||
grid: {
|
||||
top: 30,
|
||||
bottom: 30,
|
||||
right: 20,
|
||||
left: 60,
|
||||
bottom: 5,
|
||||
right: 10,
|
||||
left: 25,
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
|
||||
@@ -84,10 +84,11 @@ export default {
|
||||
// }
|
||||
},
|
||||
grid: {
|
||||
top: 30,
|
||||
bottom: 60,
|
||||
right: 30,
|
||||
left: 50,
|
||||
top: 25,
|
||||
bottom: 30,
|
||||
right: 0,
|
||||
left: 2,
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
|
||||
@@ -125,8 +125,7 @@ export default {
|
||||
width: 264px;
|
||||
height: 205px;
|
||||
background: #F9FCFF;
|
||||
padding: 16px 0 0 16px;
|
||||
|
||||
padding: 16px 0 0 10px;
|
||||
.title {
|
||||
// width: 190px;
|
||||
height: 18px;
|
||||
@@ -167,6 +166,7 @@ export default {
|
||||
letter-spacing: 1px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ getRateFlag(rate, real, target) {
|
||||
grid: {
|
||||
top: 10,
|
||||
bottom: 30,
|
||||
right: 50,
|
||||
right: 80,
|
||||
left: 30,
|
||||
containLabel: true,
|
||||
show: false // 隐藏grid背景,避免干扰
|
||||
|
||||
@@ -143,7 +143,7 @@ getRateFlag(rate, real, target) {
|
||||
min-width: 300px; // 最小宽度限制
|
||||
height: 205px;
|
||||
background: #F9FCFF;
|
||||
padding: 16px 16px 0;
|
||||
padding: 16px 0 0 10px;
|
||||
margin: 0 4px;
|
||||
|
||||
.title {
|
||||
@@ -187,6 +187,7 @@ getRateFlag(rate, real, target) {
|
||||
line-height: 18px;
|
||||
letter-spacing: 1px;
|
||||
text-align: left;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ export default {
|
||||
beilv: 1,
|
||||
month: '',
|
||||
value: 100,
|
||||
factory: 5,
|
||||
factory: null,
|
||||
dateData: {},
|
||||
monData: {},
|
||||
relatedMon: {},
|
||||
@@ -178,7 +178,13 @@ export default {
|
||||
this.beilv = _this.clientWidth / 1920;
|
||||
})();
|
||||
};
|
||||
this.factory = this.$route.query.factory ? Number(this.$route.query.factory) : 5
|
||||
if(this.$route.query.factory){
|
||||
this.factory =Number(this.$route.query.factory)
|
||||
}else if(this.$store.getters.levelList.length > 0 && this.$store.getters.levelList[0].id !== 1) {
|
||||
this.factory = this.$store.getters.levelList[0].id
|
||||
}else{
|
||||
this.factory = this.$store.getters.levelList[1].id
|
||||
}
|
||||
this.dateData = this.$route.query.dateData ? this.$route.query.dateData : undefined
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div :id="id" style="width: 100%; height:100%;"></div>
|
||||
<div class="bottomTip">
|
||||
<div class="precent">
|
||||
<span class="precentNum">{{ detailData.completeRate || 0 }} </span>
|
||||
<span class="precentNum">{{ detailData.completeRate || 0 }}% </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -142,8 +142,7 @@ getRateFlag(rate, real, target) {
|
||||
width: 264px;
|
||||
height: 205px;
|
||||
background: #F9FCFF;
|
||||
padding: 16px 0 0 16px;
|
||||
|
||||
padding: 16px 0 0 10px;
|
||||
.title {
|
||||
height: 18px;
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
@@ -157,13 +156,14 @@ getRateFlag(rate, real, target) {
|
||||
.number {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 30px;
|
||||
gap: 6px;
|
||||
height: 32px;
|
||||
font-family: YouSheBiaoTiHei;
|
||||
font-size: 32px;
|
||||
color: #0B58FF;
|
||||
line-height: 32px;
|
||||
letter-spacing: 2px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mom {
|
||||
@@ -178,6 +178,7 @@ getRateFlag(rate, real, target) {
|
||||
display: flex;
|
||||
align-items: center; // 箭头和文字垂直居中
|
||||
gap: 4px; // 文字和箭头间距
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
// 箭头样式优化
|
||||
|
||||
@@ -160,7 +160,7 @@ getRateFlag(rate, real, target) {
|
||||
width: 382px;
|
||||
height: 205px;
|
||||
background: #F9FCFF;
|
||||
padding: 16px 0 0 16px;
|
||||
padding: 16px 0 0 10px;
|
||||
|
||||
.title {
|
||||
// width: 190px;
|
||||
@@ -179,7 +179,7 @@ getRateFlag(rate, real, target) {
|
||||
.number {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 30px;
|
||||
gap: 6px;
|
||||
// width: 190px;
|
||||
height: 32px;
|
||||
font-family: YouSheBiaoTiHei;
|
||||
@@ -189,10 +189,11 @@ getRateFlag(rate, real, target) {
|
||||
letter-spacing: 2px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mom {
|
||||
width: 97px;
|
||||
width: 120px;
|
||||
height: 18px;
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
@@ -202,6 +203,7 @@ getRateFlag(rate, real, target) {
|
||||
letter-spacing: 1px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,8 +57,8 @@ export default {
|
||||
return {
|
||||
activeButton: 0,
|
||||
isDropdownShow: false,
|
||||
selectedSort: null, // 选中的label
|
||||
selectedSortValue: null, // 选中的value,用于排序逻辑
|
||||
selectedSort: '实际值:高~低', // 选中的label
|
||||
selectedSortValue: 1, // 选中的value,用于排序逻辑
|
||||
profitOptions: [
|
||||
{ label: '实际值:高~低', value: 1 },
|
||||
{ label: '实际值:低~高', value: 2 },
|
||||
|
||||
@@ -90,7 +90,9 @@ export default {
|
||||
const baseIndex = this.baseNameToIndexMap[itemName] || 0;
|
||||
|
||||
console.log(`你点击了【${itemName}】(序号:${baseIndex})`);
|
||||
|
||||
if (itemName === undefined) {
|
||||
return;
|
||||
}
|
||||
// 路由跳转时携带序号(或名称+序号)
|
||||
this.$router.push({
|
||||
path: 'netPriceAnalysisBase',
|
||||
|
||||
@@ -85,9 +85,10 @@ export default {
|
||||
},
|
||||
grid: {
|
||||
top: 30,
|
||||
bottom: 30,
|
||||
right: 20,
|
||||
left: 60,
|
||||
bottom: 5,
|
||||
right: 10,
|
||||
left: 25,
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
|
||||
@@ -83,11 +83,12 @@ export default {
|
||||
// return html;
|
||||
// }
|
||||
},
|
||||
grid: {
|
||||
top: 30,
|
||||
bottom: 60,
|
||||
right: 30,
|
||||
left: 50,
|
||||
grid: {
|
||||
top: 25,
|
||||
bottom: 20,
|
||||
right: 10,
|
||||
left: 2,
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
|
||||
@@ -153,7 +153,7 @@ getRateFlag(rate, real, target) {
|
||||
width: 264px;
|
||||
height: 205px;
|
||||
background: #F9FCFF;
|
||||
padding: 16px 0 0 16px;
|
||||
padding: 16px 0 0 10px;
|
||||
|
||||
.title {
|
||||
// width: 190px;
|
||||
@@ -172,7 +172,7 @@ getRateFlag(rate, real, target) {
|
||||
.number {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 30px;
|
||||
gap: 6px;
|
||||
// width: 190px;
|
||||
height: 32px;
|
||||
font-family: YouSheBiaoTiHei;
|
||||
@@ -182,6 +182,7 @@ getRateFlag(rate, real, target) {
|
||||
letter-spacing: 2px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mom {
|
||||
@@ -195,6 +196,7 @@ getRateFlag(rate, real, target) {
|
||||
letter-spacing: 1px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ export default {
|
||||
grid: {
|
||||
top: 10,
|
||||
bottom: 30,
|
||||
right: 50,
|
||||
right: 80,
|
||||
left: 30,
|
||||
containLabel: true,
|
||||
show: false
|
||||
|
||||
@@ -155,7 +155,7 @@ getRateFlag(rate, real, target) {
|
||||
width: 382px;
|
||||
height: 205px;
|
||||
background: #F9FCFF;
|
||||
padding: 16px 0 0 16px;
|
||||
padding: 16px 0 0 10px;
|
||||
|
||||
.title {
|
||||
// width: 190px;
|
||||
@@ -174,7 +174,7 @@ getRateFlag(rate, real, target) {
|
||||
.number {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 30px;
|
||||
gap: 6px;
|
||||
// width: 190px;
|
||||
height: 32px;
|
||||
font-family: YouSheBiaoTiHei;
|
||||
@@ -184,10 +184,11 @@ getRateFlag(rate, real, target) {
|
||||
letter-spacing: 2px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mom {
|
||||
width: 97px;
|
||||
width: 120px;
|
||||
height: 18px;
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
@@ -197,6 +198,7 @@ getRateFlag(rate, real, target) {
|
||||
letter-spacing: 1px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ export default {
|
||||
return {
|
||||
activeButton: 0,
|
||||
isDropdownShow: false,
|
||||
selectedProfit: null, // 选中的名称,初始为null
|
||||
selectedProfit: '营业收入', // 选中的名称,初始为null
|
||||
profitOptions: [
|
||||
'营业收入',
|
||||
'单价',
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div :id="id" style="width: 100%; height:100%;"></div>
|
||||
<div class="bottomTip">
|
||||
<div class="precent">
|
||||
<span class="precentNum">{{ detailData.rate || 0 }} </span>
|
||||
<span class="precentNum">{{ detailData.rate || 0 }}% </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||