|
|
@@ -41,7 +41,7 @@
|
|
|
</div>
|
|
|
|
|
|
<!-- 主折线图:某时间段在线人数统计 -->
|
|
|
- <div class="page_jg_20"></div>
|
|
|
+ <div class="page_jg_16"></div>
|
|
|
<div class="chart_panel">
|
|
|
<div class="panel_title">
|
|
|
{{ currentOnlineLabel }}人数统计
|
|
|
@@ -50,84 +50,87 @@
|
|
|
reportHeight="280px"
|
|
|
:datax="mainLineChartData.datax"
|
|
|
:datay="mainLineChartData.datay"
|
|
|
- :title="[currentOnlineLabel + '在线']"
|
|
|
:showCheckBox="false"
|
|
|
:showBackground="true"
|
|
|
:disableLabelRotate="true"
|
|
|
- isSmooth
|
|
|
+ :tooltipDetailData="chartDetailDataList"
|
|
|
+ :clickDataPoint="true"
|
|
|
unit="人"
|
|
|
+ @dataPointClick="handleDataPointClick"
|
|
|
/>
|
|
|
</div>
|
|
|
|
|
|
- <!-- 底部:柱状图 + 折线图/表格 -->
|
|
|
- <div class="page_jg_20"></div>
|
|
|
- <div class="bottom_section">
|
|
|
- <!-- 左侧:某时刻各学校在线人数 -->
|
|
|
- <div class="chart_panel left_panel">
|
|
|
- <div class="panel_title">
|
|
|
- {{ currentHourLabel }}时 {{ currentOnlineLabel }}在线人数统计
|
|
|
- </div>
|
|
|
- <MultipleBarCharts
|
|
|
- :datax="barChartData.datax"
|
|
|
- :datay="barChartData.datay"
|
|
|
- :height="260"
|
|
|
- :isClick="true"
|
|
|
- color="#2E64FA"
|
|
|
- :showDataZoom="false"
|
|
|
- @HandleChartClick="handleBarClick"
|
|
|
- />
|
|
|
+ <!-- 某时刻各学校在线人数统计(独立模块) -->
|
|
|
+ <div class="page_jg_16"></div>
|
|
|
+ <div class="chart_panel">
|
|
|
+ <div class="panel_title">
|
|
|
+ {{ currentHourLabel }}时 {{ currentOnlineLabel }}在线人数统计
|
|
|
</div>
|
|
|
+ <MultipleBarCharts
|
|
|
+ :datax="barChartData.datax"
|
|
|
+ :datay="barChartData.datay"
|
|
|
+ :height="260"
|
|
|
+ :isClick="true"
|
|
|
+ color="#5470C6"
|
|
|
+ :barMaxWidth="50"
|
|
|
+ :barMinWidth="50"
|
|
|
+ :showDataZoom="false"
|
|
|
+ @HandleChartClick="handleBarClick"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
|
|
|
- <!-- 右侧:某学校当天在线人数 -->
|
|
|
- <div class="chart_panel right_panel">
|
|
|
- <div class="panel_header">
|
|
|
- <div class="panel_title">{{ selectedSchoolName }} 当天在线人数统计</div>
|
|
|
- <div class="panel_actions">
|
|
|
- <el-button class="btn_export" @click="handleExport">
|
|
|
- <el-icon class="btn_icon"><Download /></el-icon>
|
|
|
- 导出Excel
|
|
|
- </el-button>
|
|
|
- <div class="view_toggle">
|
|
|
- <span
|
|
|
- :class="{ active: defaultVisualizationTypeTab === 'chart' }"
|
|
|
- @click="defaultVisualizationTypeTab = 'chart'"
|
|
|
- >分析图</span>
|
|
|
- <span
|
|
|
- :class="{ active: defaultVisualizationTypeTab === 'table' }"
|
|
|
- @click="defaultVisualizationTypeTab = 'table'"
|
|
|
- >分析表</span>
|
|
|
- </div>
|
|
|
+ <!-- 某学校当天在线人数统计(独立模块) -->
|
|
|
+ <div class="page_jg_16"></div>
|
|
|
+ <div class="chart_panel">
|
|
|
+ <div class="panel_header">
|
|
|
+ <div class="panel_title">{{ selectedSchoolName }} 当天在线人数统计</div>
|
|
|
+ <div class="panel_actions">
|
|
|
+ <el-button class="btn_export" @click="handleExport">
|
|
|
+ <el-icon class="btn_icon"><Download /></el-icon>
|
|
|
+ 导出Excel
|
|
|
+ </el-button>
|
|
|
+ <div class="view_toggle">
|
|
|
+ <span
|
|
|
+ :class="{ active: defaultVisualizationTypeTab === 'chart' }"
|
|
|
+ @click="defaultVisualizationTypeTab = 'chart'"
|
|
|
+ >分析图</span>
|
|
|
+ <span
|
|
|
+ :class="{ active: defaultVisualizationTypeTab === 'table' }"
|
|
|
+ @click="defaultVisualizationTypeTab = 'table'"
|
|
|
+ >分析表</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
+ </div>
|
|
|
|
|
|
- <template v-if="defaultVisualizationTypeTab === 'chart'">
|
|
|
- <LineChart
|
|
|
- reportHeight="230px"
|
|
|
- :datax="schoolLineChartData.datax"
|
|
|
- :datay="schoolLineChartData.datay"
|
|
|
- :title="[selectedSchoolName + '在线']"
|
|
|
- :showCheckBox="false"
|
|
|
- :showBackground="true"
|
|
|
- :disableLabelRotate="true"
|
|
|
- isSmooth
|
|
|
- unit="人"
|
|
|
- />
|
|
|
- </template>
|
|
|
+ <template v-if="defaultVisualizationTypeTab === 'chart'">
|
|
|
+ <LineChart
|
|
|
+ reportHeight="280px"
|
|
|
+ :datax="schoolLineChartData.datax"
|
|
|
+ :datay="schoolLineChartData.datay"
|
|
|
+ :showCheckBox="false"
|
|
|
+ :showBackground="true"
|
|
|
+ :disableLabelRotate="true"
|
|
|
+ :tooltipDetailData="schoolChartDetailDataList"
|
|
|
+ :showTooltipDetail="false"
|
|
|
+ :showYAxisInteger="true"
|
|
|
+ :clickDataPoint="false"
|
|
|
+ unit="人"
|
|
|
+ />
|
|
|
+ </template>
|
|
|
|
|
|
- <template v-else>
|
|
|
- <div class="table_info">
|
|
|
- 共 {{ schoolTableData.length }} 条数据
|
|
|
- </div>
|
|
|
- <Table
|
|
|
- :tableColumns="tableColumns"
|
|
|
- :tableData="pagedTableData"
|
|
|
- :currentPage="currentPage"
|
|
|
- :pageSize="pageSize"
|
|
|
- :totalNum="schoolTableData.length"
|
|
|
- @paginationChange="handleTablePageChange"
|
|
|
- />
|
|
|
- </template>
|
|
|
- </div>
|
|
|
+ <template v-else>
|
|
|
+ <div class="table_info">
|
|
|
+ 共 {{ schoolTableData.length }} 条数据
|
|
|
+ </div>
|
|
|
+ <Table
|
|
|
+ :tableColumns="tableColumns"
|
|
|
+ :tableData="pagedTableData"
|
|
|
+ :currentPage="currentPage"
|
|
|
+ :pageSize="pageSize"
|
|
|
+ :totalNum="schoolTableData.length"
|
|
|
+ @paginationChange="handleTablePageChange"
|
|
|
+ />
|
|
|
+ </template>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -196,34 +199,59 @@ const handleCustomDateChange = (val: [string, string] | null) => {
|
|
|
const timeHours = ['0时','1时','2时','3时','4时','5时','6时','7时','8时','9时','10时','11时','12时','13时','14时','15时','16时','17时','18时','19时','20时','21时','22时','23时']
|
|
|
|
|
|
const mainLineChartData = reactive({
|
|
|
- datax: [...timeHours],
|
|
|
- datay: [[0,2,5,3,4,3,5,8,15,25,40,60,80,100,120,150,180,200,220,210,190,160,120,80]],
|
|
|
+ datax: [] as string[],
|
|
|
+ datay: [[]] as number[][],
|
|
|
})
|
|
|
|
|
|
+const chartDetailDataList = ref<any[]>([])
|
|
|
+const schoolChartDetailDataList = ref<any[]>([])
|
|
|
+
|
|
|
+const handleDataPointClick = async (payload: { dataIndex: number; schoolList: any[]; rawData: any }) => {
|
|
|
+ // 更新柱状图数据
|
|
|
+ if (payload.schoolList && payload.schoolList.length > 0) {
|
|
|
+ barChartData.datax = payload.schoolList.map((item: any) => item.xname ?? '')
|
|
|
+ barChartData.datay = payload.schoolList.map((item: any) => item.count ?? 0)
|
|
|
+ barChartSchoolList.value = payload.schoolList
|
|
|
+
|
|
|
+ // 柱状图更新后,默认选中第一个柱子,获取其 id 调用接口更新学校折线图
|
|
|
+ const firstSchoolId = payload.schoolList[0]?.id
|
|
|
+ if (firstSchoolId != null && firstSchoolId !== undefined) {
|
|
|
+ selectedSchoolName.value = payload.schoolList[0].xname ?? ''
|
|
|
+ await fetchSchoolLineChartData(firstSchoolId)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ console.warn('schoolList 为空,无法更新柱状图')
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新时间标签
|
|
|
+ if (payload.dataIndex >= 0 && mainLineChartData.datax[payload.dataIndex]) {
|
|
|
+ const xname = mainLineChartData.datax[payload.dataIndex]
|
|
|
+ const hourMatch = xname.match(/(\d{1,2})时/)
|
|
|
+ if (hourMatch) {
|
|
|
+ onLineTime.value = parseInt(hourMatch[1], 10)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 保存柱状图的完整学校列表数据
|
|
|
+const barChartSchoolList = ref<any[]>([])
|
|
|
+
|
|
|
const barChartData = reactive({
|
|
|
- datax: ['北京师大', '师达', '五十七', '五十七', '五十七', '一分校', '北师大', '北师大', '北师大'],
|
|
|
- datay: [96, 91, 96, 96, 97, 96, 96, 96, 96],
|
|
|
+ datax: [] as string[],
|
|
|
+ datay: [] as number[],
|
|
|
})
|
|
|
|
|
|
const onLineTime = ref(0)
|
|
|
const currentHourLabel = computed(() => String(onLineTime.value))
|
|
|
|
|
|
-const selectedSchoolName = ref('北京师大')
|
|
|
+const selectedSchoolName = ref('')
|
|
|
|
|
|
const schoolLineChartData = reactive({
|
|
|
- datax: [...timeHours],
|
|
|
- datay: [[0,2,5,3,4,3,5,8,15,25,40,60,80,100,120,150,180,200,220,210,190,160,120,80]],
|
|
|
+ datax: [] as string[],
|
|
|
+ datay: [] as number[][],
|
|
|
})
|
|
|
|
|
|
-const schoolTableData = ref([
|
|
|
- { num: 1, school: '北京师大', account: '18738372732', name: '黎明村', operationDetail: '系统登录', operationTime: '26-01-03 10:05:11' },
|
|
|
- { num: 2, school: '北京师大', account: '18738372732', name: '严谨', operationDetail: '系统登录', operationTime: '26-01-03 10:05:11' },
|
|
|
- { num: 3, school: '北京师大', account: '18738372732', name: '庄重', operationDetail: '系统登录', operationTime: '26-01-03 10:05:11' },
|
|
|
- { num: 4, school: '北京师大', account: '18738372732', name: '杨晓', operationDetail: '系统登录', operationTime: '26-01-03 10:05:11' },
|
|
|
- { num: 5, school: '北京师大', account: '18738372732', name: '孙赏语', operationDetail: '系统登录', operationTime: '26-01-03 10:05:11' },
|
|
|
- { num: 6, school: '北京师大', account: '18738372732', name: '赵梓萱', operationDetail: '系统登录', operationTime: '26-01-03 10:05:11' },
|
|
|
- { num: 7, school: '北京师大', account: '18738372732', name: '朱玉哲', operationDetail: '系统登录', operationTime: '26-01-03 10:05:11' },
|
|
|
-])
|
|
|
+const schoolTableData = ref<any[]>([])
|
|
|
|
|
|
const currentPage = ref(1)
|
|
|
const pageSize = ref(20)
|
|
|
@@ -263,49 +291,47 @@ const HandleTabChange = (type: string, val: string) => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-const handleBarClick = (index: number, name: string) => {
|
|
|
+const handleBarClick = async (index: number, name: string) => {
|
|
|
selectedSchoolName.value = name
|
|
|
currentPage.value = 1
|
|
|
- const base = barChartData.datay[index] || 50
|
|
|
- schoolLineChartData.datay = [[
|
|
|
- Math.floor(Math.random() * 5),
|
|
|
- Math.floor(Math.random() * 10),
|
|
|
- Math.floor(base * 0.3),
|
|
|
- Math.floor(base * 0.2),
|
|
|
- Math.floor(base * 0.4),
|
|
|
- Math.floor(base * 0.5),
|
|
|
- Math.floor(base * 0.6),
|
|
|
- Math.floor(base * 0.8),
|
|
|
- Math.floor(base * 1.0),
|
|
|
- Math.floor(base * 1.2),
|
|
|
- Math.floor(base * 1.5),
|
|
|
- Math.floor(base * 1.8),
|
|
|
- Math.floor(base * 2.0),
|
|
|
- Math.floor(base * 2.2),
|
|
|
- Math.floor(base * 2.5),
|
|
|
- Math.floor(base * 2.2),
|
|
|
- Math.floor(base * 2.0),
|
|
|
- Math.floor(base * 1.8),
|
|
|
- Math.floor(base * 1.5),
|
|
|
- Math.floor(base * 1.2),
|
|
|
- Math.floor(base * 1.0),
|
|
|
- Math.floor(base * 0.8),
|
|
|
- Math.floor(base * 0.5),
|
|
|
- Math.floor(base * 0.3),
|
|
|
- ]]
|
|
|
- const newRows = Array.from({ length: 50 }, (_, i) => ({
|
|
|
- num: i + 1,
|
|
|
- school: name,
|
|
|
- account: `1873837273${String(i % 10).padStart(2, '0')}`,
|
|
|
- name: ['黎明村', '严谨', '庄重', '杨晓', '孙赏语', '赵梓萱', '朱玉哲', '王小明', '李华', '张伟'][i % 10],
|
|
|
- operationDetail: '系统登录',
|
|
|
- operationTime: `26-01-03 10:05:${String(10 + (i % 50)).padStart(2, '0')}`,
|
|
|
- }))
|
|
|
- schoolTableData.value = newRows
|
|
|
+
|
|
|
+ // 获取当前柱子的 schoolId (schoolList 数组中 id 字段即为 schoolId)
|
|
|
+ const schoolItem = barChartSchoolList.value[index]
|
|
|
+ const schoolId = schoolItem?.id ?? 0
|
|
|
+
|
|
|
+ // 调用接口获取学校折线图数据
|
|
|
+ const timeType = dateRangeToTimeType[defaultDateRangeTab.value] ?? 1
|
|
|
+ const isToday = defaultDateRangeTab.value === 'today'
|
|
|
+ try {
|
|
|
+ const res = await getChartData({
|
|
|
+ schoolId,
|
|
|
+ timeType,
|
|
|
+ moduleCode: Number(defaultOnlineTypeTab.value) || 0,
|
|
|
+ startTime: customDateRange.value?.[0] ?? '',
|
|
|
+ endTime: customDateRange.value?.[1] ?? '',
|
|
|
+ })
|
|
|
+ console.log('点击柱子 getChartData 响应:', res)
|
|
|
+
|
|
|
+ const data = res.data || res
|
|
|
+ if (Array.isArray(data)) {
|
|
|
+ if (isToday) {
|
|
|
+ schoolLineChartData.datax = timeHours
|
|
|
+ } else {
|
|
|
+ schoolLineChartData.datax = data.map((item: any) => formatXname(item.xname ?? '', false))
|
|
|
+ }
|
|
|
+ schoolLineChartData.datay = [data.map((item: any) => item.count ?? 0)]
|
|
|
+ schoolChartDetailDataList.value = data.map((item: any) => ({
|
|
|
+ schoolList: item.schoolList || [],
|
|
|
+ count: item.count ?? 0,
|
|
|
+ }))
|
|
|
+ }
|
|
|
+ } catch (err) {
|
|
|
+ console.error('点击柱子 getChartData 请求失败:', err)
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
const handleExport = () => {
|
|
|
- console.log('导出Excel', selectedSchoolName.value)
|
|
|
+ // console.log('导出Excel', selectedSchoolName.value)
|
|
|
}
|
|
|
|
|
|
// ==================== 数据请求 ====================
|
|
|
@@ -324,12 +350,12 @@ const fetchHeadData = async () => {
|
|
|
}
|
|
|
|
|
|
const fetchModuleList = async () => {
|
|
|
- console.log('[fetchModuleList] 开始请求模块列表...')
|
|
|
+
|
|
|
try {
|
|
|
const res = await getModuleList()
|
|
|
- console.log('[fetchModuleList] 接口原始响应:', JSON.stringify(res))
|
|
|
+
|
|
|
const data = res.data || res
|
|
|
- console.log('[fetchModuleList] 解析后的 data:', JSON.stringify(data))
|
|
|
+
|
|
|
if (!Array.isArray(data)) {
|
|
|
console.warn('[fetchModuleList] data 不是数组,实际类型:', typeof data, data)
|
|
|
return
|
|
|
@@ -343,11 +369,11 @@ const fetchModuleList = async () => {
|
|
|
label: String(item.name ?? ''),
|
|
|
}
|
|
|
})
|
|
|
- console.log('[fetchModuleList] 映射后的 onlineList:', JSON.stringify(onlineList))
|
|
|
+
|
|
|
if (onlineList.length) {
|
|
|
onlineTypeTablist.value = onlineList
|
|
|
defaultOnlineTypeTab.value = onlineList[0].key
|
|
|
- console.log('[fetchModuleList] 已设置 onlineTypeTablist,defaultOnlineTypeTab =', onlineList[0].key)
|
|
|
+
|
|
|
} else {
|
|
|
console.warn('[fetchModuleList] onlineList 为空,未更新标签列表')
|
|
|
}
|
|
|
@@ -357,9 +383,55 @@ const fetchModuleList = async () => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+const formatXname = (xname: string, isToday: boolean): string => {
|
|
|
+ if (isToday) return xname
|
|
|
+ if (!xname) return ''
|
|
|
+ // Try ISO format: 2026-04-08 12:00:00 or 2026-04-08T12:00:00
|
|
|
+ let match = xname.match(/(\d{4})-(\d{1,2})-(\d{1,2})[ T](\d{1,2})/)
|
|
|
+ if (match) {
|
|
|
+ return `${parseInt(match[2], 10)}月${parseInt(match[3], 10)}日 ${parseInt(match[4], 10)}时`
|
|
|
+ }
|
|
|
+ // Try short format: 4-8 12:00 or 4-8T12:00
|
|
|
+ match = xname.match(/^(\d{1,2})-(\d{1,2})[ T](\d{1,2})/)
|
|
|
+ if (match) {
|
|
|
+ return `${parseInt(match[1], 10)}月${parseInt(match[2], 10)}日 ${parseInt(match[3], 10)}时`
|
|
|
+ }
|
|
|
+ return xname
|
|
|
+}
|
|
|
+
|
|
|
+const fetchSchoolLineChartData = async (schoolId: number) => {
|
|
|
+ const timeType = dateRangeToTimeType[defaultDateRangeTab.value] ?? 1
|
|
|
+ const isToday = defaultDateRangeTab.value === 'today'
|
|
|
+ try {
|
|
|
+ const res = await getChartData({
|
|
|
+ schoolId,
|
|
|
+ timeType,
|
|
|
+ moduleCode: Number(defaultOnlineTypeTab.value) || 0,
|
|
|
+ startTime: customDateRange.value?.[0] ?? '',
|
|
|
+ endTime: customDateRange.value?.[1] ?? '',
|
|
|
+ })
|
|
|
+ const data = res.data || res
|
|
|
+ if (Array.isArray(data)) {
|
|
|
+ if (isToday) {
|
|
|
+ schoolLineChartData.datax = timeHours
|
|
|
+ } else {
|
|
|
+ schoolLineChartData.datax = data.map((item: any) => formatXname(item.xname ?? '', false))
|
|
|
+ }
|
|
|
+ schoolLineChartData.datay = [data.map((item: any) => item.count ?? 0)]
|
|
|
+ schoolChartDetailDataList.value = data.map((item: any) => ({
|
|
|
+ schoolList: item.schoolList || [],
|
|
|
+ count: item.count ?? 0,
|
|
|
+ }))
|
|
|
+ }
|
|
|
+ } catch (err) {
|
|
|
+ console.error('fetchSchoolLineChartData 请求失败:', err)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
const fetchChartData = async () => {
|
|
|
try {
|
|
|
const timeType = dateRangeToTimeType[defaultDateRangeTab.value] ?? 1
|
|
|
+ const isToday = defaultDateRangeTab.value === 'today'
|
|
|
const res = await getChartData({
|
|
|
schoolId: 0,
|
|
|
timeType,
|
|
|
@@ -367,10 +439,37 @@ const fetchChartData = async () => {
|
|
|
startTime: customDateRange.value?.[0] ?? '',
|
|
|
endTime: customDateRange.value?.[1] ?? '',
|
|
|
})
|
|
|
- console.log('getChartData 响应数据:', res)
|
|
|
+
|
|
|
const data = res.data || res
|
|
|
- if (data) {
|
|
|
- // TODO: 根据后端返回数据结构更新图表
|
|
|
+ if (Array.isArray(data)) {
|
|
|
+ if (isToday) {
|
|
|
+ mainLineChartData.datax = timeHours
|
|
|
+ } else {
|
|
|
+ mainLineChartData.datax = data.map((item: any) => formatXname(item.xname ?? '', false))
|
|
|
+ }
|
|
|
+ mainLineChartData.datay = [data.map((item: any) => item.count ?? 0)]
|
|
|
+ chartDetailDataList.value = data.map((item: any) => ({
|
|
|
+ schoolList: item.schoolList || [],
|
|
|
+ count: item.count ?? 0,
|
|
|
+ }))
|
|
|
+
|
|
|
+ // 初始化柱状图数据:取第一个数据点的 schoolList
|
|
|
+ if (data.length > 0) {
|
|
|
+ const firstItem = data[0]
|
|
|
+ const schoolList = firstItem.schoolList || []
|
|
|
+ if (schoolList.length > 0) {
|
|
|
+ barChartData.datax = schoolList.map((item: any) => item.xname ?? '')
|
|
|
+ barChartData.datay = schoolList.map((item: any) => item.count ?? 0)
|
|
|
+ barChartSchoolList.value = schoolList
|
|
|
+ }
|
|
|
+ // 初始化时间标签
|
|
|
+ if (firstItem.xname) {
|
|
|
+ const hourMatch = String(firstItem.xname).match(/(\d{1,2})时/)
|
|
|
+ if (hourMatch) {
|
|
|
+ onLineTime.value = parseInt(hourMatch[1], 10)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
} catch (err) {
|
|
|
console.error('getChartData 请求失败:', err)
|
|
|
@@ -451,6 +550,16 @@ onMounted(() => {
|
|
|
border: 1px solid #edf0f5;
|
|
|
border-radius: 8px;
|
|
|
padding: 20px;
|
|
|
+ width: 100%;
|
|
|
+ box-sizing: border-box;
|
|
|
+
|
|
|
+ :deep(.echart_content) {
|
|
|
+ width: 100%;
|
|
|
+
|
|
|
+ .chart_box {
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
.panel_title {
|
|
|
font-size: 16px;
|
|
|
@@ -512,17 +621,6 @@ onMounted(() => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-.bottom_section {
|
|
|
- display: grid;
|
|
|
- grid-template-columns: 1fr 1fr;
|
|
|
- gap: 16px;
|
|
|
-
|
|
|
- .left_panel,
|
|
|
- .right_panel {
|
|
|
- min-height: 360px;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
.table_info {
|
|
|
font-size: 13px;
|
|
|
color: #909399;
|