|
@@ -0,0 +1,477 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div class="container">
|
|
|
|
|
+ <Breadcrumb :items="['校园乐跑', '账号管理']" />
|
|
|
|
|
+
|
|
|
|
|
+ <userCard />
|
|
|
|
|
+
|
|
|
|
|
+ <a-card title="账号列表" style="margin-top: 15px;">
|
|
|
|
|
+ <a-button type="primary" size="large" @click="editAccount">
|
|
|
|
|
+ <template #icon>
|
|
|
|
|
+ <icon-plus />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ 添加账号
|
|
|
|
|
+ </a-button>
|
|
|
|
|
+
|
|
|
|
|
+ <a-button size="large" @click="download" style="margin-left: 10px;">
|
|
|
|
|
+ <template #icon>
|
|
|
|
|
+ <IconInfoCircle />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ 操作说明
|
|
|
|
|
+ </a-button>
|
|
|
|
|
+
|
|
|
|
|
+ <a-table :data="data" stripe hoverable column-resizable class="table" :loading="loading" :scroll="{
|
|
|
|
|
+ x: 1600
|
|
|
|
|
+ }" :pagination="{ showPageSize: true, showJumper: true, defaultPageSize: 15 }">
|
|
|
|
|
+
|
|
|
|
|
+ <template #name-filter="{ filterValue, setFilterValue, handleFilterConfirm, handleFilterReset }">
|
|
|
|
|
+ <div class="custom-filter">
|
|
|
|
|
+ <a-space direction="vertical">
|
|
|
|
|
+ <a-input :model-value="filterValue[0]" @input="(value) => setFilterValue([value])" />
|
|
|
|
|
+ <div class="custom-filter-footer">
|
|
|
|
|
+ <a-button @click="handleFilterReset">重置</a-button>
|
|
|
|
|
+ <a-button @click="handleFilterConfirm">确定</a-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </a-space>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+
|
|
|
|
|
+ <template #columns>
|
|
|
|
|
+ <a-table-column title="学号" :width="120" data-index="student_num" ellipsis tooltip :filterable="{
|
|
|
|
|
+ filter: (value, record) => (record.student_num ?? '').includes(value),
|
|
|
|
|
+ slotName: 'name-filter',
|
|
|
|
|
+ icon: () => h(IconSearch)
|
|
|
|
|
+ }"></a-table-column>
|
|
|
|
|
+ <a-table-column title="用户名" :width="130" :filterable="{
|
|
|
|
|
+ filter: (value, record) => (record.name ?? '').includes(value),
|
|
|
|
|
+ slotName: 'name-filter',
|
|
|
|
|
+ icon: () => h(IconSearch)
|
|
|
|
|
+ }">
|
|
|
|
|
+ <template #cell="{ record }">
|
|
|
|
|
+ {{ record.name }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </a-table-column>
|
|
|
|
|
+ <a-table-column title="性别" :width="80" ellipsis tooltip :filterable="{
|
|
|
|
|
+ filters: [
|
|
|
|
|
+ { text: '男', value: 1 },
|
|
|
|
|
+ { text: '女', value: 2 }
|
|
|
|
|
+ ],
|
|
|
|
|
+ filter: (value, record) => record.sex == value
|
|
|
|
|
+ }">
|
|
|
|
|
+ <template #cell="{ record }">
|
|
|
|
|
+ <icon-man v-if="record.sex === 1" />
|
|
|
|
|
+ <icon-woman v-else />
|
|
|
|
|
+ {{ record.sex === 1 ? '男' : '女' }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </a-table-column>
|
|
|
|
|
+ <a-table-column title="学院" :width="220" data-index="academy_name" ellipsis tooltip :filterable="{
|
|
|
|
|
+ filter: (value, record) => (record.academy_name ?? '').includes(value),
|
|
|
|
|
+ slotName: 'name-filter',
|
|
|
|
|
+ icon: () => h(IconSearch)
|
|
|
|
|
+ }"></a-table-column>
|
|
|
|
|
+ <a-table-column title="跑区" :width="130" :filterable="{
|
|
|
|
|
+ filter: (value, record) => (record.name ?? '').includes(value),
|
|
|
|
|
+ slotName: 'name-filter',
|
|
|
|
|
+ icon: () => h(IconSearch)
|
|
|
|
|
+ }">
|
|
|
|
|
+ <template #cell="{ record }">
|
|
|
|
|
+ <div class="vipcontent">
|
|
|
|
|
+ <span>{{ record.area || '随机分配' }} </span>
|
|
|
|
|
+ <!-- <img src="@/assets/vip.svg" alt="vip" height="20" v-if="record.area"> -->
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </a-table-column>
|
|
|
|
|
+ <a-table-column title="通知邮箱" :width="180" data-index="email" ellipsis tooltip :filterable="{
|
|
|
|
|
+ filter: (value, record) => (record.email ?? '').includes(value),
|
|
|
|
|
+ slotName: 'name-filter',
|
|
|
|
|
+ icon: () => h(IconSearch)
|
|
|
|
|
+ }"></a-table-column>
|
|
|
|
|
+ <a-table-column title="帐号状态" :width="100" ellipsis tooltip :filterable="{
|
|
|
|
|
+ filters: [
|
|
|
|
|
+ { text: '正常', value: 1 },
|
|
|
|
|
+ { text: '需登录', value: 0 },
|
|
|
|
|
+ { text: '状态异常', value: 2 },
|
|
|
|
|
+ ],
|
|
|
|
|
+ filter: (value, record) => record.state == value
|
|
|
|
|
+ }">
|
|
|
|
|
+ <template #cell="{ record }">
|
|
|
|
|
+ <div v-if="record.state === 0" class="state">
|
|
|
|
|
+ <div class="circle zero"></div>需登录
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div v-else-if="record.state === 1" class="state">
|
|
|
|
|
+ <div class="circle one"></div>正常
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div v-else class="state">
|
|
|
|
|
+ <div class="circle else"></div>状态异常
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </a-table-column>
|
|
|
|
|
+ <a-table-column title="自动乐跑" :width="100" ellipsis tooltip :filterable="{
|
|
|
|
|
+ filters: [
|
|
|
|
|
+ { text: '开启', value: 1 },
|
|
|
|
|
+ { text: '关闭', value: 0 }
|
|
|
|
|
+ ],
|
|
|
|
|
+ filter: (value, record) => record.auto_run == value
|
|
|
|
|
+ }">
|
|
|
|
|
+ <template #cell="{ record }">
|
|
|
|
|
+ <a-tag color="green" v-if="record.auto_run">开启</a-tag>
|
|
|
|
|
+ <a-tag color="red" v-else>关闭</a-tag>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </a-table-column>
|
|
|
|
|
+ <a-table-column title="自动乐跑时段" :width="100" ellipsis tooltip>
|
|
|
|
|
+ <template #cell="{ record }">
|
|
|
|
|
+ {{ autoTimeLabel(record.auto_time) }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </a-table-column>
|
|
|
|
|
+ <a-table-column title="累计次数" data-index="total_num" :width="110" ellipsis tooltip :sortable="{
|
|
|
|
|
+ sortDirections: ['ascend', 'descend']
|
|
|
|
|
+ }"></a-table-column>
|
|
|
|
|
+ <a-table-column title="剩余次数" :width="110" ellipsis tooltip>
|
|
|
|
|
+ <template #cell="{ record }">
|
|
|
|
|
+ {{ record.term_num - record.total_num > 0 ? (record.term_num - record.total_num) : '已完成' }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </a-table-column>
|
|
|
|
|
+ <a-table-column title="添加时间" :width="170" ellipsis tooltip :sortable="{
|
|
|
|
|
+ sortDirections: ['ascend', 'descend']
|
|
|
|
|
+ }">
|
|
|
|
|
+ <template #cell="{ record }">
|
|
|
|
|
+ {{ stramptoTime(record.create_time) }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </a-table-column>
|
|
|
|
|
+ <a-table-column title="更新时间" :width="170" ellipsis tooltip>
|
|
|
|
|
+ <template #cell="{ record }">
|
|
|
|
|
+ {{ stramptoTime(record.update_time || record.create_time) }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </a-table-column>
|
|
|
|
|
+
|
|
|
|
|
+ <a-table-column title="" fixed="right" :width="100">
|
|
|
|
|
+ <template #cell="{ record }">
|
|
|
|
|
+ <a-dropdown :popup-max-height="false" trigger="hover">
|
|
|
|
|
+ <a-button>操作 <icon-down /></a-button>
|
|
|
|
|
+ <template #content>
|
|
|
|
|
+ <a-doption @click="editAccount(record)"><icon-edit /> 编辑账号</a-doption>
|
|
|
|
|
+ <a-doption @click="SingleRun(record)"><icon-play-circle /> 开始单次乐跑</a-doption>
|
|
|
|
|
+ <a-doption @click="ChangeAutoRun(record)"><icon-translate /> {{ record.auto_run ? '关闭' :
|
|
|
|
|
+ '开启' }}自动乐跑</a-doption>
|
|
|
|
|
+ <a-doption @click="DeleteAccount(record)"><icon-delete /> 删除账号</a-doption>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </a-dropdown>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </a-table-column>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </a-table>
|
|
|
|
|
+ </a-card>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 账号编辑对话框 -->
|
|
|
|
|
+ <a-modal v-model:visible="visible" title="编辑账号" @cancel="handleCancel" @before-ok="handleBeforeOk" draggable
|
|
|
|
|
+ :ok-loading="ok_loading" esc-to-close closable>
|
|
|
|
|
+ <a-form :model="form">
|
|
|
|
|
+ <a-form-item field="student_num" label="学号">
|
|
|
|
|
+ <a-input v-model="form.student_num" placeholder="账号所有者学号,填写错误将无法登录" />
|
|
|
|
|
+ </a-form-item>
|
|
|
|
|
+ <a-form-item field="email" label="通知邮箱">
|
|
|
|
|
+ <a-input v-model="form.email" placeholder="用于接收乐跑失败、登录失效的通知" />
|
|
|
|
|
+ </a-form-item>
|
|
|
|
|
+ <a-form-item field="area" label="乐跑跑区">
|
|
|
|
|
+ <a-select v-model="form.area" placeholder="请选择乐跑跑区" default-value="">
|
|
|
|
|
+ <a-option value="">随机分配</a-option>
|
|
|
|
|
+ <a-option v-for="(item, index) in area" :key="index" :value="item">
|
|
|
|
|
+ <span class="vipcontent">
|
|
|
|
|
+ <span>{{ item }} </span>
|
|
|
|
|
+ <!-- <img src="@/assets/vip.svg" alt="vip" height="20"> -->
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </a-option>
|
|
|
|
|
+ </a-select>
|
|
|
|
|
+ </a-form-item>
|
|
|
|
|
+ <a-form-item field="area" label="自动乐跑时段">
|
|
|
|
|
+ <a-select v-model="form.auto_time" placeholder="请选择每天自动乐跑的时段" :options="auto_time" />
|
|
|
|
|
+ </a-form-item>
|
|
|
|
|
+ <!-- <a-form-item field="distance" label="距离区间">
|
|
|
|
|
+ <a-select v-model="form.distance" placeholder="请选择距离区间">
|
|
|
|
|
+ <a-option :value="0">默认(2~4Km)</a-option>
|
|
|
|
|
+ <a-option v-for="(item, index) in distance" :key="index" :value="item.value">
|
|
|
|
|
+ <div class="vipcontent">
|
|
|
|
|
+ <div>{{ item.label }} </div>
|
|
|
|
|
+ <img src="@/assets/vip.svg" alt="vip" height="20">
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </a-option>
|
|
|
|
|
+ </a-select>
|
|
|
|
|
+ </a-form-item> -->
|
|
|
|
|
+ </a-form>
|
|
|
|
|
+ </a-modal>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script setup>
|
|
|
|
|
+import { ref, reactive, h } from 'vue'
|
|
|
|
|
+import { useUserStore } from '@/store/modules/user'
|
|
|
|
|
+import { accountList, deleteAccount, addAccount, changeAutoRun, singleRun } from '@/api/lepao'
|
|
|
|
|
+import { getCount } from '@/api/goods'
|
|
|
|
|
+import { Modal, Notification, Message } from '@arco-design/web-vue'
|
|
|
|
|
+import { IconSearch } from '@arco-design/web-vue/es/icon'
|
|
|
|
|
+import userCard from './components/userCard.vue'
|
|
|
|
|
+
|
|
|
|
|
+const area = ["兰花湖校区跑区", "主校区北跑区", "主校区南跑区", "江北校区跑区"]
|
|
|
|
|
+const distance = [
|
|
|
|
|
+ { label: '女生(1.6~2Km)', value: [1.60, 2.00] },
|
|
|
|
|
+ { label: '男生(2.0~2.4Km)', value: [2.00, 2.40] }
|
|
|
|
|
+]
|
|
|
|
|
+const auto_time = Array.from({ length: 17 }, (_, i) => {
|
|
|
|
|
+ const hour = i + 7
|
|
|
|
|
+ return {
|
|
|
|
|
+ label: `${hour} ~ ${hour + 1}时`,
|
|
|
|
|
+ value: hour
|
|
|
|
|
+ }
|
|
|
|
|
+})
|
|
|
|
|
+const autoTimeLabel = (val) => {
|
|
|
|
|
+ const match = auto_time.find(item => item.value === val)
|
|
|
|
|
+ return match ? match.label : '-'
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const data = ref([])
|
|
|
|
|
+const loading = ref(false)
|
|
|
|
|
+
|
|
|
|
|
+const email = ref('')
|
|
|
|
|
+const userCount = ref({})
|
|
|
|
|
+const getuser = async () => {
|
|
|
|
|
+ const userStore = useUserStore()
|
|
|
|
|
+ let userInfo = await userStore.getInfo()
|
|
|
|
|
+ email.value = userInfo.email
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const GetCount = async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ loading.value = true
|
|
|
|
|
+ const res = await getCount()
|
|
|
|
|
+ if (!res || res.code !== 0)
|
|
|
|
|
+ return Notification.error({
|
|
|
|
|
+ title: '获取用户数据失败!',
|
|
|
|
|
+ content: res?.msg || '请稍后再试'
|
|
|
|
|
+ })
|
|
|
|
|
+ userCount.value = res.data
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ Notification.error({
|
|
|
|
|
+ title: '获取用户数据失败!',
|
|
|
|
|
+ content: error.message || '请稍后再试'
|
|
|
|
|
+ })
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ loading.value = false
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const visible = ref(false)
|
|
|
|
|
+const ok_loading = ref(false)
|
|
|
|
|
+const form = reactive({
|
|
|
|
|
+ id: null,
|
|
|
|
|
+ student_num: '',
|
|
|
|
|
+ email: '',
|
|
|
|
|
+ distance: [2.00, 4.00],
|
|
|
|
|
+ area: '',
|
|
|
|
|
+ auto_time: 8,
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const download = () => {
|
|
|
|
|
+ const a = document.createElement('a');
|
|
|
|
|
+ a.href = 'https://cloud.vite.net.cn/down.php/945623b0bfe7c3acc521abe11f5b3afc.pdf';
|
|
|
|
|
+ a.download = 'RunForge操作说明.pdf'
|
|
|
|
|
+ document.body.appendChild(a);
|
|
|
|
|
+ a.click();
|
|
|
|
|
+ document.body.removeChild(a);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const editAccount = (item) => {
|
|
|
|
|
+ if (item) {
|
|
|
|
|
+ form.id = item.id
|
|
|
|
|
+ form.student_num = item.student_num
|
|
|
|
|
+ form.email = item.email
|
|
|
|
|
+ form.distance[0] = item.min_distance
|
|
|
|
|
+ form.distance[1] = item.max_distance
|
|
|
|
|
+ form.area = item.area
|
|
|
|
|
+ form.auto_time = item.auto_time
|
|
|
|
|
+ } else {
|
|
|
|
|
+ form.id = null
|
|
|
|
|
+ form.student_num = ''
|
|
|
|
|
+ form.email = email.value
|
|
|
|
|
+ }
|
|
|
|
|
+ visible.value = true
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const handleBeforeOk = async (done) => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ ok_loading.value = true
|
|
|
|
|
+ const { student_num, email } = form
|
|
|
|
|
+ if (!student_num || !email) {
|
|
|
|
|
+ Message.error('请填写完整的账号信息')
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let data = {
|
|
|
|
|
+ ...form,
|
|
|
|
|
+ min_distance: form.distance[0],
|
|
|
|
|
+ max_distance: form.distance[1]
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const res = await addAccount(data)
|
|
|
|
|
+ if (!res || res.code !== 0) {
|
|
|
|
|
+ Notification.error({
|
|
|
|
|
+ title: '保存乐跑账号失败!',
|
|
|
|
|
+ content: res?.msg || '请稍后再试'
|
|
|
|
|
+ })
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Message.success('保存成功!')
|
|
|
|
|
+ done()
|
|
|
|
|
+ getAccounts()
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ Notification.error({
|
|
|
|
|
+ title: '保存乐跑账号失败!',
|
|
|
|
|
+ content: error.message || '请稍后再试'
|
|
|
|
|
+ })
|
|
|
|
|
+ return false
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ ok_loading.value = false
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const handleCancel = () => {
|
|
|
|
|
+ visible.value = false;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const getAccounts = async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ loading.value = true
|
|
|
|
|
+ const res = await accountList()
|
|
|
|
|
+ if (!res || res.code !== 0)
|
|
|
|
|
+ return Notification.error({
|
|
|
|
|
+ title: '获取账号列表失败!',
|
|
|
|
|
+ content: res?.msg || '请稍后再试'
|
|
|
|
|
+ })
|
|
|
|
|
+ data.value = res.data
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ Notification.error({
|
|
|
|
|
+ title: '获取账号列表失败!',
|
|
|
|
|
+ content: error.message || '请稍后再试'
|
|
|
|
|
+ })
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ loading.value = false
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const SingleRun = async (item) => {
|
|
|
|
|
+ Modal.confirm({
|
|
|
|
|
+ title: '开始乐跑',
|
|
|
|
|
+ content: () => h('div', [
|
|
|
|
|
+ h('p', `您是否要为${item.name}乐跑?若乐跑成功将扣减乐跑次数`)
|
|
|
|
|
+ ]),
|
|
|
|
|
+ onOk: async () => {
|
|
|
|
|
+ const res = await singleRun({ student_num: item.student_num })
|
|
|
|
|
+ if (!res || res.code !== 0)
|
|
|
|
|
+ return Notification.error({
|
|
|
|
|
+ title: '提交乐跑任务失败',
|
|
|
|
|
+ content: res?.msg || '请稍后再试'
|
|
|
|
|
+ })
|
|
|
|
|
+ Message.success('提交乐跑任务成功!')
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const DeleteAccount = async (item) => {
|
|
|
|
|
+ Modal.confirm({
|
|
|
|
|
+ title: '删除账号',
|
|
|
|
|
+ content: () => h('div', [
|
|
|
|
|
+ h('p', '您是否要删除该账号?该操作不可逆')
|
|
|
|
|
+ ]),
|
|
|
|
|
+ onOk: async () => {
|
|
|
|
|
+ const res = await deleteAccount({ id: item.id })
|
|
|
|
|
+ if (!res || res.code !== 0)
|
|
|
|
|
+ return Notification.error({
|
|
|
|
|
+ title: '删除失败',
|
|
|
|
|
+ content: res?.msg || '请稍后再试'
|
|
|
|
|
+ })
|
|
|
|
|
+ Message.success('删除成功!')
|
|
|
|
|
+ getAccounts()
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const ChangeAutoRun = async (record) => {
|
|
|
|
|
+ const oldValue = record.auto_run;
|
|
|
|
|
+ record.auto_run = oldValue === 1 ? 0 : 1;
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await changeAutoRun({ id: record.id });
|
|
|
|
|
+ if (!res || res.code !== 0) {
|
|
|
|
|
+ record.auto_run = oldValue;
|
|
|
|
|
+ Message.error('切换自动乐跑状态失败!');
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Message.success(`自动乐跑状态已${record.auto_run === 1 ? '开启' : '关闭'}`)
|
|
|
|
|
+ getAccounts()
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ record.auto_run = oldValue;
|
|
|
|
|
+ Message.error('切换自动乐跑状态失败!');
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+const stramptoTime = (time) => {
|
|
|
|
|
+ return new Date(time).toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+getAccounts()
|
|
|
|
|
+getuser()
|
|
|
|
|
+GetCount()
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped lang="less">
|
|
|
|
|
+.container {
|
|
|
|
|
+ padding: 0 20px 20px 20px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.table {
|
|
|
|
|
+ margin-top: 15px;
|
|
|
|
|
+
|
|
|
|
|
+ .state {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+
|
|
|
|
|
+ .circle {
|
|
|
|
|
+ border-radius: 50%;
|
|
|
|
|
+ height: 8px;
|
|
|
|
|
+ min-height: 8px;
|
|
|
|
|
+ width: 8px;
|
|
|
|
|
+ min-width: 8px;
|
|
|
|
|
+ margin-right: 5px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .zero {
|
|
|
|
|
+ background-color: rgb(var(--orange-6));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .one {
|
|
|
|
|
+ background-color: rgb(var(--green-6));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .else {
|
|
|
|
|
+ background-color: rgb(var(--red-6));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.custom-filter {
|
|
|
|
|
+ padding: 20px;
|
|
|
|
|
+ background: var(--color-bg-5);
|
|
|
|
|
+ border: 1px solid var(--color-neutral-3);
|
|
|
|
|
+ border-radius: var(--border-radius-medium);
|
|
|
|
|
+ box-shadow: 0 2px 5px rgb(0 0 0 / 10%);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.custom-filter-footer {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.vipcontent {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|