parent
e7c37bc426
commit
a0e518ab24
After Width: | Height: | Size: 389 B |
@ -0,0 +1,163 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, defineOptions, nextTick, onBeforeMount, onMounted, reactive, ref, unref } from 'vue'
|
||||
import CustomFieldModalVue from '../modal/CustomFieldModal.vue'
|
||||
import WorkSheetList from './WorkSheetList.vue'
|
||||
import { useWindowSizeFn } from '@/hooks/event/useWindowSizeFn'
|
||||
import { getViewportOffset } from '@/utils/domUtils'
|
||||
import type { PackageListItem } from '/#/workorder'
|
||||
import { useWorkOrder } from '@/store/modules/workOrder'
|
||||
|
||||
defineOptions({ name: 'AsideContent' })
|
||||
|
||||
const collapse = ref(false)
|
||||
const workStore = useWorkOrder()
|
||||
const filterModalRef = ref(null)
|
||||
|
||||
function collapseHandler() {
|
||||
collapse.value = !collapse.value
|
||||
}
|
||||
|
||||
const asideWidth = computed(() => {
|
||||
return collapse.value ? 0 : 308
|
||||
})
|
||||
|
||||
const asideStyle = computed(() => {
|
||||
return {
|
||||
width: `${asideWidth.value}px`,
|
||||
}
|
||||
})
|
||||
|
||||
const collapseIcon = computed(() => {
|
||||
return collapse.value ? 'expand-cir' : 'collapse-cir'
|
||||
})
|
||||
|
||||
const listHeight = ref(700)
|
||||
|
||||
function computeListHeight() {
|
||||
const listEl = document.querySelector('.work-sheet-list')!
|
||||
const { bottomIncludeBody } = getViewportOffset(listEl)
|
||||
const height = bottomIncludeBody
|
||||
listHeight.value = height - 25
|
||||
}
|
||||
|
||||
const listStyle = computed(() => {
|
||||
return {
|
||||
height: `${listHeight.value}px`,
|
||||
}
|
||||
})
|
||||
|
||||
useWindowSizeFn(computeListHeight, 280)
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
computeListHeight()
|
||||
})
|
||||
})
|
||||
|
||||
const data = ref<PackageListItem[]>([])
|
||||
|
||||
const pagination = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
})
|
||||
|
||||
onBeforeMount(async () => {
|
||||
const orderList = await workStore.fetchOrderList(pagination)
|
||||
data.value = orderList
|
||||
})
|
||||
|
||||
const asideEnter = ref(false)
|
||||
|
||||
const showCollapse = computed(() => {
|
||||
return collapse.value ? true : asideEnter.value
|
||||
})
|
||||
|
||||
function showFilter() {
|
||||
const modal = unref(filterModalRef)! as any
|
||||
modal.showModal()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="aside" :style="asideStyle" @mouseenter="asideEnter = true" @mouseleave="asideEnter = false">
|
||||
111fsfsf发送到发
|
||||
|
||||
<div v-show="showCollapse" class="aside-collapse">
|
||||
<div class="aside-collapse-btn" @click="collapseHandler">
|
||||
<SvgIcon :name="collapseIcon" size="40" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="aside-header">
|
||||
<div class="aside-header-left">
|
||||
<svg-icon name="all-worksheet" size="32" />
|
||||
<span style="margin-left: 8px;">所有工单</span>
|
||||
</div>
|
||||
<div class="aside-header-right">
|
||||
<SvgIcon style="cursor: pointer;margin-left: 10px;" size="18" name="magnifying-1" />
|
||||
<SvgIcon style="cursor: pointer;margin-left: 10px;" size="18" name="filter" @click="showFilter" />
|
||||
</div>
|
||||
</div>
|
||||
<WorkSheetList :style="listStyle" class="work-sheet-list" :data="data" :active-id="workStore.getActiveId" />
|
||||
<CustomFieldModalVue ref="filterModalRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.aside {
|
||||
display: flex;
|
||||
position: relative;
|
||||
flex-direction: column;
|
||||
background: #FFF;
|
||||
border: 1px solid rgb(239, 239, 245);
|
||||
border-radius: 3px;
|
||||
box-sizing: border-box;
|
||||
|
||||
&-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 16px;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
&-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
&-divider {
|
||||
margin-left: 16px;
|
||||
width: 292px;
|
||||
height: 1px;
|
||||
background-color: #e8e8e8;
|
||||
}
|
||||
|
||||
&-collapse {
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
background: #507afd;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
&-collapse-btn {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
top: calc(15%);
|
||||
right: -20px;
|
||||
z-index: 10;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
../types
|
@ -0,0 +1,37 @@
|
||||
<script lang="ts" setup>
|
||||
import type { PackageListItem } from '/#/workorder'
|
||||
import ListItem from './ListItem.vue'
|
||||
import { useWorkOrder } from '@/store/modules/workOrder'
|
||||
|
||||
defineOptions({ name: 'WorkSheetList' })
|
||||
|
||||
defineProps({
|
||||
activeId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
data: {
|
||||
type: Object as PropType<PackageListItem[]>,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const workStore = useWorkOrder()
|
||||
|
||||
function selectHandler(id: string, index: number) {
|
||||
workStore.setActive(index)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-scrollbar>
|
||||
<ListItem
|
||||
v-for="(item, index) in data" :key="item.id" :selected="activeId === item.id" :list-item="item"
|
||||
@click="selectHandler(item.id, index)"
|
||||
/>
|
||||
</n-scrollbar>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
</style>
|
||||
../types
|
@ -0,0 +1,515 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, onUnmounted, reactive, ref, unref, watch } from 'vue'
|
||||
import { useDialog, useMessage } from 'naive-ui'
|
||||
import { clone, pickBy } from 'lodash-es'
|
||||
import ConfrimModal from '../modal/ConfrimModal.vue'
|
||||
import type { PictureSortParam, SetTFParam } from '/#/api'
|
||||
import { useWorkOrder } from '@/store/modules/workOrder'
|
||||
import { clearTF, getPackageTaskList, getTaskDetailInfo, getTaskDetailPictureList, setTF } from '@/api/work/work'
|
||||
import { fieldMap } from '@/config/workorder'
|
||||
|
||||
const batch = ref(false)
|
||||
const selectItems = ref<any[]>([])
|
||||
const message = useMessage()
|
||||
const dialog = useDialog()
|
||||
const totalCount = ref(0)
|
||||
|
||||
function setBatch(value: boolean) {
|
||||
batch.value = value
|
||||
if (value === false) {
|
||||
selectItems.value.forEach(item => item.checked = false)
|
||||
selectItems.value.length = 0
|
||||
}
|
||||
}
|
||||
|
||||
function onCheckChange(checked: any, item: any) {
|
||||
const index = selectItems.value.indexOf(item)
|
||||
item.checked = checked
|
||||
|
||||
if (index === -1 && checked)
|
||||
selectItems.value.push(item)
|
||||
|
||||
else
|
||||
selectItems.value.splice(index, 1)
|
||||
}
|
||||
|
||||
const showActions = computed(() => {
|
||||
return selectItems.value.length > 0 && batch
|
||||
})
|
||||
|
||||
const packagepagination = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
})
|
||||
const taskpagination = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
})
|
||||
const sortBy: PictureSortParam = {
|
||||
orderbyname: 'desc',
|
||||
orderbyvalue: 'fromuptime',
|
||||
}
|
||||
const workStore = useWorkOrder()
|
||||
const selectTask = ref<any>(null)
|
||||
const overTask = ref<any>(null)
|
||||
const taskList = ref<any[]>([])
|
||||
const taskDetailInfo = ref<any>({})
|
||||
const taskDetailPictureList = ref<any[]>([])
|
||||
|
||||
const confrimModalRef = ref(null)
|
||||
let processItems: any[] = []
|
||||
const tab = ref(0)
|
||||
|
||||
function validate(items: any[]) {
|
||||
if (items.length === 0)
|
||||
return '至少选中一个任务'
|
||||
|
||||
for (const item of items) {
|
||||
const { iztrueorfalse, history, states } = item
|
||||
if (iztrueorfalse !== null)
|
||||
return '存在已经辨识过的任务'
|
||||
|
||||
else if (history)
|
||||
return '包含历史数据'
|
||||
|
||||
else if (states !== 1 && states !== 2)
|
||||
return '审批状态不合法'
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
function falseHandler() {
|
||||
let cloneItem: any
|
||||
if (batch.value) { processItems = selectItems.value }
|
||||
else if (overTask.value) {
|
||||
cloneItem = clone(overTask.value)
|
||||
processItems = [cloneItem]
|
||||
}
|
||||
const msg = validate(processItems)
|
||||
|
||||
if (msg !== null) {
|
||||
message.error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
const modal = unref(confrimModalRef)! as any
|
||||
modal.showModal()
|
||||
}
|
||||
|
||||
function trueHandler() {
|
||||
let cloneItem: any
|
||||
if (batch.value) { processItems = selectItems.value }
|
||||
else if (overTask.value) {
|
||||
cloneItem = clone(overTask.value)
|
||||
processItems = [cloneItem]
|
||||
}
|
||||
|
||||
const msg = validate(processItems)
|
||||
|
||||
if (msg !== null) {
|
||||
message.error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
dialog.info({
|
||||
title: '确认提示',
|
||||
content: '确认给该任务图判真吗?',
|
||||
positiveText: '确定',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: () => {
|
||||
setTrue()
|
||||
},
|
||||
onNegativeClick: () => { },
|
||||
})
|
||||
}
|
||||
|
||||
function setTrue() {
|
||||
const ids: any[] = processItems.map(item => item.id)
|
||||
|
||||
const param: SetTFParam = {
|
||||
taskchildpictureids: ids.join(','),
|
||||
iztrueorfalse: 1,
|
||||
packageid: workStore.getActiveId,
|
||||
judgeid: '0',
|
||||
}
|
||||
|
||||
doSetTF(param)
|
||||
}
|
||||
|
||||
function setFalse(id: string, desc: null | string) {
|
||||
const ids: any[] = processItems.map(item => item.id)
|
||||
|
||||
const param: SetTFParam = {
|
||||
taskchildpictureids: ids.join(','),
|
||||
iztrueorfalse: 0,
|
||||
packageid: workStore.getActiveId,
|
||||
judgeid: id,
|
||||
}
|
||||
|
||||
if (desc)
|
||||
param.judgedesc = desc
|
||||
|
||||
doSetTF(param)
|
||||
}
|
||||
|
||||
function doSetTF(param: SetTFParam) {
|
||||
setTF(param).then((res) => {
|
||||
const { code } = res
|
||||
processItems.length = 0
|
||||
if (code === 'OK')
|
||||
updateList(param)
|
||||
else
|
||||
message.error(res.message)
|
||||
})
|
||||
}
|
||||
|
||||
function updateList(param: SetTFParam) {
|
||||
const list = taskDetailPictureList.value
|
||||
const ids = param.taskchildpictureids.split(',')
|
||||
|
||||
for (const item of list) {
|
||||
if (ids.includes(item.id))
|
||||
item.iztrueorfalse = param.iztrueorfalse
|
||||
}
|
||||
}
|
||||
|
||||
function forwardHandler() {
|
||||
workStore.forward()
|
||||
}
|
||||
|
||||
function backHandler() {
|
||||
workStore.back()
|
||||
}
|
||||
|
||||
watch(() => workStore.activeId, async (newValue, oldValue) => {
|
||||
const res = await getPackageTaskList(newValue, packagepagination)
|
||||
const { data } = res
|
||||
taskList.value = data
|
||||
|
||||
if (taskList.value.length > 0)
|
||||
handleSelect(taskList.value[0])
|
||||
})
|
||||
|
||||
const packageName = computed(() => {
|
||||
const index = workStore.getCurrentIndex
|
||||
return workStore.getOrderList[index]?.packagename || ''
|
||||
})
|
||||
|
||||
async function handleSelect(item: any) {
|
||||
selectTask.value = item
|
||||
const taskId = item.id
|
||||
taskDetailInfo.value = await getTaskDetailInfo(taskId, workStore.activeId)
|
||||
|
||||
const { data, total } = await getTaskDetailPictureList(workStore.activeId, taskId, { ...taskpagination, ...sortBy })
|
||||
taskDetailPictureList.value = data
|
||||
totalCount.value = total
|
||||
}
|
||||
|
||||
async function sortHandler(orderby: 'pictureResult' | 'fromuptime') {
|
||||
if (!selectTask.value)
|
||||
return
|
||||
|
||||
taskpagination.pageNo = 1
|
||||
taskpagination.pageSize = 10
|
||||
sortBy.orderbyvalue = orderby
|
||||
|
||||
const res = await getTaskDetailPictureList(workStore.activeId, selectTask.value.id, { ...taskpagination, ...sortBy })
|
||||
taskDetailPictureList.value = res.data
|
||||
}
|
||||
|
||||
const propertys = computed(() => {
|
||||
const { ocrPicture } = taskDetailInfo.value
|
||||
const v = pickBy(ocrPicture, (value, key: string) => {
|
||||
return key.startsWith('field') && value !== null
|
||||
})
|
||||
return v
|
||||
})
|
||||
|
||||
async function clearMark() {
|
||||
const res = await clearTF(workStore.activeId, selectTask.value.id)
|
||||
if (res.code === 'OK') {
|
||||
taskDetailInfo.value.iztrueorfalse = null
|
||||
message.info('清除标记成功')
|
||||
}
|
||||
else { message.error(res.message) }
|
||||
}
|
||||
|
||||
function overTaskHandelr(item: any) {
|
||||
if (validate([item]) == null && batch.value === false)
|
||||
overTask.value = item
|
||||
}
|
||||
|
||||
function leaveTaskHandler() {
|
||||
overTask.value = null
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
workStore.reset()
|
||||
})
|
||||
|
||||
function getPercent(pictureid: string) {
|
||||
const { ocpictureid, pictureresult } = taskDetailInfo.value
|
||||
const index = ocpictureid.split(',').indexOf(String(pictureid))
|
||||
const results = pictureresult.split(',')
|
||||
const percent = results[index] || '0'
|
||||
const val = Number.parseFloat(percent)
|
||||
return `${val}%`
|
||||
}
|
||||
|
||||
const mark = computed(() => {
|
||||
return taskDetailInfo.value.iztrueorfalse === null ? '未标记' : '已标记'
|
||||
})
|
||||
|
||||
function switchTab(type: number) {
|
||||
tab.value = type
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="wrapper-message">
|
||||
<div class="header flex justify-between">
|
||||
<div class="header-title">
|
||||
消息通知
|
||||
</div>
|
||||
<div class="clear">
|
||||
清除未读
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="slider">
|
||||
<div :class="{ 'item-active': tab === 0 }" class="item flex" @click="switchTab(0)">
|
||||
<div class="item-left flex align-center">
|
||||
<img class="icon" src="@/assets/images/login/logo.png" alt="">
|
||||
<div class="text">
|
||||
审批通知
|
||||
</div>
|
||||
</div>
|
||||
<img class="icon-arrow" src="@/assets/images/login/arrow-active.png" alt="">
|
||||
<div v-if="tab === 0" class="line" />
|
||||
</div>
|
||||
<div :class="{ 'item-active': tab === 1 }" class="item flex" @click="switchTab(1)">
|
||||
<div class="item-left flex align-center">
|
||||
<img class="icon" src="@/assets/images/login/logo.png" alt="">
|
||||
<div class="text">
|
||||
系统消息
|
||||
</div>
|
||||
</div>
|
||||
<img class="icon-arrow" src="@/assets/images/login/arrow-active.png" alt="">
|
||||
<div v-if="tab === 1" class="line" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="list">
|
||||
<div class="item">
|
||||
<div class="left left">
|
||||
<div class="num">
|
||||
23
|
||||
<div class="point" />
|
||||
</div>
|
||||
<div class="date">
|
||||
2024.01
|
||||
</div>
|
||||
</div>
|
||||
<div class="middle">
|
||||
<div class="title">
|
||||
系统升级通知占位符占位占位系统升级通知占位符占位占位系统升级通知占位符占位占位
|
||||
</div>
|
||||
<div class="subtitle">
|
||||
<span class="name">系统管理员</span>
|
||||
<span class="time">2024-01-31 23:12:00</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="look">
|
||||
查看
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.wrapper-message {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background: #FFF;
|
||||
border-radius: 3px;
|
||||
border: 1px solid rgb(239, 239, 245);
|
||||
height: calc(100vh - 88px);
|
||||
overflow-y: scroll;
|
||||
|
||||
.header{
|
||||
padding: 24px;
|
||||
|
||||
&-title{
|
||||
font-size: 20px;
|
||||
font-family: PingFang SC, PingFang SC-Medium;
|
||||
font-weight: Medium;
|
||||
color: #333333;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
.clear{
|
||||
font-size: 14px;
|
||||
font-family: PingFang SC, PingFang SC-Regular;
|
||||
font-weight: Regular;
|
||||
color: #666666;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.content{
|
||||
display: flex;
|
||||
padding-right: 24px;
|
||||
.slider{
|
||||
|
||||
.icon{
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
}
|
||||
|
||||
.icon-arrow{
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
.item{
|
||||
width: 200px;
|
||||
height: 44px;
|
||||
position: relative;
|
||||
padding: 0 24px;
|
||||
box-sizing: border-box;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
&-active{
|
||||
background: rgba(80,122,253,.1);
|
||||
}
|
||||
}
|
||||
|
||||
.item-left{
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.text{
|
||||
font-size: 14px;
|
||||
font-family: PingFang SC, PingFang SC-Medium;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
margin-left: 12px;
|
||||
&-text{
|
||||
color: #507AFD;
|
||||
}
|
||||
}
|
||||
|
||||
.line{
|
||||
position: absolute;
|
||||
width: 3px;
|
||||
height: 44px;
|
||||
background: #5376ff;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.list{
|
||||
margin-left: 24px;
|
||||
flex: 1;
|
||||
|
||||
.item{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex: 1;
|
||||
height: 96px;
|
||||
border-bottom: 1px solid #eeeeee;
|
||||
padding-right: 25px;
|
||||
}
|
||||
|
||||
.num{
|
||||
font-size: 32px;
|
||||
font-family: HarmonyOS Sans SC, HarmonyOS Sans SC-Medium;
|
||||
font-weight: Medium;
|
||||
text-align: left;
|
||||
color: #507afd;
|
||||
line-height: 46px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.date{
|
||||
font-size: 12px;
|
||||
font-family: PingFang SC, PingFang SC-Regular;
|
||||
font-weight: Regular;
|
||||
text-align: left;
|
||||
color: #999999;
|
||||
line-height: 17px;
|
||||
}
|
||||
|
||||
.point{
|
||||
position: absolute;
|
||||
right: -2px;
|
||||
top: 5px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: #ff4e4f;
|
||||
}
|
||||
|
||||
.left{
|
||||
width: 80px;
|
||||
height: 64px;
|
||||
border-right: 1px solid #e8e8e8;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.middle{
|
||||
flex: 1;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.title{
|
||||
font-size: 16px;
|
||||
font-family: PingFang SC, PingFang SC-Medium;
|
||||
font-weight: Medium;
|
||||
text-align: left;
|
||||
color: #666666;
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
.subtitle{
|
||||
font-size: 12px;
|
||||
font-family: PingFang SC, PingFang SC-Regular;
|
||||
font-weight: Regular;
|
||||
text-align: left;
|
||||
color: #999999;
|
||||
line-height: 19px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.name{
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.look{
|
||||
font-size: 14px;
|
||||
font-family: PingFang SC, PingFang SC-Regular;
|
||||
font-weight: Regular;
|
||||
text-align: left;
|
||||
color: #5376ff;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ::v-deep(.n-divider:not(.n-divider--vertical)) {
|
||||
// margin-top: 12px;
|
||||
// margin-bottom: 12px;
|
||||
// }
|
||||
</style>
|
@ -0,0 +1,345 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, onUnmounted, reactive, ref, unref, watch } from 'vue'
|
||||
import { useDialog, useMessage } from 'naive-ui'
|
||||
import { clone, pickBy } from 'lodash-es'
|
||||
import ConfrimModal from '../modal/ConfrimModal.vue'
|
||||
import type { PictureSortParam, SetTFParam } from '/#/api'
|
||||
import { useWorkOrder } from '@/store/modules/workOrder'
|
||||
import { clearTF, getPackageTaskList, getTaskDetailInfo, getTaskDetailPictureList, setTF } from '@/api/work/work'
|
||||
import { fieldMap } from '@/config/workorder'
|
||||
|
||||
const batch = ref(false)
|
||||
const selectItems = ref<any[]>([])
|
||||
const message = useMessage()
|
||||
const dialog = useDialog()
|
||||
const totalCount = ref(0)
|
||||
|
||||
function setBatch(value: boolean) {
|
||||
batch.value = value
|
||||
if (value === false) {
|
||||
selectItems.value.forEach(item => item.checked = false)
|
||||
selectItems.value.length = 0
|
||||
}
|
||||
}
|
||||
|
||||
function onCheckChange(checked: any, item: any) {
|
||||
const index = selectItems.value.indexOf(item)
|
||||
item.checked = checked
|
||||
|
||||
if (index === -1 && checked)
|
||||
selectItems.value.push(item)
|
||||
|
||||
else
|
||||
selectItems.value.splice(index, 1)
|
||||
}
|
||||
|
||||
const showActions = computed(() => {
|
||||
return selectItems.value.length > 0 && batch
|
||||
})
|
||||
|
||||
const packagepagination = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
})
|
||||
const taskpagination = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
})
|
||||
const sortBy: PictureSortParam = {
|
||||
orderbyname: 'desc',
|
||||
orderbyvalue: 'fromuptime',
|
||||
}
|
||||
const workStore = useWorkOrder()
|
||||
const selectTask = ref<any>(null)
|
||||
const overTask = ref<any>(null)
|
||||
const taskList = ref<any[]>([])
|
||||
const taskDetailInfo = ref<any>({})
|
||||
const taskDetailPictureList = ref<any[]>([])
|
||||
|
||||
const confrimModalRef = ref(null)
|
||||
let processItems: any[] = []
|
||||
const tab = ref(0)
|
||||
|
||||
function validate(items: any[]) {
|
||||
if (items.length === 0)
|
||||
return '至少选中一个任务'
|
||||
|
||||
for (const item of items) {
|
||||
const { iztrueorfalse, history, states } = item
|
||||
if (iztrueorfalse !== null)
|
||||
return '存在已经辨识过的任务'
|
||||
|
||||
else if (history)
|
||||
return '包含历史数据'
|
||||
|
||||
else if (states !== 1 && states !== 2)
|
||||
return '审批状态不合法'
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
function falseHandler() {
|
||||
let cloneItem: any
|
||||
if (batch.value) { processItems = selectItems.value }
|
||||
else if (overTask.value) {
|
||||
cloneItem = clone(overTask.value)
|
||||
processItems = [cloneItem]
|
||||
}
|
||||
const msg = validate(processItems)
|
||||
|
||||
if (msg !== null) {
|
||||
message.error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
const modal = unref(confrimModalRef)! as any
|
||||
modal.showModal()
|
||||
}
|
||||
|
||||
function trueHandler() {
|
||||
let cloneItem: any
|
||||
if (batch.value) { processItems = selectItems.value }
|
||||
else if (overTask.value) {
|
||||
cloneItem = clone(overTask.value)
|
||||
processItems = [cloneItem]
|
||||
}
|
||||
|
||||
const msg = validate(processItems)
|
||||
|
||||
if (msg !== null) {
|
||||
message.error(msg)
|
||||
return
|
||||
}
|
||||
|
||||
dialog.info({
|
||||
title: '确认提示',
|
||||
content: '确认给该任务图判真吗?',
|
||||
positiveText: '确定',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: () => {
|
||||
setTrue()
|
||||
},
|
||||
onNegativeClick: () => { },
|
||||
})
|
||||
}
|
||||
|
||||
function setTrue() {
|
||||
const ids: any[] = processItems.map(item => item.id)
|
||||
|
||||
const param: SetTFParam = {
|
||||
taskchildpictureids: ids.join(','),
|
||||
iztrueorfalse: 1,
|
||||
packageid: workStore.getActiveId,
|
||||
judgeid: '0',
|
||||
}
|
||||
|
||||
doSetTF(param)
|
||||
}
|
||||
|
||||
function setFalse(id: string, desc: null | string) {
|
||||
const ids: any[] = processItems.map(item => item.id)
|
||||
|
||||
const param: SetTFParam = {
|
||||
taskchildpictureids: ids.join(','),
|
||||
iztrueorfalse: 0,
|
||||
packageid: workStore.getActiveId,
|
||||
judgeid: id,
|
||||
}
|
||||
|
||||
if (desc)
|
||||
param.judgedesc = desc
|
||||
|
||||
doSetTF(param)
|
||||
}
|
||||
|
||||
function doSetTF(param: SetTFParam) {
|
||||
setTF(param).then((res) => {
|
||||
const { code } = res
|
||||
processItems.length = 0
|
||||
if (code === 'OK')
|
||||
updateList(param)
|
||||
else
|
||||
message.error(res.message)
|
||||
})
|
||||
}
|
||||
|
||||
function updateList(param: SetTFParam) {
|
||||
const list = taskDetailPictureList.value
|
||||
const ids = param.taskchildpictureids.split(',')
|
||||
|
||||
for (const item of list) {
|
||||
if (ids.includes(item.id))
|
||||
item.iztrueorfalse = param.iztrueorfalse
|
||||
}
|
||||
}
|
||||
|
||||
function forwardHandler() {
|
||||
workStore.forward()
|
||||
}
|
||||
|
||||
function backHandler() {
|
||||
workStore.back()
|
||||
}
|
||||
|
||||
watch(() => workStore.activeId, async (newValue, oldValue) => {
|
||||
const res = await getPackageTaskList(newValue, packagepagination)
|
||||
const { data } = res
|
||||
taskList.value = data
|
||||
|
||||
if (taskList.value.length > 0)
|
||||
handleSelect(taskList.value[0])
|
||||
})
|
||||
|
||||
const packageName = computed(() => {
|
||||
const index = workStore.getCurrentIndex
|
||||
return workStore.getOrderList[index]?.packagename || ''
|
||||
})
|
||||
|
||||
async function handleSelect(item: any) {
|
||||
selectTask.value = item
|
||||
const taskId = item.id
|
||||
taskDetailInfo.value = await getTaskDetailInfo(taskId, workStore.activeId)
|
||||
|
||||
const { data, total } = await getTaskDetailPictureList(workStore.activeId, taskId, { ...taskpagination, ...sortBy })
|
||||
taskDetailPictureList.value = data
|
||||
totalCount.value = total
|
||||
}
|
||||
|
||||
async function sortHandler(orderby: 'pictureResult' | 'fromuptime') {
|
||||
if (!selectTask.value)
|
||||
return
|
||||
|
||||
taskpagination.pageNo = 1
|
||||
taskpagination.pageSize = 10
|
||||
sortBy.orderbyvalue = orderby
|
||||
|
||||
const res = await getTaskDetailPictureList(workStore.activeId, selectTask.value.id, { ...taskpagination, ...sortBy })
|
||||
taskDetailPictureList.value = res.data
|
||||
}
|
||||
|
||||
const propertys = computed(() => {
|
||||
const { ocrPicture } = taskDetailInfo.value
|
||||
const v = pickBy(ocrPicture, (value, key: string) => {
|
||||
return key.startsWith('field') && value !== null
|
||||
})
|
||||
return v
|
||||
})
|
||||
|
||||
async function clearMark() {
|
||||
const res = await clearTF(workStore.activeId, selectTask.value.id)
|
||||
if (res.code === 'OK') {
|
||||
taskDetailInfo.value.iztrueorfalse = null
|
||||
message.info('清除标记成功')
|
||||
}
|
||||
else { message.error(res.message) }
|
||||
}
|
||||
|
||||
function overTaskHandelr(item: any) {
|
||||
if (validate([item]) == null && batch.value === false)
|
||||
overTask.value = item
|
||||
}
|
||||
|
||||
function leaveTaskHandler() {
|
||||
overTask.value = null
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
workStore.reset()
|
||||
})
|
||||
|
||||
function getPercent(pictureid: string) {
|
||||
const { ocpictureid, pictureresult } = taskDetailInfo.value
|
||||
const index = ocpictureid.split(',').indexOf(String(pictureid))
|
||||
const results = pictureresult.split(',')
|
||||
const percent = results[index] || '0'
|
||||
const val = Number.parseFloat(percent)
|
||||
return `${val}%`
|
||||
}
|
||||
|
||||
const mark = computed(() => {
|
||||
return taskDetailInfo.value.iztrueorfalse === null ? '未标记' : '已标记'
|
||||
})
|
||||
|
||||
function switchTab(type: number) {
|
||||
tab.value = type
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="wrapper-message">
|
||||
<div class="left-card">
|
||||
dd
|
||||
</div>
|
||||
<div class="right-card">
|
||||
<img class="icon-set" src="@/assets/images/login/logo.png" alt="">
|
||||
<div class="title">
|
||||
系统消息
|
||||
</div>
|
||||
<div class="form">
|
||||
<div class="form-item">
|
||||
<div class="label">
|
||||
任务名称
|
||||
</div>
|
||||
<div class="value">
|
||||
dd
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.wrapper-message {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
box-sizing: border-box;
|
||||
border-radius: 3px;
|
||||
border: 1px solid rgb(239, 239, 245);
|
||||
height: calc(100vh - 88px);
|
||||
overflow-y: auto;
|
||||
|
||||
.left-card{
|
||||
height: 100%;
|
||||
background: #ffffff;
|
||||
border-radius: 4px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.right-card{
|
||||
width: 280px;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
background: #ffffff;
|
||||
border-radius: 4px;
|
||||
margin-left: 16px;
|
||||
padding-top: 48px;
|
||||
|
||||
.title{
|
||||
width: 80px;
|
||||
height: 22px;
|
||||
font-size: 20px;
|
||||
font-family: PingFang SC, PingFang SC-Medium;
|
||||
font-weight: Medium;
|
||||
text-align: center;
|
||||
color: #333333;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.line{
|
||||
width: 232px;
|
||||
height: 1px;
|
||||
border: 1px solid #eeeeee;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-set{
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,25 @@
|
||||
<script lang="ts" setup>
|
||||
import Aside from './aside/Aside.vue'
|
||||
import Content from './content/Content.vue'
|
||||
import Detail from './content/Detail.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="main">
|
||||
<!-- 侧边 -->
|
||||
<!-- <Aside /> -->
|
||||
|
||||
<!-- 内容 -->
|
||||
<!-- <Content /> -->
|
||||
<Detail />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.main {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,167 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, onBeforeMount, ref } from 'vue'
|
||||
import { useDictionary } from '@/store/modules/dictonary'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'commit', id: any, desc: null | string)
|
||||
}>()
|
||||
|
||||
const dictonaryStore = useDictionary()
|
||||
|
||||
const show = ref(false)
|
||||
const cardStyle = {
|
||||
'width': '520px',
|
||||
'--n-padding-bottom': '10px',
|
||||
'--n-padding-left': '0px',
|
||||
}
|
||||
|
||||
function showModal() {
|
||||
show.value = true
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
show.value = false
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
showModal,
|
||||
})
|
||||
|
||||
const options = ref<any[]>([])
|
||||
|
||||
const selectId = ref(null)
|
||||
const otherValue = ref(null)
|
||||
const showOther = computed(() => {
|
||||
for (const item of options.value) {
|
||||
if (item.value === selectId.value && item.label === '其他')
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
async function handleSumbit(e: MouseEvent) {
|
||||
e.preventDefault()
|
||||
closeModal()
|
||||
emit('commit', selectId.value, otherValue.value)
|
||||
}
|
||||
|
||||
onBeforeMount(async () => {
|
||||
const tfList = await dictonaryStore.fetchTFList()
|
||||
options.value = tfList
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-modal v-model:show="show" transform-origin="center">
|
||||
<n-card :style="cardStyle" :bordered="false" size="huge" role="dialog" aria-modal="true">
|
||||
<div class="wrapper">
|
||||
<div class="wrapper-header">
|
||||
<span class="wrapper-left">选择判假原因</span>
|
||||
<div class="wrapper-right">
|
||||
<div class="wrapper-right-close" @pointerdown="closeModal">
|
||||
<div class="wrapper-right-icon" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wrapper-content">
|
||||
<span>判假原因</span>
|
||||
<n-select v-model:value="selectId" style="margin-top: 10px;" :options="options" />
|
||||
<n-input v-show="showOther" v-model:value="otherValue" style="margin-top: 10px;" type="textarea" />
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="wrapper-footer">
|
||||
<n-button type="info" @click="handleSumbit">
|
||||
确认
|
||||
</n-button>
|
||||
<n-button secondary style="margin-left:15px" @click="closeModal">
|
||||
取消
|
||||
</n-button>
|
||||
</div>
|
||||
</template>
|
||||
</n-card>
|
||||
</n-modal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.wrapper {
|
||||
&-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
&-left {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
&-right {
|
||||
&-close {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&-icon {
|
||||
background: #000;
|
||||
display: inline-block;
|
||||
width: 18px;
|
||||
height: 1px;
|
||||
transform: rotate(45deg);
|
||||
-webkit-transform: rotate(45deg);
|
||||
margin-bottom: 8px;
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 18px;
|
||||
height: 1px;
|
||||
background: #000;
|
||||
transform: rotate(-90deg);
|
||||
-webkit-transform: rotate(-90deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-content {
|
||||
padding: 18px 10px;
|
||||
}
|
||||
|
||||
&-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
&-info {
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
background-color: #1980ff;
|
||||
content: '';
|
||||
width: 5px;
|
||||
border-radius: 2px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep(.n-card.n-card--content-segmented > .n-card__content:not(:first-child)) {
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
::v-deep(.n-card > .n-card-header) {
|
||||
--n-padding-top: 0px;
|
||||
--n-padding-bottom: 12px;
|
||||
}
|
||||
|
||||
::v-deep(.n-divider:not(.n-divider--vertical)) {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,384 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { difference } from 'lodash-es'
|
||||
import { VueDraggable } from 'vue-draggable-plus'
|
||||
import { workPackageMap } from '@/config/workorder'
|
||||
|
||||
// 左侧隐藏列表
|
||||
const offList = ref<any[]>([])
|
||||
// 右侧显示列表
|
||||
const onList = ref<any[]>([])
|
||||
|
||||
const allCount = computed(() => {
|
||||
return `全部筛选(共${offList.value.length - 1}个)`
|
||||
})
|
||||
|
||||
const selectCount = computed(() => {
|
||||
return `全部筛选(共${onList.value.length}个)`
|
||||
})
|
||||
|
||||
function generatList() {
|
||||
const keys = Object.keys(workPackageMap)
|
||||
let showList: object[] = []
|
||||
const hideList: object[] = []
|
||||
const showStr = 'status'
|
||||
const showKeys = showStr.split(',').map((key: string) => key.toLowerCase())
|
||||
|
||||
for (const key of keys) {
|
||||
const name = workPackageMap[key]?.label
|
||||
const isDefault = workPackageMap[key]?.isDefault
|
||||
|
||||
// 系统配置为Y且不是默认配置
|
||||
if (!isDefault) {
|
||||
hideList.push({
|
||||
id: key,
|
||||
name: name || '未配置',
|
||||
fix: isDefault,
|
||||
checked: workPackageMap[key].isDefault,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
showList = showKeys.reduce((acc, key) => {
|
||||
const config = {
|
||||
id: key,
|
||||
name: workPackageMap[key].label || '未配置',
|
||||
fix: workPackageMap[key].isDefault,
|
||||
}
|
||||
return [...acc, config]
|
||||
}, [])
|
||||
|
||||
const fixedList = generateDefaultList()
|
||||
|
||||
hideList.unshift(...fixedList)
|
||||
showList.unshift(...fixedList)
|
||||
|
||||
onList.value = showList
|
||||
offList.value = hideList
|
||||
return { showList, hideList }
|
||||
}
|
||||
|
||||
function generateDefaultList() {
|
||||
return Object.keys(workPackageMap).reduce((acc, key) => {
|
||||
const { label, isDefault } = workPackageMap[key]
|
||||
|
||||
if (isDefault) {
|
||||
const config = {
|
||||
id: key,
|
||||
name: label || '未配置',
|
||||
fix: true,
|
||||
checked: true,
|
||||
}
|
||||
return [...acc, config]
|
||||
}
|
||||
else {
|
||||
return acc
|
||||
}
|
||||
}, [])
|
||||
}
|
||||
|
||||
const show = ref(false)
|
||||
const checkAll = ref(false)
|
||||
|
||||
function showModal() {
|
||||
show.value = true
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
show.value = false
|
||||
}
|
||||
|
||||
async function handleSumbit(e: MouseEvent) {
|
||||
e.preventDefault()
|
||||
closeModal()
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
showModal,
|
||||
})
|
||||
|
||||
generatList()
|
||||
|
||||
const selectIds = ref<string[]>([])
|
||||
|
||||
function onCheckAllChange(value) {
|
||||
const ids: string[] = []
|
||||
|
||||
for (const item of offList.value) {
|
||||
if (!item.fix) {
|
||||
item.checked = value
|
||||
ids.push(item.id)
|
||||
}
|
||||
}
|
||||
|
||||
selectIds.value = value ? ids : []
|
||||
}
|
||||
|
||||
function onCheckChange(checked: any, item: any) {
|
||||
const index = selectIds.value.indexOf(item.id)
|
||||
|
||||
item.checked = checked
|
||||
|
||||
if (index === -1 && checked)
|
||||
selectIds.value.push(item.id)
|
||||
else
|
||||
selectIds.value.splice(index, 1)
|
||||
}
|
||||
|
||||
const showIds = computed(() => {
|
||||
return onList.value.map((item) => {
|
||||
return item.id
|
||||
})
|
||||
})
|
||||
|
||||
watch(
|
||||
() => selectIds.value.length,
|
||||
(newVal, oldVal) => {
|
||||
if (newVal === oldVal)
|
||||
return
|
||||
|
||||
const action = newVal > oldVal ? 'add' : 'remove'
|
||||
const diff = action === 'add' ? difference(selectIds.value, showIds.value) : difference(showIds.value, selectIds.value)
|
||||
|
||||
if (diff.length === 0)
|
||||
return
|
||||
|
||||
if (action === 'add') {
|
||||
for (const item of offList.value) {
|
||||
if (!item.fix && diff.includes(item.id)) {
|
||||
onList.value.push({
|
||||
id: item.id,
|
||||
name: item.name || '未配置',
|
||||
fix: item.fix || false,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const list = onList.value
|
||||
for (let index = 0; index < list.length; index++) {
|
||||
const item = list[index]
|
||||
if (!item.fix && diff.includes(item.id)) {
|
||||
list.splice(index, 1)
|
||||
index--
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
watch(
|
||||
() => showIds.value.length,
|
||||
(newVal, oldVal) => {
|
||||
if (newVal === oldVal)
|
||||
return
|
||||
|
||||
const diff = difference(selectIds.value, showIds.value)
|
||||
|
||||
if (diff.length === 0)
|
||||
return
|
||||
|
||||
for (const item of offList.value) {
|
||||
if (!item.fix && diff.includes(item.id)) {
|
||||
const index = selectIds.value.indexOf(item.id)
|
||||
item.checked = false
|
||||
selectIds.value.splice(index, 1)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
function clearDragSource() {
|
||||
onList.value = onList.value.filter((item) => {
|
||||
return item.fix === true
|
||||
})
|
||||
}
|
||||
|
||||
function removeHandler(id: string) {
|
||||
const index = onList.value.findIndex((item) => {
|
||||
return item.id === id
|
||||
})
|
||||
|
||||
if (index !== -1)
|
||||
onList.value.splice(index, 1)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-modal v-model:show="show" transform-origin="center">
|
||||
<n-card class="cardstyle" :bordered="false" size="huge" role="dialog" aria-modal="true">
|
||||
<div class="wrapper">
|
||||
<span class="wrapper-title">自定义任务包字段</span>
|
||||
<div class="wrapper-bar">
|
||||
<div class="wrapper-info">
|
||||
<span :style="{ 'margin-left': '18px' }">字段信息</span>
|
||||
</div>
|
||||
</div>
|
||||
<n-grid cols="4" class="mt-4 proCard" responsive="screen" :x-gap="24">
|
||||
<n-grid-item span="3">
|
||||
<NCard
|
||||
:title="allCount" class="dragcardStyle" :segmented="{ content: true, footer: true }" size="small"
|
||||
:bordered="false"
|
||||
>
|
||||
<div>
|
||||
<n-input placeholder="搜索关键字">
|
||||
<template #suffix>
|
||||
<SvgIcon size="14px" name="magnifying-1" />
|
||||
</template>
|
||||
</n-input>
|
||||
<div class="draggable-ul">
|
||||
<div class="draggable-li">
|
||||
<n-checkbox v-model:checked="checkAll" label="全部" @update:checked="onCheckAllChange" />
|
||||
</div>
|
||||
<div class="content">
|
||||
<div
|
||||
v-for="item in offList" :key="item.id" style="width: 170px;"
|
||||
:class="{ 'disable-check': item.fix }" class="draggable-li"
|
||||
>
|
||||
<n-checkbox
|
||||
v-model:checked="item.checked" :label="item.name" :disabled="item.fix"
|
||||
@update:checked="onCheckChange($event, item)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</NCard>
|
||||
</n-grid-item>
|
||||
<n-grid-item>
|
||||
<NCard
|
||||
:title="selectCount" class="dragcardStyle" :segmented="{ content: true, footer: true }" size="small"
|
||||
:bordered="false"
|
||||
>
|
||||
<template #header-extra>
|
||||
<span class="textbtnStyle" @click="clearDragSource">清空</span>
|
||||
</template>
|
||||
<div>
|
||||
<n-input placeholder="搜索关键字">
|
||||
<template #suffix>
|
||||
<SvgIcon size="14px" name="magnifying-1" />
|
||||
</template>
|
||||
</n-input>
|
||||
<VueDraggable v-model="onList" class="draggable-ul" :animation="150" group="shared">
|
||||
<div
|
||||
v-for="item in onList" :key="item.id" :class="{ fix: item.fix }"
|
||||
class="cursor-move draggable-item"
|
||||
>
|
||||
<span class="ml-2">{{ item.name }}</span>
|
||||
<SvgIcon
|
||||
v-if="!item.fix" size="16px" style="display: block; margin-left: auto; cursor: pointer"
|
||||
name="clear" @click="removeHandler(item.id)"
|
||||
/>
|
||||
</div>
|
||||
</VueDraggable>
|
||||
</div>
|
||||
</NCard>
|
||||
</n-grid-item>
|
||||
</n-grid>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="wrapper-footer">
|
||||
<n-button type="info" @click="handleSumbit">
|
||||
确认
|
||||
</n-button>
|
||||
<n-button secondary style="margin-left:15px" @click="closeModal">
|
||||
取消
|
||||
</n-button>
|
||||
</div>
|
||||
</template>
|
||||
</n-card>
|
||||
</n-modal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
&-title {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
&-bar {
|
||||
background-color: #e8e8e8;
|
||||
width: 100%;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
&-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
&-info {
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
background-color: #1980ff;
|
||||
content: '';
|
||||
width: 5px;
|
||||
border-radius: 2px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dragcardStyle {
|
||||
--n-padding-bottom: 0px !important;
|
||||
--n-padding-left: 0px !important;
|
||||
}
|
||||
|
||||
.cardstyle {
|
||||
width: 820px;
|
||||
--n-padding-bottom: 20px;
|
||||
--n-padding-left: 24px;
|
||||
}
|
||||
|
||||
.textbtnStyle {
|
||||
cursor: pointer;
|
||||
color: #1980ff;
|
||||
}
|
||||
|
||||
.draggable-ul {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
border: 1px solid #cad2dd;
|
||||
border-top: 0px;
|
||||
border-radius: 2px;
|
||||
display: block;
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.draggable-li {
|
||||
padding: 10px 16px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.draggable-item {
|
||||
padding: 10px 16px;
|
||||
color: #333;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.disable-check {
|
||||
color: gainsboro;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep(.n-card.n-card--content-segmented > .n-card__content:not(:first-child)) {
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
::v-deep(.n-card > .n-card-header) {
|
||||
--n-padding-top: 0px;
|
||||
--n-padding-bottom: 12px;
|
||||
}
|
||||
</style>
|
Loading…
Reference in new issue