Files
app-govern/pages/index/comp/monitoringPoint.vue
2026-07-14 09:13:20 +08:00

1092 lines
34 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<page-meta :page-style="'overflow:' + (indicatorPopupShow ? 'hidden' : 'visible')"></page-meta>
<view class="itic2-page">
<view class="itic2-content">
<view class="project-header card">
<view class="project-title-row">
<view class="project-title-left">
<uni-icons custom-prefix="iconfont" type="icon-gongcheng" size="22" color="#376cf3" />
<text class="project-name">{{ engineeringName }}</text>
</view>
<view class="switch-btn" @click="switchEngineering">
<uni-icons type="loop" size="14" color="#376cf3" />
<text>切换工程</text>
</view>
</view>
<view class="stats-row">
<view class="stats-item" v-for="(item, idx) in summaryStats" :key="idx" @click="jump(idx)">
<text class="stats-num">{{ item.value }}</text>
<text class="stats-label">{{ item.label }}</text>
</view>
</view>
</view>
<view class="monitor-section-header mb16">
<view class="section-title-row section-title-row--no-mb">
<uni-icons type="settings" size="18" color="#376cf3" />
<text class="section-title">已选展示指标</text>
</view>
</view>
<view class="indicators-card card">
<view class="indicator-group">
<text class="indicator-group-title">治理监测点指标</text>
<view class="indicator-tags">
<view
v-for="(tag, idx) in selectedIndicatorsPqCom"
:key="'governance-' + tag"
class="indicator-tag indicator-tag--active"
@click="removeIndicator(idx, 'governance')"
>
<text class="indicator-tag-text">{{ formatIndicatorTag(tag) }}</text>
<uni-icons type="closeempty" size="12" color="#376cf3" />
</view>
<view class="indicator-tag indicator-tag--add" @click="openIndicatorPopup('governance')">
<text>+添加指标</text>
</view>
</view>
</view>
<view class="indicator-group">
<text class="indicator-group-title">非治理监测点指标</text>
<view class="indicator-tags">
<view
v-for="(tag, idx) in selectedIndicators"
:key="'normal-' + tag"
class="indicator-tag indicator-tag--active"
@click="removeIndicator(idx, 'normal')"
>
<text class="indicator-tag-text">{{ formatIndicatorTag(tag) }}</text>
<uni-icons type="closeempty" size="12" color="#376cf3" />
</view>
<view class="indicator-tag indicator-tag--add" @click="openIndicatorPopup('normal')">
<text>+添加指标</text>
</view>
</view>
</view>
</view>
<view class="monitor-section">
<view class="monitor-section-header">
<view class="section-title-row section-title-row--no-mb">
<uni-icons type="map-pin-ellipse" size="20" color="#376cf3" />
<text class="section-title">监测点信息</text>
</view>
<view class="legend-row">
<view class="legend-item" v-for="phase in phaseColors" :key="phase.name">
<view class="legend-dot" :style="{ background: phase.color }" />
<text class="legend-text">{{ phase.name }}</text>
</view>
</view>
</view>
<view class="monitor-search">
<uni-search-bar
v-model="filterKeyword"
bgColor="#fff"
placeholder="搜索项目、设备、监测点"
cancelButton="none"
/>
</view>
<view class="monitor-list">
<view class="monitor-card card" v-for="(point, idx) in filteredMonitoringPoints" :key="idx">
<view class="card-header">
<view class="event-icon">
<Cn-icon-transient name="监测点" />
</view>
<view class="card-header-info">
<view class="point-name-row">
<text class="point-name ellipsis">{{ point.pointName }}</text>
<text class="event-tag" :class="point.runStatus == 0 ? 'zx-tag' : 'lx-tag'">
{{ point.runStatus == 0 ? '在线' : '离线' }}
</text>
</view>
<view class="meta-row">
<text class="meta-item ellipsis">项目{{ point.projectName }}</text>
<text class="meta-item ellipsis">设备{{ point.deviceName }}</text>
</view>
<text class="meta-time ellipsis">最新数据时间{{ point.dataTime || '-' }}</text>
</view>
</view>
<view class="params-section">
<view
v-for="(rowItems, rowIdx) in chunkedChildren(getDisplayChildren(point))"
:key="rowIdx"
class="double-row"
>
<view v-for="(child, childIdx) in rowItems" :key="childIdx" class="param-group">
<view class="param-title">
<text>{{ child.name }} {{ child.unit ? `(${child.unit})` : '' }}</text>
</view>
<view v-if="hasTPhaseData(child)" class="phase-single">
<text class="phase-value-vertical phase-value-vertical--neutral">{{
child.T
}}</text>
</view>
<view v-else class="phase-vertical">
<view class="phase-item-vertical">
<text
class="phase-value-vertical"
:style="{ color: phaseColors[0].color }"
>{{ child.A }}</text
>
</view>
<view class="phase-divider" />
<view class="phase-item-vertical">
<text
class="phase-value-vertical"
:style="{ color: phaseColors[1].color }"
>{{ child.B }}</text
>
</view>
<view class="phase-divider" />
<view class="phase-item-vertical">
<text
class="phase-value-vertical"
:style="{ color: phaseColors[2].color }"
>{{ child.C }}</text
>
</view>
</view>
</view>
</view>
</view>
<view class="more-btn" v-if="shouldShowMoreBtn(point)" @click="onMoreIndicators(point)">
<uni-icons type="list" size="16" color="#376cf3" />
<text>更多指标</text>
</view>
</view>
<uni-load-more
v-if="listStatus == 'loading' || filteredMonitoringPoints.length > 0"
:status="listStatus"
></uni-load-more>
<Cn-empty v-else-if="listStatus !== 'loading'" style="top: 45%"></Cn-empty>
</view>
</view>
</view>
<view class="back-top boxClick" v-show="showBackTop" @click="backToTop">
<uni-icons type="arrow-up" size="22" color="#fff"></uni-icons>
</view>
<uni-popup ref="indicatorPopup" type="bottom" :safe-area="false" @change="onIndicatorPopupChange">
<view class="indicator-popup">
<view class="indicator-popup-header" @touchmove.stop.prevent>
<text class="indicator-popup-cancel" @click="closeIndicatorPopup">取消</text>
<text class="indicator-popup-title">{{ indicatorPopupSubtitle }}</text>
<text class="indicator-popup-confirm" @click="confirmIndicatorPopup">确定</text>
</view>
<scroll-view class="indicator-popup-list" scroll-y :show-scrollbar="false" @touchmove.stop>
<view class="indicator-popup-section">
<!-- <text class="indicator-popup-subtitle">{{ indicatorPopupSubtitle }}</text> -->
<view v-if="currentPopupTargetLists.length === 0" class="indicator-popup-empty">
<text>暂无指标数据</text>
</view>
<view
v-for="item in currentPopupTargetLists"
:key="item.id || item.name"
class="indicator-popup-item"
:class="{
'indicator-popup-item--active': popupSelectedIndicators.includes(item.name),
}"
@click="togglePopupIndicator(item.name)"
>
<text>{{ item.name }}</text>
<uni-icons
v-if="popupSelectedIndicators.includes(item.name)"
type="checkmarkempty"
size="18"
color="#376cf3"
/>
</view>
</view>
</scroll-view>
</view>
</uni-popup>
</view>
</template>
<script>
import { queryByCode, queryCsDictTree } from '@/common/api/dictionary'
import { getLineDataByEngineer } from '@/common/api/harmonic'
import { getDevCount } from '@/common/api/device.js'
/** 无本地缓存时的默认展示指标:电压、电流 */
const DEFAULT_INDICATOR_CODES = ['Key_Power_Quality_V', 'Key_Power_Quality_I']
/** 治理测点无缓存时的默认展示指标 */
const GOVERNANCE_DEFAULT_INDICATOR_CODES = ['0', '1']
export default {
data() {
return {
targetLists: [],
targetListsPqCom: [],
indicatorPopupType: 'governance',
popupSelectedIndicators: [],
engineeringName: '',
engineeringId: '',
summaryStats: [
{ label: '项目总数', value: 0 },
{ label: '设备总数', value: 0 },
{ label: '监测点总数', value: 0 },
],
selectedIndicators: [],
selectedIndicatorsPqCom: [],
phaseColors: [
{ name: 'A相', color: '#DAA520' },
{ name: 'B相', color: '#2E8B57' },
{ name: 'C相', color: '#D54941' },
],
monitoringPoints: [],
filterKeyword: '',
listStatus: 'noMore',
lineDataRequestId: 0,
showBackTop: false,
indicatorPopupShow: false,
skipRefreshOnShow: false,
}
},
computed: {
indicatorPopupSubtitle() {
return this.indicatorPopupType === 'governance' ? '治理监测点指标' : '非治理监测点指标'
},
currentPopupTargetLists() {
return this.indicatorPopupType === 'governance' ? this.targetListsPqCom : this.targetLists
},
filteredMonitoringPoints() {
const keyword = (this.filterKeyword || '').trim().toLowerCase()
if (!keyword) return this.monitoringPoints
return this.monitoringPoints.filter((point) => {
const projectName = String(point.projectName || '').toLowerCase()
const deviceName = String(point.deviceName || '').toLowerCase()
const pointName = String(point.pointName || '').toLowerCase()
return (
projectName.indexOf(keyword) !== -1 ||
deviceName.indexOf(keyword) !== -1 ||
pointName.indexOf(keyword) !== -1
)
})
},
},
onPageScroll(e) {
this.showBackTop = e.scrollTop > 200
},
// 页面显示时同步工程名称;从指标详情返回时不刷新
onShow() {
const engineering = uni.getStorageSync('engineering')
const skipRefresh = this.skipRefreshOnShow
this.skipRefreshOnShow = false
if (engineering?.id) {
this.engineeringName = engineering.name || ''
this.engineeringId = engineering.id
if (!skipRefresh) {
this.info()
}
}
if ((this.targetLists.length || this.targetListsPqCom.length) && !skipRefresh) {
this.loadSelectedIndicators()
}
},
// 加载电能质量指标字典
created() {
const loadDictTree = (code) => queryByCode(code).then((res) => queryCsDictTree(res.data.id))
Promise.all([loadDictTree('Key_Power_Quality'), loadDictTree('Key_Power_Quality_Pq_Com')]).then(
([normalResp, pqComResp]) => {
this.targetLists = (normalResp.data || []).slice().reverse()
this.targetListsPqCom = (pqComResp.data || []).slice().reverse()
this.loadSelectedIndicators()
},
)
},
// 下拉刷新
onPullDownRefresh() {
this.info()
},
methods: {
// 查询接口
info() {
if (!this.engineeringId) {
uni.stopPullDownRefresh()
return
}
this.loadDevCount()
this.loadLineData()
},
loadDevCount() {
getDevCount(this.engineeringId).then((res) => {
if (res.code == 'A0000') {
this.updateSummaryStats(res.data)
}
})
},
loadLineData() {
this.listStatus = 'loading'
this.monitoringPoints = []
this.filterKeyword = ''
const requestId = ++this.lineDataRequestId
const engineerId = this.engineeringId
getLineDataByEngineer({ id: engineerId })
.then((res) => {
if (requestId !== this.lineDataRequestId) return
if (res.code == 'A0000') {
this.monitoringPoints = this.parseMonitoringPoints(res.data)
} else if (res.message) {
this.$util.toast(res.message)
}
})
.catch(() => {
if (requestId !== this.lineDataRequestId) return
this.$util.toast('加载失败,请稍后重试')
})
.finally(() => {
if (requestId !== this.lineDataRequestId) return
this.listStatus = 'noMore'
uni.stopPullDownRefresh()
})
},
// 接口 data 转为页面 monitoringPoints
parseMonitoringPoints(data = []) {
const list = Array.isArray(data) ? data : []
return list.map((point) => ({
projectName: point.projectName || '',
deviceName: point.deviceName || '',
pointName: point.pointName || '',
dataTime: point.dataTime || '',
lineType: point.lineType,
runStatus: point.runStatus,
children: this.groupChildren(point.children || []),
}))
},
// 将按相别拆分的指标合并为 A/B/C 结构
groupChildren(children = []) {
const map = {}
const order = []
children.forEach((item) => {
const key = item.targetId || item.name
if (!map[key]) {
map[key] = {
targetId: item.targetId,
name: item.name,
unit: item.unit,
A: '-',
B: '-',
C: '-',
T: '-',
}
order.push(key)
}
const phase = item.phase
if (phase === 'A' || phase === 'B' || phase === 'C' || phase === 'T') {
map[key][phase] = this.formatPhaseValue(item.data)
}
})
return order.map((key) => map[key])
},
formatPhaseValue(value) {
if (value === null || value === undefined || value === '' || value === 3.14159) return '-'
const num = Number(value)
if (Number.isNaN(num)) return String(value)
return num.toFixed(2)
},
hasTPhaseData(child) {
return child.T !== undefined && child.T !== null && child.T !== '-'
},
updateSummaryStats(devCount = {}) {
const deviceTotal = (devCount.currentOnLineDevCount || 0) + (devCount.currentOffLineDevCount || 0)
this.summaryStats = [
{ label: '项目总数', value: devCount.currentProjectCount || 0 },
{ label: '设备总数', value: deviceTotal },
{ label: '监测点总数', value: devCount.lineCount || 0 },
]
},
// 指标名称超过6个字截断显示
formatIndicatorTag(name) {
if (!name || name.length <= 6) return name
return `${name.slice(0, 5)}...`
},
// 判断指标名称是否匹配(兼容括号后缀)
matchIndicator(name, selected) {
if (!name || !selected) return false
const base = (name || '').replace(/\(.*\)/, '').trim()
const selectedBase = (selected || '').replace(/\(.*\)/, '').trim()
return base === selectedBase
},
// 从缓存读取已选指标,无缓存时使用默认指标
loadSelectedIndicators() {
this.loadNormalSelectedIndicators()
this.loadGovernanceSelectedIndicators()
},
loadNormalSelectedIndicators() {
if (!this.targetLists.length) return
const cached = uni.getStorageSync(this.$cacheKey.monitorSelectedIndicators)
if (Array.isArray(cached) && cached.length) {
const valid = cached.filter((name) =>
this.targetLists.some((item) => this.matchIndicator(item.name, name)),
)
if (valid.length) {
this.selectedIndicators = valid
return
}
}
this.selectedIndicators = this.getDefaultIndicatorsByCode()
this.saveSelectedIndicators()
},
loadGovernanceSelectedIndicators() {
if (!this.targetListsPqCom.length) return
const cached = uni.getStorageSync(this.$cacheKey.monitorSelectedIndicatorsPqCom)
if (Array.isArray(cached) && cached.length) {
const valid = cached.filter((name) =>
this.targetListsPqCom.some((item) => this.matchIndicator(item.name, name)),
)
if (valid.length) {
this.selectedIndicatorsPqCom = valid
return
}
}
this.selectedIndicatorsPqCom = this.getDefaultGovernanceIndicators()
this.saveSelectedIndicatorsPqCom()
},
getDefaultIndicatorsByCode() {
return this.targetLists
.filter((item) => DEFAULT_INDICATOR_CODES.includes(item.code) && item.name)
.map((item) => item.name)
},
getDefaultGovernanceIndicators() {
return this.targetListsPqCom
.filter((item) => GOVERNANCE_DEFAULT_INDICATOR_CODES.includes(item.code) && item.name)
.map((item) => item.name)
},
saveSelectedIndicators() {
uni.setStorageSync(this.$cacheKey.monitorSelectedIndicators, this.selectedIndicators)
},
saveSelectedIndicatorsPqCom() {
uni.setStorageSync(this.$cacheKey.monitorSelectedIndicatorsPqCom, this.selectedIndicatorsPqCom)
},
// 跳转切换工程
switchEngineering() {
uni.navigateTo({ url: '/pages/home/selectEngineering' })
},
// 移除已选指标
removeIndicator(idx, type = 'normal') {
const isGovernance = type === 'governance'
const selected = isGovernance ? this.selectedIndicatorsPqCom : this.selectedIndicators
if (selected.length <= 1) {
uni.showToast({ title: '至少保留一个指标', icon: 'none' })
return
}
selected.splice(idx, 1)
if (isGovernance) {
this.saveSelectedIndicatorsPqCom()
} else {
this.saveSelectedIndicators()
}
},
// 打开指标选择弹窗
openIndicatorPopup(type = 'governance') {
const isGovernance = type === 'governance'
const targetLists = isGovernance ? this.targetListsPqCom : this.targetLists
const selected = isGovernance ? this.selectedIndicatorsPqCom : this.selectedIndicators
if (!targetLists.length) {
uni.showToast({ title: '暂无指标数据', icon: 'none' })
return
}
this.indicatorPopupType = type
this.popupSelectedIndicators = targetLists
.filter((item) => selected.some((name) => this.matchIndicator(item.name, name)))
.map((item) => item.name)
this.$refs.indicatorPopup.open()
},
// 关闭指标选择弹窗
closeIndicatorPopup() {
this.$refs.indicatorPopup.close()
this.popupSelectedIndicators = []
this.indicatorPopupType = 'governance'
},
onIndicatorPopupChange(e) {
this.indicatorPopupShow = !!e.show
},
// 切换弹窗内指标勾选状态
togglePopupIndicator(name) {
const idx = this.popupSelectedIndicators.indexOf(name)
if (idx > -1) {
this.popupSelectedIndicators.splice(idx, 1)
} else {
this.popupSelectedIndicators.push(name)
}
},
// 确认指标选择
confirmIndicatorPopup() {
if (!this.popupSelectedIndicators.length) {
uni.showToast({ title: '至少保留一个指标', icon: 'none' })
return
}
if (this.indicatorPopupType === 'governance') {
this.selectedIndicatorsPqCom = [...this.popupSelectedIndicators]
this.saveSelectedIndicatorsPqCom()
} else {
this.selectedIndicators = [...this.popupSelectedIndicators]
this.saveSelectedIndicators()
}
this.closeIndicatorPopup()
},
// 跳转指标详情页,展示该监测点全部指标
onMoreIndicators(point) {
this.skipRefreshOnShow = true
uni.setStorageSync('monitorPointDetail', {
...point,
engineeringName: this.engineeringName,
showAllIndicators: true,
})
uni.navigateTo({
url: '/pages/index/comp/targetInfo',
})
},
// 按监测点类型取对应已选指标过滤展示
getDisplayChildren(point) {
const children = point.children || []
const selected = point.lineType === 0 ? this.selectedIndicatorsPqCom : this.selectedIndicators
return selected
.map((name) => children.find((child) => this.matchIndicator(child.name, name)))
.filter(Boolean)
},
// 有指标数据时显示「更多指标」
shouldShowMoreBtn(point) {
return (point.children || []).length > 0
},
// 将指标列表按每行两个分组
chunkedChildren(children) {
const result = []
for (let i = 0; i < children.length; i += 2) {
result.push(children.slice(i, i + 2))
}
return result
},
backToTop() {
uni.pageScrollTo({
scrollTop: 0,
duration: 300,
})
this.showBackTop = false
},
// 跳转页面
jump(idx) {
if (idx == 0) {
// 项目总数 -> 项目管理
const engineering = uni.getStorageSync('engineering') || {
id: this.engineeringId,
name: this.engineeringName,
}
if (!engineering?.id) {
return uni.showToast({
title: '请先选择工程',
icon: 'none',
})
}
uni.navigateTo({
url:
'/pages/project/list?engineeringName=' +
encodeURIComponent(engineering.name || '') +
'&engineeringId=' +
engineering.id,
})
} else if (idx == 1) {
// 设备总数
uni.navigateTo({
url: '/pages/device/list?type=nowEngineering',
})
}
},
},
}
</script>
<style lang="scss" scoped>
.itic2-page {
min-height: 100vh;
background: #f7f8fa;
position: relative;
}
.itic2-content {
padding: 20rpx 0 0rpx;
box-sizing: border-box;
}
.back-top {
position: fixed;
right: 30rpx;
bottom: 60rpx;
width: 80rpx;
height: 80rpx;
border-radius: 50%;
background: #376cf3;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4rpx 16rpx rgba(55, 108, 243, 0.35);
z-index: 1;
}
.card {
background: #ffffff;
border-radius: 10px;
box-shadow: rgba(0, 0, 0, 0.08) 0px 0px 3px 1px;
margin: 0 10px 10px;
overflow: hidden;
}
.project-header {
padding: 20rpx;
// margin-top: 20rpx;
}
.project-title-row {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20rpx;
}
.project-title-left {
display: flex;
align-items: center;
gap: 12rpx;
flex: 1;
min-width: 0;
}
.project-name {
font-size: 32rpx;
font-weight: 700;
color: #333333;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.switch-btn {
display: flex;
align-items: center;
gap: 6rpx;
padding: 8rpx 20rpx;
border: 1rpx solid #376cf380;
background-color: #266fff10;
border-radius: 16rpx;
flex-shrink: 0;
text {
font-size: 24rpx;
color: #376cf3;
}
}
.stats-row {
display: flex;
gap: 20rpx;
}
.stats-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 4rpx;
padding: 16rpx 12rpx;
background: #376cf3;
border-radius: 16rpx;
color: #ffffff;
}
.stats-num {
font-size: 44rpx;
font-weight: 700;
line-height: 1.2;
}
.stats-label {
font-size: 26rpx;
}
.indicators-card {
padding: 24rpx;
}
.indicator-group {
margin-bottom: 20rpx;
&:last-child {
margin-bottom: 0;
}
}
.indicator-group-title {
display: block;
margin-bottom: 12rpx;
font-size: 26rpx;
color: #666;
}
.section-title-row {
display: flex;
align-items: center;
gap: 10rpx;
margin-bottom: 20rpx;
&--no-mb {
margin-bottom: 0;
}
}
.section-title {
font-size: 30rpx;
font-weight: 600;
color: #333333;
}
.indicator-tags {
display: flex;
flex-wrap: wrap;
gap: 16rpx;
}
.indicator-tag {
display: flex;
align-items: center;
gap: 6rpx;
padding: 6rpx 14rpx;
border-radius: 16rpx;
font-size: 26rpx;
max-width: 100%;
.indicator-tag-text {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&--active {
background: #376cf315;
color: #376cf3;
}
&--add {
background: #f5f5f5;
color: #666666;
border: 1rpx dashed #dcdfe6;
}
}
.monitor-section-header {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 12rpx;
padding: 0 10px 0rpx;
}
.legend-row {
display: flex;
gap: 20rpx;
align-items: center;
}
.legend-item {
display: flex;
align-items: center;
gap: 8rpx;
}
.legend-dot {
width: 16rpx;
height: 16rpx;
border-radius: 50%;
}
.legend-text {
font-size: 24rpx;
color: #666666;
}
.monitor-search {
position: sticky;
top: 0;
z-index: 10;
padding: 16rpx 10px 16rpx;
background: #f7f8fa;
/deep/ .uni-searchbar {
padding: 0;
}
}
.monitor-list {
display: flex;
flex-direction: column;
padding-bottom: 40rpx;
}
.monitor-card {
border: 1rpx solid #eef2f6;
box-shadow: rgba(0, 0, 0, 0.08) 0px 0px 3px 1px;
}
.card-header {
padding: 20rpx 20rpx 12rpx;
display: flex;
align-items: center;
border-bottom: 1rpx solid #eef2f6;
}
.event-icon {
width: 90rpx;
height: 90rpx;
border-radius: 16rpx;
display: flex;
justify-content: center;
align-items: center;
margin-right: 20rpx;
background-color: #376cf320;
flex-shrink: 0;
}
.card-header-info {
flex: 1;
min-width: 0;
}
.point-name-row {
display: flex;
align-items: center;
gap: 12rpx;
margin-bottom: 8rpx;
min-width: 0;
}
.point-name {
// flex: 1;
min-width: 0;
font-size: 30rpx;
font-weight: 700;
color: #333333;
}
.point-type-tag {
flex-shrink: 0;
padding: 4rpx 12rpx;
font-size: 22rpx;
color: #2e8b57;
background: #2e8b5715;
border-radius: 8rpx;
line-height: 1.2;
}
.meta-row {
display: grid;
grid-template-columns: 1fr;
gap: 6rpx 12rpx;
}
.meta-item {
font-size: 24rpx;
color: #666666;
line-height: 1.2;
}
.meta-time {
display: block;
margin-top: 8rpx;
font-size: 24rpx;
color: #666666;
line-height: 1.2;
}
.params-section {
padding: 20rpx 16rpx;
}
.double-row {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16rpx;
margin-bottom: 16rpx;
&:last-child {
margin-bottom: 0;
}
}
.param-group {
min-width: 0;
background: #f3f3f3;
border-radius: 16rpx;
padding: 16rpx 8rpx 12rpx;
}
.param-title {
font-size: 24rpx;
color: #666666;
margin-bottom: 8rpx;
padding-left: 4rpx;
}
.phase-vertical {
display: flex;
align-items: stretch;
}
.phase-single {
display: flex;
justify-content: center;
align-items: center;
padding: 4rpx;
}
.phase-item-vertical {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
padding: 4rpx;
}
.phase-value-vertical {
font-size: 26rpx;
font-weight: 700;
&--neutral {
color: #333333;
}
}
.phase-divider {
width: 1px;
background: #d2d2d2;
margin: 8rpx 0;
}
.more-btn {
margin: 0 20rpx 20rpx;
height: 72rpx;
line-height: 72rpx;
text-align: center;
border: 1rpx solid #376cf380;
background-color: #266fff10;
border-radius: 16rpx;
text {
font-size: 28rpx;
color: #376cf3;
font-weight: 500;
}
}
.ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.indicator-popup {
background: #ffffff;
overflow: hidden;
}
.indicator-popup-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 18rpx 32rpx;
border-bottom: 1rpx solid #eef2f6;
}
.indicator-popup-cancel {
font-size: 27rpx;
color: #666666;
min-width: 80rpx;
}
.indicator-popup-title {
flex: 1;
text-align: center;
font-size: 28rpx;
font-weight: 600;
color: #333333;
}
.indicator-popup-confirm {
font-size: 28rpx;
color: #376cf3;
min-width: 80rpx;
text-align: right;
}
.indicator-popup-list {
height: 60vh;
padding: 8rpx 0 16rpx;
box-sizing: border-box;
}
.indicator-popup-section {
padding-bottom: 8rpx;
}
.indicator-popup-subtitle {
display: block;
padding: 16rpx 32rpx 8rpx;
font-size: 24rpx;
color: #999999;
}
.indicator-popup-empty {
padding: 40rpx 0;
text-align: center;
font-size: 28rpx;
color: #999999;
}
.indicator-popup-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx 32rpx;
font-size: 26rpx;
color: #333333;
&--active {
color: #376cf3;
background: #376cf310;
}
}
.event-tag {
font-size: 22rpx;
padding: 2rpx 10rpx;
border-radius: 8rpx;
margin-top: 5rpx;
margin-left: 10rpx;
// height: 38rpx;
}
// 在线
.zx-tag {
background-color: #10b98120;
color: #10b981;
}
.lx-tag {
background-color: #ff3b3020;
color: #ff3b30;
}
/deep/ .uni-searchbar__box {
justify-content: left;
}
</style>