feat:任务/产品查看更多页面

master
黄伟杰 3 weeks ago
parent d3dfc45074
commit b1e6d3af72

@ -31,7 +31,7 @@ export default {
subtitle: 'Besure Digital Intelligent Control Platform',
functionNav: 'Function Navigation',
productionOverview: 'Production Overview',
productionPlan: 'Production Plans',
productionPlan: 'Production Summary',
collapseList: 'Collapse',
viewMore: 'View More ',
productName: 'Product',
@ -90,6 +90,31 @@ export default {
saturday: 'Sat',
sunday: 'Sun'
},
taskList: {
taskType: 'Task Type',
orderDate: 'Order Date',
deliveryDate: 'Delivery Date',
totalNumber: 'Total',
planNumber: 'Planned',
unPlanNumber: 'Unplanned',
storedPlanNumber: 'Stored',
urgent: 'Urgent',
noData: 'No task data',
viewTask: 'View Task: {code}'
},
planList: {
taskCode: 'Task Code',
planCode: 'Plan Code',
employeeName: 'Reporter',
baogongNum: 'Reported',
passNum: 'Passed',
noPassNum: 'Failed',
passRate: 'Pass Rate',
baogongTime: 'Report Time',
reason: 'Reason',
noData: 'No report data',
viewDetail: 'View Detail: {code}'
},
functionCommon: {
search: 'Search',
cancel: 'Cancel',

@ -31,7 +31,7 @@ export default {
subtitle: '必硕数字化智能中控平台',
functionNav: '功能导航',
productionOverview: '生产整体概况',
productionPlan: '生产计划',
productionPlan: '生产概括',
collapseList: '收起列表',
viewMore: '查看更多 ',
productName: '产品名称',
@ -90,6 +90,31 @@ export default {
saturday: '周六',
sunday: '周日'
},
taskList: {
taskType: '任务类型',
orderDate: '下单日期',
deliveryDate: '交付日期',
totalNumber: '总数量',
planNumber: '已排产',
unPlanNumber: '未排产',
storedPlanNumber: '已入库',
urgent: '紧急',
noData: '暂无任务数据',
viewTask: '查看任务: {code}'
},
planList: {
taskCode: '任务编号',
planCode: '计划编号',
employeeName: '报工人',
baogongNum: '报工数',
passNum: '合格数',
noPassNum: '不合格数',
passRate: '合格率',
baogongTime: '报工时间',
reason: '原因',
noData: '暂无报工数据',
viewDetail: '查看详情: {code}'
},
functionCommon: {
search: '查询',
cancel: '取消',

@ -510,6 +510,12 @@
"style": {
"navigationBarTitleText": "生产计划"
}
},
{
"path": "taskList/index",
"style": {
"navigationBarTitleText": "任务计划"
}
}
]
}

@ -69,14 +69,14 @@
<view class="date-picker-item">
<up-icon name="calendar" size="18" color="#999" />
<up-datetime-picker ref="startPickerRef" hasInput v-model="dateRange.start" mode="datetime"
:placeholder="t('dashboard.startDate')" :formatter="datetimeFormatter"
closeOnClickOverlay @confirm="onStartDateConfirm" @close="onPickerClose" @cancel="onPickerClose" />
:placeholder="t('dashboard.startDate')" :formatter="datetimeFormatter" closeOnClickOverlay
@confirm="onStartDateConfirm" @close="onPickerClose" @cancel="onPickerClose" />
</view>
<view class="date-picker-item">
<up-icon name="calendar" size="18" color="#999" />
<up-datetime-picker ref="endPickerRef" hasInput v-model="dateRange.end" mode="datetime"
:placeholder="t('dashboard.endDate')" :formatter="datetimeFormatter"
closeOnClickOverlay @confirm="onEndDateConfirm" @close="onPickerClose" @cancel="onPickerClose" />
:placeholder="t('dashboard.endDate')" :formatter="datetimeFormatter" closeOnClickOverlay
@confirm="onEndDateConfirm" @close="onPickerClose" @cancel="onPickerClose" />
</view>
</view>
<view v-if="currentFilter === 'product'" class="trend-content">
@ -100,21 +100,17 @@
</view>
<view v-if="currentRange !== 'custom'" class="trend-chart">
<text class="chart-title">{{ t('dashboard.baogongNum') }}</text>
<scroll-view scroll-x class="chart-scroll">
<view class="chart-box" :style="{ width: chartWidth }">
<qiun-data-charts type="line" :chartData="baogongChartData" :canvas2d="false"
:opts="{ legend: { show: false }, xAxis: { disableGrid: true }, yAxis: { gridType: 'dash', dashLength: 2 }, extra: { line: { type: 'straight', width: 2, activeType: 'hollow' } } }" />
</view>
</scroll-view>
<view class="chart-box">
<qiun-data-charts type="line" :chartData="baogongChartData" :canvas2d="false"
:opts="{ color: ['#1a3a5c'], dataLabel: false, legend: { show: false }, xAxis: { disableGrid: true, labelCount: 4 }, yAxis: { gridType: 'dash', dashLength: 2 }, extra: { line: { type: 'straight', width: 2, activeType: 'hollow' } } }" />
</view>
</view>
<view v-if="currentRange !== 'custom'" class="trend-chart">
<text class="chart-title">{{ t('dashboard.passRate') }}</text>
<scroll-view scroll-x class="chart-scroll">
<view class="chart-box" :style="{ width: chartWidth }">
<qiun-data-charts type="line" :chartData="passRateChartData" :canvas2d="false"
:opts="{ legend: { show: false }, xAxis: { disableGrid: true }, yAxis: { gridType: 'dash', dashLength: 2, data: [{ min: 0, max: 100 }] }, extra: { line: { type: 'straight', width: 2, activeType: 'hollow' } } }" />
</view>
</scroll-view>
<view class="chart-box">
<qiun-data-charts type="line" :chartData="passRateChartData" :canvas2d="false"
:opts="{ color: ['#1a3a5c'], dataLabel: false, legend: { show: false }, xAxis: { disableGrid: true, labelCount: 4 }, yAxis: { gridType: 'dash', dashLength: 2, data: [{ min: 0, max: 100 }] }, extra: { line: { type: 'straight', width: 2, activeType: 'hollow' } } }" />
</view>
</view>
</view>
<view v-else class="trend-content">
@ -138,12 +134,10 @@
</view>
<view v-if="currentRange !== 'custom'" class="trend-chart">
<text class="chart-title">{{ t('dashboard.taskTrend') }}</text>
<scroll-view scroll-x class="chart-scroll">
<view class="chart-box" :style="{ width: chartWidth }">
<qiun-data-charts type="line" :chartData="taskChartData" :canvas2d="false"
:opts="{ legend: { show: false }, xAxis: { disableGrid: true }, yAxis: { gridType: 'dash', dashLength: 2 }, extra: { line: { type: 'straight', width: 2, activeType: 'hollow' } } }" />
</view>
</scroll-view>
<view class="chart-box">
<qiun-data-charts type="line" :chartData="taskChartData" :canvas2d="false"
:opts="{ color: ['#1a3a5c'], dataLabel: false, legend: { show: false }, xAxis: { disableGrid: true, labelCount: 4 }, yAxis: { gridType: 'dash', dashLength: 2 }, extra: { line: { type: 'straight', width: 2, activeType: 'hollow' } } }" />
</view>
</view>
</view>
</view>
@ -236,7 +230,7 @@ const showRangePicker = ref(false)
const startPickerRef = ref(null)
const endPickerRef = ref(null)
const currentFilter = ref('task')
const currentRange = ref('month')
const currentRange = ref('year')
const filterColumns = computed(() => [
[
@ -310,12 +304,6 @@ const taskChartData = reactive({
]
})
const chartWidth = computed(() => {
const count = baogongChartData.categories.length
if (count <= 7) return '100%'
return Math.max(count * 50, 300) + 'rpx'
})
function getDateRange(type) {
const now = new Date()
const pad2 = (n) => String(n).padStart(2, '0')
@ -602,7 +590,11 @@ function handleNavClick(item) {
}
function viewMorePlans() {
uni.navigateTo({ url: '/pages_function/pages/planList/index' })
if (currentFilter.value === 'task') {
uni.navigateTo({ url: '/pages_function/pages/taskList/index' })
} else {
uni.navigateTo({ url: '/pages_function/pages/planList/index' })
}
}
function onScroll(e) {
@ -1050,6 +1042,9 @@ onUnmounted(() => {
padding: 20rpx 12rpx;
margin: 0 6rpx;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
&:first-child {
margin-left: 0;
@ -1098,11 +1093,6 @@ onUnmounted(() => {
margin-bottom: 16rpx;
}
.chart-scroll {
width: 100%;
white-space: nowrap;
}
.chart-box {
width: 100%;
height: 450rpx;

@ -1,46 +1,66 @@
<template>
<view class="page-container">
<view class="plan-list">
<view v-for="(plan, index) in planList" :key="index" class="plan-card" @click="handlePlanClick(plan)">
<view v-for="(item, index) in planList" :key="index" class="plan-card" @click="handleItemClick(item)">
<view class="plan-header">
<text class="plan-code">{{ plan.code }}</text>
<view class="plan-status" :class="'status-' + plan.statusType">
<text>{{ plan.status }}</text>
</view>
<text class="plan-code">{{ item.productName }}</text>
<text class="plan-product-code">{{ item.productCode }}</text>
</view>
<view class="plan-body">
<view class="plan-row">
<text class="plan-label">{{ t('dashboard.productName') }}</text>
<text class="plan-value">{{ plan.productName }}</text>
<text class="plan-label">{{ t('planList.taskCode') }}</text>
<text class="plan-value">{{ item.taskCode }}</text>
</view>
<view class="plan-row">
<text class="plan-label">{{ t('planList.planCode') }}</text>
<text class="plan-value">{{ item.planCode }}</text>
</view>
<view class="plan-row">
<text class="plan-label">{{ t('planList.employeeName') }}</text>
<text class="plan-value">{{ item.employeeName }}</text>
</view>
<view class="plan-row">
<text class="plan-label">{{ t('dashboard.pipeline') }}</text>
<text class="plan-value">{{ plan.feedingPipelineName }}</text>
<text class="plan-label">{{ t('planList.baogongNum') }}</text>
<text class="plan-value plan-num">{{ item.baogongNum }}</text>
</view>
<view class="plan-row">
<text class="plan-label">{{ t('dashboard.planNumber') }}</text>
<text class="plan-value plan-num">{{ plan.planNumber }}</text>
<text class="plan-label">{{ t('planList.passNum') }}</text>
<text class="plan-value plan-num pass">{{ item.passNum }}</text>
</view>
<view class="plan-row">
<text class="plan-label">{{ t('dashboard.planStart') }}</text>
<text class="plan-value">{{ plan.planStartTimeText }}</text>
<text class="plan-label">{{ t('planList.noPassNum') }}</text>
<text class="plan-value plan-num fail">{{ item.noPassNum }}</text>
</view>
<view class="plan-row">
<text class="plan-label">{{ t('dashboard.planEnd') }}</text>
<text class="plan-value">{{ plan.planEndTimeText }}</text>
<text class="plan-label">{{ t('planList.passRate') }}</text>
<text class="plan-value plan-num" :class="item.passRate >= 90 ? 'pass' : item.passRate >= 70 ? 'warn' : 'fail'">{{ item.passRateText }}</text>
</view>
<view class="plan-row">
<text class="plan-label">{{ t('planList.baogongTime') }}</text>
<text class="plan-value">{{ item.baogongTimeText }}</text>
</view>
<view v-if="item.reason" class="plan-row">
<text class="plan-label">{{ t('planList.reason') }}</text>
<text class="plan-value reason-text">{{ item.reason }}</text>
</view>
</view>
</view>
</view>
<view v-if="planList.length === 0" class="empty-state">
<text class="empty-text">{{ t('functionCommon.loadFailed') }}</text>
<view v-if="loading" class="loading-state">
<text class="loading-text">{{ t('functionCommon.loading') }}</text>
</view>
<view v-else-if="planList.length === 0" class="empty-state">
<text class="empty-text">{{ t('planList.noData') }}</text>
</view>
<view v-else-if="noMore" class="no-more-state">
<text class="no-more-text">{{ t('functionCommon.noMoreData') }}</text>
</view>
</view>
</template>
<script setup>
import { onMounted, reactive } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { ref, reactive, onMounted } from 'vue'
import { onReachBottom, onShow } from '@dcloudio/uni-app'
import { useI18n } from 'vue-i18n'
import request from '@/utils/request'
import { setNavigationTitle } from '@/locales'
@ -48,8 +68,13 @@ import { setNavigationTitle } from '@/locales'
const { t } = useI18n()
const planList = reactive([])
const pageNo = ref(1)
const pageSize = ref(10)
const total = ref(0)
const loading = ref(false)
const noMore = ref(false)
function formatDate(ms) {
function formatDateTime(ms) {
if (!ms) return '-'
const date = new Date(ms)
if (Number.isNaN(date.getTime())) return '-'
@ -57,62 +82,70 @@ function formatDate(ms) {
const y = date.getFullYear()
const m = pad2(date.getMonth() + 1)
const d = pad2(date.getDate())
return `${y}-${m}-${d}`
}
const getPlanStatusLabel = (value) => {
const v = value === '' || value === null || value === undefined ? undefined : String(value)
if (v == '1') return t('dashboard.statusScheduled')
if (v == '6') return t('dashboard.statusTrial')
if (v == '2') return t('dashboard.statusMass')
if (v == '3') return t('dashboard.statusPause')
if (v == '4') return t('dashboard.statusWaitStockIn')
return '-'
}
function mapPlanStatus(status) {
const v = status === '' || status === null || status === undefined ? undefined : String(status)
if (v == '1') return { status: getPlanStatusLabel(v), statusType: 'pending' }
if (v == '6') return { status: getPlanStatusLabel(v), statusType: 'running' }
if (v == '2') return { status: getPlanStatusLabel(v), statusType: 'running' }
if (v == '3') return { status: getPlanStatusLabel(v), statusType: 'pending' }
if (v == '4') return { status: getPlanStatusLabel(v), statusType: 'finished' }
return { status: getPlanStatusLabel(v), statusType: 'pending' }
}
function handlePlanClick(plan) {
uni.showToast({
title: t('dashboard.viewPlan', { code: plan.code }),
icon: 'none'
})
}
async function loadPlanList() {
const res = await request({ url: '/admin-api/mes/dashboard/getPlan', method: 'get' })
const raw = Array.isArray(res?.data) ? res.data : (res?.data ? [res.data] : [])
const mapped = raw.map((p) => {
const statusInfo = mapPlanStatus(p?.status)
return {
id: p?.id,
code: p?.code ?? '-',
status: statusInfo.status,
statusType: statusInfo.statusType,
productName: p?.productName ?? '-',
feedingPipelineName: p?.feedingPipelineName ?? '-',
planNumber: p?.planNumber ?? 0,
planStartTimeText: formatDate(p?.planStartTime),
planEndTimeText: formatDate(p?.planEndTime),
const h = pad2(date.getHours())
const min = pad2(date.getMinutes())
const s = pad2(date.getSeconds())
return `${y}-${m}-${d} ${h}:${min}:${s}`
}
function handleItemClick(item) {
uni.showToast({ title: t('planList.viewDetail', { code: item.taskCode }), icon: 'none' })
}
async function loadPlanList(reset = false) {
if (loading.value) return
if (reset) {
pageNo.value = 1
noMore.value = false
planList.splice(0, planList.length)
}
if (noMore.value && !reset) return
loading.value = true
try {
const res = await request({
url: '/admin-api/mes/baogong-record/stat-page',
method: 'get',
params: { pageNo: pageNo.value, pageSize: pageSize.value }
})
const list = res?.data?.list || []
total.value = res?.data?.total || 0
const mapped = list.map((item) => ({
id: item?.id,
taskCode: item?.taskCode ?? '-',
planCode: item?.planCode ?? '-',
employeeName: item?.employeeName ?? '-',
productName: item?.productName ?? '-',
productCode: item?.productCode ?? '-',
baogongNum: item?.baogongNum ?? 0,
passNum: item?.passNum ?? 0,
noPassNum: item?.noPassNum ?? 0,
passRate: item?.passRate ?? 0,
passRateText: item?.passRate != null ? `${item.passRate.toFixed(2)}%` : '-',
reason: item?.reason ?? '',
baogongTime: item?.baogongTime,
baogongTimeText: formatDateTime(item?.baogongTime)
}))
planList.splice(planList.length, 0, ...mapped)
if (planList.length >= total.value) {
noMore.value = true
} else {
pageNo.value++
}
})
planList.splice(0, planList.length, ...mapped)
} finally {
loading.value = false
}
}
onMounted(() => {
loadPlanList(true)
})
onReachBottom(() => {
loadPlanList()
})
onShow(() => {
setNavigationTitle('nav.home')
setNavigationTitle('dashboard.productionPlan')
})
</script>
@ -153,25 +186,12 @@ onShow(() => {
color: #1a3a5c;
}
.plan-status {
padding: 8rpx 20rpx;
border-radius: 20rpx;
font-size: 22rpx;
}
.status-pending {
background: rgba(255, 140, 0, 0.15);
color: #ff8c00;
}
.status-running {
background: rgba(24, 188, 55, 0.15);
color: #18bc37;
}
.status-finished {
background: rgba(74, 144, 194, 0.15);
color: #4a90c2;
.plan-product-code {
font-size: 24rpx;
color: #999999;
background: #f0f2f5;
padding: 4rpx 16rpx;
border-radius: 8rpx;
}
.plan-body {
@ -203,17 +223,39 @@ onShow(() => {
.plan-num {
font-weight: 600;
color: #1a3a5c;
&.pass {
color: #18bc37;
}
&.warn {
color: #ff8c00;
}
&.fail {
color: #ff3b30;
}
}
.reason-text {
max-width: 400rpx;
text-align: right;
word-break: break-all;
}
.empty-state {
.loading-state,
.empty-state,
.no-more-state {
display: flex;
align-items: center;
justify-content: center;
height: 400rpx;
height: 200rpx;
}
.empty-text {
font-size: 28rpx;
color: #999999;
}
.loading-text,
.empty-text,
.no-more-text {
font-size: 28rpx;
color: #999999;
}
</style>

@ -0,0 +1,273 @@
<template>
<view class="page-container">
<view class="task-list">
<view v-for="(task, index) in taskList" :key="index" class="task-card" @click="handleTaskClick(task)">
<view class="task-header">
<text class="task-code">{{ task.code }}</text>
<view class="task-status" :class="'status-' + task.statusType">
<text>{{ task.statusText }}</text>
</view>
</view>
<view class="task-body">
<view class="task-row">
<text class="task-label">{{ t('taskList.taskType') }}</text>
<text class="task-value">{{ task.taskType || '-' }}</text>
</view>
<view class="task-row">
<text class="task-label">{{ t('taskList.orderDate') }}</text>
<text class="task-value">{{ task.orderDateText }}</text>
</view>
<view class="task-row">
<text class="task-label">{{ t('taskList.deliveryDate') }}</text>
<text class="task-value">{{ task.deliveryDateText }}</text>
</view>
<view class="task-row">
<text class="task-label">{{ t('taskList.totalNumber') }}</text>
<text class="task-value task-num">{{ task.totalNumber }}</text>
</view>
<view class="task-row">
<text class="task-label">{{ t('taskList.planNumber') }}</text>
<text class="task-value task-num">{{ task.planNumber }}</text>
</view>
<view class="task-row">
<text class="task-label">{{ t('taskList.unPlanNumber') }}</text>
<text class="task-value task-num">{{ task.unPlanNumber }}</text>
</view>
<view class="task-row">
<text class="task-label">{{ t('taskList.storedPlanNumber') }}</text>
<text class="task-value task-num">{{ task.storedPlanNumber }}</text>
</view>
<view v-if="task.isUrgent === 1" class="task-urgent">
<text class="urgent-text">{{ t('taskList.urgent') }}</text>
</view>
</view>
</view>
</view>
<view v-if="loading" class="loading-state">
<text class="loading-text">{{ t('functionCommon.loading') }}</text>
</view>
<view v-else-if="taskList.length === 0" class="empty-state">
<text class="empty-text">{{ t('taskList.noData') }}</text>
</view>
<view v-else-if="noMore" class="no-more-state">
<text class="no-more-text">{{ t('functionCommon.noMoreData') }}</text>
</view>
</view>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { onReachBottom, onShow } from '@dcloudio/uni-app'
import { useI18n } from 'vue-i18n'
import request from '@/utils/request'
import { setNavigationTitle } from '@/locales'
const { t } = useI18n()
const taskList = reactive([])
const pageNo = ref(1)
const pageSize = ref(10)
const total = ref(0)
const loading = ref(false)
const noMore = ref(false)
function formatDate(dateStr) {
if (!dateStr) return '-'
const date = new Date(dateStr)
if (Number.isNaN(date.getTime())) return '-'
const pad2 = (n) => String(n).padStart(2, '0')
return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())}`
}
function mapTaskStatus(status) {
const v = status === '' || status === null || status === undefined ? undefined : String(status)
if (v === '1') return { statusText: t('dashboard.pending'), statusType: 'pending' }
if (v === '2') return { statusText: t('dashboard.running'), statusType: 'running' }
if (v === '3') return { statusText: t('dashboard.finished'), statusType: 'finished' }
return { statusText: '-', statusType: 'pending' }
}
function handleTaskClick(task) {
uni.showToast({ title: t('taskList.viewTask', { code: task.code }), icon: 'none' })
}
async function loadTaskList(reset = false) {
if (loading.value) return
if (reset) {
pageNo.value = 1
noMore.value = false
taskList.splice(0, taskList.length)
}
if (noMore.value && !reset) return
loading.value = true
try {
const res = await request({
url: '/admin-api/mes/task/pagePlanTask',
method: 'get',
params: { pageNo: pageNo.value, pageSize: pageSize.value }
})
const list = res?.data?.list || []
total.value = res?.data?.total || 0
const mapped = list.map((item) => {
const statusInfo = mapTaskStatus(item?.status)
return {
id: item?.id,
code: item?.code ?? '-',
taskType: item?.taskType ?? '-',
orderDateText: formatDate(item?.orderDate),
deliveryDateText: formatDate(item?.deliveryDate),
isUrgent: item?.isUrgent,
isScheduled: item?.isScheduled,
status: item?.status,
statusText: statusInfo.statusText,
statusType: statusInfo.statusType,
totalNumber: item?.totalNumber ?? 0,
planNumber: item?.planNumber ?? 0,
unPlanNumber: item?.unPlanNumber ?? 0,
storedPlanNumber: item?.storedPlanNumber ?? 0,
remark: item?.remark ?? ''
}
})
taskList.splice(taskList.length, 0, ...mapped)
if (taskList.length >= total.value) {
noMore.value = true
} else {
pageNo.value++
}
} finally {
loading.value = false
}
}
onMounted(() => {
loadTaskList(true)
})
onReachBottom(() => {
loadTaskList()
})
onShow(() => {
setNavigationTitle('dashboard.productionPlan')
})
</script>
<style lang="scss" scoped>
.page-container {
min-height: 100vh;
background-color: #f0f2f5;
padding: 24rpx;
}
.task-list {
display: flex;
flex-direction: column;
}
.task-card {
background: #ffffff;
border-radius: 16rpx;
padding: 24rpx;
margin-bottom: 20rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
&:active {
background: #e8f4ff;
}
}
.task-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
}
.task-code {
font-size: 28rpx;
font-weight: 600;
color: #1a3a5c;
}
.task-status {
padding: 8rpx 20rpx;
border-radius: 20rpx;
font-size: 22rpx;
}
.status-pending {
background: rgba(255, 140, 0, 0.15);
color: #ff8c00;
}
.status-running {
background: rgba(24, 188, 55, 0.15);
color: #18bc37;
}
.status-finished {
background: rgba(74, 144, 194, 0.15);
color: #4a90c2;
}
.task-body {
display: flex;
flex-direction: column;
}
.task-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12rpx;
&:last-child {
margin-bottom: 0;
}
}
.task-label {
font-size: 26rpx;
color: #999999;
}
.task-value {
font-size: 26rpx;
color: #333333;
}
.task-num {
font-weight: 600;
color: #1a3a5c;
}
.task-urgent {
margin-top: 12rpx;
padding: 8rpx 16rpx;
background: rgba(255, 59, 48, 0.1);
border-radius: 8rpx;
align-self: flex-start;
}
.urgent-text {
font-size: 22rpx;
color: #ff3b30;
font-weight: 600;
}
.loading-state,
.empty-state,
.no-more-state {
display: flex;
align-items: center;
justify-content: center;
height: 200rpx;
}
.loading-text,
.empty-text,
.no-more-text {
font-size: 28rpx;
color: #999999;
}
</style>
Loading…
Cancel
Save