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/Content.vue

1202 lines
28 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 type {
DataTableColumns,
DataTableRowKey,
PaginationProps,
} from 'naive-ui'
import { NButton, NDataTable, useDialog, useMessage } from 'naive-ui'
import {
computed,
defineEmits,
defineProps,
h,
nextTick,
onBeforeMount,
onMounted,
onUnmounted,
reactive,
ref,
unref,
watch,
} from 'vue'
import { rowPropKeys } from 'naive-ui/es/legacy-grid/src/Row'
import { useRoute, useRouter } from 'vue-router'
import dayjs from 'dayjs'
import { cloneDeep } from 'lodash-es'
import {
CustomTabelModal,
ImportExcelModal,
ListAction,
RepeatModal,
RepeatTaskTableModal,
StatusItem,
} from '../comp'
import { getFinalList } from '@/api/final'
import { audit } from '@/api/task/task'
import SvgIcon from '@/components/Icon/SvgIcon.vue'
import type { RowData } from '@/config/final'
import { findKey, headRules } from '@/config/final'
import { useWindowSizeFn } from '@/hooks/event/useWindowSizeFn'
import { useUser } from '@/store/modules/user'
import { useFinal } from '@/store/modules/final'
import { getViewportOffset } from '@/utils/domUtils'
import { isBoolean } from '@/utils/is'
import { useDictionary } from '@/store/modules/dictonary'
import NotPassed from '@/components/Approval/NotPassed.vue'
import type { ApprovalParam } from '/#/api'
import emitter from '@/utils/mitt'
import { formatToDateHMS } from '@/utils/dateUtil'
import { getAllfieldList, getfieldList, savefield } from '@/api/home/filter'
import DataHeader from '@/components/DataHeader/index.vue'
import { useDataHeaderStore } from '@/store/modules/DataHeader'
const props = defineProps({
taskvalue: {
type: String,
default: '',
},
})
const emit = defineEmits(['changeShow','goDetailx'])
function changeContent() {
emit('changeShow')
}
const headerref = ref(null)
const checkedRowKeys = ref([])
const dicStore = useDictionary()
const izstatusList = ref([])
const router = useRouter()
const route = useRoute()
const reviewType = 0
const sortorder = ref('asc')
const sortname = ref('states')
const searchContent = route.query.searchContent as string
const actionsColumns = {
title: '操作',
key: 'actions',
minWidth: 200,
width: 200,
fixed: 'right',
render(row) {
return h(ListAction, {
id: row.id,
status: row.states,
trigger: (action) => {
actionHandler(action, row)
},
})
},
}
const columnsRef = ref<DataTableColumns<RowData>>([])
const haeaderstore = useDataHeaderStore()
async function getColumns() {
columnsRef.value = [
{
type: 'selection',
fixed: 'left',
width: 50,
disabled(row: any) {
return row.states !== 2
},
},
]
const userStore = useUser()
const userInfo = userStore.getUserInfo
let res
res = await getAllfieldList(reviewType) // 所有筛选项目
const allList = res.data
res = await getfieldList(reviewType, userInfo.id) // 当前用户选择的项目
const useList = res.data
const userFieldFixed = useList.userFieldFixed?.split(',')
const userFieldUnFixed = useList.userFieldUnFixed?.split(',')
if (!userFieldFixed?.length && !userFieldUnFixed?.length) {
allList?.map((v) => {
if (v.isrequired == 2) {
columnsRef.value.push({
title: v.fieldDesc,
fixed: 'left',
key: v.name,
width: 120,
})
}
return v
})
}
else {
userFieldFixed.map((v) => {
const item = allList.find(v2 => v2.name == v)
columnsRef.value.push({
title: item.fieldDesc,
key: item.name,
fixed: 'left',
width: 120,
})
return v
})
userFieldUnFixed.map((v) => {
const item = allList.find(v2 => v2.name == v)
columnsRef.value.push({
title: item.fieldDesc,
key: item.name,
width: 120,
})
return v
})
}
columnsRef.value.push(actionsColumns as any)
formatColumns()
}
async function formatColumns() {
// TODO处理特殊字段
let index
index = columnsRef.value.findIndex(v => v.title == '任务ID')
if (index > -1) {
columnsRef.value[index] = {
title: '任务ID',
key: columnsRef.value[index].key, // "id"
fixed: columnsRef.value[index].fixed || undefined,
width: 200,
render(row) {
const item: any = izstatusList.value.find(
(item: any) => item.value == row.states,
)
return h(
NButton,
{
'strong': true,
// 'tertiary': true,
'text': true,
'size': 'small',
'text-color': '#507AFD',
'onClick': () => goDetail(row),
},
{ default: () => row.fromtaskid },
)
},
}
}
index = columnsRef.value.findIndex(v => v.title == '所属项目')
if (index > -1) {
columnsRef.value[index] = {
title: '所属项目',
key: columnsRef.value[index].key, // "fromtaskname"
fixed: columnsRef.value[index].fixed || undefined,
width: 200,
ellipsis: {
tooltip: true,
},
}
}
index = columnsRef.value.findIndex(v => v.title == '任务名称')
if (index > -1) {
columnsRef.value[index] = {
title: '任务名称',
key: columnsRef.value[index].key, // "fromtaskname"
fixed: columnsRef.value[index].fixed || undefined,
width: 200,
ellipsis: {
tooltip: true,
},
}
}
index = columnsRef.value.findIndex(v => v.title == '审批状态')
if (index > -1) {
columnsRef.value[index] = {
title: '审批状态',
key: columnsRef.value[index].key,
fixed: columnsRef.value[index].fixed || undefined,
width: 120,
sorter: 'default',
renderSorterIcon: ({ order }) => {
if (order === false)
return h(SvgIcon, { name: 'sort-2' })
if (order === 'ascend')
return h(SvgIcon, { name: 'sort-1' })
if (order === 'descend')
return h(SvgIcon, { name: 'sort-3' })
},
render(row) {
const item: any = izstatusList.value.find(
(item: any) => item.value == row.states,
)
return h(StatusItem, {
id: row.id,
status: row.states,
label: item ? item.label : '',
})
},
}
}
index = columnsRef.value.findIndex(v => v.title == '图片相似度')
if (index > -1) {
columnsRef.value[index] = {
title: '图片相似度',
key: columnsRef.value[index].key,
fixed: columnsRef.value[index].fixed || undefined,
width: 150,
sorter: 'default',
renderSorterIcon: ({ order }) => {
if (order === false)
return h(SvgIcon, { name: 'sort-2' })
if (order === 'ascend')
return h(SvgIcon, { name: 'sort-1' })
if (order === 'descend')
return h(SvgIcon, { name: 'sort-3' })
},
render(row: any) {
return h(
'div',
{
id: row.id,
style: { color: row.similarityscore === 100 ? '#FF4E4F' : '' },
},
{
default: () =>
row.similarityscore ? `${row.similarityscore}%` : '',
},
)
},
}
}
index = columnsRef.value.findIndex(v => v.title == '提报时间')
if (index > -1) {
columnsRef.value[index] = {
title: '提报时间',
key: columnsRef.value[index].key,
fixed: columnsRef.value[index].fixed || undefined,
width: 200,
sorter: 'default',
renderSorterIcon: ({ order }) => {
if (order === false)
return h(SvgIcon, { name: 'sort-2' })
if (order === 'ascend')
return h(SvgIcon, { name: 'sort-1' })
if (order === 'descend')
return h(SvgIcon, { name: 'sort-3' })
},
render(row: any) {
return formatToDateHMS(row.fromuptime || 0)
},
}
}
index = columnsRef.value.findIndex(v => v.title == '提报人')
if (index > -1) {
columnsRef.value[index] = {
title: '提报人',
key: columnsRef.value[index].key,
fixed: columnsRef.value[index].fixed || undefined,
width: 200,
sorter: 'default',
renderSorterIcon: ({ order }) => {
if (order === false)
return h(SvgIcon, { name: 'sort-2' })
if (order === 'ascend')
return h(SvgIcon, { name: 'sort-1' })
if (order === 'descend')
return h(SvgIcon, { name: 'sort-3' })
},
render(row: any) {
return row.fromusername
},
}
}
index = columnsRef.value.findIndex(v => v.title == '更新时间')
if (index > -1) {
columnsRef.value[index] = {
title: '更新时间',
key: columnsRef.value[index].key,
fixed: columnsRef.value[index].fixed || undefined,
width: 200,
render(row: any) {
return row.updatetime ? formatToDateHMS(row.updatetime) : ''
},
}
}
}
const deviceHeight = ref(600)
onBeforeMount(() => {
dicStore.fetchizstatusListt()
})
watch(
() => dicStore.izstatusList,
(newval) => {
izstatusList.value = newval
},
)
onUnmounted(() => {
emitter.off('filter-final', refreshHandler)
})
const tableRef = ref<InstanceType<typeof NDataTable>>()
const rowKey = (row: RowData) => row.id
const loading = ref(true)
const total = ref(0)
const pagination = reactive({
page: 1,
pageCount: 10,
pageSize: 10,
showSizePicker: true,
pageSizes: [
{
label: '10 每页',
value: 10,
},
{
label: '15 每页',
value: 15,
},
{
label: '30 每页',
value: 30,
},
{
label: '50 每页',
value: 50,
},
],
showQuickJumper: true,
prefix: () => `${total.value} 条数据`,
})
const tableData = ref<Array<RowData>>([])
const selectionIds = ref<DataTableRowKey[]>([])
const dialog = useDialog()
const message = useMessage()
const finalStore = useFinal()
async function query(
page: number,
pageSize: number,
filterId?: any,
taskName?: string,
) {
console.log('query', taskName)
const asideParmas = cloneDeep(unref(finalStore.getAsideValue))
console.log(asideParmas)
if (asideParmas.izyear) {
asideParmas.izuptime = cloneDeep(asideParmas.izyear)
if (typeof asideParmas.izuptime == 'object') {
asideParmas.izuptime[0] = dayjs(asideParmas.izuptime[0]).format(
'YYYY/MM/DD',
)
asideParmas.izuptime[1] = dayjs(asideParmas.izuptime[1]).format(
'YYYY/MM/DD',
)
asideParmas.izuptime = asideParmas.izuptime.join('-')
delete asideParmas.izyear
}
}
// 有过滤配置的时候优先使用过滤配置,不要使用左侧参数
// let params = filterId ? { userSearchId: filterId } : asideParmas
const 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,
...params,
})
const { data, pageCount, totalCount } = result
tableData.value = data
total.value = totalCount
pagination.page = page
pagination.pageCount = Math.ceil(totalCount / pageSize)
loading.value = false
}
async function handleSorterChange(value) {
let name = value.columnKey
if (name === 'fromuptime')
name = 'submit_date_timestamp'
else if (name === 'similarityscore')
name = 'similarity_score'
else if (name === 'fromusername')
name = 'field1'
sortname.value = name
sortorder.value = value.order === 'ascend' ? 'asc' : 'desc'
refreshHandler()
}
async function handlePageChange(currentPage) {
if (loading.value)
return
const { pageSize } = pagination
pagination.page = currentPage
await query(currentPage, pageSize, {}, props.taskvalue)
}
async function handlePageSizeChange(currentPageSize) {
if (loading.value)
return
const { page } = pagination
pagination.pageSize = currentPageSize
await query(page, currentPageSize, {}, props.taskvalue)
}
function handleCheck(rowKeys: DataTableRowKey[]) {
selectionIds.value = rowKeys
}
async function computeListHeight() {
const table = unref(tableRef)
if (!table)
return
const tableEl: any = table?.$el
const headEl = tableEl.querySelector('.n-data-table-thead ')
const { bottomIncludeBody } = getViewportOffset(headEl)
const headerH = 64
let paginationH = 2
const marginH = 60
if (!isBoolean(unref(pagination))) {
const paginationEl = tableEl.querySelector(
'.n-data-table__pagination',
) as HTMLElement
if (paginationEl) {
const offsetHeight = paginationEl.offsetHeight
paginationH += offsetHeight || 0
}
else {
paginationH += 28
}
}
let height = bottomIncludeBody - (headerH + paginationH + marginH)
const maxHeight = 800
height = maxHeight && maxHeight < height ? maxHeight : height
deviceHeight.value = height
}
useWindowSizeFn(computeListHeight)
const maxHeight = computed(() => {
return tableData.value.length ? `${unref(deviceHeight)}px` : 'auto'
})
const scrollX = computed(() => {
const table = unref(tableRef)
if (!table)
return
const tableEl: any = table?.$el
const wrapper = tableEl.querySelector('.n-data-table-wrapper')
// const arr = columnsRef.value.filter(item => !item.fixed)
let width = 0
columnsRef.value.forEach((item) => {
width += Number(item.width) || 200
})
return width
})
const customTabelRef = ref(null)
const importExcelRef = ref(null)
const notPassModalRef = ref(null) // 不通过弹窗
const repeatModalRef = ref(null)
const repeatTaskTableModalRef = ref(null)
function showModal(modalRef: any) {
const modal = unref(modalRef)! as any
modal.showModal()
}
const popover = ref<ComponentRef | null>(null)
function importHandler() {
(popover.value as any).setShow(false)
showModal(importExcelRef)
}
function exportHandler() {
loading.value = true
import('@/utils/exportExcel').then((excel) => {
const tHeader = [
'任务Id',
'任务名称',
'审批节点',
'审批状态',
'图片相似度',
'提报时间',
'更新时间',
]
const filterVal = [
'pictureid',
'name',
'approvalnode',
'approvalstatus',
'similarity',
'uptime',
'updatetime',
]
const list = tableData.value
const data = formatJson(filterVal, list)
excel.export_json_to_excel({
header: tHeader,
data,
filename: 'data',
autoWidth: true,
bookType: 'xlsx',
})
loading.value = false
})
}
function formatJson(filterVal, jsonDataList) {
return jsonDataList.map(v =>
filterVal.map((j) => {
return v[j]
}),
)
}
function sucessHandler(excelData) {
const data = excelData.content.map((item) => {
const obj = {}
Object.keys(item).forEach((key) => {
const k = findKey(columns, key)
obj[k] = item[key]
})
return obj
})
tableData.value = data
}
function commitHandler(columns) {
columnsRef.value = [...columns, actionsColumns]
formatColumns()
}
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
}
}
// states:1未提交2待审批3通过4不通过
function validate(items: any[]) {
if (items.length === 0)
return '至少选中一个任务'
return null
}
function goDetail(row) {
emit('goDetailx',{ id: row.id, packageid: row.packageid, taskindex: row.taskNode, type: 'table' })
}
function resetHandler() {
dialog.info({
title: '确认提示',
content: '确认重置当前选中的任务的审批吗?',
positiveText: '确定',
negativeText: '取消',
onPositiveClick: async () => {
// TODO需要支持重置
// const result = await resetApproval()
},
onNegativeClick: () => {},
})
}
function getSelectItems() {
return tableData.value.filter(item => selectionIds.value.includes(item.id))
}
const showActions = computed(() => {
return selectionIds.value.length
})
// 单个审批通过
function singleApproval(row) {
const param = {
result: true,
comment: '',
disposeType: '',
disposeTypeId: '',
failCauseId: '',
failCauseName: '',
flowTaskInfoList: [
{
formId: row.id,
taskId: row.taskId,
taskName: row.fromTaskName,
},
],
}
doAudit(param)
}
// 批量通过
function batchApproval() {
const items: any = getSelectItems()
const msg = validate(items)
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)
}
// 小结批量不通过
function repeatBatchReject(items) {
console.log(items)
rejectHandler(items)
}
// 批量不通过
function batchReject() {
const items: any = getSelectItems()
rejectHandler(items)
}
// 审核不通过
function rejectHandler(list) {
const msg = validate(list)
if (msg !== null) {
message.error(msg)
return
}
const modal = unref(notPassModalRef)! as any
modal.showModal(list)
}
// 审核通过
function doAudit(param: any) {
const modal = unref(headerref)! as any
dialog.info({
title: '确认提示',
content: '确认给该任务审批为【通过】吗?',
positiveText: '确定',
negativeText: '取消',
onPositiveClick: () => {
audit(param).then((res) => {
const { code } = res
if (code === 'OK') {
message.success(res.message)
reload()
modal.getData()
// haeaderstore.setDataConfig(true)
}
else {
message.error(res.message)
}
})
},
onNegativeClick: () => {},
})
}
function switchBatch() {
selectionIds.value = []
checkedRowKeys.value = []
}
function reload() {
const modal = unref(headerref)! as any
selectionIds.value = []
checkedRowKeys.value = []
const { page, pageSize } = unref(
tableRef.value?.pagination,
) as PaginationProps
query(page!, pageSize!, {}, props.taskvalue)
modal.getData()
// haeaderstore.setDataConfig(true)
}
watch(
() => finalStore.asideValue,
(newVal, oldVal) => {
refreshHandler()
},
{ deep: true },
)
watch(
() => finalStore.listKey,
(newVal, oldVal) => {
refreshHandler()
},
)
function reset() {
pagination.page = 1
pagination.pageCount = 1
}
async function refreshHandler(searchId?: any) {
reset()
let searchKeyword = ''
if (searchContent) {
const id_param = searchContent.match(/-\d+-/)
if (id_param)
searchKeyword = id_param[0].slice(1, -1)
}
console.log('refreshHandler', searchKeyword)
query(pagination.page, pagination.pageSize, searchId, searchKeyword)
}
function filterTableData(keyword) {
pagination.page = 1
pagination.pageSize = 10
if (keyword)
query(pagination.page, pagination.pageSize, '', keyword)
else query(pagination.page, pagination.pageSize)
}
async function initData(pageSize, page, filterId?: any, taskName?: string) {
const asideParmas = unref(finalStore.getAsideValue)
if (asideParmas.izyear) {
asideParmas.izuptime = cloneDeep(asideParmas.izyear)
if (typeof asideParmas.izuptime == 'object') {
asideParmas.izuptime[0] = dayjs(asideParmas.izuptime[0]).format(
'YYYY/MM/DD',
)
asideParmas.izuptime[1] = dayjs(asideParmas.izuptime[1]).format(
'YYYY/MM/DD',
)
asideParmas.izuptime = asideParmas.izuptime.join('-')
delete asideParmas.izyear
}
}
// 有过滤配置的时候优先使用过滤配置,不要使用左侧参数
// let params = filterId ? { userSearchId: filterId } : asideParmas
const 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
tableData.value = data
total.value = totalCount
pagination.page = page
pagination.pageCount = Math.ceil(totalCount / pageSize)
loading.value = false
}
onMounted(() => {
// query(pagination.page, pagination.pageSize);
const asideParmas = cloneDeep(unref(finalStore.getAsideValue))
console.log(asideParmas)
emitter.on('filter-final', refreshHandler)
getColumns()
if (asideParmas == null) {
initData(1, 20, {}, props.taskvalue)
}
else {
reset()
filterTableData(props.taskvalue)
}
// alert(1)
nextTick(() => {
computeListHeight()
})
})
defineExpose({
filterTableData,
})
</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="list-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
style="margin-right: 5px;"
class="btn-approval"
src="@/assets/images/task/btn-pass.png"
alt=""
@click.stop="batchApproval"
>
</div>
<n-popover
ref="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 ref="headerref" :has-color="true" />
</div>
<div class="wrapper-settings">
<div class="sltedtext">
已选<span style="width:20px;margin-left:10px;margin-right:10px;color:#507AFD">{{ checkedRowKeys.length }}</span>项
</div>
<SvgIcon
style="cursor: pointer"
size="18"
name="column"
@click="showModal(customTabelRef)"
/>
</div>
<div class="wrapper-content">
<NDataTable
id="table"
ref="tableRef"
v-model:checked-row-keys="checkedRowKeys"
remote
:columns="columnsRef"
:scroll-x="scrollX"
:max-height="maxHeight"
:data="tableData"
:loading="loading"
:pagination="pagination"
:row-key="rowKey"
@update:page="handlePageChange"
@update-page-size="handlePageSizeChange"
@update:checked-row-keys="handleCheck"
@update:sorter="handleSorterChange"
/>
</div>
<CustomTabelModal ref="customTabelRef" @commit="commitHandler" />
<ImportExcelModal
ref="importExcelRef"
:on-success="sucessHandler"
:header-config="headRules"
/>
<NotPassed ref="notPassModalRef" @success="reload" />
<RepeatModal
ref="repeatModalRef"
@reject="repeatBatchReject"
@viewrepeat="showModal(repeatTaskTableModalRef)"
/>
<RepeatTaskTableModal ref="repeatTaskTableModalRef" />
</div>
</template>
<style lang="less" scoped>
.color-red {
color: #ff4e4f !important;
}
.batch {
display: flex;
align-items: center;
margin-right: 10px;
.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;
}
.wrapper {
display: flex;
flex: 1;
overflow: hidden;
flex-direction: column;
box-sizing: border-box;
margin-left: 16px;
margin-right:16px ;
width: 100%;
background: #fff;
padding: 0px 24px 24px 24px;
.sltedtext{
position: absolute;
left: 437px;
color:#202020
}
&-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 {
font-weight: bold;
color: #507afd;
margin-right: 20px;
}
.title {
color: #507afd;
font-weight: bold;
font-size: 14px;
margin-left: 8px;
}
.btn {
width: 160px;
height: 27px;
background: url(/src/assets/images/pocitypass.png) no-repeat;
background-size: 100% 100%;
border-radius: 17px;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
margin-right: 16px;
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;
align-items: center;
justify-content: flex-end;
padding: 12px 0px;
}
&-statistic {
width: 100%;
height: 76px;
background: #f9fafb;
border-radius: 4px;
display: flex;
padding: 0px 10px;
justify-content: space-between;
.item {
display: flex;
align-items: center;
padding: 20px 0;
.icon {
background-color: #ecf2fe;
width: 50px;
height: 50px;
border-radius: 50px;
}
.content {
text-align: center;
margin-left: 12px;
.num {
font-weight: bold;
color: #202020;
font-size: 18px;
}
.label {
color: #202020;
opacity: 0.6;
}
span {
display: block;
}
}
.divider {
background-color: #e8e8e8;
margin: 0px 10px;
width: 3px;
height: 20px;
}
}
}
&-content {
flex: auto;
background: #fff;
}
}
:deep(.n-data-table .n-data-table-td.n-data-table-td--fixed-right) {
z-index: 100 !important;
}
:deep(.n-data-table-th__title) {
color: #333;
}
:deep(.n-data-table .n-data-table-td) {
color: #666;
}
:deep(.n-data-table .n-data-table-base-table-header) {
overflow: hidden;
}
</style>