| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- <script lang="ts" setup>
- import { IotStatApi } from '@/api/pms/stat'
- import { rangeShortcuts } from '@/utils/formatTime'
- import dayjs from 'dayjs'
- interface RyProductionBriefRow {
- id: number
- projectClassification: string
- projectName: string
- deptName: string
- taskName: string
- constructionStatusName: string
- dailyFootage: number | null
- completedWells: number | null
- dailyPowerUsage: number | null
- dailyFuel: number | null
- nonProductionTime: number | null
- nextPlan: string
- constructionBrief: string
- projectSort?: number | null
- teamSort?: number | null
- }
- interface SpanMethodProps {
- rowIndex: number
- columnIndex: number
- }
- const TABLE_HEIGHT = 220
- const MERGE_COLUMN_INDEXES = [0, 1]
- const COMPANY_ORDER = ['钻井', '修井']
- const DEFAULT_TIME_RANGE = rangeShortcuts[2]
- .value()
- .map((item) => dayjs(item).format('YYYY-MM-DD HH:mm:ss'))
- const createTime = ref<string[]>(DEFAULT_TIME_RANGE)
- const loading = ref(false)
- const list = ref<RyProductionBriefRow[]>([])
- const tableData = computed(() => {
- return [...list.value].sort((a, b) => {
- const companySort =
- getCompanyOrder(a.projectClassification) - getCompanyOrder(b.projectClassification)
- if (companySort !== 0) return companySort
- const projectSort = Number(a.projectSort ?? 9999) - Number(b.projectSort ?? 9999)
- if (projectSort !== 0) return projectSort
- const projectNameSort = (a.projectName || '').localeCompare(b.projectName || '', 'zh-Hans-CN')
- if (projectNameSort !== 0) return projectNameSort
- return Number(a.teamSort ?? 9999) - Number(b.teamSort ?? 9999)
- })
- })
- const spanMaps = computed(() => {
- return {
- company: createSpanMap(tableData.value, (row) => row.projectClassification || '-'),
- project: createSpanMap(
- tableData.value,
- (row) => `${row.projectClassification || '-'}__${row.projectName || '-'}`
- )
- }
- })
- function getCompanyOrder(value?: string) {
- const index = COMPANY_ORDER.indexOf(value || '')
- return index === -1 ? COMPANY_ORDER.length : index
- }
- function createSpanMap(
- rows: RyProductionBriefRow[],
- getKey: (row: RyProductionBriefRow) => string
- ) {
- const spanMap: number[] = []
- rows.forEach((row, index) => {
- const key = getKey(row)
- if (index > 0 && getKey(rows[index - 1]) === key) {
- spanMap[index] = 0
- return
- }
- let span = 1
- for (let nextIndex = index + 1; nextIndex < rows.length; nextIndex++) {
- if (getKey(rows[nextIndex]) !== key) break
- span += 1
- }
- spanMap[index] = span
- })
- return spanMap
- }
- function tableSpanMethod({ rowIndex, columnIndex }: SpanMethodProps) {
- if (!MERGE_COLUMN_INDEXES.includes(columnIndex)) {
- return {
- rowspan: 1,
- colspan: 1
- }
- }
- const rowspan =
- columnIndex === 0 ? spanMaps.value.company[rowIndex] : spanMaps.value.project[rowIndex]
- return {
- rowspan,
- colspan: rowspan > 0 ? 1 : 0
- }
- }
- function formatNumber(value?: number | null, fractionDigits = 1) {
- const numberValue = Number(value ?? 0)
- return Number.isInteger(numberValue) ? `${numberValue}` : numberValue.toFixed(fractionDigits)
- }
- function formatFootageOrWell(row: RyProductionBriefRow) {
- if (row.projectClassification === '钻井') {
- return `${formatNumber(row.dailyFootage)}m`
- }
- return formatNumber(row.completedWells, 0)
- }
- function normalizeList(res: any): RyProductionBriefRow[] {
- if (Array.isArray(res)) return res
- if (Array.isArray(res?.list)) return res.list
- if (Array.isArray(res?.records)) return res.records
- if (Array.isArray(res?.data)) return res.data
- return []
- }
- function handleDateChange() {
- getList()
- }
- async function getList() {
- loading.value = true
- try {
- const res = await IotStatApi.getRyProductionBriefs({ createTime: createTime.value })
- list.value = normalizeList(res).filter((row) =>
- COMPANY_ORDER.includes(row.projectClassification || '')
- )
- } catch (error) {
- console.error('获取瑞鹰生产简报失败:', error)
- list.value = []
- } finally {
- loading.value = false
- }
- }
- onMounted(() => {
- getList()
- })
- </script>
- <template>
- <div class="panel w-full h-[280px] flex flex-col mt-3">
- <div class="panel-title h-9 flex items-center justify-between">
- <div class="flex items-center">
- <div class="icon-decorator">
- <span></span>
- <span></span>
- </div>
- 生产简报
- </div>
- <div class="w-260px! -translate-y-[4px]">
- <el-date-picker
- v-model="createTime"
- value-format="YYYY-MM-DD HH:mm:ss"
- type="daterange"
- start-placeholder="开始日期"
- end-placeholder="结束日期"
- :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
- :clearable="false"
- class="w-260px!"
- @change="handleDateChange" />
- </div>
- </div>
- <div class="flex-1 min-h-0 px-4 py-2">
- <el-table
- v-loading="loading"
- :data="tableData"
- :height="TABLE_HEIGHT"
- :span-method="tableSpanMethod"
- class="device-list-table production-brief-table">
- <el-table-column prop="projectClassification" label="公司" min-width="72" align="center" />
- <el-table-column prop="projectName" label="项目" min-width="150" align="center" />
- <el-table-column prop="deptName" label="队伍" min-width="94" align="center" />
- <el-table-column prop="taskName" label="生产任务" min-width="130" align="center" />
- <el-table-column
- prop="constructionStatusName"
- label="运行状态"
- min-width="88"
- align="center" />
- <el-table-column prop="nextPlan" label="下步任务" min-width="130" align="center" />
- <el-table-column
- prop="constructionBrief"
- label="当日生产简况"
- min-width="160"
- align="center" />
- <el-table-column label="当日进尺(m)/当日井次" min-width="150" align="center">
- <template #default="{ row }">
- {{ formatFootageOrWell(row) }}
- </template>
- </el-table-column>
- <el-table-column label="当日电耗(kwh)" min-width="120" align="center">
- <template #default="{ row }">
- {{ formatNumber(row.dailyPowerUsage) }}
- </template>
- </el-table-column>
- <el-table-column label="当日油耗(升)" min-width="112" align="center">
- <template #default="{ row }">
- {{ formatNumber(row.dailyFuel) }}
- </template>
- </el-table-column>
- <el-table-column label="当日非生产时间" min-width="126" align="center">
- <template #default="{ row }">
- {{ formatNumber(row.nonProductionTime) }}
- </template>
- </el-table-column>
- <template #empty>
- <div class="h-full min-h-[220px] flex items-center justify-center">
- <el-empty description="暂无数据" :image-size="72" />
- </div>
- </template>
- </el-table>
- </div>
- </div>
- </template>
- <style lang="scss" scoped>
- @import url('@/styles/kb.scss');
- .production-brief-table {
- :deep(.el-table__header-wrapper th.el-table__cell) {
- font-size: 16px;
- line-height: 1.2;
- }
- :deep(.el-table__body td.el-table__cell) {
- padding: 7px 0;
- font-size: 14px;
- }
- }
- </style>
|