|
@@ -1,699 +0,0 @@
|
|
|
-<template>
|
|
|
-<<<<<<< HEAD
|
|
|
- <div class="camera-page">
|
|
|
- <!-- 顶部标签页 -->
|
|
|
- <div class="camera-header" v-if="Object.values(oldTotalObj).reduce((t,c) => t+c, 0)">
|
|
|
- <el-tabs v-model="tabActive" @tab-click="handleTabClick">
|
|
|
- <el-tab-pane
|
|
|
- v-for="item in tabList"
|
|
|
- :key="item.id"
|
|
|
- :label="`${item.name}(${totalObj[item.id]})`"
|
|
|
- :name="item.id"
|
|
|
- v-show="oldTotalObj[item.id]"
|
|
|
- />
|
|
|
- </el-tabs>
|
|
|
-
|
|
|
- <!-- 操作栏 -->
|
|
|
- <div class="main-list">
|
|
|
- <div class="btns">
|
|
|
- <!-- 全选 -->
|
|
|
- <div v-show="isImgType" class="all-select" :class="{disable: !cameraList.length}">
|
|
|
- <el-checkbox
|
|
|
- v-model="selectAll"
|
|
|
- @change="handleSelectAll"
|
|
|
- :disabled="!cameraList.length"
|
|
|
- >
|
|
|
- 全选
|
|
|
- </el-checkbox>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 协作按钮 -->
|
|
|
- <el-button
|
|
|
- v-if="tabActive !== 0 && selectedArr.length > 0"
|
|
|
- type="primary"
|
|
|
- size="small"
|
|
|
- @click="multCop"
|
|
|
- >
|
|
|
- 协作
|
|
|
- </el-button>
|
|
|
-
|
|
|
- <!-- 解绑按钮 -->
|
|
|
- <el-button
|
|
|
- v-if="tabActive !== 0 && selectedArr.length > 0"
|
|
|
- type="danger"
|
|
|
- size="small"
|
|
|
- @click="multDel"
|
|
|
- >
|
|
|
- 解绑
|
|
|
- </el-button>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="rig-con">
|
|
|
- <!-- 添加设备 -->
|
|
|
- <el-button type="primary" size="small" @click="addDevice">
|
|
|
- 添加设备
|
|
|
- </el-button>
|
|
|
-
|
|
|
- <!-- 视图切换 -->
|
|
|
- <template v-if="tabActive !== 0">
|
|
|
- <el-button-group class="view-toggle">
|
|
|
- <el-button
|
|
|
- :type="isImgType ? 'primary' : 'default'"
|
|
|
- size="small"
|
|
|
- @click="changeType(true)"
|
|
|
- >
|
|
|
- 卡片
|
|
|
- </el-button>
|
|
|
- <el-button
|
|
|
- :type="!isImgType ? 'primary' : 'default'"
|
|
|
- size="small"
|
|
|
- @click="changeType(false)"
|
|
|
- >
|
|
|
- 列表
|
|
|
- </el-button>
|
|
|
- </el-button-group>
|
|
|
- </template>
|
|
|
-
|
|
|
- <!-- 搜索框 -->
|
|
|
- <el-input
|
|
|
- v-model="searchKey"
|
|
|
- placeholder="搜索设备ID"
|
|
|
- class="search-input"
|
|
|
- @keyup.enter="handleSearch"
|
|
|
- clearable
|
|
|
- >
|
|
|
- <template #prepend>
|
|
|
- <el-select v-model="selectedType" placeholder="选择类型" style="width: 100px">
|
|
|
- <el-option
|
|
|
- v-for="item in searchTypeList"
|
|
|
- :key="item.value"
|
|
|
- :label="item.name"
|
|
|
- :value="item"
|
|
|
- />
|
|
|
- </el-select>
|
|
|
- </template>
|
|
|
- <template #append>
|
|
|
- <el-button @click="handleSearch">
|
|
|
- 搜索
|
|
|
- </el-button>
|
|
|
- </template>
|
|
|
- </el-input>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 内容区域 -->
|
|
|
- <template>
|
|
|
- <!-- 卡片视图 -->
|
|
|
- <el-row :gutter="20" class="camera-cards" v-show="isImgType || tabActive === 0">
|
|
|
- <template v-if="!loading">
|
|
|
- <el-col
|
|
|
- :span="8"
|
|
|
- v-for="(item, index) in cameraList"
|
|
|
- :key="index"
|
|
|
- class="camera-item"
|
|
|
- >
|
|
|
- <div class="card-wrapper">
|
|
|
- <el-checkbox
|
|
|
- v-model="item.selected"
|
|
|
- @change="handleItemSelect(item)"
|
|
|
- class="item-checkbox"
|
|
|
- />
|
|
|
- <camera-item
|
|
|
- :item="item"
|
|
|
- :tabActive="tabActive"
|
|
|
- @handleCooperation="handleCooperation"
|
|
|
- @unbind="unbind"
|
|
|
- @renew="handleRenew"
|
|
|
- />
|
|
|
- </div>
|
|
|
- </el-col>
|
|
|
- </template>
|
|
|
- </el-row>
|
|
|
-
|
|
|
- <!-- 列表视图 -->
|
|
|
- <table-list
|
|
|
- v-show="!(isImgType || tabActive === 0)"
|
|
|
- ref="tableRef"
|
|
|
- @selection-change="selectHandle"
|
|
|
- @unbind="unbind"
|
|
|
- @cooperation="handleCooperation"
|
|
|
- @renew="handleRenew"
|
|
|
- :header="tabHeader"
|
|
|
- :selection="cameraList.length > 0"
|
|
|
- :data="cameraList"
|
|
|
- :show-view-toggle="false"
|
|
|
- class="table-list"
|
|
|
- >
|
|
|
- <template #item="{ data, type, canclick, item }">
|
|
|
- <template v-if="canclick">
|
|
|
- <span
|
|
|
- class="table-btn"
|
|
|
- @click="handleCooperation(item)"
|
|
|
- v-if="item.status !== 0"
|
|
|
- >
|
|
|
- 协作列表
|
|
|
- </span>
|
|
|
-
|
|
|
- <span class="info-wrapper">
|
|
|
- <span class="table-btn" @mouseover="showInfo = item.id" @mouseout="showInfo = null">
|
|
|
- 详细信息
|
|
|
- </span>
|
|
|
- <div
|
|
|
- v-show="showInfo === item.id"
|
|
|
- class="info-tooltip"
|
|
|
- >
|
|
|
- <div class="info-content">
|
|
|
- <span class="th">场景数量</span><span class="th">最后时间</span>
|
|
|
- <span class="td">{{ item.sceneNum || '-' }}</span><span class="td">{{ item.lastTime || '-' }}</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </span>
|
|
|
- </template>
|
|
|
-
|
|
|
- <span v-else-if="type === 'image'" class="flex-avatar">
|
|
|
- <span v-if="isMember(item)" class="vip-icon"></span>
|
|
|
- <span v-else-if="isExpiredMember(item)" class="vip-icon vip-expired-icon"></span>
|
|
|
- {{ item.snCode }}
|
|
|
- </span>
|
|
|
-
|
|
|
- <span v-else-if="type === 'qingkuang'">
|
|
|
- <span v-if="item.usedSpaceStr && item.totalSpaceStr && item.totalSpaceStr != '0B'">
|
|
|
- {{ item.usedSpaceStr }}{{ isMember(item) ? "" : ` / ${item.totalSpaceStr}` }}
|
|
|
- </span>
|
|
|
- <span v-else>--</span>
|
|
|
- </span>
|
|
|
-
|
|
|
- <span v-else-if="type === 'spaceEndStr'">
|
|
|
- {{ item.spaceEndStr || "--" }}
|
|
|
- <span v-if="isExpired(item)" class="expired-icon" @mouseover="showCtrls = item.id" @mouseout="showCtrls = null">
|
|
|
- ⚠️
|
|
|
- <div v-show="showCtrls === item.id" class="expired-tooltip">
|
|
|
- <p>{{ isExpired(item) ? '会员已过期' : '会员即将过期' }}</p>
|
|
|
- <div class="ctrls-w">
|
|
|
- <el-button size="small" @click="showCtrls = null">取消</el-button>
|
|
|
- <el-button size="small" type="primary" @click="handleRenew(item)">续费</el-button>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </span>
|
|
|
- </span>
|
|
|
-
|
|
|
- <span v-else>{{ data || "-" }}</span>
|
|
|
- </template>
|
|
|
- </table-list>
|
|
|
- </template>
|
|
|
-
|
|
|
- <!-- 空状态 -->
|
|
|
- <div class="empty-state" v-if="!loading && !total">
|
|
|
- <el-empty description="暂无数据">
|
|
|
- <template v-if="!Object.values(oldTotalObj).reduce((t,c) => t+c, 0)">
|
|
|
- <el-button type="primary" @click="addDevice">添加设备</el-button>
|
|
|
- </template>
|
|
|
- </el-empty>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 分页 -->
|
|
|
- <div class="pagination-wrapper" v-if="total">
|
|
|
- <el-pagination
|
|
|
- v-model:current-page="currentPage"
|
|
|
- v-model:page-size="pageSize"
|
|
|
- :page-sizes="[9, 18, 36, 72]"
|
|
|
- :total="total"
|
|
|
- layout="total, sizes, prev, pager, next, jumper"
|
|
|
- @size-change="handleSizeChange"
|
|
|
- @current-change="handleCurrentChange"
|
|
|
- />
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 绑定设备弹窗 -->
|
|
|
- <el-dialog v-model="showBinding" title="绑定设备" width="600px">
|
|
|
- <div>绑定设备功能</div>
|
|
|
- <template #footer>
|
|
|
- <el-button @click="showBinding = false">取消</el-button>
|
|
|
- <el-button type="primary" @click="handleBindingSuccess">确定</el-button>
|
|
|
- </template>
|
|
|
- </el-dialog>
|
|
|
-
|
|
|
- <!-- 续费弹窗 -->
|
|
|
- <el-dialog v-model="showRenew" title="会员续费" width="600px">
|
|
|
- <div>会员续费功能</div>
|
|
|
- <template #footer>
|
|
|
- <el-button @click="showRenew = false">取消</el-button>
|
|
|
- <el-button type="primary" @click="handleRenewSuccess">确定</el-button>
|
|
|
- </template>
|
|
|
- </el-dialog>
|
|
|
-=======
|
|
|
- <div class="pcPage">
|
|
|
- <h-icon class="icon" type="sousuo" />
|
|
|
->>>>>>> master
|
|
|
- </div>
|
|
|
-</template>
|
|
|
-
|
|
|
-<script setup lang="ts">
|
|
|
-import { ref, computed, onMounted, watch, nextTick } from 'vue'
|
|
|
-import { ElMessage, ElMessageBox } from 'element-plus'
|
|
|
-import TableList from '@/components/tableList/index.vue'
|
|
|
-
|
|
|
-// 静态数据
|
|
|
-const tabList = ref([
|
|
|
- { id: 0, name: '协作设备' },
|
|
|
- { id: 4, name: '我的设备' },
|
|
|
- { id: 10, name: '共享设备' },
|
|
|
- { id: 11, name: '租赁设备' }
|
|
|
-])
|
|
|
-
|
|
|
-const searchTypeList = ref([
|
|
|
- { name: '设备编号', value: 2 },
|
|
|
- { name: '用户名', value: 1 }
|
|
|
-])
|
|
|
-
|
|
|
-// 表格头部配置
|
|
|
-const tabHeader = ref([
|
|
|
- { key: 'snCode', name: '设备编号', type: 'image', width: 200 },
|
|
|
- { key: 'status', name: '状态', width: 100 },
|
|
|
- { key: 'qingkuang', name: '使用情况', type: 'qingkuang', width: 150 },
|
|
|
- { key: 'spaceEndStr', name: '到期时间', type: 'spaceEndStr', width: 150 },
|
|
|
- { key: 'operation', name: '操作', canclick: true, width: 200 }
|
|
|
-])
|
|
|
-
|
|
|
-// 静态设备数据
|
|
|
-const mockCameraData = ref([
|
|
|
- {
|
|
|
- id: 1,
|
|
|
- snCode: 'CAM001',
|
|
|
- status: 1,
|
|
|
- usedSpaceStr: '2.5GB',
|
|
|
- totalSpaceStr: '10GB',
|
|
|
- spaceEndStr: '2024-12-31',
|
|
|
- spaceEndTime: '2024-12-31',
|
|
|
- userIncrementId: 'inc_001',
|
|
|
- sceneNum: 5,
|
|
|
- lastTime: '2024-01-15 10:30:00',
|
|
|
- selected: false
|
|
|
- },
|
|
|
- {
|
|
|
- id: 2,
|
|
|
- snCode: 'CAM002',
|
|
|
- status: 1,
|
|
|
- usedSpaceStr: '5.2GB',
|
|
|
- totalSpaceStr: '20GB',
|
|
|
- spaceEndStr: '2024-11-30',
|
|
|
- spaceEndTime: '2024-11-30',
|
|
|
- userIncrementId: 'inc_002',
|
|
|
- sceneNum: 8,
|
|
|
- lastTime: '2024-01-14 15:20:00',
|
|
|
- selected: false
|
|
|
- },
|
|
|
- {
|
|
|
- id: 3,
|
|
|
- snCode: 'CAM003',
|
|
|
- status: 0,
|
|
|
- usedSpaceStr: '1.8GB',
|
|
|
- totalSpaceStr: '5GB',
|
|
|
- spaceEndStr: '2024-10-15',
|
|
|
- spaceEndTime: '2024-10-15',
|
|
|
- userIncrementId: null,
|
|
|
- sceneNum: 3,
|
|
|
- lastTime: '2024-01-13 09:15:00',
|
|
|
- selected: false
|
|
|
- }
|
|
|
-])
|
|
|
-
|
|
|
-// 响应式数据
|
|
|
-const tabActive = ref(4)
|
|
|
-const currentPage = ref(1)
|
|
|
-const pageSize = ref(9)
|
|
|
-const total = ref(0)
|
|
|
-const isImgType = ref(localStorage.getItem("isImgTypeForDevice") !== "false")
|
|
|
-const searchKey = ref("")
|
|
|
-const loading = ref(false)
|
|
|
-const selectedArr = ref([])
|
|
|
-const selectAll = ref(false)
|
|
|
-const showBinding = ref(false)
|
|
|
-const showRenew = ref(false)
|
|
|
-const reNewItem = ref({})
|
|
|
-const showCtrls = ref(null)
|
|
|
-const showInfo = ref(null)
|
|
|
-const selectedType = ref({ name: '设备编号', value: 2 })
|
|
|
-
|
|
|
-// 计算属性
|
|
|
-const totalObj = ref({
|
|
|
- 0: 0,
|
|
|
- 4: 0,
|
|
|
- 10: 0,
|
|
|
- 11: 0
|
|
|
-})
|
|
|
-
|
|
|
-const oldTotalObj = ref({
|
|
|
- 0: 0,
|
|
|
- 4: 0,
|
|
|
- 10: 0,
|
|
|
- 11: 0
|
|
|
-})
|
|
|
-
|
|
|
-const cameraList = computed(() => {
|
|
|
- let filteredData = mockCameraData.value
|
|
|
-
|
|
|
- // 根据当前标签页过滤
|
|
|
- if (tabActive.value !== 4) {
|
|
|
- // 这里可以根据不同的标签页显示不同的数据
|
|
|
- filteredData = mockCameraData.value.filter(item => {
|
|
|
- if (tabActive.value === 0) return item.status === 0 // 协作设备
|
|
|
- if (tabActive.value === 10) return item.id % 2 === 0 // 共享设备
|
|
|
- if (tabActive.value === 11) return item.id % 3 === 0 // 租赁设备
|
|
|
- return true
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- // 搜索过滤
|
|
|
- if (searchKey.value) {
|
|
|
- filteredData = filteredData.filter(item => {
|
|
|
- if (selectedType.value.value === 2) {
|
|
|
- return item.snCode.toLowerCase().includes(searchKey.value.toLowerCase())
|
|
|
- }
|
|
|
- return true
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- // 分页
|
|
|
- const start = (currentPage.value - 1) * pageSize.value
|
|
|
- const end = start + pageSize.value
|
|
|
- total.value = filteredData.length
|
|
|
-
|
|
|
- return filteredData.slice(start, end)
|
|
|
-})
|
|
|
-
|
|
|
-// 组件引用
|
|
|
-const tableRef = ref()
|
|
|
-
|
|
|
-// 方法
|
|
|
-const handleTabClick = (tab: any) => {
|
|
|
- tabActive.value = parseInt(tab.name)
|
|
|
- currentPage.value = 1
|
|
|
- updateTotalCount()
|
|
|
-}
|
|
|
-
|
|
|
-const updateTotalCount = () => {
|
|
|
- // 更新各个标签的数量
|
|
|
- totalObj.value[0] = mockCameraData.value.filter(item => item.status === 0).length
|
|
|
- totalObj.value[4] = mockCameraData.value.length
|
|
|
- totalObj.value[10] = mockCameraData.value.filter(item => item.id % 2 === 0).length
|
|
|
- totalObj.value[11] = mockCameraData.value.filter(item => item.id % 3 === 0).length
|
|
|
-
|
|
|
- oldTotalObj.value = { ...totalObj.value }
|
|
|
-}
|
|
|
-
|
|
|
-const changeType = (status: boolean) => {
|
|
|
- isImgType.value = status
|
|
|
- localStorage.setItem("isImgTypeForDevice", status.toString())
|
|
|
-}
|
|
|
-
|
|
|
-const handleSearch = () => {
|
|
|
- currentPage.value = 1
|
|
|
-}
|
|
|
-
|
|
|
-const handleSelectAll = (val: boolean) => {
|
|
|
- cameraList.value.forEach(item => {
|
|
|
- item.selected = val
|
|
|
- })
|
|
|
- updateSelectedArr()
|
|
|
-}
|
|
|
-
|
|
|
-const handleItemSelect = (item: any) => {
|
|
|
- updateSelectedArr()
|
|
|
-
|
|
|
- // 更新全选状态
|
|
|
- selectAll.value = cameraList.value.every(item => item.selected)
|
|
|
-}
|
|
|
-
|
|
|
-const updateSelectedArr = () => {
|
|
|
- selectedArr.value = cameraList.value.filter(item => item.selected)
|
|
|
-}
|
|
|
-
|
|
|
-const selectHandle = (selection: any[]) => {
|
|
|
- selectedArr.value = selection
|
|
|
-}
|
|
|
-
|
|
|
-const multCop = () => {
|
|
|
- if (selectedArr.value.length === 0) {
|
|
|
- ElMessage.warning('请至少选择一个设备')
|
|
|
- return
|
|
|
- }
|
|
|
- ElMessage.success('批量协作功能')
|
|
|
-}
|
|
|
-
|
|
|
-const multDel = async () => {
|
|
|
- if (selectedArr.value.length === 0) {
|
|
|
- ElMessage.warning('请至少选择一个设备')
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- try {
|
|
|
- await ElMessageBox.confirm('确定要解绑选中的设备吗?', '提示', {
|
|
|
- confirmButtonText: '确定',
|
|
|
- cancelButtonText: '取消',
|
|
|
- type: 'warning'
|
|
|
- })
|
|
|
- ElMessage.success('解绑成功')
|
|
|
- selectedArr.value = []
|
|
|
- } catch {
|
|
|
- // 用户取消
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-const handleCooperation = (item: any) => {
|
|
|
- ElMessage.success(`设备 ${item.snCode} 协作功能`)
|
|
|
-}
|
|
|
-
|
|
|
-const unbind = async (item: any) => {
|
|
|
- try {
|
|
|
- await ElMessageBox.confirm(`确定要解绑设备 ${item.snCode} 吗?`, '提示', {
|
|
|
- confirmButtonText: '确定',
|
|
|
- cancelButtonText: '取消',
|
|
|
- type: 'warning'
|
|
|
- })
|
|
|
- ElMessage.success('解绑成功')
|
|
|
- } catch {
|
|
|
- // 用户取消
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-const handleRenew = (item: any) => {
|
|
|
- reNewItem.value = item
|
|
|
- showRenew.value = true
|
|
|
-}
|
|
|
-
|
|
|
-const addDevice = () => {
|
|
|
- showBinding.value = true
|
|
|
-}
|
|
|
-
|
|
|
-const handleBindingSuccess = () => {
|
|
|
- showBinding.value = false
|
|
|
- ElMessage.success('绑定成功')
|
|
|
- updateTotalCount()
|
|
|
-}
|
|
|
-
|
|
|
-const handleRenewSuccess = () => {
|
|
|
- showRenew.value = false
|
|
|
- ElMessage.success('续费成功')
|
|
|
-}
|
|
|
-
|
|
|
-const handleSizeChange = (val: number) => {
|
|
|
- pageSize.value = val
|
|
|
- currentPage.value = 1
|
|
|
-}
|
|
|
-
|
|
|
-const handleCurrentChange = (val: number) => {
|
|
|
- currentPage.value = val
|
|
|
-}
|
|
|
-
|
|
|
-// 工具方法
|
|
|
-const isMember = (item: any) => {
|
|
|
- return item.userIncrementId && !isExpired(item)
|
|
|
-}
|
|
|
-
|
|
|
-const isExpiredMember = (item: any) => {
|
|
|
- return item.userIncrementId && isExpired(item)
|
|
|
-}
|
|
|
-
|
|
|
-const isExpired = (item: any) => {
|
|
|
- if (!item.spaceEndTime) return false
|
|
|
- const expired = Math.floor((new Date(item.spaceEndTime).getTime() - new Date().getTime()) / 86400000) + 1
|
|
|
- return expired < 0
|
|
|
-}
|
|
|
-
|
|
|
-// 生命周期
|
|
|
-onMounted(() => {
|
|
|
- updateTotalCount()
|
|
|
-})
|
|
|
-
|
|
|
-// 监听器
|
|
|
-watch(tabActive, () => {
|
|
|
- selectedArr.value = []
|
|
|
- selectAll.value = false
|
|
|
-})
|
|
|
-</script>
|
|
|
-
|
|
|
-<style lang="less" scoped>
|
|
|
-.camera-page {
|
|
|
- padding: 30px;
|
|
|
- background: #fff;
|
|
|
- min-height: calc(100vh - 60px);
|
|
|
-}
|
|
|
-
|
|
|
-.camera-header {
|
|
|
- margin-bottom: 20px;
|
|
|
-
|
|
|
- :deep(.el-tabs__header) {
|
|
|
- margin-bottom: 20px;
|
|
|
- }
|
|
|
-
|
|
|
- .main-list {
|
|
|
- display: flex;
|
|
|
- justify-content: space-between;
|
|
|
- align-items: center;
|
|
|
- padding: 10px 0;
|
|
|
- border-bottom: 1px solid #e5e5e5;
|
|
|
-
|
|
|
- .btns {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- gap: 10px;
|
|
|
-
|
|
|
- .all-select {
|
|
|
- &.disable {
|
|
|
- opacity: 0.5;
|
|
|
- pointer-events: none;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .rig-con {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- gap: 10px;
|
|
|
-
|
|
|
- .view-toggle {
|
|
|
- margin: 0 10px;
|
|
|
- }
|
|
|
-
|
|
|
- .search-input {
|
|
|
- width: 300px;
|
|
|
-
|
|
|
- :deep(.el-input-group__prepend) {
|
|
|
- padding: 0;
|
|
|
-
|
|
|
- .el-select {
|
|
|
- border: none;
|
|
|
-
|
|
|
- .el-input__wrapper {
|
|
|
- box-shadow: none;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-.camera-cards {
|
|
|
- padding: 20px 0;
|
|
|
-
|
|
|
- .camera-item {
|
|
|
- margin-bottom: 20px;
|
|
|
-
|
|
|
- .card-wrapper {
|
|
|
- position: relative;
|
|
|
- background: #f7f7f7;
|
|
|
- padding: 20px;
|
|
|
- border-radius: 8px;
|
|
|
- min-height: 180px;
|
|
|
-
|
|
|
- .item-checkbox {
|
|
|
- position: absolute;
|
|
|
- top: 10px;
|
|
|
- left: 10px;
|
|
|
- z-index: 1;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-.table-list {
|
|
|
- margin: 20px 0;
|
|
|
-}
|
|
|
-
|
|
|
-.empty-state {
|
|
|
- padding: 60px 0;
|
|
|
- text-align: center;
|
|
|
-}
|
|
|
-
|
|
|
-.pagination-wrapper {
|
|
|
- margin-top: 40px;
|
|
|
- text-align: center;
|
|
|
-}
|
|
|
-
|
|
|
-// 工具提示样式
|
|
|
-.info-wrapper, .expired-icon {
|
|
|
- position: relative;
|
|
|
-
|
|
|
- .info-tooltip, .expired-tooltip {
|
|
|
- position: absolute;
|
|
|
- background: #fff;
|
|
|
- border: 1px solid #e5e5e5;
|
|
|
- border-radius: 4px;
|
|
|
- padding: 10px;
|
|
|
- box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
|
|
- z-index: 1000;
|
|
|
- min-width: 200px;
|
|
|
- top: 100%;
|
|
|
- left: 0;
|
|
|
-
|
|
|
- .info-content {
|
|
|
- display: grid;
|
|
|
- grid-template-columns: 1fr 1fr;
|
|
|
- gap: 5px;
|
|
|
-
|
|
|
- .th {
|
|
|
- font-weight: 600;
|
|
|
- color: #323233;
|
|
|
- }
|
|
|
-
|
|
|
- .td {
|
|
|
- color: #666;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .ctrls-w {
|
|
|
- margin-top: 10px;
|
|
|
- text-align: right;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-.table-btn {
|
|
|
- color: #15bec8;
|
|
|
- cursor: pointer;
|
|
|
-
|
|
|
- &:hover {
|
|
|
- text-decoration: underline;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-.flex-avatar {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
-
|
|
|
- .vip-icon {
|
|
|
- width: 16px;
|
|
|
- height: 16px;
|
|
|
- background: url('@/assets/images/information/avatar_vip.png') no-repeat center center;
|
|
|
- background-size: cover;
|
|
|
- margin-right: 5px;
|
|
|
-
|
|
|
- &.vip-expired-icon {
|
|
|
- opacity: 0.5;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-</style>
|