0930-noon
This commit is contained in:
parent
998310cf2e
commit
7734c0cd89
@ -1,4 +1,4 @@
|
|||||||
const BASE_URL = 'http://10.3.1.212:8089';//定义后端基础接口地址
|
const BASE_URL = 'http://110.42.33.196:8089';//定义后端基础接口地址
|
||||||
import config from '../../config.js'; // 引入配置文件
|
import config from '../../config.js'; // 引入配置文件
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
const BASE_URL = 'http://10.3.1.212:8089';
|
const BASE_URL = 'http://110.42.33.196:8089';
|
||||||
const config = require('config.js');
|
const config = require('config.js');
|
||||||
const formatTime = date => {
|
const formatTime = date => {
|
||||||
date = new Date(date);
|
date = new Date(date);
|
||||||
|
|||||||
@ -1,25 +1,95 @@
|
|||||||
<template>
|
<template>
|
||||||
<scroll-view scroll-y class="page">
|
<scroll-view scroll-y class="page">
|
||||||
<view v-for="item in detailPlan" :key="item.Id || item.id" class="item-card">
|
<!-- 搜索栏 -->
|
||||||
<view class="row"><text class="label">物资名称:</text><text class="value">{{ item.goodsName }}</text></view>
|
<view class="search-sticky">
|
||||||
<view class="row"><text class="label">发放数量:</text><text class="value highlight">{{ item.actualQuantity
|
<view class="search-bar">
|
||||||
}}</text></view>
|
<text class="search-label">领用小组</text>
|
||||||
<view class="row"><text class="label">领用小组:</text><text class="value">{{ item.groupName }}</text></view>
|
<input
|
||||||
<view class="row"><text class="label">备注:</text><text class="value">{{ item.notes || '无' }}</text></view>
|
class="search-input"
|
||||||
<view class="row"><text class="label">发放计划:</text><text class="value">{{ item.planTitle }}</text></view>
|
v-model.trim="keyword"
|
||||||
|
type="text"
|
||||||
|
confirm-type="search"
|
||||||
|
placeholder="输入小组名称筛选"
|
||||||
|
@confirm="onSearchConfirm"
|
||||||
|
/>
|
||||||
|
<button v-if="keyword" size="mini" class="clear-btn" @tap="clearKeyword">清除</button>
|
||||||
|
</view>
|
||||||
|
<view class="search-meta">
|
||||||
|
<text class="meta-chip">共 {{ detailPlan.length }} 条</text>
|
||||||
|
<text v-if="keyword" class="meta-dot">·</text>
|
||||||
|
<text v-if="keyword" class="meta-chip accent">筛选出 {{ filteredPlan.length }} 条</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 加载骨架屏 -->
|
||||||
|
<view v-if="loading" class="skeleton-list">
|
||||||
|
<view class="card skeleton" v-for="n in 3" :key="n">
|
||||||
|
<view class="skeleton-line w-70"></view>
|
||||||
|
<view class="skeleton-line w-40"></view>
|
||||||
|
<view class="skeleton-line w-90"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 列表卡片 -->
|
||||||
|
<view v-else>
|
||||||
|
<view v-for="item in filteredPlan" :key="item.Id || item.id" class="card">
|
||||||
|
<!-- 卡片头部:名称 + 状态 -->
|
||||||
|
<view class="card-header">
|
||||||
|
<text class="goods-name">{{ item.goodsName }}</text>
|
||||||
|
<view class="status-badge" :class="item.isDistributed == 0 ? 'pending' : 'done'">
|
||||||
|
<text>{{ item.isDistributed == 0 ? '待领用' : '已领用' }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 关键指标:数量、组别 -->
|
||||||
|
<view class="key-meta">
|
||||||
|
<view class="meta-block">
|
||||||
|
<text class="meta-label">发放数量</text>
|
||||||
|
<text class="meta-value number">{{ item.actualQuantity }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="meta-block">
|
||||||
|
<text class="meta-label">领用小组</text>
|
||||||
|
<text class="meta-value tag">{{ item.groupName }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 详细信息 -->
|
||||||
|
<view class="detail">
|
||||||
|
<view class="detail-row">
|
||||||
|
<text class="label">备注</text>
|
||||||
|
<text class="value ellipsis-2">{{ item.notes || '无' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="detail-row">
|
||||||
|
<text class="label">发放计划</text>
|
||||||
|
<text class="value">{{ item.planTitle }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="detail-row">
|
||||||
|
<text class="label">领用时间</text>
|
||||||
|
<text class="value">{{ item.getTime ?? '-' }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 操作区 -->
|
||||||
<view class="action">
|
<view class="action">
|
||||||
<button v-if="item.isDistributed == 0" size="mini" class="primary" @tap="reciept(item)">领用</button>
|
<button
|
||||||
<view v-else class="done">已领用</view>
|
v-if="item.isDistributed == 0"
|
||||||
|
size="mini"
|
||||||
|
class="primary"
|
||||||
|
@tap="reciept(item)"
|
||||||
|
>领用</button>
|
||||||
|
<view v-else class="done-text">已领用</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view v-if="detailPlan.length === 0 && !loading" class="empty">暂无更多数据</view>
|
<view v-if="!loading && filteredPlan.length === 0 && detailPlan.length > 0" class="empty">未找到匹配的小组</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-if="!loading && detailPlan.length === 0" class="empty">暂无数据</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
import { onLoad } from '@dcloudio/uni-app'
|
import { onLoad } from '@dcloudio/uni-app'
|
||||||
// @ts-ignore JS模块无类型声明
|
// @ts-ignore JS模块无类型声明
|
||||||
import { getConsumptionDetail, consumptonConfirm } from '@/pages/api/fixedAssets.js'
|
import { getConsumptionDetail, consumptonConfirm } from '@/pages/api/fixedAssets.js'
|
||||||
@ -29,6 +99,13 @@ type Item = Record<string, any>
|
|||||||
const detailPlan = ref<Item[]>([])
|
const detailPlan = ref<Item[]>([])
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const planId = ref<string | number>('')
|
const planId = ref<string | number>('')
|
||||||
|
const keyword = ref('')
|
||||||
|
|
||||||
|
const filteredPlan = computed<Item[]>(() => {
|
||||||
|
const kw = keyword.value.trim().toLowerCase()
|
||||||
|
if (!kw) return detailPlan.value
|
||||||
|
return detailPlan.value.filter((i: any) => String(i?.groupName ?? '').toLowerCase().includes(kw))
|
||||||
|
})
|
||||||
|
|
||||||
async function loadDetail(id: string | number) {
|
async function loadDetail(id: string | number) {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
@ -69,6 +146,14 @@ async function reciept(item: any) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clearKeyword() {
|
||||||
|
keyword.value = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSearchConfirm() {
|
||||||
|
// 保留占位,若后续需要联动键盘收起等,可在此处理
|
||||||
|
}
|
||||||
|
|
||||||
onLoad((query) => {
|
onLoad((query) => {
|
||||||
const id = query?.id
|
const id = query?.id
|
||||||
if (!id) {
|
if (!id) {
|
||||||
@ -88,18 +173,155 @@ onLoad((query) => {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-card {
|
.search-sticky {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 10;
|
||||||
|
background: #f5f7fb;
|
||||||
|
padding-bottom: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-bar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16rpx;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-radius: 16rpx;
|
border-radius: 999rpx;
|
||||||
padding: 20rpx;
|
padding: 12rpx 16rpx;
|
||||||
margin-bottom: 16rpx;
|
|
||||||
box-shadow: 0 6rpx 16rpx rgba(0, 0, 0, 0.06);
|
box-shadow: 0 6rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||||
}
|
}
|
||||||
|
|
||||||
.row {
|
.search-label {
|
||||||
|
color: #666;
|
||||||
|
font-size: 26rpx;
|
||||||
|
margin-left: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input {
|
||||||
|
flex: 1;
|
||||||
|
height: 64rpx;
|
||||||
|
line-height: 64rpx;
|
||||||
|
padding: 0 8rpx;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
font-size: 28rpx;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clear-btn {
|
||||||
|
margin: 0;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
background: #eff3ff;
|
||||||
|
color: #4b7aff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-meta {
|
||||||
|
margin-top: 10rpx;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 8rpx;
|
gap: 8rpx;
|
||||||
|
padding: 0 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-chip {
|
||||||
|
color: #8a8f99;
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-chip.accent {
|
||||||
|
color: #4b7aff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-dot {
|
||||||
|
color: #c0c4cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 20rpx;
|
||||||
|
margin: 16rpx 0;
|
||||||
|
box-shadow: 0 6rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-name {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-badge {
|
||||||
|
padding: 4rpx 12rpx;
|
||||||
|
border-radius: 999rpx;
|
||||||
|
font-size: 22rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-badge.pending {
|
||||||
|
background: #fff4e5;
|
||||||
|
color: #ff9800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-badge.done {
|
||||||
|
background: #e8f5e9;
|
||||||
|
color: #2e7d32;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-meta {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 16rpx;
|
||||||
|
margin: 8rpx 0 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-block {
|
||||||
|
background: #f7f9ff;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
padding: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-label {
|
||||||
|
display: block;
|
||||||
|
color: #8a8f99;
|
||||||
|
font-size: 22rpx;
|
||||||
|
margin-bottom: 6rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-value {
|
||||||
|
color: #333;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-value.number {
|
||||||
|
color: #e53935;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 36rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-value.tag {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 2rpx 12rpx;
|
||||||
|
background: #eff3ff;
|
||||||
|
color: #4b7aff;
|
||||||
|
border-radius: 999rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail {
|
||||||
|
margin-top: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin: 8rpx 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
@ -111,9 +333,12 @@ onLoad((query) => {
|
|||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
.highlight {
|
.ellipsis-2 {
|
||||||
color: #e53935;
|
display: -webkit-box;
|
||||||
font-weight: 600;
|
line-clamp: 2;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action {
|
.action {
|
||||||
@ -123,7 +348,7 @@ onLoad((query) => {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.done {
|
.done-text {
|
||||||
color: #2e7d32;
|
color: #2e7d32;
|
||||||
font-size: 24rpx;
|
font-size: 24rpx;
|
||||||
}
|
}
|
||||||
@ -141,4 +366,40 @@ button.primary {
|
|||||||
padding: 0rpx 24rpx;
|
padding: 0rpx 24rpx;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 骨架屏样式 */
|
||||||
|
.skeleton-list .card {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(90deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.04) 50%, rgba(0,0,0,0) 100%);
|
||||||
|
animation: shimmer 1.2s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-line {
|
||||||
|
height: 28rpx;
|
||||||
|
background: #f0f2f5;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
margin: 14rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-line.w-70 { width: 70%; }
|
||||||
|
.skeleton-line.w-40 { width: 40%; }
|
||||||
|
.skeleton-line.w-90 { width: 90%; }
|
||||||
|
|
||||||
|
@keyframes shimmer {
|
||||||
|
0% { transform: translateX(-100%); }
|
||||||
|
100% { transform: translateX(100%); }
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -1,24 +1,53 @@
|
|||||||
<template>
|
<template>
|
||||||
<scroll-view scroll-y class="page">
|
<scroll-view scroll-y class="page">
|
||||||
<view v-if="inventoryPlanList.length === 0 && !loading" class="empty">暂无更多数据</view>
|
<!-- 加载骨架屏 -->
|
||||||
|
<view v-if="loading" class="skeleton-list">
|
||||||
|
<view class="card skeleton" v-for="n in 3" :key="n">
|
||||||
|
<view class="skeleton-line w-70"></view>
|
||||||
|
<view class="skeleton-line w-40"></view>
|
||||||
|
<view class="skeleton-line w-90"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 列表内容 -->
|
||||||
|
<view v-else>
|
||||||
|
<view v-if="inventoryPlanList.length === 0" class="empty">暂无数据</view>
|
||||||
|
|
||||||
<view class="inventory-list">
|
<view class="inventory-list">
|
||||||
<view class="inventory-item" v-for="item in inventoryPlanList" :key="item.inventoryId || item.id" @tap="gotoPlanDetail(item)">
|
<view class="card inventory-item" v-for="item in inventoryPlanList" :key="item.inventoryId || item.id" @tap="gotoPlanDetail(item)">
|
||||||
<view class="header">
|
<!-- 卡片头部:标题 + 状态 -->
|
||||||
<text class="title">📋 盘点计划</text>
|
<view class="card-header">
|
||||||
<text class="status-tag" :class="statusClass(item.status)">{{ item.status || '未知' }}</text>
|
<text class="title ellipsis-1">📋 盘点计划</text>
|
||||||
|
<text class="status-badge" :class="statusClass(item.status)">{{ item.status || '未知' }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 关键指标:开始/结束日期 -->
|
||||||
|
<view class="key-meta">
|
||||||
|
<view class="meta-block">
|
||||||
|
<text class="meta-label">开始日期</text>
|
||||||
|
<text class="meta-value">{{ item.checkStartDate || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="meta-block">
|
||||||
|
<text class="meta-label">结束日期</text>
|
||||||
|
<text class="meta-value">{{ item.checkEndDate || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 详情信息 -->
|
||||||
|
<view class="detail">
|
||||||
|
<view class="detail-row">
|
||||||
|
<text class="label">创建人</text>
|
||||||
|
<text class="value ellipsis-1">{{ item.createByName || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="detail-row">
|
||||||
|
<text class="label">计划ID</text>
|
||||||
|
<text class="value">{{ item.id || item.inventoryId }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="content">
|
|
||||||
<view class="row">开始日期:<text class="value">{{ item.checkStartDate || '-' }}</text></view>
|
|
||||||
<view class="row">结束日期:<text class="value">{{ item.checkEndDate || '-' }}</text></view>
|
|
||||||
<view class="row">创建人:<text class="value">{{ item.createByName || '-' }}</text></view>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="load-status">
|
<view class="load-status" v-if="noMore && inventoryPlanList.length > 0">没有更多数据了</view>
|
||||||
<text v-if="loading">加载中...</text>
|
|
||||||
<text v-else-if="noMore">没有更多数据了</text>
|
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
</template>
|
</template>
|
||||||
@ -88,14 +117,37 @@ onReachBottom(() => {
|
|||||||
.page { min-height: 100vh; background: #f5f7fb; padding: 24rpx; box-sizing: border-box; }
|
.page { min-height: 100vh; background: #f5f7fb; padding: 24rpx; box-sizing: border-box; }
|
||||||
.empty { color: #9a9aa0; text-align: center; padding: 24rpx 0; }
|
.empty { color: #9a9aa0; text-align: center; padding: 24rpx 0; }
|
||||||
.inventory-list { display: flex; flex-direction: column; gap: 16rpx; }
|
.inventory-list { display: flex; flex-direction: column; gap: 16rpx; }
|
||||||
.inventory-item { background: #fff; border-radius: 16rpx; padding: 20rpx; box-shadow: 0 6rpx 16rpx rgba(0,0,0,0.06); }
|
|
||||||
.header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12rpx; }
|
.card { background: #fff; border-radius: 16rpx; padding: 20rpx; box-shadow: 0 6rpx 16rpx rgba(0,0,0,0.06); }
|
||||||
.title { font-size: 30rpx; color: #222; font-weight: 600; }
|
.card-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12rpx; }
|
||||||
.status-tag { font-size: 24rpx; padding: 4rpx 10rpx; border-radius: 999rpx; }
|
.title { font-size: 32rpx; color: #222; font-weight: 600; }
|
||||||
.status-tag.running { color: #1e88e5; background: #e3f2fd; }
|
|
||||||
.status-tag.ended { color: #2e7d32; background: #e8f5e9; }
|
.status-badge { font-size: 24rpx; padding: 4rpx 12rpx; border-radius: 999rpx; }
|
||||||
.status-tag.unknown { color: #757575; background: #eeeeee; }
|
.status-badge.running { color: #1e88e5; background: #e3f2fd; }
|
||||||
.content .row { margin-top: 6rpx; color: #444; }
|
.status-badge.ended { color: #2e7d32; background: #e8f5e9; }
|
||||||
|
.status-badge.unknown { color: #757575; background: #eeeeee; }
|
||||||
|
|
||||||
|
.key-meta { display: grid; grid-template-columns: 1fr 1fr; gap: 16rpx; margin: 8rpx 0 12rpx; }
|
||||||
|
.meta-block { background: #f7f9ff; border-radius: 12rpx; padding: 16rpx; }
|
||||||
|
.meta-label { display: block; color: #8a8f99; font-size: 22rpx; margin-bottom: 6rpx; }
|
||||||
|
.meta-value { color: #333; font-size: 28rpx; }
|
||||||
|
|
||||||
|
.detail { margin-top: 8rpx; }
|
||||||
|
.detail-row { display: flex; align-items: flex-start; margin: 8rpx 0; }
|
||||||
|
.label { color: #888; min-width: 140rpx; }
|
||||||
.value { color: #333; }
|
.value { color: #333; }
|
||||||
|
|
||||||
|
.ellipsis-1 { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||||
|
|
||||||
.load-status { text-align: center; color: #9a9aa0; padding: 20rpx 0; }
|
.load-status { text-align: center; color: #9a9aa0; padding: 20rpx 0; }
|
||||||
|
|
||||||
|
/* 骨架屏样式 */
|
||||||
|
.skeleton-list .card { overflow: hidden; }
|
||||||
|
.skeleton { position: relative; }
|
||||||
|
.skeleton::after { content: ''; position: absolute; left: 0; top: 0; width: 100%; height: 100%; background: linear-gradient(90deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.04) 50%, rgba(0,0,0,0) 100%); animation: shimmer 1.2s infinite; }
|
||||||
|
.skeleton-line { height: 28rpx; background: #f0f2f5; border-radius: 8rpx; margin: 14rpx 0; }
|
||||||
|
.skeleton-line.w-70 { width: 70%; }
|
||||||
|
.skeleton-line.w-40 { width: 40%; }
|
||||||
|
.skeleton-line.w-90 { width: 90%; }
|
||||||
|
@keyframes shimmer { 0% { transform: translateX(-100%);} 100% { transform: translateX(100%);} }
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -1,48 +1,55 @@
|
|||||||
<template>
|
<template>
|
||||||
<scroll-view scroll-y class="page">
|
<scroll-view scroll-y class="page">
|
||||||
<view v-if="planList.length === 0 && !loading" class="empty">暂无更多数据</view>
|
<!-- 加载骨架屏 -->
|
||||||
|
<view v-if="loading" class="skeleton-list">
|
||||||
|
<view class="card skeleton" v-for="n in 3" :key="n">
|
||||||
|
<view class="skeleton-line w-70"></view>
|
||||||
|
<view class="skeleton-line w-40"></view>
|
||||||
|
<view class="skeleton-line w-90"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<view v-for="plan in planList" :key="plan.id" class="plan-card">
|
<!-- 列表内容 -->
|
||||||
<view class="plan-header">
|
<view v-else>
|
||||||
<text class="plan-title">{{ plan.planTitle }}</text>
|
<view v-if="planList.length === 0" class="empty">暂无数据</view>
|
||||||
|
|
||||||
|
<view v-for="plan in planList" :key="plan.id" class="card plan-card">
|
||||||
|
<!-- 头部:标题 + 操作 -->
|
||||||
|
<view class="card-header">
|
||||||
|
<text class="plan-title ellipsis-1">{{ plan.planTitle }}</text>
|
||||||
<text class="plan-action" @tap="goToDistribution(plan.id)">发放物资</text>
|
<text class="plan-action" @tap="goToDistribution(plan.id)">发放物资</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="plan-info">
|
<!-- 关键指标:数量 + 周期类型 -->
|
||||||
<view class="info-item">
|
<view class="key-meta">
|
||||||
<text class="label">医院:</text>
|
<view class="meta-block">
|
||||||
<text class="value">{{ plan.hospName }}</text>
|
<text class="meta-label">发放数量</text>
|
||||||
|
<text class="meta-value number">{{ plan.quantityPerPeriod }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="info-item">
|
<view class="meta-block">
|
||||||
<text class="label">周期类型:</text>
|
<text class="meta-label">周期类型</text>
|
||||||
<text class="value">{{ plan.periodType }}</text>
|
<text class="meta-value tag">{{ plan.periodType }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="info-item">
|
|
||||||
<text class="label">发放数量:</text>
|
<view class="time-item">
|
||||||
<text class="value">{{ plan.quantityPerPeriod }}</text>
|
<text class="time-label">上次分配</text>
|
||||||
</view>
|
<text class="time-value">{{ plan.lastDistributionDate || '-' }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="time-item">
|
||||||
<view class="plan-time">
|
<text class="time-label">下次分配</text>
|
||||||
<view class="info-item">
|
<text class="time-value">{{ plan.nextDistributionDate || '-' }}</text>
|
||||||
<text class="label">上次分配:</text>
|
|
||||||
<text class="value">{{ plan.lastDistributionDate || '-' }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="info-item">
|
|
||||||
<text class="label">下次分配:</text>
|
|
||||||
<text class="value">{{ plan.nextDistributionDate || '-' }}</text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- 底部信息 -->
|
||||||
<view class="plan-footer">
|
<view class="plan-footer">
|
||||||
<text class="created">创建人:{{ plan.createdByName }}({{ plan.createdByMobile }})</text>
|
<text class="hosp ellipsis-1">医院:{{ plan.hospName }}</text>
|
||||||
<text class="time">创建时间:{{ plan.createdTime }}</text>
|
<text class="created ellipsis-1">创建人:{{ plan.createdByName }}({{ plan.createdByMobile }})</text>
|
||||||
|
<text class="time ellipsis-1">创建时间:{{ plan.createdTime }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="load-status">
|
<view class="load-status" v-if="noMore && planList.length > 0">没有更多数据了</view>
|
||||||
<text v-if="loading">加载中...</text>
|
|
||||||
<text v-else-if="noMore">没有更多数据了</text>
|
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
|
|
||||||
@ -118,42 +125,196 @@ onReachBottom(() => {
|
|||||||
background: #f5f7fb;
|
background: #f5f7fb;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty {
|
.empty {
|
||||||
color: #9a9aa0;
|
color: #9a9aa0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 24rpx 0;
|
padding: 24rpx 0;
|
||||||
}
|
}
|
||||||
.plan-card {
|
|
||||||
|
.card {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-radius: 16rpx;
|
border-radius: 16rpx;
|
||||||
padding: 20rpx;
|
padding: 20rpx;
|
||||||
margin-bottom: 16rpx;
|
margin-bottom: 16rpx;
|
||||||
box-shadow: 0 6rpx 16rpx rgba(0, 0, 0, 0.06);
|
box-shadow: 0 6rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||||
}
|
}
|
||||||
.plan-header {
|
|
||||||
|
.card-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-bottom: 12rpx;
|
margin-bottom: 12rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plan-title {
|
.plan-title {
|
||||||
font-size: 30rpx;
|
font-size: 32rpx;
|
||||||
color: #222;
|
color: #222;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plan-action {
|
.plan-action {
|
||||||
font-size: 26rpx;
|
font-size: 26rpx;
|
||||||
color: #4b7aff;
|
color: #4b7aff;
|
||||||
|
padding: 8rpx 16rpx;
|
||||||
|
border: 2rpx solid #4b7aff;
|
||||||
|
border-radius: 999rpx;
|
||||||
}
|
}
|
||||||
.plan-info, .plan-time {
|
|
||||||
|
.key-meta {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: 1fr 1fr;
|
||||||
gap: 12rpx;
|
gap: 16rpx;
|
||||||
margin-bottom: 8rpx;
|
margin: 8rpx 0 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-block {
|
||||||
|
background: #f7f9ff;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
padding: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-label {
|
||||||
|
display: block;
|
||||||
|
color: #8a8f99;
|
||||||
|
font-size: 22rpx;
|
||||||
|
margin-bottom: 6rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-value {
|
||||||
|
color: #333;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-value.number {
|
||||||
|
color: #e53935;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 36rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-value.tag {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 2rpx 12rpx;
|
||||||
|
background: #eff3ff;
|
||||||
|
color: #4b7aff;
|
||||||
|
border-radius: 999rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail {
|
||||||
|
margin: 8rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin: 8rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
color: #888;
|
||||||
|
min-width: 140rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 12rpx;
|
||||||
|
margin-top: 4rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 6rpx;
|
||||||
|
background: #fafafa;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
padding: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-label {
|
||||||
|
color: #8a8f99;
|
||||||
|
font-size: 22rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-value {
|
||||||
|
color: #333;
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plan-footer {
|
||||||
|
color: #666;
|
||||||
|
font-size: 24rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6rpx;
|
||||||
|
margin-top: 6rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load-status {
|
||||||
|
text-align: center;
|
||||||
|
color: #9a9aa0;
|
||||||
|
padding: 20rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ellipsis-1 {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 骨架屏样式 */
|
||||||
|
.skeleton-list .card {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.04) 50%, rgba(0, 0, 0, 0) 100%);
|
||||||
|
animation: shimmer 1.2s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-line {
|
||||||
|
height: 28rpx;
|
||||||
|
background: #f0f2f5;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
margin: 14rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-line.w-70 {
|
||||||
|
width: 70%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-line.w-40 {
|
||||||
|
width: 40%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-line.w-90 {
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes shimmer {
|
||||||
|
0% {
|
||||||
|
transform: translateX(-100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: translateX(100%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.info-item { color: #444; }
|
|
||||||
.label { color: #888; }
|
|
||||||
.value { color: #333; }
|
|
||||||
.plan-footer { color: #666; font-size: 24rpx; display: flex; flex-direction: column; gap: 6rpx; }
|
|
||||||
.load-status { text-align: center; color: #9a9aa0; padding: 20rpx 0; }
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -62,8 +62,8 @@
|
|||||||
<view class="image-viewer">
|
<view class="image-viewer">
|
||||||
<view class="image-label">设备照片</view>
|
<view class="image-label">设备照片</view>
|
||||||
<view class="image-container" @tap="previewImage">
|
<view class="image-container" @tap="previewImage">
|
||||||
<image class="image" :src="detailData.assetPic || defaultImage" mode="aspectFit" />
|
<image class="image" :src="detailData.image || defaultImage" mode="aspectFit" />
|
||||||
<view class="image-hint" v-if="detailData.assetPic">点击预览大图</view>
|
<view class="image-hint" v-if="detailData.image">点击预览大图</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -99,10 +99,7 @@ async function fetchBySn(sn: string) {
|
|||||||
const d = data?.data
|
const d = data?.data
|
||||||
if (Array.isArray(d) && d.length > 0) {
|
if (Array.isArray(d) && d.length > 0) {
|
||||||
detailData.value = d[0]
|
detailData.value = d[0]
|
||||||
} else if (Array.isArray(d?.list) && d.list.length > 0) {
|
detailData.value.image = 'data:image/png;base64,' + detailData.value.image
|
||||||
detailData.value = d.list[0]
|
|
||||||
} else if (d && typeof d === 'object') {
|
|
||||||
detailData.value = d
|
|
||||||
} else {
|
} else {
|
||||||
detailData.value = {}
|
detailData.value = {}
|
||||||
}
|
}
|
||||||
@ -113,8 +110,8 @@ async function fetchBySn(sn: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function previewImage() {
|
function previewImage() {
|
||||||
if (detailData.value.assetPic) {
|
if (detailData.value.image) {
|
||||||
uni.previewImage({ urls: [detailData.value.assetPic], current: detailData.value.assetPic,
|
uni.previewImage({ urls: [detailData.value.image], current: detailData.value.image,
|
||||||
fail: () => uni.showToast({ title: '预览失败,请稍后重试', icon: 'none' }) })
|
fail: () => uni.showToast({ title: '预览失败,请稍后重试', icon: 'none' }) })
|
||||||
} else {
|
} else {
|
||||||
uni.showToast({ title: '暂无设备照片', icon: 'none' })
|
uni.showToast({ title: '暂无设备照片', icon: 'none' })
|
||||||
|
|||||||
@ -73,7 +73,7 @@
|
|||||||
</view> -->
|
</view> -->
|
||||||
<view class="form-item">
|
<view class="form-item">
|
||||||
<text class="label">借用日期:</text>
|
<text class="label">借用日期:</text>
|
||||||
<picker mode="date" @change="onBorrowDateChange">
|
<picker mode="date" :value="borrowForm.borrowDate" @change="onBorrowDateChange">
|
||||||
<view class="picker-value">{{ borrowForm.borrowDate || '请选择借用日期' }}</view>
|
<view class="picker-value">{{ borrowForm.borrowDate || '请选择借用日期' }}</view>
|
||||||
</picker>
|
</picker>
|
||||||
</view>
|
</view>
|
||||||
@ -129,6 +129,13 @@ const userSuggestions = ref<any[]>([])
|
|||||||
let searchTimeout: any = null
|
let searchTimeout: any = null
|
||||||
const isSearching = ref(false)
|
const isSearching = ref(false)
|
||||||
|
|
||||||
|
function formatDate(d: Date) {
|
||||||
|
const y = d.getFullYear()
|
||||||
|
const m = String(d.getMonth() + 1).padStart(2, '0')
|
||||||
|
const day = String(d.getDate()).padStart(2, '0')
|
||||||
|
return `${y}-${m}-${day}`
|
||||||
|
}
|
||||||
|
|
||||||
onLoad(() => {
|
onLoad(() => {
|
||||||
getAssetList()
|
getAssetList()
|
||||||
})
|
})
|
||||||
@ -199,6 +206,8 @@ function borrow(item: AssetItem) {
|
|||||||
showBorrowPopup.value = true
|
showBorrowPopup.value = true
|
||||||
userSuggestions.value = []
|
userSuggestions.value = []
|
||||||
borrowForm.value.lenderMobile = ''
|
borrowForm.value.lenderMobile = ''
|
||||||
|
// 默认借用日期为今天
|
||||||
|
borrowForm.value.borrowDate = formatDate(new Date())
|
||||||
}
|
}
|
||||||
|
|
||||||
function cancelBorrow() {
|
function cancelBorrow() {
|
||||||
@ -356,7 +365,7 @@ async function confirmBorrow() {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
z-index: 1000;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-content {
|
.modal-content {
|
||||||
|
|||||||
@ -1,27 +1,70 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="page">
|
<view class="page">
|
||||||
<view class="load-status" v-if="!inventoryPlanList.length && !loading">没有更多数据了</view>
|
<!-- 加载骨架屏 -->
|
||||||
|
<view v-if="loading" class="skeleton-list">
|
||||||
|
<view class="card skeleton" v-for="n in 3" :key="n">
|
||||||
|
<view class="skeleton-line w-70"></view>
|
||||||
|
<view class="skeleton-line w-40"></view>
|
||||||
|
<view class="skeleton-line w-90"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 列表内容 -->
|
||||||
|
<view v-else>
|
||||||
|
<view v-if="!inventoryPlanList.length" class="empty">暂无数据</view>
|
||||||
|
|
||||||
<view class="inventory-list">
|
<view class="inventory-list">
|
||||||
<view class="inventory-item card" v-for="item in inventoryPlanList" :key="item.inventoryPlanId">
|
<view class="inventory-item card" v-for="item in inventoryPlanList" :key="item.inventoryPlanId">
|
||||||
<view class="left" @tap="gotoPlanDetail(item)">
|
<view class="left">
|
||||||
<view class="header"><text class="title">📋 盘点计划</text></view>
|
<!-- 头部:标题 + 状态徽章 -->
|
||||||
<view class="content">
|
<view class="card-header">
|
||||||
<view class="row">开始日期:<text class="value">{{ item.inventoryStartDate }}</text></view>
|
<text class="title ellipsis-1">📋 盘点计划</text>
|
||||||
<view class="row">结束日期:<text class="value">{{ item.inventoryEndDate }}</text></view>
|
<text class="status-badge" :class="statusClass(item.status)">{{ item.status || '未知'
|
||||||
<view class="row">盘点人:<text class="value">{{ item.inventoryManName }}</text></view>
|
}}</text>
|
||||||
<view class="row">备注:<text class="value">{{ item.note || '无' }}</text></view>
|
|
||||||
</view>
|
</view>
|
||||||
<view class="status">计划状态:<text class="value">{{ item.status || '无' }}</text></view>
|
|
||||||
|
<!-- 关键指标:开始/结束日期 -->
|
||||||
|
<view class="key-meta">
|
||||||
|
<view class="meta-block">
|
||||||
|
<text class="meta-label">开始日期</text>
|
||||||
|
<text class="meta-value">{{ item.inventoryStartDate || '-' }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="preview" @click="previewImage(item.image)">
|
<view class="meta-block">
|
||||||
|
<text class="meta-label">结束日期</text>
|
||||||
|
<text class="meta-value">{{ item.inventoryEndDate || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 详情:盘点人、备注 -->
|
||||||
|
<view class="detail">
|
||||||
|
<view class="detail-row">
|
||||||
|
<text class="label">盘点人</text>
|
||||||
|
<text class="value ellipsis-1">{{ item.inventoryManName || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="detail-row">
|
||||||
|
<text class="label">备注</text>
|
||||||
|
<text class="value ellipsis-2">{{ item.note || '无' }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 右侧预览图(仅当有图片时显示) -->
|
||||||
|
<view class="preview" v-if="item.image" @click="previewImage(item.image)">
|
||||||
<image class="preview-img" :src="'data:image/png;base64,' + item.image" mode="aspectFill" />
|
<image class="preview-img" :src="'data:image/png;base64,' + item.image" mode="aspectFill" />
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<view class="action">
|
||||||
|
<view class="chevron-link" @tap="gotoPlanDetail(item)">
|
||||||
|
<svg class="chevron-icon" viewBox="0 0 24 24" aria-hidden="true">
|
||||||
|
<path d="M9 6l6 6-6 6" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||||
|
</svg>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="load-status">
|
</view>
|
||||||
<text v-if="loading">加载中...</text>
|
|
||||||
<text v-else-if="noMore && inventoryPlanList.length">没有更多数据了</text>
|
</view>
|
||||||
|
|
||||||
|
<view class="load-status" v-if="noMore && inventoryPlanList.length">没有更多数据了</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
@ -38,6 +81,12 @@ const loading = ref(false)
|
|||||||
const noMore = ref(false)
|
const noMore = ref(false)
|
||||||
const inventoryPlanList = ref<any[]>([])
|
const inventoryPlanList = ref<any[]>([])
|
||||||
|
|
||||||
|
function statusClass(status?: string) {
|
||||||
|
if (status === '已结束') return 'ended'
|
||||||
|
if (status === '正在进行') return 'running'
|
||||||
|
return 'unknown'
|
||||||
|
}
|
||||||
|
|
||||||
onLoad(() => { fetchInventoryList() })
|
onLoad(() => { fetchInventoryList() })
|
||||||
|
|
||||||
onReachBottom(() => {
|
onReachBottom(() => {
|
||||||
@ -113,15 +162,15 @@ function previewImage(imageBase64: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.left {
|
.left {
|
||||||
/* 按内容宽度,不挤占右侧空间 */
|
/* 左侧内容占据剩余空间 */
|
||||||
flex: 0 0 auto;
|
flex: 1 1 auto;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview {
|
.preview {
|
||||||
/* 占据剩余空间 */
|
/* 固定宽度的预览区域,避免占满 */
|
||||||
flex: 1 1 0;
|
flex: 0 0 220rpx;
|
||||||
min-width: 0;
|
width: 220rpx;
|
||||||
display: flex;
|
display: flex;
|
||||||
/* 使内部图片可以 100% 拉伸 */
|
/* 使内部图片可以 100% 拉伸 */
|
||||||
}
|
}
|
||||||
@ -131,21 +180,108 @@ function previewImage(imageBase64: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: 28rpx;
|
font-size: 32rpx;
|
||||||
color: #222;
|
color: #222;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content .row {
|
/* 卡片头与状态徽章 */
|
||||||
font-size: 24rpx;
|
.card-header {
|
||||||
color: #666;
|
display: flex;
|
||||||
margin-top: 6rpx;
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status {
|
.status-badge {
|
||||||
font-size: 24rpx;
|
font-size: 24rpx;
|
||||||
|
padding: 4rpx 12rpx;
|
||||||
|
border-radius: 999rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-badge.running {
|
||||||
|
color: #1e88e5;
|
||||||
|
background: #e3f2fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-badge.ended {
|
||||||
|
color: #2e7d32;
|
||||||
|
background: #e8f5e9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-badge.unknown {
|
||||||
|
color: #757575;
|
||||||
|
background: #eeeeee;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 关键指标与详情 */
|
||||||
|
.key-meta {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 16rpx;
|
||||||
|
margin: 8rpx 0 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-block {
|
||||||
|
background: #f7f9ff;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
padding: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-label {
|
||||||
|
display: block;
|
||||||
|
color: #8a8f99;
|
||||||
|
font-size: 22rpx;
|
||||||
|
margin-bottom: 6rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-value {
|
||||||
color: #333;
|
color: #333;
|
||||||
margin-top: 10rpx;
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail {
|
||||||
|
margin-top: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin: 8rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
color: #888;
|
||||||
|
min-width: 140rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 操作区 */
|
||||||
|
.action {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 简约右箭头点击区域 */
|
||||||
|
.chevron-link {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 48rpx;
|
||||||
|
height: 48rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #f1f3f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chevron-icon {
|
||||||
|
width: 32rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
color: #86909c;
|
||||||
}
|
}
|
||||||
|
|
||||||
.load-status {
|
.load-status {
|
||||||
@ -154,17 +290,89 @@ function previewImage(imageBase64: string) {
|
|||||||
margin: 20rpx 0;
|
margin: 20rpx 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.empty {
|
||||||
|
color: #9a9aa0;
|
||||||
|
text-align: center;
|
||||||
|
padding: 24rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
.value {
|
.value {
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ellipsis-1 {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ellipsis-2 {
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
line-clamp: 2;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
/* 右侧图片自适应填满容器,保持裁剪 */
|
/* 右侧图片自适应填满容器,保持裁剪 */
|
||||||
.preview-img {
|
.preview-img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: auto;
|
||||||
|
aspect-ratio: 1 / 1;
|
||||||
display: block;
|
display: block;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
/* H5 有效;小程序端由 mode=aspectFill 生效 */
|
/* H5 有效;小程序端由 mode=aspectFill 生效 */
|
||||||
border-radius: 12rpx;
|
border-radius: 12rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 骨架屏样式 */
|
||||||
|
.skeleton-list .card {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton {
|
||||||
|
position: relative;
|
||||||
|
padding: 20rpx;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.04) 50%, rgba(0, 0, 0, 0) 100%);
|
||||||
|
animation: shimmer 1.2s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-line {
|
||||||
|
height: 28rpx;
|
||||||
|
background: #f0f2f5;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
margin: 14rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-line.w-70 {
|
||||||
|
width: 70%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-line.w-40 {
|
||||||
|
width: 40%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-line.w-90 {
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes shimmer {
|
||||||
|
0% {
|
||||||
|
transform: translateX(-100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: translateX(100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user