对接运三大屏开发环境接口,完善客运页数据展示
统一 ysdp 请求封装并接入首页/客运页接口,新增线路与单站客流对接,补充 gitignore 与开发环境配置说明。 Co-authored-by: Cursor <cursoragent@cursor.com>main
parent
763956d7ed
commit
35440a9493
|
|
@ -1,3 +1,3 @@
|
|||
# 开发环境配置
|
||||
# 使用相对路径,通过 vite proxy 代理到目标服务器
|
||||
# 留空则通过 vite proxy 代理到 http://101.133.172.2:8082
|
||||
VITE_API_BASE_URL=
|
||||
|
|
|
|||
|
|
@ -1,2 +1,53 @@
|
|||
# 依赖
|
||||
node_modules
|
||||
|
||||
# 构建产物
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# 项目文档(本地维护,不纳入版本库)
|
||||
doc/
|
||||
|
||||
# 环境变量(保留 .env.development / .env.production,忽略本地覆盖)
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# 日志
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# 编辑器 / IDE
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
# 操作系统
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
Desktop.ini
|
||||
|
||||
# 测试 / 覆盖率
|
||||
coverage
|
||||
*.lcov
|
||||
.nyc_output
|
||||
|
||||
# 缓存 / 临时文件
|
||||
.cache
|
||||
.temp
|
||||
.tmp
|
||||
*.tsbuildinfo
|
||||
.eslintcache
|
||||
.stylelintcache
|
||||
|
||||
# Vite
|
||||
vite.config.js.timestamp-*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,102 @@
|
|||
import { ref, watch, onMounted } from 'vue'
|
||||
import server from '@/utils/service'
|
||||
import metroMenuData from '@/utils/lineStationList.json'
|
||||
|
||||
const localLineStationList = metroMenuData.lineStationList || []
|
||||
|
||||
function mapLocalLines() {
|
||||
return localLineStationList.map(item => ({
|
||||
label: item.nameCn,
|
||||
value: item.lineId
|
||||
}))
|
||||
}
|
||||
|
||||
function mapLocalStations(lineId) {
|
||||
const currentLine = localLineStationList.find(item => item.lineId === lineId)
|
||||
return (currentLine?.stationList || []).map(item => ({
|
||||
label: item.nameCn,
|
||||
value: item.statId
|
||||
}))
|
||||
}
|
||||
|
||||
/** 客运页线路/站点下拉:优先接口,空数据时回退本地 JSON */
|
||||
export function useTrafficLineStation(getLine, getStation, emit) {
|
||||
const lineOptions = ref([])
|
||||
const stationOptions = ref([])
|
||||
|
||||
const loadLines = async () => {
|
||||
try {
|
||||
const response = await server.getLineList()
|
||||
if (response.data.success && response.data.data?.length) {
|
||||
lineOptions.value = response.data.data.map(item => ({
|
||||
label: item.name,
|
||||
value: String(item.lineId)
|
||||
}))
|
||||
return
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取线路列表失败:', error)
|
||||
}
|
||||
lineOptions.value = mapLocalLines()
|
||||
}
|
||||
|
||||
const loadStations = async lineId => {
|
||||
if (!lineId) {
|
||||
stationOptions.value = []
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await server.getStationsByLine(lineId)
|
||||
if (response.data.success && response.data.data?.length) {
|
||||
stationOptions.value = response.data.data.map(item => ({
|
||||
label: item.stationName || item.name || item.nameCn,
|
||||
value: item.stationId || item.statId
|
||||
}))
|
||||
syncStationSelection()
|
||||
return
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取站点列表失败:', error)
|
||||
}
|
||||
|
||||
stationOptions.value = mapLocalStations(lineId)
|
||||
syncStationSelection()
|
||||
}
|
||||
|
||||
const syncStationSelection = () => {
|
||||
const options = stationOptions.value
|
||||
if (!options.length) {
|
||||
emit('update:station', '')
|
||||
return
|
||||
}
|
||||
const currentStation = getStation()
|
||||
const hasCurrent = options.some(item => item.value === currentStation)
|
||||
if (!hasCurrent) {
|
||||
emit('update:station', options[0].value)
|
||||
}
|
||||
}
|
||||
|
||||
const initLineSelection = () => {
|
||||
if (!lineOptions.value.length) return
|
||||
const currentLine = getLine()
|
||||
const hasCurrent = lineOptions.value.some(item => item.value === currentLine)
|
||||
if (!hasCurrent) {
|
||||
emit('update:line', lineOptions.value[0].value)
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => getLine(),
|
||||
lineId => loadStations(lineId),
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
onMounted(async () => {
|
||||
await loadLines()
|
||||
initLineSelection()
|
||||
await loadStations(getLine())
|
||||
})
|
||||
|
||||
return { lineOptions, stationOptions }
|
||||
}
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
import { request } from './request'
|
||||
import { encrypt } from './decrypt'
|
||||
import axios from 'axios'
|
||||
import { ysdpPost } from './ysdpRequest'
|
||||
|
||||
var ipRoot = "http://140.206.138.190:8900"
|
||||
var ip = "http://140.206.138.190:8905"
|
||||
var ysdpmIp = import.meta.env.VITE_API_BASE_URL || "http://192.168.16.193:8888"
|
||||
|
||||
var getToken = "/app/getToken"
|
||||
var getTblMetroInout = ipRoot + '/api/xckf/getTblMetroInout/v1'
|
||||
|
|
@ -22,14 +21,6 @@ var getBusInfo = ipRoot + '/api/xckf/getBusInfo/v1'
|
|||
var updayeBusEntrance = ipRoot + '/api/xckf/updayeBusEntrance/v1'
|
||||
var getHotEventList = ipRoot + '/api/xckf/getHotEventList/v1'
|
||||
var updateHotEvent = ipRoot + '/api/xckf/updateHotEvent/v1'
|
||||
var getOperateInfo = (import.meta.env.DEV ? '' : import.meta.env.VITE_API_BASE_URL) + '/juntech-ysdp/api/getOperateInfo/v1'
|
||||
var getCommonMonitor = (import.meta.env.DEV ? '' : import.meta.env.VITE_API_BASE_URL) + '/juntech-ysdp/api/getCommonMonitor/v1'
|
||||
var getDutyList = (import.meta.env.DEV ? '' : import.meta.env.VITE_API_BASE_URL) + '/juntech-ysdp/api/getDutyList/v1'
|
||||
var getStationMaxList = (import.meta.env.DEV ? '' : import.meta.env.VITE_API_BASE_URL) + '/juntech-ysdp/api/getStationMaxList/v1'
|
||||
var getIndicator = (import.meta.env.DEV ? '' : import.meta.env.VITE_API_BASE_URL) + '/juntech-ysdp/api/getIndicator/v1'
|
||||
var getYunyingInfo = (import.meta.env.DEV ? '' : import.meta.env.VITE_API_BASE_URL) + '/juntech-ysdp/api/getYunyingInfo/v1'
|
||||
var getQxjGdybHour = (import.meta.env.DEV ? '' : import.meta.env.VITE_API_BASE_URL) + '/juntech-ysdp/api/getQxjGdybHour/v1'
|
||||
var getTaskNotice = (import.meta.env.DEV ? '' : import.meta.env.VITE_API_BASE_URL) + '/juntech-ysdp/api/getTaskNotice/v1'
|
||||
var xcImg = ip + '/1734.jpg'
|
||||
var xcImgGd = ip + '/lineCrossImg/1734.jpg'
|
||||
|
||||
|
|
@ -142,35 +133,67 @@ var server = {
|
|||
},
|
||||
|
||||
getOperateInfo() {
|
||||
return axios.post(getOperateInfo, {})
|
||||
return ysdpPost('/api/getOperateInfo/v1')
|
||||
},
|
||||
|
||||
getCommonMonitor() {
|
||||
return axios.post(getCommonMonitor, {})
|
||||
return ysdpPost('/api/getCommonMonitor/v1')
|
||||
},
|
||||
|
||||
getDutyList() {
|
||||
return axios.post(getDutyList, {})
|
||||
return ysdpPost('/api/getDutyList/v1')
|
||||
},
|
||||
|
||||
getStationMaxList() {
|
||||
return axios.post(getStationMaxList, {})
|
||||
return ysdpPost('/api/getStationMaxList/v1')
|
||||
},
|
||||
|
||||
getIndicator() {
|
||||
return axios.post(getIndicator, {})
|
||||
return ysdpPost('/api/getIndicator/v1')
|
||||
},
|
||||
|
||||
getQxjGdybHour() {
|
||||
return axios.post(getQxjGdybHour, {})
|
||||
return ysdpPost('/api/getQxjGdybHour/v1')
|
||||
},
|
||||
|
||||
getYunyingInfo() {
|
||||
return axios.post(getYunyingInfo, {})
|
||||
return ysdpPost('/api/getYunyingInfo/v1')
|
||||
},
|
||||
|
||||
getTaskNotice() {
|
||||
return axios.post(getTaskNotice, {})
|
||||
return ysdpPost('/api/getTaskNotice/v1')
|
||||
},
|
||||
|
||||
getInOutStationRank() {
|
||||
return ysdpPost('/api/traffic/getInOutStationRank/v1')
|
||||
},
|
||||
|
||||
getTransferStationRank() {
|
||||
return ysdpPost('/api/traffic/getTransferStationRank/v1')
|
||||
},
|
||||
|
||||
getLineList() {
|
||||
return ysdpPost('/api/traffic/getLineList/v1')
|
||||
},
|
||||
|
||||
getLinePassengerFlow() {
|
||||
return ysdpPost('/api/traffic/getLinePassengerFlow/v1')
|
||||
},
|
||||
|
||||
getStationPassengerFlow(stationId) {
|
||||
return ysdpPost('/api/traffic/getStationPassengerFlow/v1', { stationId })
|
||||
},
|
||||
|
||||
getStationsByLine(lineId) {
|
||||
return ysdpPost('/api/traffic/getStationsByLine/v1', { lineId })
|
||||
},
|
||||
|
||||
cleanTrafficCache() {
|
||||
return ysdpPost('/api/traffic/cleanCache')
|
||||
},
|
||||
|
||||
cleanApiCache() {
|
||||
return ysdpPost('/api/cleanApiCache')
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
const TIME_KEYS = ['time1', 'time2', 'time3', 'time4', 'time5', 'time6', 'time7', 'time8', 'time9', 'time10']
|
||||
|
||||
/** 从 time1~time10 对象提取时序数值 */
|
||||
export function extractTimeValues(dataObj) {
|
||||
return TIME_KEYS.map(key => {
|
||||
const value = dataObj?.[key]
|
||||
return value ? parseFloat(value) : 0
|
||||
})
|
||||
}
|
||||
|
||||
/** 将单站客流接口数据转为 Traffic4 图表结构 */
|
||||
export function processStationPassengerFlow(data) {
|
||||
if (!data) return null
|
||||
|
||||
return {
|
||||
compareDate: data.compareDate || '',
|
||||
inOut: {
|
||||
actual: extractTimeValues(data.inOut?.today),
|
||||
compare: extractTimeValues(data.inOut?.compareDay)
|
||||
},
|
||||
transfer: {
|
||||
actual: extractTimeValues(data.transfer?.today),
|
||||
compare: extractTimeValues(data.transfer?.compareDay)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 计算图表 Y 轴最大值(按万取整) */
|
||||
export function calcChartYAxisMax(...seriesList) {
|
||||
const maxValue = Math.max(...seriesList.flat(), 0)
|
||||
return Math.ceil(maxValue / 10000) * 10000 || 10000
|
||||
}
|
||||
|
||||
/** 将接口 lineId(如 07、04,07)转为页面展示格式(7、4,7) */
|
||||
export function normalizeLineIds(lineId) {
|
||||
if (!lineId) return ''
|
||||
return String(lineId)
|
||||
.split(',')
|
||||
.map(id => String(parseInt(id.trim(), 10)))
|
||||
.filter(id => id && id !== 'NaN')
|
||||
.join(',')
|
||||
}
|
||||
|
||||
/** 客流数值转万人(保留两位小数) */
|
||||
export function toWanRen(value) {
|
||||
const num = parseFloat(value) || 0
|
||||
return (num / 10000).toFixed(2)
|
||||
}
|
||||
|
||||
/** 将站点排名接口数据映射为 TrafficRankRow 所需结构 */
|
||||
export function mapStationRankList(data, type = '进出站') {
|
||||
if (!Array.isArray(data) || !data.length) return []
|
||||
|
||||
const maxTotal = Math.max(...data.map(item => parseFloat(item.total) || 0))
|
||||
|
||||
return data.map((item, index) => {
|
||||
const total = parseFloat(item.total) || 0
|
||||
const compare = parseFloat(item.compareTotal) || 0
|
||||
|
||||
return {
|
||||
rank: index + 1,
|
||||
lines: normalizeLineIds(item.lineId),
|
||||
station: item.stationName || '',
|
||||
type,
|
||||
today: toWanRen(total),
|
||||
compare: toWanRen(compare),
|
||||
percent: maxTotal > 0 ? Math.round((total / maxTotal) * 100) : 0
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
import axios from 'axios'
|
||||
|
||||
const ysdpRequest = axios.create({
|
||||
baseURL: `${import.meta.env.VITE_API_BASE_URL || ''}/juntech-ysdp`,
|
||||
timeout: 30000
|
||||
})
|
||||
|
||||
/** POST 请求,参数以 application/x-www-form-urlencoded 提交 */
|
||||
export function ysdpPost(path, data = {}) {
|
||||
const body = new URLSearchParams()
|
||||
Object.entries(data).forEach(([key, value]) => {
|
||||
if (value !== undefined && value !== null && value !== '') {
|
||||
body.append(key, value)
|
||||
}
|
||||
})
|
||||
return ysdpRequest.post(path, body, {
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
|
||||
})
|
||||
}
|
||||
|
||||
export default ysdpRequest
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
const TIME_KEYS = ['time1', 'time2', 'time3', 'time4', 'time5', 'time6', 'time7', 'time8', 'time9', 'time10']
|
||||
|
||||
/** 根据当前时刻计算对应的 time 索引(time1~time10) */
|
||||
export function getCurrentTimeIndex() {
|
||||
const hour = new Date().getHours()
|
||||
if (hour < 5) return 0
|
||||
return Math.min(Math.ceil((hour - 5) / 2), 9)
|
||||
}
|
||||
|
||||
function getTimeValues(dataObj) {
|
||||
return TIME_KEYS.map(key => {
|
||||
const value = dataObj?.[key]
|
||||
return value ? parseFloat(value) : 0
|
||||
})
|
||||
}
|
||||
|
||||
/** 将 getYunyingInfo 接口数据转为图表组件所需结构 */
|
||||
export function processYunyingInfo(dataList) {
|
||||
if (!Array.isArray(dataList)) return []
|
||||
|
||||
const currentTimeIndex = getCurrentTimeIndex()
|
||||
|
||||
return dataList.map(item => {
|
||||
const barData = getTimeValues(item.today)
|
||||
const yellowData = getTimeValues(item.compareDay)
|
||||
const redData = getTimeValues(item.maxDay)
|
||||
|
||||
const maxValue = redData[currentTimeIndex]
|
||||
const compareMaxValue = yellowData[currentTimeIndex]
|
||||
const totalSum = item.today?.totalSum ? parseFloat(item.today.totalSum) : 0
|
||||
const total = barData.reduce((sum, val) => sum + val, 0)
|
||||
const totalStr = Math.floor(total).toString()
|
||||
|
||||
return {
|
||||
lineId: parseInt(item.line, 10),
|
||||
line: parseInt(item.line, 10),
|
||||
total: totalStr,
|
||||
actual: barData,
|
||||
compare: yellowData,
|
||||
history: redData,
|
||||
barData,
|
||||
yellowData,
|
||||
redData,
|
||||
digits: totalStr.split('').map(Number),
|
||||
compareDate: item.compareDate || '',
|
||||
maxDate: item.maxDay?.maxDate || '',
|
||||
maxValue,
|
||||
compareMaxValue,
|
||||
totalSum
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -48,7 +48,8 @@ const fetchOperateInfo = async () => {
|
|||
const response = await server.getOperateInfo()
|
||||
if (response.data.success) {
|
||||
const { level: levelData, begindate } = response.data.data
|
||||
level.value = levelData
|
||||
const levelMatch = String(levelData).match(/\d+/)
|
||||
level.value = levelMatch ? levelMatch[0] : levelData
|
||||
|
||||
const now = new Date()
|
||||
const begin = new Date(begindate)
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
import { ref, onMounted, nextTick } from 'vue'
|
||||
import * as echarts from 'echarts'
|
||||
import server from '@/utils/service'
|
||||
import { processYunyingInfo } from '@/utils/yunying'
|
||||
|
||||
const chartRefs = ref([])
|
||||
|
||||
|
|
@ -55,8 +56,6 @@ const charts = ref(chartDataList.value)
|
|||
|
||||
const chartInstances = ref([])
|
||||
|
||||
const timeKeys = ['time1', 'time2', 'time3', 'time4', 'time5', 'time6', 'time7', 'time8', 'time9', 'time10']
|
||||
|
||||
const getNumberBoxColor = (number) => {
|
||||
const colors = {
|
||||
3: '#FBD61D',
|
||||
|
|
@ -99,60 +98,18 @@ const getBaifenbiColorStyle = (chart) => {
|
|||
}
|
||||
}
|
||||
const processData = (dataList) => {
|
||||
// 根据当前系统时间计算对应的 time 索引
|
||||
const getCurrentTimeIndex = () => {
|
||||
const now = new Date()
|
||||
const hour = now.getHours()
|
||||
const minutes = now.getMinutes()
|
||||
// 5 点和 6 点对应 time1,7 点和 8 点对应 time2,以此类推
|
||||
// time1: 5-6, time2: 7-8, time3: 9-10, time4: 11-12, time5: 13-14
|
||||
// time6: 15-16, time7: 17-18, time8: 19-20, time9: 21-22, time10: 23-24
|
||||
if (hour < 5) return 0
|
||||
// 如果当前小时是偶数且分钟大于 0,或者当前小时是奇数,都算下一个时间段
|
||||
// 例如:10:30,10 是偶数,但已经过了 10 点,应该算 time4
|
||||
// 11:00-11:59 也算 time4,12:00-12:59 也算 time4
|
||||
const timeIndex = Math.ceil((hour - 5) / 2)
|
||||
const result = Math.min(timeIndex, 9) // 最大到 time10 (索引 9)
|
||||
console.log(`当前时间:${hour}:${minutes},计算得到的 time 索引:${result}, 对应 ${timeKeys[result]}`)
|
||||
return result
|
||||
}
|
||||
|
||||
const currentTimeIndex = getCurrentTimeIndex()
|
||||
|
||||
return dataList.map(item => {
|
||||
const getValues = (dataObj) => {
|
||||
return timeKeys.map(key => {
|
||||
const value = dataObj[key]
|
||||
return value ? parseFloat(value) : 0
|
||||
})
|
||||
}
|
||||
|
||||
const barData = getValues(item.today)
|
||||
const yellowData = getValues(item.compareDay)
|
||||
const redData = getValues(item.maxDay)
|
||||
|
||||
// 根据当前时间获取对应的 maxDay 值和 compareDay 值
|
||||
const maxValue = redData[currentTimeIndex]
|
||||
const compareMaxValue = yellowData[currentTimeIndex]
|
||||
const totalSum = item.today?.totalSum ? parseFloat(item.today.totalSum) : 0
|
||||
|
||||
const total = barData.reduce((sum, val) => sum + val, 0)
|
||||
const totalStr = Math.floor(total).toString()
|
||||
const digits = totalStr.split('').map(Number)
|
||||
|
||||
return {
|
||||
barData,
|
||||
yellowData,
|
||||
redData,
|
||||
number: parseInt(item.line),
|
||||
digits: digits.length > 0 ? digits : [0],
|
||||
return processYunyingInfo(dataList).map(item => ({
|
||||
barData: item.barData,
|
||||
yellowData: item.yellowData,
|
||||
redData: item.redData,
|
||||
number: item.line,
|
||||
digits: item.digits.length > 0 ? item.digits : [0],
|
||||
compareDate: item.compareDate,
|
||||
maxDate: item.maxDay?.maxDate || '',
|
||||
maxValue: maxValue,
|
||||
compareMaxValue: compareMaxValue,
|
||||
totalSum: totalSum
|
||||
}
|
||||
})
|
||||
maxDate: item.maxDate,
|
||||
maxValue: item.maxValue,
|
||||
compareMaxValue: item.compareMaxValue,
|
||||
totalSum: item.totalSum
|
||||
}))
|
||||
}
|
||||
|
||||
const fetchYunyingInfo = async () => {
|
||||
|
|
|
|||
|
|
@ -18,10 +18,9 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, watch } from 'vue'
|
||||
import metroMenuData from '@/utils/lineStationList.json'
|
||||
import { computed } from 'vue'
|
||||
import { METRO_LINES } from '@/utils/const'
|
||||
|
||||
import { useTrafficLineStation } from '@/composables/useTrafficLineStation'
|
||||
|
||||
const props = defineProps({
|
||||
line: {
|
||||
|
|
@ -31,12 +30,10 @@ const props = defineProps({
|
|||
station: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:line', 'update:station'])
|
||||
const lineStationList = metroMenuData.lineStationList || []
|
||||
|
||||
const selectedLine = computed({
|
||||
get: () => props.line,
|
||||
|
|
@ -48,25 +45,11 @@ const selectedStation = computed({
|
|||
set: value => emit('update:station', value)
|
||||
})
|
||||
|
||||
|
||||
|
||||
const lineOptions = computed(() => {
|
||||
return lineStationList.map(item => ({
|
||||
label: item.nameCn,
|
||||
value: item.lineId
|
||||
}))
|
||||
})
|
||||
|
||||
const stationOptions = computed(() => {
|
||||
const currentLine = lineStationList.find(item => item.lineId === selectedLine.value)
|
||||
const stationList = currentLine?.stationList || []
|
||||
|
||||
return stationList.map(item => ({
|
||||
label: item.nameCn,
|
||||
value: item.statId,
|
||||
line: item.line
|
||||
}))
|
||||
})
|
||||
const { lineOptions, stationOptions } = useTrafficLineStation(
|
||||
() => props.line,
|
||||
() => props.station,
|
||||
emit
|
||||
)
|
||||
|
||||
const lineDisplayText = computed(() => {
|
||||
const currentLine = lineOptions.value.find(item => item.value === props.line)
|
||||
|
|
@ -78,8 +61,6 @@ const stationDisplayText = computed(() => {
|
|||
return String(currentStation?.label || stationOptions.value[0]?.label || '')
|
||||
})
|
||||
|
||||
|
||||
|
||||
const lineTheme = computed(() => {
|
||||
return METRO_LINES[Number(selectedLine.value)] || {
|
||||
bg: '#ED6E00',
|
||||
|
|
@ -89,7 +70,7 @@ const lineTheme = computed(() => {
|
|||
|
||||
const themeStyle = computed(() => ({
|
||||
'--metro-bg': lineTheme.value.bg,
|
||||
'--metro-text': lineTheme.value.color,
|
||||
'--metro-text': lineTheme.value.color
|
||||
}))
|
||||
|
||||
const getFilterItemStyle = (text, type) => {
|
||||
|
|
@ -105,18 +86,6 @@ const getFilterItemStyle = (text, type) => {
|
|||
width: `${Math.max(rule.padding + contentLength * rule.charWidth)}px`
|
||||
}
|
||||
}
|
||||
|
||||
watch(stationOptions, options => {
|
||||
if (!options.length) {
|
||||
emit('update:station', '')
|
||||
return
|
||||
}
|
||||
|
||||
const hasCurrentStation = options.some(item => item.value === props.station)
|
||||
if (!hasCurrentStation) {
|
||||
emit('update:station', options[0].value)
|
||||
}
|
||||
}, { immediate: true })
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -26,12 +26,12 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, watch } from 'vue'
|
||||
import { computed } from 'vue'
|
||||
import { Calendar } from '@element-plus/icons-vue'
|
||||
import dayjs from 'dayjs'
|
||||
import zhCn from 'element-plus/es/locale/lang/zh-cn'
|
||||
import metroMenuData from '@/utils/lineStationList.json'
|
||||
import { METRO_LINES } from '@/utils/const'
|
||||
import { useTrafficLineStation } from '@/composables/useTrafficLineStation'
|
||||
|
||||
import 'dayjs/locale/zh-cn'
|
||||
|
||||
|
|
@ -53,7 +53,6 @@ const props = defineProps({
|
|||
})
|
||||
|
||||
const emit = defineEmits(['update:line', 'update:station', 'update:month'])
|
||||
const lineStationList = metroMenuData.lineStationList || []
|
||||
|
||||
const selectedLine = computed({
|
||||
get: () => props.line,
|
||||
|
|
@ -70,23 +69,11 @@ const selectedMonth = computed({
|
|||
set: value => emit('update:month', value)
|
||||
})
|
||||
|
||||
const lineOptions = computed(() => {
|
||||
return lineStationList.map(item => ({
|
||||
label: item.nameCn,
|
||||
value: item.lineId
|
||||
}))
|
||||
})
|
||||
|
||||
const stationOptions = computed(() => {
|
||||
const currentLine = lineStationList.find(item => item.lineId === selectedLine.value)
|
||||
const stationList = currentLine?.stationList || []
|
||||
|
||||
return stationList.map(item => ({
|
||||
label: item.nameCn,
|
||||
value: item.statId,
|
||||
line: item.line
|
||||
}))
|
||||
})
|
||||
const { lineOptions, stationOptions } = useTrafficLineStation(
|
||||
() => props.line,
|
||||
() => props.station,
|
||||
emit
|
||||
)
|
||||
|
||||
const lineDisplayText = computed(() => {
|
||||
const currentLine = lineOptions.value.find(item => item.value === props.line)
|
||||
|
|
@ -109,7 +96,7 @@ const lineTheme = computed(() => {
|
|||
|
||||
const themeStyle = computed(() => ({
|
||||
'--metro-bg': lineTheme.value.bg,
|
||||
'--metro-text': lineTheme.value.color,
|
||||
'--metro-text': lineTheme.value.color
|
||||
}))
|
||||
|
||||
const getFilterItemStyle = (text, type) => {
|
||||
|
|
@ -125,18 +112,6 @@ const getFilterItemStyle = (text, type) => {
|
|||
width: `${Math.max(rule.padding + contentLength * rule.charWidth)}px`
|
||||
}
|
||||
}
|
||||
|
||||
watch(stationOptions, options => {
|
||||
if (!options.length) {
|
||||
emit('update:station', '')
|
||||
return
|
||||
}
|
||||
|
||||
const hasCurrentStation = options.some(item => item.value === props.station)
|
||||
if (!hasCurrentStation) {
|
||||
emit('update:station', options[0].value)
|
||||
}
|
||||
}, { immediate: true })
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -7,21 +7,27 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import TrafficRankRow from './TrafficRankRow.vue'
|
||||
import server from '@/utils/service'
|
||||
import { mapStationRankList } from '@/utils/traffic'
|
||||
|
||||
const rankList = ref([
|
||||
{ rank: 1, lines: '1,3,7,15', station: '上海火车站', type: '进出站', today: '8.40', compare: '6.20', percent: 92 },
|
||||
{ rank: 2, lines: '1,3,7,15', station: '上海体育场', type: '进出站', today: '8.20', compare: '5.20', percent: 80 },
|
||||
{ rank: 3, lines: '1,3,7,15', station: '延安西路', type: '进出站', today: '6.40', compare: '3.20', percent: 70 },
|
||||
{ rank: 4, lines: '1,3,7,15', station: '上大路', type: '进出站', today: '6.20', compare: '6.20', percent: 50 },
|
||||
{ rank: 5, lines: '1,3,7,15', station: '上海体育馆', type: '进出站', today: '6.20', compare: '6.20', percent: 40 },
|
||||
{ rank: 6, lines: '1,3,7,15', station: '上海南站', type: '进出站', today: '6.20', compare: '6.20', percent: 38 },
|
||||
{ rank: 7, lines: '1,3,7,15', station: '大渡河路', type: '进出站', today: '6.20', compare: '6.20', percent: 38 },
|
||||
{ rank: 8, lines: '1,3,7,15', station: '大渡河路', type: '进出站', today: '6.20', compare: '6.20', percent: 38 },
|
||||
{ rank: 9, lines: '1,3,7,15', station: '红宝石路', type: '进出站', today: '6.20', compare: '6.20', percent: 38 },
|
||||
{ rank: 10, lines: '1,3,7,15', station: '吴中路', type: '进出站', today: '6.20', compare: '6.20', percent: 10 }
|
||||
])
|
||||
const rankList = ref([])
|
||||
|
||||
const fetchRankList = async () => {
|
||||
try {
|
||||
const response = await server.getInOutStationRank()
|
||||
if (response.data.success) {
|
||||
rankList.value = mapStationRankList(response.data.data, '进出站')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取进出站客流排名失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchRankList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -6,21 +6,27 @@
|
|||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import TrafficRankRow from './TrafficRankRow.vue'
|
||||
import server from '@/utils/service'
|
||||
import { mapStationRankList } from '@/utils/traffic'
|
||||
|
||||
const rankList = ref([
|
||||
{ rank: 1, lines: '1,3,7,15', station: '上海火车站', type: '进出站', today: '18.40', compare: '6.20', percent: 92 },
|
||||
{ rank: 2, lines: '3,7', station: '上海体育场', type: '进出站', today: '18.20', compare: '5.20', percent: 80 },
|
||||
{ rank: 3, lines: '1,3,7,15', station: '延安西路', type: '进出站', today: '16.40', compare: '3.20', percent: 70 },
|
||||
{ rank: 4, lines: '1,3,7', station: '上大路', type: '进出站', today: '6.20', compare: '6.20', percent: 50 },
|
||||
{ rank: 5, lines: '1,15', station: '上海体育馆', type: '进出站', today: '6.20', compare: '6.20', percent: 40 },
|
||||
{ rank: 6, lines: '1,3,7,15', station: '上海南站', type: '进出站', today: '6.20', compare: '6.20', percent: 38 },
|
||||
{ rank: 7, lines: '1,3,15', station: '大渡河路', type: '进出站', today: '6.20', compare: '6.20', percent: 38 },
|
||||
{ rank: 8, lines: '1,3,7,15', station: '大渡河路', type: '进出站', today: '6.20', compare: '6.20', percent: 38 },
|
||||
{ rank: 9, lines: '1,3', station: '红宝石路', type: '进出站', today: '6.20', compare: '6.20', percent: 38 },
|
||||
{ rank: 10, lines: '15', station: '吴中路', type: '进出站', today: '6.20', compare: '6.20', percent: 10 }
|
||||
])
|
||||
const rankList = ref([])
|
||||
|
||||
const fetchRankList = async () => {
|
||||
try {
|
||||
const response = await server.getTransferStationRank()
|
||||
if (response.data.success) {
|
||||
rankList.value = mapStationRankList(response.data.data, '换乘站')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取换乘站客流排名失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchRankList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<section class="traffic-3">
|
||||
<div class="chart-legend">
|
||||
<span class="legend-item legend-item--actual">实际</span>
|
||||
<span class="legend-item legend-item--compare">对比日(2026-03-05)</span>
|
||||
<span class="legend-item legend-item--compare">对比日{{ compareDateLabel }}</span>
|
||||
<span class="legend-item legend-item--history">历史峰值</span>
|
||||
<span class="legend-unit">单位:万人次</span>
|
||||
</div>
|
||||
|
|
@ -35,45 +35,37 @@ import * as echarts from 'echarts'
|
|||
import Odometer from 'odometer'
|
||||
import 'odometer/themes/odometer-theme-default.css'
|
||||
import { METRO_LINES } from '@/utils/const'
|
||||
import server from '@/utils/service'
|
||||
import { processYunyingInfo } from '@/utils/yunying'
|
||||
|
||||
const hours = ['5', '7', '9', '11', '13', '15', '17', '19', '21', '23']
|
||||
const pointGlowSymbol = 'image:///imgs/traffic/4-item.png'
|
||||
|
||||
const lineCards = ref([
|
||||
{
|
||||
lineId: 3,
|
||||
total: '2746782',
|
||||
actual: [2600, 4700, 2400, 3900, 2300, 4100, 2600, 3300, 1700, 2200],
|
||||
compare: [4850, 4550, 4650, 4300, 4300, 4550, 4700, 3900, 3900, 3000],
|
||||
history: [5000, 4600, 4700, 4200, 4200, 4450, 4600, 4300, 3900, 3600]
|
||||
},
|
||||
{
|
||||
lineId: 4,
|
||||
total: '2746782',
|
||||
actual: [700, 950, 1550, 4200, 1700, 1350, 1600, 1550, 2500, 1400],
|
||||
compare: [1150, 1450, 2200, 3900, 2500, 1550, 1700, 1650, 2950, 2050],
|
||||
history: [1350, 2200, 3100, 4450, 3000, 2650, 2550, 2750, 4200, 4550]
|
||||
},
|
||||
{
|
||||
lineId: 7,
|
||||
total: '2746782',
|
||||
actual: [2900, 3300, 5000, 2300, 2000, 1900, 2600, 4050, 1700, 1700],
|
||||
compare: [3200, 3700, 5200, 2500, 2400, 2500, 3100, 4700, 2400, 2400],
|
||||
history: [3300, 4100, 5300, 2700, 2650, 2900, 3500, 4950, 3300, 2700]
|
||||
},
|
||||
{
|
||||
lineId: 15,
|
||||
total: '2746782',
|
||||
actual: [3000, 3600, 4550, 2400, 3900, 2200, 3400, 4050, 2800, 3300],
|
||||
compare: [4700, 4300, 4500, 4100, 4100, 4300, 4400, 4550, 4000, 3900],
|
||||
history: [4850, 4350, 4550, 4100, 4100, 4300, 4450, 4500, 3950, 3600]
|
||||
const lineCards = ref([])
|
||||
const compareDate = ref('')
|
||||
|
||||
const compareDateLabel = computed(() => {
|
||||
return compareDate.value ? `(${compareDate.value})` : ''
|
||||
})
|
||||
|
||||
const fetchLinePassengerFlow = async () => {
|
||||
try {
|
||||
const response = await server.getLinePassengerFlow()
|
||||
if (response.data.success) {
|
||||
const processed = processYunyingInfo(response.data.data)
|
||||
compareDate.value = processed[0]?.compareDate || ''
|
||||
lineCards.value = processed.map(item => ({
|
||||
lineId: item.lineId,
|
||||
total: String(Math.floor(item.totalSum || 0)),
|
||||
actual: item.actual,
|
||||
compare: item.compare,
|
||||
history: item.history
|
||||
}))
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
setTimeout(() => {
|
||||
lineCards.value[0].total = '8846081'
|
||||
}, 8000);
|
||||
} catch (error) {
|
||||
console.error('获取线路客流信息失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
const chartCards = computed(() => {
|
||||
return lineCards.value.map(item => ({
|
||||
|
|
@ -82,7 +74,7 @@ const chartCards = computed(() => {
|
|||
}))
|
||||
})
|
||||
|
||||
const targetTotals = computed(() => lineCards.value.map(item => item.total.split('')))
|
||||
const targetTotals = computed(() => lineCards.value.map(item => String(item.total || '0').split('')))
|
||||
const digitEls = []
|
||||
const odometerInstances = []
|
||||
|
||||
|
|
@ -132,6 +124,7 @@ watch(targetTotals, async () => {
|
|||
})
|
||||
|
||||
onMounted(async () => {
|
||||
await fetchLinePassengerFlow()
|
||||
await nextTick()
|
||||
initOdometers()
|
||||
requestAnimationFrame(updateOdometers)
|
||||
|
|
@ -149,7 +142,11 @@ const getLineStyle = lineId => {
|
|||
}
|
||||
}
|
||||
|
||||
const createChartOption = item => ({
|
||||
const createChartOption = item => {
|
||||
const maxValue = Math.max(...item.actual, ...item.compare, ...item.history, 0)
|
||||
const yAxisMax = Math.ceil(maxValue / 10000) * 10000 || 10000
|
||||
|
||||
return {
|
||||
backgroundColor: 'transparent',
|
||||
animationDuration: 900,
|
||||
grid: {
|
||||
|
|
@ -184,8 +181,8 @@ const createChartOption = item => ({
|
|||
yAxis: {
|
||||
type: 'value',
|
||||
min: 0,
|
||||
max: 5000,
|
||||
interval: 1000,
|
||||
max: yAxisMax,
|
||||
interval: yAxisMax / 5,
|
||||
axisLine: {
|
||||
show: false
|
||||
},
|
||||
|
|
@ -196,7 +193,8 @@ const createChartOption = item => ({
|
|||
color: 'rgba(226, 239, 255, 0.96)',
|
||||
fontSize: 13,
|
||||
fontWeight: 600,
|
||||
margin: 10
|
||||
margin: 10,
|
||||
formatter: value => (value / 10000).toFixed(0)
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
|
|
@ -248,7 +246,7 @@ const createChartOption = item => ({
|
|||
}
|
||||
},
|
||||
{
|
||||
name: '对比日(2026-03-05)',
|
||||
name: compareDateLabel.value || '对比日',
|
||||
type: 'line',
|
||||
data: item.compare,
|
||||
smooth: false,
|
||||
|
|
@ -281,7 +279,8 @@ const createChartOption = item => ({
|
|||
fontSize: 12
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
<template>
|
||||
<section class="traffic-4">
|
||||
<StationFilter class="traffic-4__filter" v-model:line="selectedLine" v-model:station="selectedStation"
|
||||
/>
|
||||
<StationFilter class="traffic-4__filter" v-model:line="selectedLine" v-model:station="selectedStation" />
|
||||
<div class="chart-shell">
|
||||
<v-chart class="traffic-4__chart" :option="chartOption" autoresize />
|
||||
</div>
|
||||
|
|
@ -9,31 +8,54 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed ,ref} from 'vue'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import StationFilter from './StationFilter.vue'
|
||||
import VChart from 'vue-echarts'
|
||||
import * as echarts from 'echarts'
|
||||
|
||||
|
||||
import server from '@/utils/service'
|
||||
import { processStationPassengerFlow, calcChartYAxisMax } from '@/utils/traffic'
|
||||
|
||||
const selectedLine = ref('3')
|
||||
const selectedStation = ref('0313')
|
||||
|
||||
|
||||
|
||||
const hours = ['5', '7', '9', '11', '13', '15', '17', '19', '21', '23']
|
||||
|
||||
const topActual = [800, 900, 2100, 4050, 1500, 1450, 1200, 2300, 900, 900]
|
||||
const topCompare = [1400, 1800, 3400, 4500, 2950, 2600, 2800, 4300, 4300, 4850]
|
||||
|
||||
const bottomActual = [4800, 4400, 3000, 1600, 3150, 3500, 3350, 1850, 1450, 1650]
|
||||
const bottomCompare = [5400, 5300, 4900, 2200, 4700, 5000, 3850, 4700, 5350, 5350 ]
|
||||
|
||||
const pointGlowSymbol = 'image:///imgs/traffic/4-item.png'
|
||||
const pointGlowSymbol1 = 'image:///imgs/traffic/4-item1.png'
|
||||
const topPointGlow = hours.map((hour, index) => [hour, topActual[index]])
|
||||
const bottomPointGlow = hours.map((hour, index) => [hour, bottomActual[index]])
|
||||
|
||||
const topActual = ref([])
|
||||
const topCompare = ref([])
|
||||
const bottomActual = ref([])
|
||||
const bottomCompare = ref([])
|
||||
|
||||
const fetchStationFlow = async () => {
|
||||
if (!selectedStation.value) return
|
||||
|
||||
try {
|
||||
const response = await server.getStationPassengerFlow(selectedStation.value)
|
||||
if (response.data.success) {
|
||||
const processed = processStationPassengerFlow(response.data.data)
|
||||
if (!processed) return
|
||||
topActual.value = processed.inOut.actual
|
||||
topCompare.value = processed.inOut.compare
|
||||
bottomActual.value = processed.transfer.actual
|
||||
bottomCompare.value = processed.transfer.compare
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取车站客流详情失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
watch(selectedStation, () => {
|
||||
fetchStationFlow()
|
||||
}, { immediate: true })
|
||||
|
||||
const topPointGlow = computed(() => hours.map((hour, index) => [hour, topActual.value[index] || 0]))
|
||||
const bottomPointGlow = computed(() => hours.map((hour, index) => [hour, bottomActual.value[index] || 0]))
|
||||
|
||||
const yAxisMaxTop = computed(() => calcChartYAxisMax(topActual.value, topCompare.value))
|
||||
const yAxisMaxBottom = computed(() => calcChartYAxisMax(bottomActual.value, bottomCompare.value))
|
||||
const yAxisIntervalTop = computed(() => yAxisMaxTop.value / 5)
|
||||
const yAxisIntervalBottom = computed(() => yAxisMaxBottom.value / 5)
|
||||
|
||||
const chartOption = computed(() => ({
|
||||
backgroundColor: 'transparent',
|
||||
|
|
@ -63,21 +85,15 @@ const chartOption = computed(() => ({
|
|||
boundaryGap: false,
|
||||
data: hours,
|
||||
gridIndex: 0,
|
||||
axisLine: {
|
||||
show: true
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
axisLine: { show: true },
|
||||
axisTick: { show: false },
|
||||
axisLabel: {
|
||||
color: 'rgba(226, 239, 255, 0.95)',
|
||||
fontSize: 13,
|
||||
fontWeight: 600,
|
||||
margin: 12
|
||||
},
|
||||
splitLine: {
|
||||
show: false
|
||||
}
|
||||
splitLine: { show: false }
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
|
|
@ -85,35 +101,26 @@ const chartOption = computed(() => ({
|
|||
data: hours,
|
||||
gridIndex: 1,
|
||||
position: 'top',
|
||||
axisLine: {
|
||||
show: true
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
axisLabel: {
|
||||
show: false
|
||||
},
|
||||
splitLine: {
|
||||
show: false
|
||||
}
|
||||
axisLine: { show: true },
|
||||
axisTick: { show: false },
|
||||
axisLabel: { show: false },
|
||||
splitLine: { show: false }
|
||||
}
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
gridIndex: 0,
|
||||
interval: 1000,
|
||||
axisLine: {
|
||||
show: false
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
min: 0,
|
||||
max: yAxisMaxTop.value,
|
||||
interval: yAxisIntervalTop.value,
|
||||
axisLine: { show: false },
|
||||
axisTick: { show: false },
|
||||
axisLabel: {
|
||||
color: 'rgba(222, 236, 255, 0.9)',
|
||||
fontSize: 12,
|
||||
margin: 10
|
||||
margin: 10,
|
||||
formatter: value => (value / 10000).toFixed(0)
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
|
|
@ -127,18 +134,17 @@ const chartOption = computed(() => ({
|
|||
{
|
||||
type: 'value',
|
||||
gridIndex: 1,
|
||||
interval: 1000,
|
||||
min: 0,
|
||||
max: yAxisMaxBottom.value,
|
||||
interval: yAxisIntervalBottom.value,
|
||||
inverse: true,
|
||||
axisLine: {
|
||||
show: false
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
axisLine: { show: false },
|
||||
axisTick: { show: false },
|
||||
axisLabel: {
|
||||
color: 'rgba(222, 236, 255, 0.9)',
|
||||
fontSize: 12,
|
||||
margin: 10
|
||||
margin: 10,
|
||||
formatter: value => (value / 10000).toFixed(0)
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
|
|
@ -155,38 +161,34 @@ const chartOption = computed(() => ({
|
|||
type: 'scatter',
|
||||
xAxisIndex: 0,
|
||||
yAxisIndex: 0,
|
||||
data: topPointGlow,
|
||||
data: topPointGlow.value,
|
||||
symbol: pointGlowSymbol,
|
||||
symbolSize: [47, 109],
|
||||
symbolOffset: [4, 0],
|
||||
symbolKeepAspect: false,
|
||||
silent: false,
|
||||
z: 4,
|
||||
tooltip: {
|
||||
show: false
|
||||
}
|
||||
tooltip: { show: false }
|
||||
},
|
||||
{
|
||||
type: 'scatter',
|
||||
xAxisIndex: 1,
|
||||
yAxisIndex: 1,
|
||||
data: bottomPointGlow,
|
||||
data: bottomPointGlow.value,
|
||||
symbol: pointGlowSymbol1,
|
||||
symbolSize: [47, 109],
|
||||
symbolOffset: [4,0],
|
||||
symbolOffset: [4, 0],
|
||||
symbolKeepAspect: true,
|
||||
silent: true,
|
||||
z: 4,
|
||||
tooltip: {
|
||||
show: false
|
||||
}
|
||||
tooltip: { show: false }
|
||||
},
|
||||
{
|
||||
name: '进出站',
|
||||
type: 'line',
|
||||
xAxisIndex: 0,
|
||||
yAxisIndex: 0,
|
||||
data: topActual,
|
||||
data: topActual.value,
|
||||
smooth: false,
|
||||
symbol: 'circle',
|
||||
symbolSize: 6,
|
||||
|
|
@ -219,7 +221,7 @@ const chartOption = computed(() => ({
|
|||
type: 'line',
|
||||
xAxisIndex: 0,
|
||||
yAxisIndex: 0,
|
||||
data: topCompare,
|
||||
data: topCompare.value,
|
||||
smooth: false,
|
||||
symbol: 'none',
|
||||
z: 4,
|
||||
|
|
@ -235,7 +237,7 @@ const chartOption = computed(() => ({
|
|||
type: 'line',
|
||||
xAxisIndex: 1,
|
||||
yAxisIndex: 1,
|
||||
data: bottomActual,
|
||||
data: bottomActual.value,
|
||||
smooth: false,
|
||||
symbol: 'circle',
|
||||
symbolSize: 6,
|
||||
|
|
@ -268,7 +270,7 @@ const chartOption = computed(() => ({
|
|||
type: 'line',
|
||||
xAxisIndex: 1,
|
||||
yAxisIndex: 1,
|
||||
data: bottomCompare,
|
||||
data: bottomCompare.value,
|
||||
smooth: false,
|
||||
symbol: 'none',
|
||||
z: 4,
|
||||
|
|
@ -289,7 +291,7 @@ const chartOption = computed(() => ({
|
|||
},
|
||||
formatter: params => {
|
||||
const { name, seriesName, value } = params[0]
|
||||
return `${name}时<br>${seriesName}: ${value}`
|
||||
return `${name}时<br>${seriesName}: ${(value / 10000).toFixed(2)}万`
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
|
@ -305,8 +307,6 @@ const chartOption = computed(() => ({
|
|||
background: url('/imgs/traffic/4-bg.png') no-repeat center center;
|
||||
background-size: cover;
|
||||
|
||||
|
||||
|
||||
.traffic-4__filter {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
|
|
|
|||
Loading…
Reference in New Issue