Files
tkPage/src/views/hosts/hostsList.vue

910 lines
26 KiB
Vue
Raw Normal View History

2026-01-16 13:35:17 +08:00
<template>
2025-07-01 21:02:39 +08:00
<div class="hostList">
<div>
<div style="display: flex;">
<el-select v-model="searchForm.country" filterable :placeholder="$t('hostList.placeCountry')" size="large"
style="width: 160px">
<el-option :label="$t('hostList.selectAll')" :value="''" />
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<div></div>
<el-date-picker v-model="searchForm.createTime" type="date" value-format="YYYY-MM-DD"
:placeholder="$t('hostList.placeSeletTime')" size="large" style="margin-left: 50px;width: 160px;" />
<el-input v-model="searchForm.hostsId" :placeholder="$t('hostList.placeHostId')" size="large"
style="width: 160px; margin-left: 50px;" clearable />
<el-button class="serch-button" style="margin-left: 50px;" type="primary" @click="serch">{{
$t('hostList.query') }}</el-button>
2025-07-02 19:21:48 +08:00
<!-- <el-button class="put-button" :disabled="tableData.length == 0" type="primary" @click="exportList">{{
$t('hostList.export') }}</el-button> -->
2025-07-01 21:02:39 +08:00
<!-- <el-button class="put-button" type="primary" @click="dialogFormVisible = true">分配给指定员工</el-button> -->
<el-button @click="filterdialogVisible = true" style="width: 50px;" class="put-button" type="primary"><img
style="height: 30px;" src="@/assets/filter.png"></el-button>
</div>
<div class="hostTable center-justify">
<el-table ref="multipleTableRef" :data="tableData" stripe v-loading="loading" height="500"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="35" />
<el-table-column fixed prop="hostId" :label="$t('hostList.hostId')" width="160">
<template #default="scope">
<div class="hostIdText" @click="openHTML(scope.row.hostId)"> {{
scope.row.hostId }}</div>
</template>
</el-table-column>
<el-table-column prop="hostlevel" :label="$t('hostList.grade')" width="80">
<template #default="scope">
{{ scope.row.hostlevel }}
</template>
</el-table-column>
<el-table-column prop="invitationType" :label="$t('hostList.invitationType')" width="80">
<template #default="scope">
2026-01-07 18:57:30 +08:00
<el-tag :type="scope.row.invitationType == 1 ? 'success' : 'warning'">
2025-07-01 21:02:39 +08:00
{{ scope.row.invitationType == 1 ? $t('hostList.invitationType1') : $t('hostList.invitationType2') }}
</el-tag>
</template>
</el-table-column>
2026-01-16 13:35:17 +08:00
<el-table-column :label="$t('hostList.liveSessions')" width="120">
2026-01-07 18:57:30 +08:00
<template #default="scope">
<el-button class="live-btn" size="small" @click="getliveHost(scope.row.hostId)">
2026-01-16 13:35:17 +08:00
{{ $t('hostList.viewSessions') }}
</el-button>
</template>
</el-table-column>
<el-table-column :label="$t('hostList.liveRevenue')" width="120">
<template #default="scope">
<el-button class="live-btn" size="small" @click="getRevenueStats(scope.row.hostId)">
{{ $t('hostList.viewRevenue') }}
2026-01-07 18:57:30 +08:00
</el-button>
</template>
</el-table-column>
2025-07-01 21:02:39 +08:00
<el-table-column v-for="label in labelList" :key="label.paramCode" :prop="label.paramCode"
:label="label.paramCodeMeaning" width="120">
<template v-if="label.paramCode != 'createDt'" #default="scope">
</template>
</el-table-column>
<!-- <el-table-column label="操作">
<template #default="scope">
<div style="display: flex; align-items: center">
<el-button type="primary" @click="getTkhostdetail(scope.row.hostId)">查看</el-button>
</div>
</template>
</el-table-column> -->
</el-table>
</div>
<!-- 分页 -->
<div class="center-justify" style="margin-top: 30px;">
<el-pagination v-model:current-page="page" v-model:page-size="pageSize" background
layout="sizes, prev, pager, next" :total="total" :page-sizes="[10, 20, 50, 100]"
@size-change="handleSizeChange" @current-change="handleCurrentChange" />
</div>
</div>
<el-dialog v-model="filterdialogVisible" width="800px" :before-close="handleClose">
<el-row v-for="(field, index) in fields" :key="index" :gutter="20" style="margin-bottom: 10px">
<el-col :span="4">
<div style="height: 100%; padding-top: 10px" class="center-justify">
{{ field.label }}
</div>
</el-col>
<el-col :span="10">
<div><label>{{ $t('hostList.min') }}</label></div>
<el-input type="number" :oninput="'if(value.length>9)value=value.slice(0,9)'"
v-model.number="searchForm[field.minModel]" :placeholder="$t('hostList.placeMin')" />
</el-col>
<el-col :span="10">
<div><label>{{ $t('hostList.max') }}</label></div>
<el-input type="number" :oninput="'if(value.length>9)value=value.slice(0,9)'"
v-model.number="searchForm[field.maxModel]" :placeholder="$t('hostList.placeMax')" />
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="4">
<!-- <label>选择筛选条件</label> -->
<div style="height: 100%;padding-top: 10px;" class="center-justify">
{{ $t('hostList.sort') }}
</div>
</el-col>
<el-col :span="10">
<div><label>{{ $t('hostList.sortType') }}</label></div>
2026-01-16 13:35:17 +08:00
<el-select v-model="sortData.sortType" filterable :placeholder="$t('hostList.selectPlaceholder')"
style="width: 240px">
2025-07-01 21:02:39 +08:00
<el-option v-for="item in sortNameOptions" :key="item.type" :label="item.label" :value="item.type" />
</el-select>
</el-col>
<el-col :span="10">
<div><label>{{ $t('hostList.ascending') }}/{{ $t('hostList.descending') }}</label></div>
2026-01-16 13:35:17 +08:00
<el-select v-model="sortData.sortForm" filterable :placeholder="$t('hostList.selectPlaceholder')"
style="width: 240px">
2025-07-01 21:02:39 +08:00
<el-option
v-for="item in [{ label: $t('hostList.ascending'), value: 'asc' }, { label: $t('hostList.descending'), value: 'desc' }]"
:key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-col>
</el-row>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="reset">
{{ $t('hostList.reset') }}
</el-button>
<!-- <el-button @click="filterdialogVisible = false">取消</el-button> -->
<el-button type="primary" @click="handelClick">
{{ $t('hostList.sure') }}
</el-button>
</span>
</template>
</el-dialog>
2026-01-07 18:57:30 +08:00
<LiveRecordDialog v-model:modelValue="liveDetailDialogVisible" :rows="liveDetailRecords"
@select="handleLiveSelect" />
2026-01-16 13:35:17 +08:00
<el-dialog v-model="revenueDialogVisible" :title="$t('hostList.liveRevenue')" width="80vw" top="6vh"
:close-on-click-modal="false" destroy-on-close>
<el-table :data="revenueRecords" border height="62vh" style="width: 100%" v-loading="revenueLoading"
table-layout="auto">
<el-table-column prop="displayId" :label="$t('hostList.revenueHost')" />
<el-table-column prop="todayRevenue" :label="$t('hostList.todayRevenueUsd')" />
<el-table-column prop="totalRevenue" :label="$t('hostList.totalRevenueUsd')" />
<el-table-column prop="lastDaysCount" :label="$t('hostList.liveDays')" />
<el-table-column prop="history" :label="$t('hostList.historyRevenueUsd')">
<template #default="{ row }">
<el-tooltip v-if="hasHistory(row.history)" effect="dark" placement="top">
<template #content>{{ buildHistoryTitle(row.history) }}</template>
<div class="history-sparkline-wrap">
<div class="history-sparkline-top">
<span class="history-sparkline-min-top">
{{ $t('hostList.revenueLow') }}: {{ formatRevenueValue(getHistoryMin(row.history)) }}
</span>
<span class="history-sparkline-max">
{{ $t('hostList.revenueHigh') }}: {{ formatRevenueValue(getHistoryMax(row.history)) }}
</span>
</div>
<svg class="history-sparkline" viewBox="0 0 180 48" preserveAspectRatio="none">
<line x1="2" y1="46" x2="178" y2="46" stroke="#e6eef7" stroke-width="1" />
<polyline :points="buildSparklinePoints(row.history)" fill="none" stroke="#45a1ff" stroke-width="2" />
</svg>
<div class="history-sparkline-bottom">
<div class="history-sparkline-dates">
<span class="history-sparkline-date">{{ getHistoryStartDate(row.history) }}</span>
<span class="history-sparkline-date">{{ getHistoryEndDate(row.history) }}</span>
</div>
</div>
</div>
</el-tooltip>
<span v-else>-</span>
</template>
</el-table-column>
<!-- <el-table-column prop="updatedAt" label="updatedAt" /> -->
<el-table-column prop="createdAt" :label="$t('hostList.revenueTime')">
<template #default="scope">
{{ formatTimestamp(scope.row.createdAt) }}
</template>
</el-table-column>
</el-table>
<template #footer>
<el-button @click="revenueDialogVisible = false">{{ $t('hostList.close') }}</el-button>
</template>
</el-dialog>
2025-07-01 21:02:39 +08:00
</div>
</template>
<script setup>
// import { getToken, setToken, removeToken } from '@/utils/storage'
2026-01-16 13:35:17 +08:00
import { tkhostdata, dicts, tkhostdetail, downList, getStaffList, managerhosts, upholdinfo, getCountryinfo, accountName, liveHostDetail, revenueStats } from '@/api/account';
2025-07-01 21:02:39 +08:00
import { usePythonBridge, } from '@/utils/pythonBridge'
import { getUser, setSerch, getSerch } from '@/utils/storage'
import { ref, reactive, onMounted } from 'vue';
// import EChartsComponent from '@/components/EChartsComponent.vue';
// import { ElMessage, ElMessageBox } from 'element-plus'
// import { color } from 'echarts';
import { useI18n } from 'vue-i18n'
2026-01-07 18:57:30 +08:00
import LiveRecordDialog from '@/components/LiveRecordDialog.vue'
2025-07-01 21:02:39 +08:00
2025-12-18 20:09:21 +08:00
2025-07-01 21:02:39 +08:00
const { t } = useI18n()
const loading = ref(false)
//py方法
const { givePyAnchorId, exportToExcel } = usePythonBridge();
let num = ref(0)
//账号信息
const userInfo = ref(getUser())
//主播列表DOM
const multipleTableRef = ref(null)
let labelList = ref([
{ paramCode: 'country', paramCodeMeaning: t('hostList.country') },
{ paramCode: 'createTime', paramCodeMeaning: t('hostList.creationTime') },
{ paramCode: 'hostsCoins', paramCodeMeaning: t('hostList.anchorcoins') },
{ paramCode: 'yesterdayCoins', paramCodeMeaning: t('hostList.yesterdayGoldCoins') },
{ paramCode: 'fans', paramCodeMeaning: t('hostList.fansNum') },
{ paramCode: 'fllowernum', paramCodeMeaning: t('hostList.followersNum') },
{ paramCode: 'onlineFans', paramCodeMeaning: t('hostList.onlineFans') },
{ paramCode: 'hostsKind', paramCodeMeaning: t('hostList.anchorType') },
// { paramCode: 'invitationType', paramCodeMeaning: t('hostList.invitationType') },
]);
const tableData = ref([])
//主播列表传参
const searchForm = ref({})
const fields = [
{ label: t('hostList.fansNum'), minModel: 'fansMin', maxModel: 'fansMax' },
{ label: t('hostList.onlineFans'), minModel: 'onlineFansMin', maxModel: 'onlineFansMax' },
{ label: t('hostList.anchorcoins'), minModel: 'hostsCoinsMin', maxModel: 'hostsCoinsMax' },
{ label: t('hostList.followersNum'), minModel: 'fllowernumMin', maxModel: 'fllowernumMax' },
]
//排序
let sortData = ref({ sortForm: 'desc', sortType: "createTime" })
//排序类型
let sortNameOptions = ref([
{ label: t('hostList.creationTime'), type: 'createTime' },
{ label: t('hostList.anchorcoins'), type: 'hostsCoins' },
{ label: t('hostList.fansNum'), type: 'fans' },
{ label: t('hostList.yesterdayGoldCoins'), type: 'yesterdayCoins' },
{ label: t('hostList.onlineFans'), type: 'onlineFans' },
{ label: t('hostList.followersNum'), type: 'fllowernum' },
])
//员工选择列表
let staffOptions = ref([])
//筛选条件选择列表
//选择的员工
let staffValue = ref('')
//选择的主播列表
let selectHostList = ref([])
//分配弹窗是否弹出
let dialogFormVisible = ref(false)
//分配情况弹窗是否弹出
let hostNameVisible = ref(false)
//备注弹窗是否弹出
let commentVisible = ref(false)
//筛选弹窗是否弹出
let filterdialogVisible = ref(false)
//分配的员工
let staffId = ref({})
//备注信息
let commentInfo = ref('')
//备注信息主播
let commentHost = ref('')
2026-01-07 18:57:30 +08:00
let liveDetailDialogVisible = ref(false)
let liveDetailRecords = ref([])
let liveDetailLoading = ref(false)
2026-01-16 13:35:17 +08:00
let revenueDialogVisible = ref(false)
let revenueRecords = ref([])
let revenueLoading = ref(false)
2025-07-01 21:02:39 +08:00
//分页
let pageSize = ref(10)
let page = ref(1)
let total = ref(0)
//是否渲染
const isPopoverVisible = reactive({})
let options = ref([])
let version = ref('0.0.0');
onMounted(() => {
getCountry(); //获取国家
// getSerchStorage();//获取搜索条件
getlist();//获取主播列表
})
function serch() {
page.value = 1
console.log(t('hostList.yesterdayGoldCoins'))
getlist();
}
function exportList() {
if (searchForm.value.dataType == 'InvitationType') {
searchForm.value.dataEnd = searchForm.value.dataStart
}
exportToExcel({})
// //浏览器导出方法
// downList('export/hostsinfo',
// {
// searchTime: searchForm.value.time,
// region: searchForm.value.country,
// pageSize: pageSize.value,
// page: page.value,
// userId: userInfo.value.userId,
// }
// );
}
//分页每页条数
function handleSizeChange(val) {
console.log(`${val} items per page`)
getlist();
}
//分页页数
function handleCurrentChange(val) {
console.log(`current page: ${val}`)
getlist();
}
//选择行
function handleSelectionChange(data) {
console.log(data)
selectHostList.value = []
data.forEach(item => {
selectHostList.value.push(item.hostId)
})
// multipleTableRef.value = data
// console.log(multipleTableRef.value)
}
//获取主播列表
const getlist = () => {
loading.value = true
console.log(searchForm.value)
tkhostdata({
tenantId: Number(userInfo.value.tenantId),
sort: sortData.value.sortForm,//正序倒序
sortName: sortData.value.sortType,//排序类型
"current": page.value,
"pageSize": pageSize.value,
...searchForm.value,//筛选条件
}).then(res => {
loading.value = false
if (res) {
console.log('主播列表', res)
total.value = Number(res.total)
tableData.value = res.records.map(item => ({
hostId: item.hostsId, // 注意:原字段是 hostId你的数据是 hostsId需手动映射
hostlevel: item.hostsLevel, // 原字段 hostlevel 对应你的数据 hostsLevel
country: item.country,
createTime: item.createTime,
fans: item.fans,
fllowernum: item.fllowernum,
hostsCoins: item.hostsCoins,
hostsKind: item.hostsKind,
onlineFans: item.onlineFans,
yesterdayCoins: item.yesterdayCoins,
// 保留原有字段(如 belongBy、useable 等)
belongBy: item.belongBy,
useable: item.useable,
invitationType: item.invitationType,
}));
}
})
}
function handelClick() {
filterdialogVisible.value = false
}
function reset() {
searchForm.value.fansMin = null
searchForm.value.fansMax = null
searchForm.value.onlineFansMin = null
searchForm.value.onlineFansMax = null
searchForm.value.hostsCoinsMin = null
searchForm.value.hostsCoinsMax = null
searchForm.value.fllowernumMin = null
searchForm.value.fllowernumMax = null
}
function handleClose(done) {
console.log('关闭')
// searchForm.value = {
// dataType: '',
// dataStart: '',
// dataEnd: '',
// }
done()
}
2026-01-07 18:57:30 +08:00
function getliveHost(hostId) {
liveDetailLoading.value = true
2025-12-18 20:09:21 +08:00
liveHostDetail(
{
2026-01-07 18:57:30 +08:00
"hostsId": hostId,
2025-12-18 20:09:21 +08:00
"tenantId": userInfo.value.tenantId
}
).then(res => {
2026-01-07 18:57:30 +08:00
const detailList = Array.isArray(res) ? res : (res?.records || [])
liveDetailRecords.value = detailList
liveDetailDialogVisible.value = true
}).catch(err => {
console.log('liveHostDetail error', err)
}).finally(() => {
liveDetailLoading.value = false
2025-12-18 20:09:21 +08:00
})
}
2026-01-07 18:57:30 +08:00
function handleLiveSelect(row) {
console.log('selected live row', row)
liveDetailDialogVisible.value = false
}
2026-01-16 13:35:17 +08:00
function getRevenueStats(hostId) {
revenueLoading.value = true
revenueStats(hostId).then(res => {
const detailList = Array.isArray(res) ? res : (res?.records || [])
revenueRecords.value = detailList
revenueDialogVisible.value = true
}).catch(err => {
console.log('revenueStats error', err)
}).finally(() => {
revenueLoading.value = false
})
}
function parseHistoryItems(history) {
if (!history) return []
let arr = history
if (typeof history === 'string') {
try {
arr = JSON.parse(history)
} catch {
return []
}
}
if (!Array.isArray(arr)) return []
return arr
.map((item, index) => {
if (typeof item === 'number') {
return { date: `Day ${index + 1}`, value: item }
}
if (item && typeof item === 'object') {
return {
date: item.date ? String(item.date) : '',
value: Number(item.value ?? 0),
}
}
return null
})
.filter(Boolean)
}
function hasHistory(history) {
return parseHistoryItems(history).length > 0
}
function getHistoryStats(history) {
const items = parseHistoryItems(history)
if (items.length === 0) {
return { min: 0, max: 0, start: '', end: '' }
}
const values = items.map(item => item.value)
return {
min: Math.min(...values),
max: Math.max(...values),
start: items[0].date || '',
end: items[items.length - 1].date || '',
}
}
function getHistoryMin(history) {
return getHistoryStats(history).min
}
function getHistoryMax(history) {
return getHistoryStats(history).max
}
function getHistoryStartDate(history) {
return getHistoryStats(history).start
}
function getHistoryEndDate(history) {
return getHistoryStats(history).end
}
function formatRevenueValue(value) {
const num = Number(value)
if (!Number.isFinite(num)) return ''
const fixed = num.toFixed(3)
return fixed.replace(/\.0+$/, '').replace(/(\.\d*?)0+$/, '$1')
}
function buildHistoryTitle(history) {
const items = parseHistoryItems(history)
if (items.length === 0) return '-'
return items.map(item => `${item.date}: ${formatRevenueValue(item.value)}`).join('\n')
}
function buildSparklinePoints(history) {
const items = parseHistoryItems(history)
if (items.length === 0) return ''
const values = items.map(item => item.value)
const min = Math.min(...values)
const max = Math.max(...values)
const range = max - min || 1
const width = 180
const height = 48
const padding = 2
const step = items.length > 1 ? (width - padding * 2) / (items.length - 1) : 0
return items.map((item, index) => {
const x = padding + index * step
const y = padding + (height - padding * 2) * (1 - (item.value - min) / range)
return `${x},${y}`
}).join(' ')
}
function formatTimestamp(value) {
if (value === null || value === undefined || value === '') {
return ''
}
if (value instanceof Date) {
return formatDate(value)
}
if (typeof value === 'number') {
const ms = value < 1e12 ? value * 1000 : value
return formatDate(new Date(ms))
}
if (typeof value === 'string') {
const trimmed = value.trim()
if (/^\d+$/.test(trimmed)) {
const num = Number(trimmed)
const ms = num < 1e12 ? num * 1000 : num
return formatDate(new Date(ms))
}
const parsed = Date.parse(trimmed)
if (!Number.isNaN(parsed)) {
return formatDate(new Date(parsed))
}
return trimmed
}
return String(value)
}
function formatDate(date) {
const y = date.getFullYear()
const m = String(date.getMonth() + 1).padStart(2, '0')
const d = String(date.getDate()).padStart(2, '0')
const hh = String(date.getHours()).padStart(2, '0')
const mm = String(date.getMinutes()).padStart(2, '0')
const ss = String(date.getSeconds()).padStart(2, '0')
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
}
2025-07-01 21:02:39 +08:00
//修改主播维护状态
// function handleSelectChange(event, data) {
// upholdinfo({
// "hostId": data.hostId,
// "userId": userInfo.value.userId,
// "tenantId": userInfo.value.tenantId,
// // "comment": "我已经尽力维护,但是失败了",
// "useable": event.target.value
// }).then(res => {
// console.log(res)
// })
// }
//更改主播维护备注
// function uphostcomment() {
// upholdinfo({
// "hostId": commentHost.value,
// "userId": userInfo.value.userId,
// "tenantId": userInfo.value.tenantId,
// "comment": commentInfo.value,
// }).then(res => {
// console.log(res)
// serch()
// commentVisible.value = false
// })
// }
function filterTag(value, row) {
console.log(row.useable, value)
return row.useable === value;
}
//获取国家
function getCountry() {
getCountryinfo({}).then(res => {
2025-12-18 20:09:21 +08:00
// console.log(res)
2025-07-01 21:02:39 +08:00
res.forEach(item => {
if (item.countryGroupName) {
options.value.push({ value: item.countryGroupName, label: item.countryGroupName })
}
})
2025-12-18 20:09:21 +08:00
// console.log(options.value)
2025-07-01 21:02:39 +08:00
}).catch(err => {
console.log('getCountry', err)
})
}
//获取下级员工
// const getStaff = () => {
// getStaffList({
// userId: userInfo.value.userId,
// activeYn: userInfo.value.activeYn,
// tenantId: userInfo.value.tenantId,
// }).then(res => {
// console.log(res)
// res.forEach(item => {
// staffOptions.value.push({
// value: item.userId,
// label: item.userName
// })
// })
// })
// }
// //分配主播给员工
// function allocation() {
// managerhosts({
// "manaId": userInfo.value.userId,
// "userId": staffValue.value,
// "tenantId": userInfo.value.tenantId,
// "hostIds": selectHostList.value
// }).then(res => {
// if (res) {
// dialogFormVisible.value = false
// }
// })
// }
//获取主播信息
// const getTkhostdetail = (id) => {
// tkhostdetail({
// hostId: id,
// // page: 1,
// searchTimeStart: '20250401',
// searchTimeEnd: '20250403'
// }).then(res => {
// console.log(labelList.value)
// })
// }
function openPopover(hostId, paramCode) {
isPopoverVisible[`${hostId}-${paramCode}`] = true;
}
function closePopover(hostId, paramCode) {
// isPopoverVisible[`${hostId}-${paramCode}`] = false;
}
function openHTML(id) {
givePyAnchorId(id)
// upholdinfo({
// "hostId": id,
// "userId": userInfo.value.userId,
// "tenantId": userInfo.value.tenantId,
// // "comment": "我已经尽力维护,但是失败了",
// "useable": "Y"
// }).then(res => {
// getlist();
// })
}
// function openAccountName(idStr) {
// if (idStr) {
// hostNameVisible.value = true
// accountName(idStr).then(res => {
// staffId.value = JSON.stringify(res).replace(/[{}"]/g, '') // 移除所有 {} 和 "
// .split(',') // 按逗号分割成数组
// console.log(res)
// })
// }
// }
</script>
<style lang="less">
.hostList {
box-sizing: border-box;
// height: 100vh;
padding: 40px;
2026-01-07 18:57:30 +08:00
background: linear-gradient(135deg, #f7fbff 0%, #f2f9f8 100%);
border-radius: 16px;
2025-07-01 21:02:39 +08:00
/* 页面无法选中 */
// -webkit-user-select: none;
// -moz-user-select: none;
// -ms-user-select: none;
// user-select: none;
.hostTable {
width: 100%;
2026-01-07 18:57:30 +08:00
max-width: 100%;
overflow: hidden;
padding: 16px;
background: #ffffff;
border-radius: 12px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.04);
box-sizing: border-box;
2025-07-01 21:02:39 +08:00
.hostIdText {
text-decoration: underline;
cursor: pointer;
}
2026-01-07 18:57:30 +08:00
.live-btn {
background: linear-gradient(90deg, #45a1ff, #5ad9ff);
border: none;
color: #fff;
}
.live-btn:hover {
filter: brightness(1.05);
}
:deep(.el-table) {
width: 100% !important;
table-layout: fixed;
}
:deep(.el-table__header-wrapper),
:deep(.el-table__body-wrapper) {
overflow-x: auto;
}
2025-07-01 21:02:39 +08:00
}
.serch-button {
width: 80px;
height: 47px;
background: @btn-bg-color;
border-radius: 10px;
border: none;
}
.put-button {
width: 132px;
height: 47px;
background: @btn-bg-color;
border-radius: 10px;
border: none;
}
}
.el-dialog {
--el-dialog-font-line-height: 50px;
--el-dialog-width: 600px;
--el-dialog-border-radius: 8px;
// border: 10px solid @bg-color-light;
}
.center-line {
display: flex;
flex-direction: column;
align-items: center;
// justify-content: center;
}
.center-justify {
display: flex;
justify-content: space-around;
align-items: center;
}
.center-align {
display: flex;
justify-content: space-between;
}
.center-flex {
display: flex;
justify-content: center;
align-items: center;
}
</style>
<style scoped lang="less">
2026-01-16 13:35:17 +08:00
.history-sparkline {
width: 180px;
height: 48px;
}
.history-sparkline-wrap {
display: flex;
flex-direction: column;
gap: 4px;
width: 180px;
}
.history-sparkline-top {
display: flex;
justify-content: space-between;
font-size: 12px;
color: #1f5fa8;
}
.history-sparkline-bottom {
display: flex;
justify-content: space-between;
font-size: 12px;
color: #7a8aa0;
gap: 8px;
}
.history-sparkline-min-top {
color: #4a5b73;
font-weight: 600;
}
.history-sparkline-dates {
display: flex;
justify-content: space-between;
align-items: center;
flex: 1;
min-width: 0;
}
.history-sparkline-date {
font-size: 12px;
color: #7a8aa0;
}
2025-07-01 21:02:39 +08:00
::v-deep(.el-input__wrapper) {
background-color: #F2FAF9;
border: 1px solid @bg-color;
height: 44px;
}
::v-deep(.el-select__wrapper) {
background-color: #F2FAF9;
border: 1px solid @bg-color;
height: 48px;
}
::v-deep(.el-pagination.is-background .el-pager li.is-active) {
background-color: @bg-color;
}
</style>