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.
ocr-web/src/views/final/content/ListContent.vue

1066 lines
27 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<script lang="ts" setup>
import { computed, onMounted, reactive, ref, unref, watch,defineProps } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { chunk } from 'lodash-es'
import { useDialog, useMessage } from 'naive-ui'
import { RepeatModal, RepeatTaskTableModal } from '../comp'
import testImg from '@/assets/images/test.png'
import type { RowData } from '@/config/final'
import { getFinalList } from '@/api/final'
import { useFinal } from '@/store/modules/final'
import { formatToDateHMS } from '@/utils/dateUtil'
import { audit } from '@/api/task/task'
import dayjs from 'dayjs'
import { cloneDeep } from 'lodash-es'
import NotPassed from '@/components/Approval/NotPassed.vue'
const emit = defineEmits(['changeShow'])
const dialog = useDialog()
const message = useMessage()
const router = useRouter()
const notPassModalRef = ref(null) // 不通过弹窗
const sortorder = ref('asc')
const sortname = ref('states')
const loading = ref(true)
const total = ref(0)
const scrollContainer = ref(null)
const tableData = ref<any>([])
const finalStore = useFinal()
const props = defineProps({
taskvalue: {
type: String,
default: ""
}
});
let num = 1
const pagination = reactive({
page: 1,
pageCount: 20,
pageSize: 20,
})
const repeatModalRef = ref(null)
const repeatTaskTableModalRef = ref(null)
const selectionIds = ref([])
const showActions = computed(() => {
return selectionIds.value.length
})
function handleCheck(row: any, showcheck: any) {
if (showcheck == false) {
console.log(tableData.value)
tableData.value.forEach((item) => {
if (item.length > 0) {
item.forEach((itemx, index) => {
if (row.id == itemx.id)
itemx.showcheck = true
// newlistx.push(itemx)
})
}
})
selectionIds.value.push(row)
}
else {
tableData.value.forEach((item) => {
if (item.length > 0) {
item.forEach((itemx, index) => {
if (row.id == itemx.id)
itemx.showcheck = false
// newlistx.push(itemx)
})
}
})
selectionIds.value.pop(row)
}
}
function switchBatch() {
tableData.value.forEach((item) => {
item.forEach((itemx, index) => {
itemx.showcheck = false
})
})
selectionIds.value = []
}
function changeContent() {
emit('changeShow')
}
function initRem() {
const designWidth = 1440
const rempPx = 16
const scale = window.innerWidth / designWidth
document.documentElement.style.fontSize = `${scale * rempPx}px`
}
async function initData(
page: number,
pageSize: number,
filterId?: any,
taskName?: string,
) {
const asideParmas = unref(finalStore.getAsideValue)
if(asideParmas.izyear){
// console.log(asideParmas.izyear)
// asideParmas.izuptime = cloneDeep(asideParmas.izyear)
// asideParmas.izuptime = asideParmas.izyear.split(",");
let ontime = dayjs(asideParmas.izyear[0]).format(
'YYYY/MM/DD',
)
let twotime = dayjs(asideParmas.izyear[1]).format(
'YYYY/MM/DD',
)
asideParmas.izuptime =ontime+"-"+twotime
// delete asideParmas.izyear
}
// 有过滤配置的时候优先使用过滤配置,不要使用左侧参数
// let params = filterId ? { userSearchId: filterId } : asideParmas
let params = asideParmas
if (params?.izshowall == true)
{
params.isFail = true
delete params.izshowall;
}
const result = await getFinalList({
sortorder: sortorder.value,
pageSize,
currPage: page,
sortname: sortname.value,
taskName,
...params,
})
const { data, pageCount, totalCount } = result
//console.log(data, pageCount, totalCount)
// tableData.value = tableData.value.concat(data);
tableData.value = data
// console.log(tableData.value)
total.value = totalCount
pagination.page = page
pagination.pageCount = Math.ceil(totalCount / pageSize)
loading.value = false
tableData.value.forEach((item) => {
item.showcheck = false
if (isValidTimestamp(item.fromuptime))
item.fromuptime = formatToDateHMS(item.fromuptime)
})
tableData.value = chunk(tableData.value, 4)
}
async function query(
page: number,
pageSize: number,
filterId?: any,
taskName?: string,
) {
console.log('query', taskName)
const asideParmas = unref(finalStore.getAsideValue)
// 有过滤配置的时候优先使用过滤配置,不要使用左侧参数
// let params = filterId ? { userSearchId: filterId } : asideParmas
if(asideParmas.izyear){
// console.log(asideParmas.izyear)
// asideParmas.izuptime = cloneDeep(asideParmas.izyear)
// asideParmas.izuptime = asideParmas.izyear.split(",");
let ontime = dayjs(asideParmas.izyear[0]).format(
'YYYY/MM/DD',
)
let twotime = dayjs(asideParmas.izyear[1]).format(
'YYYY/MM/DD',
)
asideParmas.izuptime =ontime+"-"+twotime
// delete asideParmas.izyear
}
let params = asideParmas
if (params?.izshowall == true)
{
params.isFail = true
delete params.izshowall;
}
params = params?.izshowall ? {isFail:true} : params;
const result = await getFinalList({
sortorder: sortorder.value,
pageSize,
currPage: page,
sortname: sortname.value,
taskName,
// isFail: true,
...params,
})
const { data, pageCount, totalCount } = result
console.log(data, pageCount, totalCount);
const newlist = []
const oldlist = tableData.value
if (oldlist.length > 0) {
oldlist.forEach((item) => {
// console.log(item);
if (item.length > 0) {
item.forEach((itemx: any) => {
itemx.showcheck = false
newlist.push(itemx)
})
}
})
data.forEach((item) => {
item.showcheck = false
newlist.push(item)
})
}
else {
data.forEach((item) => {
item.showcheck = false
newlist.push(item)
})
}
// tableData.value = tableData.value.concat(data);
tableData.value = newlist
// console.log(tableData.value);
total.value = totalCount
pagination.page = page
pagination.pageCount = Math.ceil(totalCount / pageSize)
loading.value = false
tableData.value.forEach((item) => {
if (isValidTimestamp(item.fromuptime))
item.fromuptime = formatToDateHMS(item.fromuptime)
})
tableData.value = chunk(tableData.value, 4)
}
function isValidTimestamp(value) {
if (typeof value !== 'number' || !Number.isInteger(value))
return false // 首先确保值是一个整数数字
const date = new Date(value)
return !Number.isNaN(date.getTime()) // 验证能否转换为有效日期
}
// 查看详情页
function goDetail(row) {
router.push({
name: 'final-detail',
query: { id: row.id, packageid: row.packageid, taskindex: row.taskNode, type:'card' },
})
}
// 小结批量不通过
function repeatBatchReject(items) {
console.log(items)
rejectHandler(items)
}
// 审核不通过
function rejectHandler(list) {
console.log(list)
const msg = validate(list)
if (msg !== null) {
message.error(msg)
return
}
function validate(items: any[]) {
if (items.length === 0)
return '至少选中一个任务'
return null
}
console.log(notPassModalRef)
const modal = unref(notPassModalRef)! as any
modal.showModal(list)
}
function showModal(modalRef: any) {
const modal = unref(modalRef)! as any
modal.showModal()
}
onMounted(() => {
initRem()
initData(1, 20,{},props.taskvalue)
})
const item = {
img: testImg,
checked: false,
title: 'YP45678',
date: '2023-12-19 12:09:18',
}
const data = ref<any[]>([])
function actionHandler(action: any, row: any) {
const { key } = action
switch (key) {
case 'view':
goDetail(row)
break
case 'reset':
// resetHandler()
break
case 'approval':
singleApproval(row)
break
case 'reject':
rejectHandler(row)
break
default:
break
}
}
// 审核通过
function doAudit(param: any, row: any) {
dialog.info({
title: '确认提示',
content: '确认给该任务审批为【通过】吗?',
positiveText: '确定',
negativeText: '取消',
onPositiveClick: () => {
audit(param).then((res) => {
const { code } = res
if (code === 'OK') {
message.success(res.message)
// changecardstatus(3, row);
initData(1, 20,{},props.taskvalue)
num = 1
reload()
selectionIds.value = []
}
else {
message.error(res.message)
selectionIds.value = []
}
})
},
onNegativeClick: () => {},
})
}
// 单个审批通过
function singleApproval(row) {
console.log(row)
const param = {
result: true,
comment: '',
disposeType: '',
disposeTypeId: '',
failCauseId: '',
failCauseName: '',
flowTaskInfoList: [
{
formId: row.id,
taskId: row.taskId,
taskName: row.fromTaskName,
},
],
}
doAudit(param, row)
}
// 批量通过
function batchApproval() {
const items: any = selectionIds.value
const msg = validate(items)
function validate(items: any[]) {
if (items.length === 0)
return '至少选中一个任务'
return null
}
if (msg !== null) {
message.error(msg)
return
}
console.log(items)
const list: any = []
items.forEach((item) => {
list.push({
formId: item.id,
taskId: item.taskId,
taskName: item.fromtaskname,
})
})
const param = {
result: true,
comment: '',
disposeType: '',
disposeTypeId: '',
failCauseId: '',
failCauseName: '',
flowTaskInfoList: list,
}
doAudit(param, {})
selectionIds.value = []
num = 1
}
// 批量不通过
function batchReject() {
const items: any = selectionIds.value
rejectHandler(items)
selectionIds.value = []
num = 1
}
// 修改卡片状态渲染效果
function changecardstatus(states, item) {
// let index = tableData.value.findIndex(itemx => itemx.id === item.id);
const newlist = []
tableData.value.forEach((itemarr, indexarr) => {
itemarr.forEach((itemobj, indexobj) => {
if (item.id == itemobj.id)
itemobj.states = states
newlist.push(itemobj)
})
})
tableData.value = chunk(newlist, 4)
}
function reload() {
// query(1, 20)
// num=1
// selectionIds.value = []
// checkedRowKeys.value = []
// const { page, pageSize } = unref(tableRef.value?.pagination) as PaginationProps
// query(page!, pageSize!)
}
let debounceTimer
// 检查是否滚动到底部
function checkBottom() {
const container = scrollContainer.value
// console.log(1)
if (!container)
return
// const { scrollTop, clientHeight, scrollHeight } = container;
const scrollTop = window.pageYOffset || document.documentElement.scrollTop
// 获取视口的内部高度
const clientHeight
= window.innerHeight || document.documentElement.clientHeight
// 获取整个文档的高度
const scrollHeight = document.documentElement.scrollHeight
clearTimeout(debounceTimer)
// console.log(pagination)
debounceTimer = setTimeout(() => {
if (scrollTop + clientHeight >= scrollHeight -500&&!(pagination.pageCount<num)) {
num = num + 1
console.log(num)
console.log( pagination.pageCount)
query(num, 20,{},props.taskvalue)
// fetchData(); //
}
}, 500)
}
function changesort(sortnamex) {
if (sortorder.value == 'asc' && sortnamex == 'submit_date_timestamp') {
sortorder.value = 'desc'
sortname.value = 'submit_date_timestamp'
}
else if (sortorder.value == 'desc' && sortnamex == 'submit_date_timestamp') {
sortorder.value = 'asc'
sortname.value = 'submit_date_timestamp'
}
else if (sortorder.value == 'desc' && sortnamex == 'similarity_score') {
sortorder.value = 'asc'
sortname.value = 'similarity_score'
}
else if (sortorder.value == 'asc' && sortnamex == 'similarity_score') {
sortorder.value = 'desc'
sortname.value = 'similarity_score'
}
else if (sortorder.value == 'asc' && sortnamex == 'field1') {
sortorder.value = 'desc'
sortname.value = 'field1'
}
else if (sortorder.value == 'desc' && sortnamex == 'field1') {
sortorder.value = 'asc'
sortname.value = 'field1'
}
initData(1, 20,{},props.taskvalue)
num = 1
}
function notpass (){
initData(1, 20,{},props.taskvalue)
selectionIds.value = []
}
watch(
() => finalStore.asideValue,
(newVal, oldVal) => {
initData(1, 20,{},props.taskvalue)
num=1
},
{ deep: true },
)
defineExpose({
initData,
})
</script>
<template>
<div class="wrapper">
<div class="wrapper-header">
<div class="wrapper-header-left">
<span class="wrapper-header-font">任务管理列表</span>
<SvgIcon
style="cursor: pointer"
size="16"
name="card-mode"
@click="changeContent"
/>
</div>
<div>
<SvgIcon
style="margin-right: 6px"
size="13"
name="summary"
@click="showModal(repeatModalRef)"
/>
<NButton class="xjcc" text @click="showModal(repeatModalRef)">
</NButton>
<div v-show="!showActions" style="display: flex; align-items: center">
<div class="btn">
<SvgIcon style="margin-right: 6px" size="22" name="batch" />
批量审批
</div>
</div>
<div v-show="showActions" class="batch">
<NButton text @click="switchBatch()">
<template #icon>
<SvgIcon name="revoke" />
</template>
取消
</NButton>
<img
class="btn-approval btn-left"
src="@/assets/images/task/btn-not-pass.png"
alt=""
@click.stop="batchReject"
>
<SvgIcon size="24" name="vs" />
<img
class="btn-approval"
src="@/assets/images/task/btn-pass.png"
alt=""
@click.stop="batchApproval"
>
</div>
<n-popover
:style="{ padding: '0px' }"
style="width: 148px"
:show-arrow="false"
placement="bottom-start"
trigger="click"
>
<template #trigger>
<div class="icon-wrap">
<SvgIcon size="20" name="more-blue" />
</div>
</template>
<ul class="wrapper-header-action">
<li @click="importHandler">
<SvgIcon size="20" name="import" /><span style="margin-left: 5px">批量导入数据</span>
</li>
<li @click="exportHandler">
<SvgIcon size="20" name="download" /><span
style="margin-left: 5px"
>导出待审数据</span>
</li>
<li>
<SvgIcon size="20" name="download" /><span
style="margin-left: 5px"
>导出全部数据</span>
</li>
<li>
<SvgIcon size="20" name="look" /><span style="margin-left: 5px">查看导入记录</span>
</li>
</ul>
</n-popover>
</div>
</div>
<div class="header_data">
<DataHeader :has-color="true" />
</div>
<div class="wrapper-settings">
<div>
<div @click="changesort('submit_date_timestamp')">
<span>提报时间排序</span><SvgIcon style="margin-left: 6px" name="sort" size="13" />
</div>
<div @click="changesort('similarity_score')">
<span>相似度排序</span><SvgIcon style="margin-left: 6px" name="sort" size="13" />
</div>
<div @click="changesort('field1')">
<span>提报人排序</span><SvgIcon style="margin-left: 6px" name="sort" size="13" />
</div>
</div>
<div style="width: 3vw">
<!--<SvgIcon name="magnifying-1" size="18" style="margin-right: 8px" />
<SvgIcon
style="cursor: pointer"
size="18"
name="column"
@click="showModal(customTabelRef)"
/>-->
</div>
</div>
<div ref="scrollContainer" :class="tableData.length > 4 ? 'cotnet_wrapeer' : 'cotnet_wrapeertwo'" @scroll="checkBottom">
<div
v-for="(sitem, sindex) in tableData"
:key="sindex"
class="data_wrapper"
:style="
sitem.length == 1
? { width: '25%' }
: sitem.length == 2
? { width: '50%' }
: sitem.length == 3
? { width: '75%' }
: {}
"
>
<div
v-for="(item, index) in sitem"
:key="index"
class="item"
:style="
sitem.length == 1
? { margin: '0 4% 0 4%' }
: sitem.length == 2
? { margin: '0 2% 0 2%' }
: sitem.length == 3
? { margin: '0 1.2% 0 1.2%' }
: {}
"
>
<div class="top">
<div
class="img"
:style="
item.serverThumbnailUrl != null
? `background:url(${item.serverThumbnailUrl});background-size:100% 100%;background-repeat: no-repeat;`
: `background:url(${item.imgUrl});background-size:100% 100%;background-repeat: no-repeat;`
"
@click="goDetail(item)"
>
<div v-if="item.similarityscore != -1" class="percent">
<SvgIcon size="30" :name="item.similarityscore == 100 ? 'error_tag' : 'tag'" />
<div class="val">
{{ `${item.similarityscore}%` }}
</div>
</div>
</div>
<div v-show="item.states == 2" class="check_box">
<n-checkbox
size="medium"
label=" "
:checked="item.showcheck"
@click="handleCheck(item, item.showcheck)"
/>
</div>
<div class="content" @click="goDetail(item)">
<div class="title">
<n-ellipsis style="max-width: 100%">
任务ID{{ item.fromtaskid }}
</n-ellipsis>
</div>
<div class="date">
<n-ellipsis style="max-width: 100%">
{{ item.fromuptime }}
</n-ellipsis>
</div>
<div class="tag_box">
<div
v-for="index in 2"
:key="index"
class="tag_item"
:style="
index == 2 || item.states == 3
? 'color:#02C984'
: item.states == 2
? 'color: #fe9800;background:#f7eac075'
: item.states == 5
? 'color:#FF4E4F;background:#f7c0c06b'
: 'color:#02C984'
"
>
{{
index == 1
? item.states == 3
? "通过"
: item.states == 2
? "待审核"
: item.states == 5
? "不通过"
: ""
: item.fromusername
}}
</div>
</div>
</div>
</div>
<div class="bottom">
<!-- <div class="reset_action">重置审批</div> -->
<div
v-show="item.states != 2"
class="resovle_action"
@click="goDetail(item)"
>
查看
</div>
<div
v-show="item.states == 2"
class="resovle_action"
@click="actionHandler({ key: 'approval' }, item)"
>
通过
</div>
<div
v-show="item.states == 2"
class="reject_action"
@click="actionHandler({ key: 'reject' }, [item])"
>
不通过
</div>
</div>
</div>
</div>
</div>
<NotPassed ref="notPassModalRef" @success="notpass" />
<RepeatModal
ref="repeatModalRef"
@reject="repeatBatchReject"
@viewrepeat="showModal(repeatTaskTableModalRef)"
/>
<RepeatTaskTableModal ref="repeatTaskTableModalRef" />
</div>
</template>
<style scoped lang="less">
.wrapper {
// display: flex;
// flex-flow: row wrap;
// align-items: center;
// justify-content: flex-start;
// flex: 1;
// box-sizing: border-box;
// margin-left: 16px;
//width: 100%;
//background: #fff;
// padding: 0px 24px 24px 24px;
display: flex;
flex: 1;
overflow: hidden;
flex-direction: column;
box-sizing: border-box;
margin-left: 16px;
width: 100%;
background: #fff;
padding: 0px 24px 24px 24px;
.btn-approval {
width: 68px;
height: 28px;
cursor: pointer;
}
.btn-left {
margin-left: 16px;
}
.icon-wrap {
display: flex;
align-items: center;
justify-content: center;
width: 30px;
height: 30px;
background: rgba(80, 122, 253, 0.1);
border-radius: 8px;
cursor: pointer;
}
&-header {
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
height: 64px;
width: 100%;
div {
display: flex;
align-items: center;
}
.xjcc {
//width: 226px;
font-weight: bold;
color: #507afd;
margin-right: 20px;
}
.title {
color: #507afd;
font-weight: bold;
font-size: 14px;
margin-left: 8px;
}
.btn {
width: 118px;
height: 36px;
background: linear-gradient(135deg, #5b85f8, #3c6cf0);
border-radius: 17px;
box-shadow: 0px 2px 6px 0px rgba(116, 153, 253, 0.3);
display: flex;
align-items: center;
justify-content: center;
color: #fff;
margin-right: 6px;
cursor: pointer;
}
.more {
width: 30px;
height: 30px;
line-height: 30px;
opacity: 0.1;
background: linear-gradient(144deg, #73a7f9 0%, #3e6ef1 96%);
border-radius: 8px;
}
&-font {
font-size: 20px;
font-family: PingFang SC, PingFang SC-Medium;
font-weight: 600;
color: #0d0b22;
margin-right: 8px;
}
&-action {
padding: 8px;
li {
height: 32px;
line-height: 32px;
cursor: pointer;
&:hover {
background-color: #f3f8ff;
}
}
}
}
&-settings {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 0px;
> div {
display: flex;
// justify-content: space-between;
//width: 20vw;
> div {
cursor: pointer;
margin-right: 30px;
font-size: 13px;
height: 18px;
line-height: 18px;
/* font-family: PingFang SC, PingFang SC-Regular; */
font-weight: 600;
text-align: left;
color: #666666;
line-height: 0.88rem;
}
}
}
.header_data {
width: 100%;
}
.data_wrapper {
// padding-right: 10px;
display: flex;
//box-sizing: border-box;
flex-flow: row wrap;
align-items: center;
// justify-content: flex-start;
// justify-content: space-between;
// flex: 1;
.item {
flex: 1;
width: 23%;
margin-left: 2.3%;
height: 7rem;
background: url("@/assets/images/cardbg.png");
background-repeat: no-repeat;
background-size: 100% 100%;
// border: 0.075rem solid #e8e8e8;
border-radius: 0.18rem;
padding: 0.5rem 0.625rem;
// margin-right: 20px;
margin: 0 1% 0 1%;
margin-bottom: 1rem;
cursor: pointer;
.top {
display: flex;
flex-flow: row nowrap;
align-items: center;
justify-content: flex-start;
height: 75%;
border-bottom: 0.05rem solid #e8e8e8;
position: relative;
.img {
//width: 35%;
width: 5.25rem;
height: 3.43rem;
// height: auto;
object-fit: cover;
border-radius: 0.18rem;
position: relative;
}
.check_box {
position: absolute;
left: 0.25rem;
top: 0.6rem;
}
.content {
margin-left: 0.8rem;
width: calc(100% - 6rem);
.title,
.date {
font-size: 11px;
font-weight: 500;
text-align: left;
color: #323233;
line-height: 1rem;
}
}
.tag_box {
display: flex;
flex-flow: row nowrap;
align-items: center;
justify-content: flex-start;
margin-top: 0.5rem;
.tag_item {
min-width: 2rem;
min-height: 0.875rem;
font-size: 0.52rem;
padding: 0.0625rem 0.18rem;
font-weight: bolder;
text-align: left;
// color: #507afd;
line-height: 0.875rem;
letter-spacing: 0.006rem;
margin-right: 0.2rem;
// opacity: 0.1;
background: #c0f7ec69;
border-radius: 0.125rem;
text-align: center;
white-space: nowrap;
}
}
}
.bottom {
display: flex;
flex-flow: row nowrap;
align-items: center;
justify-content: flex-end;
margin-top: 0.375rem;
div {
cursor: pointer;
}
.reset_action {
font-size: 12px;
font-weight: bolder;
text-align: left;
color: #666666;
}
.resovle_action {
font-size: 12px;
font-weight: bolder;
text-align: left;
color: #507afd;
line-height: 1rem;
margin-left: 0.9rem;
}
.reject_action {
font-size: 12px;
font-weight: bolder;
text-align: left;
color: #ff4e4f;
line-height: 1rem;
margin-left: 0.9rem;
}
}
}
}
.cotnet_wrapeer {
width: 100%;
height: 67vh;
//padding-right: 10px; /* 右侧内边距 */
overflow: hidden; /* 默认隐藏滚动条 */
} .cotnet_wrapeertwo {
width: 100%;
height: 67vh;
//padding-right: 10px; /* 右侧内边距 */
overflow: hidden; /* 默认隐藏滚动条 */
}
.cotnet_wrapeer:hover {
overflow: auto;
width: calc(100% + 5px);
}
.percent {
position: absolute;
text-align: center;
z-index: 3;
right: 2px;
top: -6px;
color: #fff;
.val {
position: absolute;
left: 0;
top: 0;
display: block;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
font-size: 10px;
font-family: PingFang SC, PingFang SC-Semibold;
font-weight: Semibold;
text-align: left;
color: #ffffff;
line-height: 24px;
}
}
/* 定义滚动条的宽度及背景颜色 */
::-webkit-scrollbar {
position: fixed;
width: 5px; /* for vertical scrollbars */
height: 10px; /* for horizontal scrollbars */
background: #f1f1f1;
}
/* 定义滚动条轨道的样式 */
::-webkit-scrollbar-track {
background-color: #e1e1e1;
border-radius: 10px; /* 圆角 */
}
/* 定义滚动条滑块的样式 */
::-webkit-scrollbar-thumb {
background-color: #888;
border-radius: 10px; /* 圆角 */
}
/* 滑块hover时的样式 */
::-webkit-scrollbar-thumb:hover {
background-color: #555;
}
:deep(.n-checkbox .n-checkbox-box) {
width: 0.85rem;
height: 0.85rem;
}
}
</style>