You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
853 lines
18 KiB
853 lines
18 KiB
|
3 weeks ago
|
<template>
|
||
|
|
<view class="container">
|
||
|
|
<!-- Content -->
|
||
|
|
<scroll-view
|
||
|
|
class="scroll-content"
|
||
|
|
scroll-y
|
||
|
|
refresher-enabled
|
||
|
|
:refresher-triggered="isRefreshing"
|
||
|
|
@refresherrefresh="onRefresh"
|
||
|
|
@scrolltolower="handleLoadMore"
|
||
|
|
lower-threshold="100"
|
||
|
|
>
|
||
|
|
<view class="content">
|
||
|
|
<!-- 站点码输入区域 -->
|
||
|
|
<view class="input-section">
|
||
|
|
<text class="label">站点码:</text>
|
||
|
|
<view class="input-wrapper">
|
||
|
|
<input
|
||
|
|
class="input"
|
||
|
|
type="text"
|
||
|
|
placeholder="站点码"
|
||
|
|
:value="siteCode"
|
||
|
|
@input="handleInput"
|
||
|
|
@confirm="handleSearch"
|
||
|
|
confirm-type="search"
|
||
|
|
/>
|
||
|
|
<!-- <view class="scan-btn" @tap="handleScan">
|
||
|
|
<text class="scan-icon">⚏</text>
|
||
|
|
</view> -->
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
|
||
|
|
<!-- 空状态 -->
|
||
|
|
<view v-if="sites.length === 0" class="empty-state">
|
||
|
|
<view class="empty-icon">
|
||
|
|
<text class="icon-large">⚏</text>
|
||
|
|
</view>
|
||
|
|
<text class="empty-title">未找到匹配的站点</text>
|
||
|
|
<text class="empty-desc">请尝试其他站点码</text>
|
||
|
|
</view>
|
||
|
|
|
||
|
|
<!-- 站点列表 -->
|
||
|
|
<view v-else class="site-list">
|
||
|
|
<view class="list-header">
|
||
|
|
<text class="list-title">{{
|
||
|
|
hasSearched ? "搜索结果" : "全部站点"
|
||
|
|
}}</text>
|
||
|
|
<view class="site-count">{{ page.total }} 个站点</view>
|
||
|
|
</view>
|
||
|
|
|
||
|
|
<view v-for="(site,index) in displayedSites" :key="index" class="site-card">
|
||
|
|
<!-- 头部 -->
|
||
|
|
<view class="card-header">
|
||
|
|
<view class="card-info">
|
||
|
|
<text class="site-name">{{ site.stationName }}</text>
|
||
|
|
<text class="site-code">站点编码: {{ site.stationCode }}</text>
|
||
|
|
</view>
|
||
|
|
<view class="status-btn" @tap="handleStatusChange(site)">
|
||
|
|
{{ site.stationStatus == "1" ? "闲置" : "占用" }}
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
|
||
|
|
<!-- 详情 -->
|
||
|
|
<view class="card-details">
|
||
|
|
<view class="detail-row">
|
||
|
|
<text class="detail-label">站点区域</text>
|
||
|
|
<text class="detail-value">{{ site.stationRegion }}</text>
|
||
|
|
</view>
|
||
|
|
|
||
|
|
<view class="detail-row">
|
||
|
|
<text class="detail-label">站点楼层</text>
|
||
|
|
<text class="detail-value">{{ site.stationPosition }}楼</text>
|
||
|
|
</view>
|
||
|
|
|
||
|
|
<view class="detail-row">
|
||
|
|
<text class="detail-label">作业中心</text>
|
||
|
|
<text class="detail-value">{{ site.wcName }}</text>
|
||
|
|
</view>
|
||
|
|
|
||
|
|
<view class="detail-row">
|
||
|
|
<text class="detail-label">站点状态</text>
|
||
|
|
<view
|
||
|
|
:class="['status-badge', getStatusClass(site.stationStatus)]"
|
||
|
|
>
|
||
|
|
<view class="status-dot">
|
||
|
|
<view class="dot-ping"></view>
|
||
|
|
<view class="dot-core"></view>
|
||
|
|
</view>
|
||
|
|
<text class="status-text">{{
|
||
|
|
getStatusLabel(site.stationStatus)
|
||
|
|
}}</text>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
|
||
|
|
<!-- 加载中 -->
|
||
|
|
<view v-if="isLoading" class="loading">
|
||
|
|
<text class="loading-text">加载中...</text>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</scroll-view>
|
||
|
|
|
||
|
|
<!-- 确认对话框 -->
|
||
|
|
<view
|
||
|
|
v-if="confirmDialog.isOpen"
|
||
|
|
class="modal-overlay"
|
||
|
|
@tap="cancelStatusChange"
|
||
|
|
>
|
||
|
|
<view class="modal-content" @tap.stop>
|
||
|
|
<text class="modal-title">确认状态变更</text>
|
||
|
|
<text class="modal-desc">
|
||
|
|
确认将站点
|
||
|
|
<text class="bold">{{ confirmDialog.siteName }}</text> 的状态从
|
||
|
|
<text
|
||
|
|
:class="[
|
||
|
|
'bold',
|
||
|
|
confirmDialog.currentStatus === '占用'
|
||
|
|
? 'text-red'
|
||
|
|
: 'text-green',
|
||
|
|
]"
|
||
|
|
>
|
||
|
|
{{ confirmDialog.currentStatus }}
|
||
|
|
</text>
|
||
|
|
变更为
|
||
|
|
<text
|
||
|
|
:class="[
|
||
|
|
'bold',
|
||
|
|
confirmDialog.newStatus === '占用' ? 'text-red' : 'text-green',
|
||
|
|
]"
|
||
|
|
>
|
||
|
|
{{ confirmDialog.newStatus }}
|
||
|
|
</text>
|
||
|
|
吗?
|
||
|
|
</text>
|
||
|
|
<view class="modal-actions">
|
||
|
|
<view class="modal-btn btn-cancel" @tap="cancelStatusChange">
|
||
|
|
取消
|
||
|
|
</view>
|
||
|
|
<view class="modal-btn btn-confirm" @tap="confirmStatusChange">
|
||
|
|
确认
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
export default {
|
||
|
|
data() {
|
||
|
|
return {
|
||
|
|
siteCode: "",
|
||
|
|
sites: [], // 当前显示的站点列表
|
||
|
|
allSites: [], // 缓存所有数据(可选)
|
||
|
|
hasSearched: false,
|
||
|
|
isLoading: false,
|
||
|
|
isRefreshing: false,
|
||
|
|
noMoreData: false, // 是否没有更多数据
|
||
|
|
confirmDialog: {
|
||
|
|
isOpen: false,
|
||
|
|
siteId: null,
|
||
|
|
siteName: "",
|
||
|
|
currentStatus: "",
|
||
|
|
newStatus: "",
|
||
|
|
},
|
||
|
|
page: {
|
||
|
|
pageSize: 10,
|
||
|
|
currentPage: 1,
|
||
|
|
total: 0,
|
||
|
|
},
|
||
|
|
searchParams: {}, // 搜索参数
|
||
|
|
};
|
||
|
|
},
|
||
|
|
|
||
|
|
computed: {
|
||
|
|
displayedSites() {
|
||
|
|
return this.sites.slice(0, this.displayCount);
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
mounted() {
|
||
|
|
this.initData();
|
||
|
|
},
|
||
|
|
|
||
|
|
methods: {
|
||
|
|
// 添加方法
|
||
|
|
onRefresh() {
|
||
|
|
this.isRefreshing = true;
|
||
|
|
this.loadSites(true).then(() => {
|
||
|
|
this.isRefreshing = false;
|
||
|
|
});
|
||
|
|
},
|
||
|
|
// 初始化数据
|
||
|
|
initData() {
|
||
|
|
this.loadSites(true);
|
||
|
|
},
|
||
|
|
// 加载站点数据
|
||
|
|
loadSites(isRefresh = false) {
|
||
|
|
if (this.isLoading || (this.noMoreData && !isRefresh)) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
this.isLoading = true;
|
||
|
|
|
||
|
|
if (isRefresh) {
|
||
|
|
this.page.currentPage = 1;
|
||
|
|
this.sites = [];
|
||
|
|
this.noMoreData = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
this.$u.api
|
||
|
|
.getStationList({
|
||
|
|
pageSize: this.page.pageSize,
|
||
|
|
currentPage: this.page.currentPage,
|
||
|
|
stationCode: this.siteCode ? this.siteCode : null,
|
||
|
|
...this.searchParams,
|
||
|
|
})
|
||
|
|
.then((res) => {
|
||
|
|
const records = res.data?.records || [];
|
||
|
|
const total = res.data?.total || 0;
|
||
|
|
|
||
|
|
// 处理数据格式
|
||
|
|
const formattedData = records.map((item) => ({
|
||
|
|
id: item.id,
|
||
|
|
code: item.stationCode,
|
||
|
|
name: item.stationName,
|
||
|
|
area: item.wcName || "",
|
||
|
|
floor: item.stationPosition || "",
|
||
|
|
workCenter: item.wcName || "",
|
||
|
|
status: item.stationStatus == "1" ? "occupied" : "available",
|
||
|
|
...item,
|
||
|
|
}));
|
||
|
|
|
||
|
|
if (isRefresh) {
|
||
|
|
this.sites = formattedData;
|
||
|
|
} else {
|
||
|
|
this.sites = [...this.sites, ...formattedData];
|
||
|
|
}
|
||
|
|
|
||
|
|
this.page.total = total;
|
||
|
|
|
||
|
|
// 判断是否还有更多数据
|
||
|
|
if (this.sites.length >= total) {
|
||
|
|
this.noMoreData = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
this.isLoading = false;
|
||
|
|
})
|
||
|
|
.catch((err) => {
|
||
|
|
this.isLoading = false;
|
||
|
|
uni.showToast({
|
||
|
|
title: "加载失败",
|
||
|
|
icon: "error",
|
||
|
|
});
|
||
|
|
});
|
||
|
|
},
|
||
|
|
|
||
|
|
// 输入框输入事件
|
||
|
|
handleInput(e) {
|
||
|
|
const value = e.detail.value;
|
||
|
|
this.siteCode = value;
|
||
|
|
},
|
||
|
|
|
||
|
|
// 回车搜索
|
||
|
|
handleSearch() {
|
||
|
|
this.page.currentPage = 1;
|
||
|
|
this.sites = [];
|
||
|
|
this.noMoreData = false;
|
||
|
|
this.loadSites(true);
|
||
|
|
// 收起键盘
|
||
|
|
uni.hideKeyboard();
|
||
|
|
},
|
||
|
|
|
||
|
|
// 过滤站点
|
||
|
|
filterSites(keyword) {
|
||
|
|
const lowerKeyword = keyword.toLowerCase();
|
||
|
|
this.sites = this.allSites.filter(
|
||
|
|
(site) =>
|
||
|
|
site.code.toLowerCase().includes(lowerKeyword) ||
|
||
|
|
site.name.toLowerCase().includes(lowerKeyword) ||
|
||
|
|
site.area.toLowerCase().includes(lowerKeyword)
|
||
|
|
);
|
||
|
|
this.hasSearched = true;
|
||
|
|
},
|
||
|
|
|
||
|
|
// 模拟扫描
|
||
|
|
handleScan() {
|
||
|
|
// 使用UniApp的扫码API
|
||
|
|
uni.scanCode({
|
||
|
|
success: (res) => {
|
||
|
|
this.siteCode = res.result;
|
||
|
|
this.filterSites(res.result);
|
||
|
|
},
|
||
|
|
fail: () => {
|
||
|
|
// 扫码失败,使用模拟数据
|
||
|
|
const randomSite =
|
||
|
|
this.allSites[Math.floor(Math.random() * this.allSites.length)];
|
||
|
|
this.siteCode = randomSite.code;
|
||
|
|
this.sites = this.allSites.filter((s) => s.code === randomSite.code);
|
||
|
|
this.hasSearched = true;
|
||
|
|
},
|
||
|
|
});
|
||
|
|
},
|
||
|
|
|
||
|
|
// 重置
|
||
|
|
handleReset() {
|
||
|
|
this.siteCode = "";
|
||
|
|
this.searchParams = {};
|
||
|
|
this.page.currentPage = 1;
|
||
|
|
this.sites = [];
|
||
|
|
this.noMoreData = false;
|
||
|
|
this.loadSites(true);
|
||
|
|
},
|
||
|
|
|
||
|
|
// 关闭页面
|
||
|
|
handleClose() {
|
||
|
|
uni.navigateBack();
|
||
|
|
},
|
||
|
|
|
||
|
|
// 懒加载更多
|
||
|
|
handleLoadMore() {
|
||
|
|
if (this.isLoading || this.noMoreData) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
this.page.currentPage += 1;
|
||
|
|
this.loadSites(false);
|
||
|
|
},
|
||
|
|
|
||
|
|
// 获取状态样式类
|
||
|
|
getStatusClass(status) {
|
||
|
|
return status == 1 ? "status-occupied" : "status-available";
|
||
|
|
},
|
||
|
|
|
||
|
|
// 获取状态标签
|
||
|
|
getStatusLabel(status) {
|
||
|
|
return status == 0 ? "闲置" : "占用";
|
||
|
|
},
|
||
|
|
|
||
|
|
// 打开状态变更确认对话框
|
||
|
|
handleStatusChange(site) {
|
||
|
|
const newStatus = site.stationStatus == 0 ? 1 : 0;
|
||
|
|
this.confirmDialog = {
|
||
|
|
...site,
|
||
|
|
isOpen: true,
|
||
|
|
siteName: site.name,
|
||
|
|
currentStatus: this.getStatusLabel(site.stationStatus),
|
||
|
|
newStatus: this.getStatusLabel(newStatus),
|
||
|
|
newStationStatus: newStatus,
|
||
|
|
};
|
||
|
|
},
|
||
|
|
|
||
|
|
// 确认状态变更
|
||
|
|
confirmStatusChange() {
|
||
|
|
if (this.confirmDialog.siteId !== null) {
|
||
|
|
this.confirmDialog.stationStatus = this.confirmDialog.newStationStatus;
|
||
|
|
console.log("获取当前列表的数据", this.confirmDialog);
|
||
|
|
// 调用接口更新状态
|
||
|
|
this.$u.api
|
||
|
|
.stationUpdate(this.confirmDialog)
|
||
|
|
.then((res) => {
|
||
|
|
// 更新本地数据
|
||
|
|
const index = this.sites.findIndex(
|
||
|
|
(s) => s.id == this.confirmDialog.id
|
||
|
|
);
|
||
|
|
console.log(
|
||
|
|
"更新站点状态成功",
|
||
|
|
this.confirmDialog.id,
|
||
|
|
this.sites,
|
||
|
|
index
|
||
|
|
);
|
||
|
|
if (index !== -1) {
|
||
|
|
this.sites[index].stationStatus =
|
||
|
|
this.confirmDialog.stationStatus;
|
||
|
|
}
|
||
|
|
|
||
|
|
uni.showToast({
|
||
|
|
title: "状态更新成功",
|
||
|
|
icon: "success",
|
||
|
|
});
|
||
|
|
this.cancelStatusChange();
|
||
|
|
})
|
||
|
|
.catch((err) => {
|
||
|
|
uni.showToast({
|
||
|
|
title: "状态更新失败",
|
||
|
|
icon: "error",
|
||
|
|
});
|
||
|
|
this.cancelStatusChange();
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
},
|
||
|
|
|
||
|
|
// 取消确认
|
||
|
|
cancelStatusChange() {
|
||
|
|
this.confirmDialog = {
|
||
|
|
isOpen: false,
|
||
|
|
|
||
|
|
};
|
||
|
|
},
|
||
|
|
},
|
||
|
|
};
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style scoped>
|
||
|
|
/* 容器 */
|
||
|
|
.container {
|
||
|
|
width: 100%;
|
||
|
|
height: 100vh;
|
||
|
|
background-color: #f7f8fa;
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Header */
|
||
|
|
.header {
|
||
|
|
background: linear-gradient(135deg, #4a7de8 0%, #5b8ff9 100%);
|
||
|
|
padding: 32rpx;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: space-between;
|
||
|
|
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
|
||
|
|
}
|
||
|
|
|
||
|
|
.header-left {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 16rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
.header-btn {
|
||
|
|
width: 72rpx;
|
||
|
|
height: 72rpx;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
border-radius: 50%;
|
||
|
|
transition: all 0.2s;
|
||
|
|
}
|
||
|
|
|
||
|
|
.header-btn:active {
|
||
|
|
background-color: rgba(255, 255, 255, 0.2);
|
||
|
|
transform: scale(0.95);
|
||
|
|
}
|
||
|
|
|
||
|
|
.icon {
|
||
|
|
color: #ffffff;
|
||
|
|
font-size: 40rpx;
|
||
|
|
font-weight: bold;
|
||
|
|
}
|
||
|
|
|
||
|
|
.header-title {
|
||
|
|
color: #ffffff;
|
||
|
|
font-size: 36rpx;
|
||
|
|
font-weight: 600;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 滚动内容 */
|
||
|
|
.scroll-content {
|
||
|
|
flex: 1;
|
||
|
|
height: 100%;
|
||
|
|
}
|
||
|
|
|
||
|
|
.content {
|
||
|
|
padding: 32rpx;
|
||
|
|
padding-bottom: 60rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 输入区域 */
|
||
|
|
.input-section {
|
||
|
|
margin-bottom: 48rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
.label {
|
||
|
|
color: #374151;
|
||
|
|
font-size: 28rpx;
|
||
|
|
font-weight: 500;
|
||
|
|
display: block;
|
||
|
|
margin-bottom: 24rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
.input-wrapper {
|
||
|
|
position: relative;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
}
|
||
|
|
|
||
|
|
.input {
|
||
|
|
width: 100%;
|
||
|
|
padding: 24rpx 32rpx;
|
||
|
|
/* padding-right: 100rpx; */
|
||
|
|
background-color: #ffffff;
|
||
|
|
border: 2rpx solid #e5e7eb;
|
||
|
|
border-radius: 16rpx;
|
||
|
|
color: #374151;
|
||
|
|
font-size: 28rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
.input::placeholder {
|
||
|
|
color: #9ca3af;
|
||
|
|
}
|
||
|
|
|
||
|
|
.scan-btn {
|
||
|
|
position: absolute;
|
||
|
|
right: 16rpx;
|
||
|
|
width: 72rpx;
|
||
|
|
height: 72rpx;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
border-radius: 12rpx;
|
||
|
|
transition: all 0.2s;
|
||
|
|
}
|
||
|
|
|
||
|
|
.scan-btn:active {
|
||
|
|
background-color: #f3f4f6;
|
||
|
|
transform: scale(0.95);
|
||
|
|
}
|
||
|
|
|
||
|
|
.scan-icon {
|
||
|
|
color: #5b8ff9;
|
||
|
|
font-size: 40rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 空状态 */
|
||
|
|
.empty-state {
|
||
|
|
text-align: center;
|
||
|
|
padding: 120rpx 0;
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
align-items: center;
|
||
|
|
}
|
||
|
|
|
||
|
|
.empty-icon {
|
||
|
|
width: 160rpx;
|
||
|
|
height: 160rpx;
|
||
|
|
background-color: #f3f4f6;
|
||
|
|
border-radius: 32rpx;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
margin-bottom: 32rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
.icon-large {
|
||
|
|
font-size: 80rpx;
|
||
|
|
color: #9ca3af;
|
||
|
|
}
|
||
|
|
|
||
|
|
.empty-title {
|
||
|
|
color: #6b7280;
|
||
|
|
font-size: 28rpx;
|
||
|
|
font-weight: 500;
|
||
|
|
margin-bottom: 8rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
.empty-desc {
|
||
|
|
color: #9ca3af;
|
||
|
|
font-size: 24rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 站点列表 */
|
||
|
|
.site-list {
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
gap: 24rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
.list-header {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: space-between;
|
||
|
|
margin-bottom: 16rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
.list-title {
|
||
|
|
color: #374151;
|
||
|
|
font-size: 26rpx;
|
||
|
|
font-weight: 600;
|
||
|
|
}
|
||
|
|
|
||
|
|
.site-count {
|
||
|
|
background-color: #f3f4f6;
|
||
|
|
color: #6b7280;
|
||
|
|
font-size: 22rpx;
|
||
|
|
padding: 6rpx 20rpx;
|
||
|
|
border-radius: 999rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 站点卡片 */
|
||
|
|
.site-card {
|
||
|
|
background-color: #ffffff;
|
||
|
|
border-radius: 20rpx;
|
||
|
|
padding: 24rpx;
|
||
|
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
|
||
|
|
border: 2rpx solid #e5e7eb;
|
||
|
|
}
|
||
|
|
|
||
|
|
.card-header {
|
||
|
|
display: flex;
|
||
|
|
align-items: flex-start;
|
||
|
|
justify-content: space-between;
|
||
|
|
margin-bottom: 20rpx;
|
||
|
|
padding-bottom: 20rpx;
|
||
|
|
border-bottom: 2rpx solid #f3f4f6;
|
||
|
|
}
|
||
|
|
|
||
|
|
.card-info {
|
||
|
|
flex: 1;
|
||
|
|
padding-right: 20rpx;
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
}
|
||
|
|
|
||
|
|
.site-name {
|
||
|
|
color: #111827;
|
||
|
|
font-size: 30rpx;
|
||
|
|
font-weight: bold;
|
||
|
|
margin-bottom: 6rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
.site-code {
|
||
|
|
color: #6b7280;
|
||
|
|
font-size: 22rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-btn {
|
||
|
|
padding: 10rpx 24rpx;
|
||
|
|
border-radius: 10rpx;
|
||
|
|
font-size: 22rpx;
|
||
|
|
font-weight: 600;
|
||
|
|
color: #ffffff;
|
||
|
|
white-space: nowrap;
|
||
|
|
transition: all 0.2s;
|
||
|
|
background-color: #5b8ff9;
|
||
|
|
box-shadow: 0 4rpx 12rpx rgba(91, 143, 249, 0.3);
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-btn:active {
|
||
|
|
transform: scale(0.95);
|
||
|
|
}
|
||
|
|
|
||
|
|
.btn-green {
|
||
|
|
background-color: #10b981;
|
||
|
|
}
|
||
|
|
|
||
|
|
.btn-red {
|
||
|
|
background-color: #ef4444;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 卡片详情 */
|
||
|
|
.card-details {
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
gap: 16rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
.detail-row {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: space-between;
|
||
|
|
font-size: 26rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
.detail-label {
|
||
|
|
color: #6b7280;
|
||
|
|
}
|
||
|
|
|
||
|
|
.detail-value {
|
||
|
|
color: #111827;
|
||
|
|
font-weight: 500;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 状态徽章 */
|
||
|
|
.status-badge {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 10rpx;
|
||
|
|
padding: 8rpx 16rpx;
|
||
|
|
border-radius: 999rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-occupied {
|
||
|
|
background-color: #fef2f2;
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-available {
|
||
|
|
background-color: #f0fdf4;
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-dot {
|
||
|
|
position: relative;
|
||
|
|
width: 12rpx;
|
||
|
|
height: 12rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
.dot-ping {
|
||
|
|
position: absolute;
|
||
|
|
width: 100%;
|
||
|
|
height: 100%;
|
||
|
|
border-radius: 50%;
|
||
|
|
animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite;
|
||
|
|
opacity: 0.75;
|
||
|
|
}
|
||
|
|
|
||
|
|
.dot-core {
|
||
|
|
position: relative;
|
||
|
|
width: 100%;
|
||
|
|
height: 100%;
|
||
|
|
border-radius: 50%;
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-occupied .dot-ping,
|
||
|
|
.status-occupied .dot-core {
|
||
|
|
background-color: #ef4444;
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-available .dot-ping,
|
||
|
|
.status-available .dot-core {
|
||
|
|
background-color: #10b981;
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-text {
|
||
|
|
font-size: 24rpx;
|
||
|
|
font-weight: 600;
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-occupied .status-text {
|
||
|
|
color: #b91c1c;
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-available .status-text {
|
||
|
|
color: #15803d;
|
||
|
|
}
|
||
|
|
|
||
|
|
@keyframes ping {
|
||
|
|
75%,
|
||
|
|
100% {
|
||
|
|
transform: scale(2);
|
||
|
|
opacity: 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 加载中 */
|
||
|
|
.loading {
|
||
|
|
text-align: center;
|
||
|
|
padding: 32rpx 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.loading-text {
|
||
|
|
color: #6b7280;
|
||
|
|
font-size: 28rpx;
|
||
|
|
font-weight: 500;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 模态框 */
|
||
|
|
.modal-overlay {
|
||
|
|
position: fixed;
|
||
|
|
top: 0;
|
||
|
|
left: 0;
|
||
|
|
right: 0;
|
||
|
|
bottom: 0;
|
||
|
|
background-color: rgba(0, 0, 0, 0.5);
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
z-index: 9999;
|
||
|
|
padding: 32rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
.modal-content {
|
||
|
|
background-color: #ffffff;
|
||
|
|
border-radius: 32rpx;
|
||
|
|
padding: 48rpx;
|
||
|
|
width: 100%;
|
||
|
|
max-width: 600rpx;
|
||
|
|
box-shadow: 0 20rpx 60rpx rgba(0, 0, 0, 0.3);
|
||
|
|
animation: modal-in 0.2s ease-out;
|
||
|
|
}
|
||
|
|
|
||
|
|
@keyframes modal-in {
|
||
|
|
from {
|
||
|
|
opacity: 0;
|
||
|
|
transform: scale(0.9);
|
||
|
|
}
|
||
|
|
to {
|
||
|
|
opacity: 1;
|
||
|
|
transform: scale(1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
.modal-title {
|
||
|
|
color: #111827;
|
||
|
|
font-size: 36rpx;
|
||
|
|
font-weight: bold;
|
||
|
|
margin-bottom: 24rpx;
|
||
|
|
display: block;
|
||
|
|
}
|
||
|
|
|
||
|
|
.modal-desc {
|
||
|
|
color: #6b7280;
|
||
|
|
font-size: 28rpx;
|
||
|
|
line-height: 1.6;
|
||
|
|
margin-bottom: 48rpx;
|
||
|
|
display: block;
|
||
|
|
}
|
||
|
|
|
||
|
|
.bold {
|
||
|
|
font-weight: bold;
|
||
|
|
color: #111827;
|
||
|
|
}
|
||
|
|
|
||
|
|
.text-red {
|
||
|
|
color: #dc2626 !important;
|
||
|
|
}
|
||
|
|
|
||
|
|
.text-green {
|
||
|
|
color: #16a34a !important;
|
||
|
|
}
|
||
|
|
|
||
|
|
.modal-actions {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 24rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
.modal-btn {
|
||
|
|
flex: 1;
|
||
|
|
padding: 24rpx 32rpx;
|
||
|
|
border-radius: 12rpx;
|
||
|
|
font-size: 28rpx;
|
||
|
|
font-weight: 600;
|
||
|
|
text-align: center;
|
||
|
|
transition: all 0.2s;
|
||
|
|
}
|
||
|
|
|
||
|
|
.modal-btn:active {
|
||
|
|
transform: scale(0.95);
|
||
|
|
}
|
||
|
|
|
||
|
|
.btn-cancel {
|
||
|
|
background-color: #f3f4f6;
|
||
|
|
color: #374151;
|
||
|
|
}
|
||
|
|
|
||
|
|
.btn-confirm {
|
||
|
|
background-color: #5b8ff9;
|
||
|
|
color: #ffffff;
|
||
|
|
box-shadow: 0 4rpx 12rpx rgba(91, 143, 249, 0.3);
|
||
|
|
}
|
||
|
|
</style>
|