图鉴审批样式修复
fix/modifyStyle
zhouxiaoan 1 year ago
parent f59ac652db
commit dae1ebcffd

@ -23,7 +23,7 @@ const adminInfo = {
value: 'task-main', value: 'task-main',
}, },
{ {
label: '图审审批管理', label: '图审审批',
value: 'worksheet-main', value: 'worksheet-main',
}, },
], ],

@ -22,7 +22,7 @@ export async function getPackageList(params: PageParam, packageName: string) {
} }
/** /**
* - * -
* @returns * @returns
*/ */
export async function getPackagePicture(params: PageParam, packagename: string) { export async function getPackagePicture(params: PageParam, packagename: string) {
@ -62,12 +62,11 @@ export async function getPackageTaskList(packageid: string, params: PageParam) {
} }
/** /**
* - * -
* @param checkDuplicateId id * @param checkDuplicateId id
* @returns * @returns
*/ */
export async function getTaskDetailInfo(checkDuplicateId: string) { export async function getTaskDetailInfo(checkDuplicateId: string) {
const res = await http.request({ const res = await http.request({
url: `/ocr/ocrPicture/getPackagePicture?checkDuplicateId=${checkDuplicateId}`, url: `/ocr/ocrPicture/getPackagePicture?checkDuplicateId=${checkDuplicateId}`,
method: 'get', method: 'get',
@ -75,7 +74,18 @@ export async function getTaskDetailInfo(checkDuplicateId: string) {
return res.data return res.data
} }
/**
*
* @param pictureid id xx,xx,xx,xx
* @returns
*/
export async function dubiousfileyd(pictureid: string) {
const res = await http.request({
url: `/ocr/dubiousfile/dubiousfileyd?pictureid=${pictureid}`,
method: 'get',
})
return res.data
}
/** /**
* () * ()
* @param packageid id * @param packageid id
@ -84,7 +94,6 @@ export async function getTaskDetailInfo(checkDuplicateId: string) {
* @returns * @returns
*/ */
export async function getPictureSimilarityList(params: PageParam & PictureSortParam & SimilarityPictureSortParam) { export async function getPictureSimilarityList(params: PageParam & PictureSortParam & SimilarityPictureSortParam) {
const res = await http.request({ const res = await http.request({
url: `/backstage/jifen/ocrtaskchildpicture/getPictureSimilarityList`, url: `/backstage/jifen/ocrtaskchildpicture/getPictureSimilarityList`,
method: 'get', method: 'get',
@ -94,7 +103,7 @@ export async function getPictureSimilarityList(params: PageParam & PictureSortPa
const { data: { records, pages, total } } = res const { data: { records, pages, total } } = res
// 精简一下数据 // 精简一下数据
const list = records.map((item,index) => { const list = records.map((item, index) => {
return { return {
id: item.id, id: item.id,
checkDuplicateId: item.checkDuplicateId, checkDuplicateId: item.checkDuplicateId,
@ -108,9 +117,9 @@ export async function getPictureSimilarityList(params: PageParam & PictureSortPa
iztrueorfalse: item.iztrueorfalse, iztrueorfalse: item.iztrueorfalse,
states: item.states, states: item.states,
history: item.ocpictureid && item.picturecompare && hasHistory(item.ocpictureid, item.picturecompare), history: item.ocpictureid && item.picturecompare && hasHistory(item.ocpictureid, item.picturecompare),
historyStates:item.historyStates, historyStates: item.historyStates,
submitDateTimestamp:item.submitDateTimestamp, submitDateTimestamp: item.submitDateTimestamp,
photoDateTimestamp:item.photoDateTimestamp, photoDateTimestamp: item.photoDateTimestamp,
} }
}) })
return { return {

@ -1,76 +1,80 @@
<template>
<div class="header_wrap">
<div v-for="(item, index) in data" :key="index" class="header_item">
<SvgIcon :name="item.link"/>
<div class="data_wrap">
<div class="data_title" :style="hasColor?`color:${item.color || ''}`:''">{{ item.count }}</div>
<div class="data_content">{{ item.title }}</div>
</div>
</div>
<SvgIcon size="14px" style="cursor: pointer" name="setting" class="settingSvg"></SvgIcon>
</div>
</template>
<script lang="ts" setup> <script lang="ts" setup>
import { defineProps, onMounted } from "vue"; import { defineProps, onMounted } from 'vue'
defineProps({ defineProps({
hasColor: { hasColor: {
type: Boolean, type: Boolean,
default: () => false, default: () => false,
}, },
}); })
const initRem = () => { function initRem() {
const designWidth = 1440; const designWidth = 1440
const rempPx = 16; const rempPx = 16
const scale = window.innerWidth / designWidth; const scale = window.innerWidth / designWidth
document.documentElement.style.fontSize = scale * rempPx + "px"; document.documentElement.style.fontSize = `${scale * rempPx}px`
}; }
onMounted(()=>{ onMounted(() => {
initRem(); initRem()
}) })
const data = [ const data = [
{ {
link: "count", link: 'count',
title: "任务总数", title: '任务总数',
count: 6399, count: 6399,
}, },
{ {
link: "wait", link: 'wait',
title: "待审批", title: '待审批',
count: 6290, count: 6290,
}, },
{ {
link: "done", link: 'done',
title: "已审批", title: '已审批',
count: 109, count: 109,
}, },
{ {
link: "resolve", link: 'resolve',
title: "通过", title: '通过',
count: 3290, count: 3290,
color: "#03c984", color: '#03c984',
}, },
{ {
link: "reject", link: 'reject',
title: "不通过", title: '不通过',
count: 3000, count: 3000,
color: "#ff8b8b", color: '#ff8b8b',
}, },
{ {
link: "reimg", link: 'reimg',
title: "图片重复数", title: '图片重复数',
count: 230, count: 230,
}, },
{ {
link: "breakcount", link: 'breakcount',
title: "小结重复数", title: '小结重复数',
count: 365, count: 365,
}, },
]; ]
</script> </script>
<template>
<div class="header_wrap">
<div v-for="(item, index) in data" :key="index" class="header_item">
<SvgIcon :name="item.link" />
<div class="data_wrap">
<div class="data_title" :style="hasColor ? `color:${item.color || ''}` : ''">
{{ item.count }}
</div>
<div class="data_content">
{{ item.title }}
</div>
</div>
</div>
<SvgIcon size="14px" style="cursor: pointer" name="setting" class="settingSvg" />
</div>
</template>
<style scoped lang="less"> <style scoped lang="less">
.header_wrap { .header_wrap {
display: flex; display: flex;

@ -11,11 +11,11 @@ import { msgPolling } from '@/api/message/message'
import { getImgUrl } from '@/utils/urlUtils' import { getImgUrl } from '@/utils/urlUtils'
import { useUser } from '@/store/modules/user' import { useUser } from '@/store/modules/user'
import { useTaskStore } from '@/store/modules/task' import { useTaskStore } from '@/store/modules/task'
import defaultAvatar from '@/assets/icons/avatar.svg'; import defaultAvatar from '@/assets/icons/avatar.svg'
const taskStore = useTaskStore(); const taskStore = useTaskStore()
export default defineComponent({ export default defineComponent({
name: "PageHeader", name: 'PageHeader',
components: { components: {
UserSettings, UserSettings,
QuillModal, QuillModal,
@ -31,139 +31,140 @@ export default defineComponent({
type: Boolean, type: Boolean,
}, },
}, },
emits: ["update:collapsed"], emits: ['update:collapsed'],
setup() { setup() {
const message = useMessage(); const message = useMessage()
const dialog = useDialog(); const dialog = useDialog()
const userStore = useUser(); const userStore = useUser()
const useInfo = userStore.getUserInfo; const useInfo = userStore.getUserInfo
const name = ""; const name = ''
const state = reactive({ const state = reactive({
username: name ?? "", username: name ?? '',
fullscreenIcon: "FullscreenOutlined", fullscreenIcon: 'FullscreenOutlined',
}); })
const router = useRouter(); const router = useRouter()
const route = useRoute(); const route = useRoute()
const routename = ref(route.meta.title); const routename = ref(route.meta.title)
// mm // mm
const iconList = ref([ const iconList = ref([
{ {
icon: "magnifying-1", icon: 'magnifying-1',
handle: searchHandler, handle: searchHandler,
}, },
{ {
icon: "shortcut-keys", icon: 'shortcut-keys',
handle: shortcutHandler, handle: shortcutHandler,
}, },
{ {
icon: "suspicious-folder", icon: 'suspicious-folder',
handle: recycleHandler, handle: recycleHandler,
}, },
{ {
icon: "memo", icon: 'memo',
handle: quillHandler, handle: quillHandler,
}, },
{ {
icon: "nomessage", icon: 'nomessage',
handle: goMessage, handle: goMessage,
}, },
]); ])
watch( watch(
() => route.fullPath, () => route.fullPath,
() => { () => {
routename.value = route.meta.title; routename.value = route.meta.title
} },
); )
const handleDragOver = (event, item) => { const handleDragOver = (event, item) => {
taskStore.setInFile(true); taskStore.setInFile(true)
}; }
const handleDragLeave = (event, item) => { const handleDragLeave = (event, item) => {
taskStore.setInFile(false); taskStore.setInFile(false)
}; }
const dropdownSelect = (key) => { const dropdownSelect = (key) => {
router.push({ name: key }); router.push({ name: key })
}; }
// 退 // 退
const doLogout = () => { const doLogout = () => {
dialog.info({ dialog.info({
title: "提示", title: '提示',
content: "您确定要退出登录吗", content: '您确定要退出登录吗',
positiveText: "确定", positiveText: '确定',
negativeText: "取消", negativeText: '取消',
onPositiveClick: () => { onPositiveClick: () => {
userStore.logout().then(() => { userStore.logout().then(() => {
message.success("成功退出登录"); message.success('成功退出登录')
router router
.replace({ .replace({
name: "Login", name: 'Login',
query: { query: {
// redirect: route.fullPath, // redirect: route.fullPath,
}, },
}) })
.finally(() => location.reload()); .finally(() => location.reload())
}); })
}, },
onNegativeClick: () => {}, onNegativeClick: () => {},
}); })
}; }
const quillModalRef = ref(null); const quillModalRef = ref(null)
const shortcutModal = ref(null); const shortcutModal = ref(null)
const recycleModalRef = ref(null); const recycleModalRef = ref(null)
const SearchModalRef = ref(null); const SearchModalRef = ref(null)
function quillHandler() { function quillHandler() {
const modal = unref(quillModalRef)! as any; const modal = unref(quillModalRef)! as any
modal.showModal(); modal.showModal()
} }
function shortcutHandler() { function shortcutHandler() {
const modal = unref(shortcutModal)! as any; const modal = unref(shortcutModal)! as any
modal.showModal(); modal.showModal()
} }
function recycleHandler() { function recycleHandler() {
const modal = unref(recycleModalRef)! as any; const modal = unref(recycleModalRef)! as any
modal.showModal(); modal.showModal()
} }
function searchHandler() { function searchHandler() {
const modal = unref(SearchModalRef)! as any; const modal = unref(SearchModalRef)! as any
modal.showModal(); modal.showModal()
} }
function goMessage() { function goMessage() {
router.push({ name: "message-main" }); router.push({ name: 'message-main' })
} }
async function getMessage() { async function getMessage() {
const res = await msgPolling(); const res = await msgPolling()
if (res.data) iconList.value[4].icon = "hasmessage"; if (res.data)
else iconList.value[4].icon = "nomessage"; iconList.value[4].icon = 'hasmessage'
else iconList.value[4].icon = 'nomessage'
} }
setInterval(() => { setInterval(() => {
getMessage(); getMessage()
}, 5000); }, 5000)
const mousetrap = inject("mousetrap") as any; const mousetrap = inject('mousetrap') as any
onMounted(() => { onMounted(() => {
getMessage(); getMessage()
mousetrap.bind("n r", quillHandler); mousetrap.bind('n r', quillHandler)
mousetrap.bind("n t", quillHandler); mousetrap.bind('n t', quillHandler)
mousetrap.bind("n n", recycleHandler); mousetrap.bind('n n', recycleHandler)
mousetrap.bind("m m", searchHandler); mousetrap.bind('m m', searchHandler)
}); })
const defaultAvatarSrc = ref(defaultAvatar); const defaultAvatarSrc = ref(defaultAvatar)
return { return {
...toRefs(state), ...toRefs(state),
@ -187,7 +188,7 @@ export default defineComponent({
defaultAvatarSrc, defaultAvatarSrc,
} }
}, },
}); })
</script> </script>
<template> <template>
@ -228,7 +229,7 @@ export default defineComponent({
<!-- 个人中心 --> <!-- 个人中心 -->
<div class="layout-header-trigger layout-header-trigger-min"> <div class="layout-header-trigger layout-header-trigger-min">
<!-- <n-avatar :src="getImgUrl(useInfo.usericon)" round /> --> <!-- <n-avatar :src="getImgUrl(useInfo.usericon)" round /> -->
<n-avatar :src="(useInfo.usericon && getImgUrl(useInfo.usericon)) || defaultAvatarSrc" round/> <n-avatar :src="(useInfo.usericon && getImgUrl(useInfo.usericon)) || defaultAvatarSrc" round />
</div> </div>
<!-- 设置 --> <!-- 设置 -->
<UserSettings @logout="doLogout" /> <UserSettings @logout="doLogout" />

@ -1,5 +1,5 @@
import { Layout } from '@/router/constant'
import type { RouteRecordRaw } from 'vue-router' import type { RouteRecordRaw } from 'vue-router'
import { Layout } from '@/router/constant'
/** /**
* @param name , , * @param name , ,
@ -19,7 +19,7 @@ const routes: Array<RouteRecordRaw> = [
redirect: '/worksheet', redirect: '/worksheet',
component: Layout, component: Layout,
meta: { meta: {
title: '图审审批管理', title: '图审审批',
permissions: ['worksheet-main'], permissions: ['worksheet-main'],
svgname: 'worksheet', svgname: 'worksheet',
svgsize: 22, svgsize: 22,
@ -30,7 +30,7 @@ const routes: Array<RouteRecordRaw> = [
path: 'worksheet', path: 'worksheet',
name: 'worksheet-main', name: 'worksheet-main',
meta: { meta: {
title: '图审审批管理', title: '图审审批',
}, },
component: () => import('@/views/worksheet/index.vue'), component: () => import('@/views/worksheet/index.vue'),
}, },

@ -124,10 +124,9 @@ export const useUserStore = defineStore({
// 默认设置为第一个租户 // 默认设置为第一个租户
const firstTenant = data.tenantList.length > 0 ? data.tenantList[0] : null const firstTenant = data.tenantList.length > 0 ? data.tenantList[0] : null
const tenantId = firstTenant ? firstTenant.id : '' const tenantId = firstTenant ? firstTenant.id : ''
data.frontmenuTList.forEach(ele=>{ data.frontmenuTList.forEach((ele) => {
if(ele.description === 'AI工单'){ if (ele.description === 'AI工单')
ele.description = '图审审批管理' ele.description = '图审审批'
}
}) })
storage.set(CURRENT_USER, data, ex) storage.set(CURRENT_USER, data, ex)
storage.set(TENANT_ID, tenantId) storage.set(TENANT_ID, tenantId)

File diff suppressed because it is too large Load Diff

@ -32,7 +32,7 @@ const dialog = useDialog()
const svgName = computed(() => { const svgName = computed(() => {
return props.selected ? 'taskpack-select' : 'taskpack' return props.selected ? 'taskpack-select' : 'taskpack'
}) })
const showFull = ref(false)
const popconfirmTarget: any = ref(null) const popconfirmTarget: any = ref(null)
const popconfirmRef: any = ref(null) const popconfirmRef: any = ref(null)
@ -66,7 +66,7 @@ onMounted(async () => {
</script> </script>
<template> <template>
<div ref="popconfirmTarget" class="list-item" :class="{ 'list-item-selected': selected }"> <div ref="popconfirmTarget" class="list-item relative" :class="{ 'list-item-selected': selected, 'h200': showFieldList?.length > 5 && !showFull }">
<div v-for="(item, index) in showFieldList" :key="index"> <div v-for="(item, index) in showFieldList" :key="index">
<div v-if="item.id === 'name'" class="list-item-header"> <div v-if="item.id === 'name'" class="list-item-header">
<div class="id-wrap"> <div class="id-wrap">
@ -129,6 +129,17 @@ onMounted(async () => {
</li> </li>
</ul> </ul>
</div> </div>
<template
v-if="showFieldList?.length > 5"
>
<div class="absolute bottom-0 py-[8px] pl-[36px] item-action">
<span class="cursor-pointer" @click.stop="showFull = !showFull">
<SvgIcon style="margin-left: 6px" name="expand" size="16" />
<SvgIcon style="margin-left: 6px" name="collapse" size="16" />
{{ showFull ? '收起' : '展开' }}
</span>
</div>
</template>
<!-- <div class="list-item-header"> <!-- <div class="list-item-header">
<div style="display: flex;"> <div style="display: flex;">
<SvgIcon :name="svgName" size="28" /> <SvgIcon :name="svgName" size="28" />
@ -151,7 +162,12 @@ onMounted(async () => {
padding: 10px 0px 10px 8px; padding: 10px 0px 10px 8px;
position: relative; position: relative;
border-bottom: 1px solid #e8e8e8; border-bottom: 1px solid #e8e8e8;
// · transition: height: 0.2s ease-out;
// transform: ;
&.h200 {
height: 206px;
overflow: hidden;
}
&-header { &-header {
display: flex; display: flex;
align-items: center; align-items: center;
@ -199,9 +215,16 @@ onMounted(async () => {
color: #507afd !important; color: #507afd !important;
} }
} }
.item-action {
background-color: #fff;
width: calc(100% - 8px);
}
&-selected { &-selected {
background-color: #f2f5fe; background-color: #f2f5fe;
.item-action {
background-color: #f2f5fe;
}
} }
&-detail { &-detail {

@ -1,12 +1,13 @@
<script lang="ts" setup> <script lang="ts" setup>
import { useInfiniteScroll } from '@vueuse/core'
import { useMessage } from 'naive-ui'
import { onMounted, onUnmounted, reactive, ref, watch } from 'vue'
import { throttle } from 'lodash'
import ApprovalModal from '../modal/ApprovalModal.vue'
import { deletePackage } from '@/api/home/main' import { deletePackage } from '@/api/home/main'
import NotPassed from '@/components/NotPassed.vue' import NotPassed from '@/components/NotPassed.vue'
import { useWorkOrder } from '@/store/modules/workOrder' import { useWorkOrder } from '@/store/modules/workOrder'
import { isEmpty } from '@/utils' import { isEmpty } from '@/utils'
import { useInfiniteScroll } from '@vueuse/core'
import { useMessage } from 'naive-ui'
import { reactive, ref, watch } from 'vue'
import ApprovalModal from '../modal/ApprovalModal.vue'
import ListItem from './ListItem.vue' import ListItem from './ListItem.vue'
import type { PackageListItem } from '/#/workorder' import type { PackageListItem } from '/#/workorder'
@ -150,6 +151,50 @@ function ApprovalOver(packageId) {
defineExpose({ defineExpose({
search, search,
}) })
const onKeydown = throttle((event) => {
const eles = ['INPUT', 'TEXTAREA']
if (eles.includes(event.target.tagName))
return
if (event.defaultPrevented)
return //
const handled = false
if (event.key !== undefined) {
// 使 KeyboardEvent.key handled true
}
else if (event.keyCode !== undefined) {
// 使 KeyboardEvent.keyCode handled true
}
if (handled) {
//
event.preventDefault()
}
if (event.key === 'ArrowUp') {
const prev = data.value[workStore.currentIndex - 1]?.id
if (prev)
selectHandler(prev, workStore.currentIndex - 1)
}
if (event.key === 'ArrowDown') {
const next = data.value[workStore.currentIndex + 1]?.id
if (next)
selectHandler(next, workStore.currentIndex + 1)
}
if (event.key === 'ArrowRight' || event.key === 'ArrowLeft') {
if (activeId.value)
activeId.value = ''
else
activeId.value = data.value[workStore.currentIndex]?.checkDuplicateId
}
}, 500)
onMounted(() => {
document.addEventListener('keydown', onKeydown, true)
})
onUnmounted(() => {
document.removeEventListener('keydown', onKeydown)
})
</script> </script>
<template> <template>

@ -28,10 +28,18 @@ const propertys = computed(() => {
任务ID{{ taskDetailInfo.taskname }} 任务ID{{ taskDetailInfo.taskname }}
</n-ellipsis> </n-ellipsis>
<div class="tags"> <div class="tags">
<div class="tag tag-submiting" v-if="taskDetailInfo.historyStates == 1"></div> <div v-if="taskDetailInfo.historyStates == 1" class="tag tag-submiting">
<div class="tag tag-submited" v-else-if="taskDetailInfo.historyStates == 2 || taskDetailInfo.workStatus == 3">已审批</div> 待审批
<div class="tag tag-passed" v-if="taskDetailInfo.historyStates == 2">{{ TASK_STATUS_OBJ[taskDetailInfo.historyStates] }}</div> </div>
<div class="tag tag-not-passed" v-else-if="taskDetailInfo.historyStates == 3">{{ TASK_STATUS_OBJ[taskDetailInfo.historyStates] }}</div> <div v-else-if="taskDetailInfo.historyStates == 2 || taskDetailInfo.workStatus == 3 || taskDetailInfo.historyStates == 3" class="tag tag-submited">
已审批
</div>
<div v-if="taskDetailInfo.historyStates == 2" class="tag tag-passed">
{{ TASK_STATUS_OBJ[taskDetailInfo.historyStates] }}
</div>
<div v-else-if="taskDetailInfo.historyStates == 3" class="tag tag-not-passed">
{{ TASK_STATUS_OBJ[taskDetailInfo.historyStates] }}
</div>
</div> </div>
<n-divider class="divider-line" /> <n-divider class="divider-line" />
<div class="property"> <div class="property">

@ -1,84 +1,88 @@
<script lang="ts" setup> <script lang="ts" setup>
import { audit } from '@/api/task/task'; import { audit } from '@/api/task/task'
import { import {
getPictureSimilarityList, getTaskDetailInfo dubiousfileyd,
} from "@/api/work/work"; getPictureSimilarityList,
import NotPassed from '@/components/Approval/NotPassed.vue'; getTaskDetailInfo,
import { TASK_STATUS_OBJ } from '@/enums/index'; } from '@/api/work/work'
import { useWorkOrder } from "@/store/modules/workOrder"; import NotPassed from '@/components/Approval/NotPassed.vue'
import { isEmpty } from "@/utils"; import { TASK_STATUS_OBJ } from '@/enums/index'
import { formatToDateHMS } from "@/utils/dateUtil"; import { useWorkOrder } from '@/store/modules/workOrder'
import { hideDownload } from "@/utils/image"; import { isEmpty } from '@/utils'
import emitter from '@/utils/mitt'; import { formatToDateHMS } from '@/utils/dateUtil'
import { useInfiniteScroll } from "@vueuse/core"; import { hideDownload } from '@/utils/image'
import { format } from 'date-fns'; import emitter from '@/utils/mitt'
import imagesloaded from "imagesloaded"; import { useInfiniteScroll } from '@vueuse/core'
import { clone, cloneDeep, debounce, pickBy } from "lodash-es"; import { format } from 'date-fns'
import { useDialog, useMessage } from "naive-ui"; import imagesloaded from 'imagesloaded'
import { computed, onUnmounted, onUpdated, reactive, ref, unref, watch } from "vue"; import { clone, cloneDeep, debounce, pickBy } from 'lodash-es'
import PictureInfo from "../components/PictureInfo.vue"; import { useDialog, useMessage } from 'naive-ui'
import ConfrimModal from "../modal/ConfrimModal.vue"; import { computed, onMounted, onUnmounted, onUpdated, reactive, ref, unref, watch } from 'vue'
import type { ApprovalParam, SimilarityPictureSortParam } from "/#/api"; import PictureInfo from '../components/PictureInfo.vue'
import ConfrimModal from '../modal/ConfrimModal.vue'
const batch = ref(false); // import type { ApprovalParam, SimilarityPictureSortParam } from '/#/api'
const selectItems = ref<any[]>([]);
const message = useMessage(); const batch = ref(false) //
const dialog = useDialog(); const selectItems = ref<any[]>([])
const totalCount = ref(0); const message = useMessage()
let _imagesload: any; const dialog = useDialog()
const totalCount = ref(0)
let _imagesload: any
function setBatch(value: boolean) { function setBatch(value: boolean) {
if (value && batch.value) { if (value && batch.value)
batch.value = !value; batch.value = !value
} else { else
batch.value = value; batch.value = value
}
if (value === false) { if (value === false) {
selectItems.value.forEach((item) => (item.checked = false)); selectItems.value.forEach(item => (item.checked = false))
selectItems.value.length = 0; selectItems.value.length = 0
} }
} }
function onCheckChange(checked: any, item: any) { function onCheckChange(checked: any, item: any) {
const index = selectItems.value.indexOf(item); const index = selectItems.value.indexOf(item)
item.checked = checked; item.checked = checked
if (index === -1 && checked) selectItems.value.push(item); if (index === -1 && checked)
else selectItems.value.splice(index, 1); selectItems.value.push(item)
else selectItems.value.splice(index, 1)
} }
const showActions = computed(() => { const showActions = computed(() => {
return selectItems.value.length > 0 && batch; return selectItems.value.length > 0 && batch
}); })
const taskpagination = reactive({ const taskpagination = reactive({
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
}); })
const sortBy: SimilarityPictureSortParam = { const sortBy: SimilarityPictureSortParam = {
orderType: "desc", orderType: 'desc',
orderName: "similarityScore", orderName: 'similarityScore',
}; }
const workStore = useWorkOrder(); const workStore = useWorkOrder()
const selectTask = ref<any>(null); const selectTask = ref<any>(null)
const overTask = ref<any>(null); const overTask = ref<any>(null)
const taskDetailInfo = ref<any>({}); const taskDetailInfo = ref<any>({})
const confrimModalRef = ref(null); const confrimModalRef = ref(null)
const imageRef = ref<ComponentElRef | null>(); const imageRef = ref<ComponentElRef | null>()
const listData = ref<any[]>([]); const listData = ref<any[]>([])
const loading = ref(false); const loading = ref(false)
const el = ref<HTMLDivElement | null>(null); const el = ref<HTMLDivElement | null>(null)
const selectedSortName = ref(''); const selectedSortName = ref('')
const isFullScreen = ref(false); const isFullScreen = ref(false)
const notPassModalRef = ref(null) const notPassModalRef = ref(null)
const mainImageModalRef = ref(null) const mainImageModalRef = ref(null)
const wrapperListRef = ref<HTMLElement | undefined>(undefined)
let canloadMore = true
let canloadMore = true; let processItems: any[] = []
let processItems: any[] = [];
function validate(items: any[]) { function validate(items: any[]) {
if (items.length === 0) return "至少选中一个任务"; if (items.length === 0)
return '至少选中一个任务'
// for (const item of items) { // for (const item of items) {
// const { iztrueorfalse, history, states } = item // const { iztrueorfalse, history, states } = item
@ -92,202 +96,210 @@ function validate(items: any[]) {
// return '' // return ''
// } // }
return null; return null
} }
function forwardHandler() { function forwardHandler() {
workStore.forward(); workStore.forward()
} }
function backHandler() { function backHandler() {
workStore.back(); workStore.back()
} }
function reset() { function reset() {
taskpagination.pageNo = 0; taskpagination.pageNo = 0
taskpagination.pageSize = 20; taskpagination.pageSize = 20
listData.value.length = 0; listData.value.length = 0
loading.value = false; loading.value = false
canloadMore = true; canloadMore = true
} }
async function refreshHandler() { async function refreshHandler() {
reset(); reset()
useInfiniteScroll( useInfiniteScroll(
el as any, el as any,
() => { () => {
loadMore(); loadMore()
}, },
{ distance: 10, canLoadMore: () => canloadMore } { distance: 10, canLoadMore: () => canloadMore },
); )
} }
async function loadMore() { async function loadMore() {
if (loading.value || el.value == null) return; if (loading.value || el.value == null)
return
const more = await featchList(); const more = await featchList()
listData.value.push(...more); listData.value.push(...more)
} }
async function featchList() { async function featchList() {
loading.value = true
loading.value = true;
try { try {
taskpagination.pageNo += 1; taskpagination.pageNo += 1
const { data, total, pageCount } = await getPictureSimilarityList( const { data, total, pageCount } = await getPictureSimilarityList(
{ ...taskpagination, ...sortBy, checkDuplicateId: workStore.activeId, pictureId: taskDetailInfo.value.id } { ...taskpagination, ...sortBy, checkDuplicateId: workStore.activeId, pictureId: taskDetailInfo.value.id },
); )
totalCount.value = total; totalCount.value = total
canloadMore = pageCount >= taskpagination.pageNo && pageCount > 0; canloadMore = pageCount >= taskpagination.pageNo && pageCount > 0
return data; return data
} catch (error) { }
canloadMore = false; catch (error) {
return []; canloadMore = false
return []
} }
} }
const layout = debounce(() => { const layout = debounce(() => {
if (el.value == null) return; if (el.value == null)
return
_imagesload = imagesloaded(".grid-item");
_imagesload.on("done", (instance) => { _imagesload = imagesloaded('.grid-item')
if (!el.value) return;
loading.value = false;
});
_imagesload.on("fail", (instance) => { _imagesload.on('done', (instance) => {
message.error("图片错误"); if (!el.value)
loading.value = false; return
}); loading.value = false
}, 300); })
_imagesload.on('fail', (instance) => {
message.error('图片错误')
loading.value = false
})
}, 300)
const fullscreenStyles = computed<any>(() => ({ const fullscreenStyles = computed<any>(() => ({
'width': isFullScreen.value ? '100vw' : '', width: isFullScreen.value ? '100vw' : '',
'height': isFullScreen.value ? '100vh' : '', height: isFullScreen.value ? '100vh' : '',
'position': isFullScreen.value ? 'fixed' : '', position: isFullScreen.value ? 'fixed' : '',
'top': isFullScreen.value ? '0' : '', top: isFullScreen.value ? '0' : '',
'left': isFullScreen.value ? '0' : '', left: isFullScreen.value ? '0' : '',
'zIndex': isFullScreen.value ? '100' : '', zIndex: isFullScreen.value ? '100' : '',
})); }))
// //
const toggleFullScreen = () => { function toggleFullScreen() {
isFullScreen.value = !isFullScreen.value; isFullScreen.value = !isFullScreen.value
}; }
onUpdated(() => { onUpdated(() => {
layout(); layout()
}); })
watch( watch(
() => workStore.activeId, () => workStore.activeId,
async (newValue, oldValue) => { async (newValue, oldValue) => {
const packageid = workStore.getActiveId; const packageid = workStore.getActiveId
if (isEmpty(packageid)) { if (isEmpty(packageid)) {
listData.value.length = 0; listData.value.length = 0
totalCount.value = 0; totalCount.value = 0
taskDetailInfo.value = {} taskDetailInfo.value = {}
return; return
} }
queryDetail(packageid) queryDetail(packageid)
// const res = await getPackageTaskList(newValue, packagepagination); // const res = await getPackageTaskList(newValue, packagepagination);
// const { data } = res; // const { data } = res;
// taskList.value = data; // taskList.value = data;
// if (taskList.value.length > 0) handleSelect(taskList.value[0]); // // if (taskList.value.length > 0) handleSelect(taskList.value[0]); //
} },
); )
const packageName = computed(() => { const packageName = computed(() => {
const index = workStore.getCurrentIndex; const index = workStore.getCurrentIndex
return workStore.getOrderList[index]?.name || ""; return workStore.getOrderList[index]?.name || ''
}); })
async function queryDetail(checkDuplicateId: any) { async function queryDetail(checkDuplicateId: any) {
taskDetailInfo.value = await getTaskDetailInfo(checkDuplicateId); taskDetailInfo.value = await getTaskDetailInfo(checkDuplicateId)
const packageid = workStore.getActiveId; const packageid = workStore.getActiveId
if (isEmpty(packageid)) { if (isEmpty(packageid)) {
listData.value.length = 0; listData.value.length = 0
totalCount.value = 0; totalCount.value = 0
return; return
} }
refreshHandler(); refreshHandler()
} }
// //
async function handleSelect(item: any) { async function handleSelect(item: any) {
// taskDetailInfo.value = await getTaskDetailInfo(item.id) // taskDetailInfo.value = await getTaskDetailInfo(item.id)
const packageid = workStore.getActiveId; const packageid = workStore.getActiveId
if (isEmpty(packageid)) { if (isEmpty(packageid)) {
listData.value.length = 0; listData.value.length = 0
totalCount.value = 0; totalCount.value = 0
return;
} }
// refreshHandler(); // refreshHandler();
} }
async function sortHandler(orderby: "similarityScore" | "createdate") { async function sortHandler(orderby: 'similarityScore' | 'createdate') {
selectedSortName.value = orderby; selectedSortName.value = orderby
sortBy.orderName = orderby; sortBy.orderName = orderby
sortBy.orderType = sortBy.orderType === "asc" ? "desc" : "asc"; sortBy.orderType = sortBy.orderType === 'asc' ? 'desc' : 'asc'
refreshHandler(); refreshHandler()
} }
const propertys = computed(() => { const propertys = computed(() => {
const { ocrPicture } = taskDetailInfo.value; const { ocrPicture } = taskDetailInfo.value
const v = pickBy(ocrPicture, (value, key: string) => { const v = pickBy(ocrPicture, (value, key: string) => {
return key.startsWith("field") && value !== null; return key.startsWith('field') && value !== null
}); })
return v; return v
}); })
function overTaskHandelr(item: any) { function overTaskHandelr(item: any) {
if (item?.historyStates === 2 || item?.historyStates == 3) { if (item?.historyStates === 2 || item?.historyStates == 3) {
overTask.value = null; overTask.value = null
return; return
} }
if (validate([item]) == null && batch.value === false) overTask.value = item; if (validate([item]) == null && batch.value === false)
overTask.value = item
} }
function leaveTaskHandler() { function leaveTaskHandler() {
overTask.value = null; overTask.value = null
}
function onEsc() {
if (isFullScreen.value && !(document.querySelector('.n-modal-container')))
isFullScreen.value = false
} }
onUnmounted(() => { onUnmounted(() => {
workStore.reset(); workStore.reset()
}); document.removeEventListener('keydown', onEsc)
})
onMounted(() => {
document.addEventListener('keydown', onEsc)
})
function immersionHandler() { function immersionHandler() {
// class="wrapper" // class="wrapper"
// workStore.updateImmersion(); // workStore.updateImmersion();
toggleFullScreen();
toggleFullScreen()
} }
function showAction() { function showAction() {
const item = taskDetailInfo.value; const item = taskDetailInfo.value
if (item.historyStates === 2 || item.historyStates === 3) { if (item.historyStates === 2 || item.historyStates === 3)
return return
}
if (batch.value === false) overTask.value = item; if (batch.value === false)
overTask.value = item
} }
function hideAction() { function hideAction() {
overTask.value = null; overTask.value = null
} }
function previewHandler(event: MouseEvent) { function previewHandler(event: MouseEvent) {
event.stopImmediatePropagation(); event.stopImmediatePropagation()
event.stopPropagation(); event.stopPropagation()
if (imageRef.value && (imageRef.value as any).src) if (imageRef.value && (imageRef.value as any).src)
(imageRef.value as any).mergedOnClick(); (imageRef.value as any).mergedOnClick()
} }
function rejectHandler() { function rejectHandler() {
const modal = unref(notPassModalRef)! as any const modal = unref(notPassModalRef)! as any
@ -319,9 +331,9 @@ function handleRejectMainImage() {
params.id = params.taskchildpictureid params.id = params.taskchildpictureid
modal.showModal([params]) modal.showModal([params])
} }
async function reloadDetailInfo(){ async function reloadDetailInfo() {
const packageid = workStore.getActiveId; const packageid = workStore.getActiveId
taskDetailInfo.value = await getTaskDetailInfo(packageid); taskDetailInfo.value = await getTaskDetailInfo(packageid)
} }
function handleApproveMainImage(items?: any) { function handleApproveMainImage(items?: any) {
let cloneItem: any let cloneItem: any
@ -361,14 +373,14 @@ function handleApproveMainImage(items?: any) {
positiveText: '确定', positiveText: '确定',
negativeText: '取消', negativeText: '取消',
onPositiveClick: () => { onPositiveClick: () => {
audit(param).then(async(res) => { audit(param).then(async (res) => {
const { code } = res const { code } = res
if (code === 'OK') { if (code === 'OK') {
message.info(res.message) message.info(res.message)
const packageid = workStore.getActiveId; const packageid = workStore.getActiveId
taskDetailInfo.value = await getTaskDetailInfo(packageid); taskDetailInfo.value = await getTaskDetailInfo(packageid)
} }
else message.error(res.message) else { message.error(res.message) }
}) })
}, },
onNegativeClick: () => { }, onNegativeClick: () => { },
@ -434,7 +446,7 @@ function doAudit(param: any) {
emitter.emit('refresh') emitter.emit('refresh')
refreshHandler() refreshHandler()
} }
else message.error(res.message) else { message.error(res.message) }
}) })
} }
@ -442,8 +454,28 @@ function reloadList() {
setBatch(false) setBatch(false)
refreshHandler() refreshHandler()
} }
function handleRejectdubiousfileyd() {
dialog.info({
title: '确认提示',
content: '确认将图片移入可疑文件夹吗?',
positiveText: '确定',
negativeText: '取消',
onPositiveClick: () => {
audit(param).then(async (res) => {
const { code } = res
if (code === 'OK') {
dubiousfileyd(taskDetailInfo.value.pictureId).then(() => {
refreshHandler()
})
}
else { message.error(res.message) }
})
},
onNegativeClick: () => { },
})
}
defineExpose({ defineExpose({
queryDetail queryDetail,
}) })
</script> </script>
@ -462,8 +494,8 @@ defineExpose({
批量审批 批量审批
</div> </div>
<div class="icon-wrap"> <div class="icon-wrap">
<SvgIcon size="20" v-if="isFullScreen" name="power-off" @click="immersionHandler" style="cursor: pointer;" /> <SvgIcon v-if="isFullScreen" size="20" name="power-off" style="cursor: pointer;" @click="immersionHandler" />
<SvgIcon size="20" v-else name="immersion-model" @click="immersionHandler" style="cursor: pointer;" /> <SvgIcon v-else size="20" name="immersion-model" style="cursor: pointer;" @click="immersionHandler" />
</div> </div>
</div> </div>
@ -489,8 +521,10 @@ defineExpose({
<div ref="el" class="scroll"> <div ref="el" class="scroll">
<div class="wrapper-detail"> <div class="wrapper-detail">
<!-- 左侧大图 图片信息 --> <!-- 左侧大图 图片信息 -->
<div class="left" :style="{ 'background-image': `url(${taskDetailInfo?.imgurl})` }" @click="showAction" <div
@mouseleave="leaveTaskHandler"> class="left" :style="{ 'background-image': `url(${taskDetailInfo?.serverThumbnailUrl || taskDetailInfo?.imgurl})` }" @click="showAction"
@mouseleave="leaveTaskHandler"
>
<div class="footer-times"> <div class="footer-times">
<div class="time" style="margin-bottom: 4px;"> <div class="time" style="margin-bottom: 4px;">
<SvgIcon color="#FFF" size="16" name="camera" /> <SvgIcon color="#FFF" size="16" name="camera" />
@ -501,16 +535,19 @@ defineExpose({
<SvgIcon color="#FFF" size="16" name="save" /> <SvgIcon color="#FFF" size="16" name="save" />
<span class="time-value">{{ <span class="time-value">{{
taskDetailInfo?.submitDateTimestamp ? format(taskDetailInfo?.submitDateTimestamp, 'yyyy-MM-dd HH:mm:ss') taskDetailInfo?.submitDateTimestamp ? format(taskDetailInfo?.submitDateTimestamp, 'yyyy-MM-dd HH:mm:ss')
: : '-'
'-'
}} </span> }} </span>
</div> </div>
</div> </div>
<div class="status"> <div class="status">
<img v-show="taskDetailInfo?.historyStates === 2" class="img-status" src="@/assets/images/task/pass.png" <img
alt=""> v-show="taskDetailInfo?.historyStates === 2" class="img-status" src="@/assets/images/task/pass.png"
<img v-show="taskDetailInfo?.historyStates === 3" class="img-status" src="@/assets/images/task/not_pass.png" alt=""
alt=""> >
<img
v-show="taskDetailInfo?.historyStates === 3" class="img-status" src="@/assets/images/task/not_pass.png"
alt=""
>
</div> </div>
<!-- 右下信息 --> <!-- 右下信息 -->
<div class="info img-info"> <div class="info img-info">
@ -547,41 +584,47 @@ defineExpose({
</div> </div>
<!-- 操作 --> <!-- 操作 -->
<div v-show="overTask && overTask.id === taskDetailInfo.id" class="action" @click.stop="hideAction"> <div v-show="overTask && overTask.id === taskDetailInfo.id" class="action" @click.stop="hideAction">
<SvgIcon style="cursor: pointer" name="t1" @click.stop="handleApproveMainImage" /> <SvgIcon v-if="[1].includes(taskDetailInfo.historyStates)" style="cursor: pointer" name="t1" @click.stop="handleApproveMainImage" />
<SvgIcon style="cursor: pointer; margin-left: 30px" name="t2" @click.stop="handleRejectMainImage" /> <SvgIcon v-if="[1].includes(taskDetailInfo.historyStates)" style="cursor: pointer; margin-left: 30px" name="t2" @click.stop="handleRejectMainImage" />
<SvgIcon v-if="[1, 2, 3].includes(taskDetailInfo.historyStates)" style="cursor: pointer; margin-left: 30px" name="t2" @click.stop="handleRejectdubiousfileyd" />
</div> </div>
</div> </div>
<PictureInfo :taskDetailInfo="taskDetailInfo"></PictureInfo> <PictureInfo :task-detail-info="taskDetailInfo" />
</div> </div>
<div style="display: flex; justify-content: space-between; padding: 12px 0px 3px 0"> <div style="display: flex; justify-content: space-between; padding: 12px 0px 3px 0">
<div> <div>
<span <span
style="font-size: 18px; font-weight: Medium;color: #333333;font-family: PingFang SC, PingFang SC-Medium;">任务包图片</span> style="font-size: 18px; font-weight: Medium;color: #333333;font-family: PingFang SC, PingFang SC-Medium;"
>任务包图片</span>
</div> </div>
<div style="display: flex; align-items: center;font-size: 14px;margin-right: 25px;color:#323233"> <div style="display: flex; align-items: center;font-size: 14px;margin-right: 25px;color:#323233">
<div style="cursor: pointer" @click="sortHandler('createdate')"> <div style="cursor: pointer" @click="sortHandler('createdate')">
<span>时间排序</span> <span>时间排序</span>
<SvgIcon style="margin-left: 5px" name="sort" size="12" v-show="selectedSortName !== 'createdate'" /> <SvgIcon v-show="selectedSortName !== 'createdate'" style="margin-left: 5px" name="sort" size="12" />
<SvgIcon style="margin-left: 5px" name="active-sort" size="12" v-show="selectedSortName === 'createdate'" /> <SvgIcon v-show="selectedSortName === 'createdate'" style="margin-left: 5px" name="active-sort" size="12" />
</div> </div>
<div style="margin-left: 15px; cursor: pointer" @click="sortHandler('similarityScore')"> <div style="margin-left: 15px; cursor: pointer" @click="sortHandler('similarityScore')">
<span>相似度排序</span> <span>相似度排序</span>
<SvgIcon style="margin-left: 5px" name="sort" size="12" v-show="selectedSortName !== 'similarityScore'" /> <SvgIcon v-show="selectedSortName !== 'similarityScore'" style="margin-left: 5px" name="sort" size="12" />
<SvgIcon style="margin-left: 5px" name="active-sort" size="12" <SvgIcon
v-show="selectedSortName === 'similarityScore'" /> v-show="selectedSortName === 'similarityScore'" style="margin-left: 5px" name="active-sort"
size="12"
/>
</div> </div>
</div> </div>
</div> </div>
<div class="wrapper-list"> <div ref="wrapperListRef" class="wrapper-list">
<div v-for="(item, index) in listData" :key="index" :class="{ 'item-selected': item === selectTask }" <div
v-for="(item, index) in listData" :key="index" :class="{ 'item-selected': item === selectTask }"
class="grid-item" @click="handleSelect(item)" @mouseover="overTaskHandelr(item)" class="grid-item" @click="handleSelect(item)" @mouseover="overTaskHandelr(item)"
@mouseleave="leaveTaskHandler"> @mouseleave="leaveTaskHandler"
>
<div class="img-wrapper" :style="{ 'background-image': `url(${item.imgurl})` }" /> <div class="img-wrapper" :style="{ 'background-image': `url(${item.imgurl})` }" />
<div class="time-wrapper"> <div class="time-wrapper">
<div class="time"> <div class="time">
<SvgIcon color="#FFF" size="16" name="camera" /> <SvgIcon color="#FFF" size="16" name="camera" />
<span class="current-time">{{ item.photoDateTimestamp ? formatToDateHMS(Number(item.photoDateTimestamp) || <span class="current-time">{{ item.photoDateTimestamp ? formatToDateHMS(Number(item.photoDateTimestamp)
0) : '-' || 0) : '-'
}}</span> }}</span>
</div> </div>
<div class="time"> <div class="time">
@ -592,8 +635,10 @@ defineExpose({
</div> </div>
</div> </div>
<div class="check"> <div class="check">
<n-checkbox v-show="batch && item.historyStates !== 2 && item.historyStates !== 3" <n-checkbox
v-model:checked="item.checked" @click.stop @update:checked="onCheckChange($event, item)" /> v-show="batch && item.historyStates !== 2 && item.historyStates !== 3"
v-model:checked="item.checked" @click.stop @update:checked="onCheckChange($event, item)"
/>
</div> </div>
<div class="percent" :class="{ 'percent-red': item?.maxSimilarity >= 100 }"> <div class="percent" :class="{ 'percent-red': item?.maxSimilarity >= 100 }">
<div class="val"> <div class="val">
@ -601,10 +646,10 @@ defineExpose({
</div> </div>
</div> </div>
<div class="pass-status" v-if="item.historyStates === 2"> <div v-if="item.historyStates === 2" class="pass-status">
<SvgIcon name="pass-icon" style="width:52;height:24px" /> <SvgIcon name="pass-icon" style="width:52;height:24px" />
</div> </div>
<div class="pass-status" v-else-if="item.historyStates === 3"> <div v-else-if="item.historyStates === 3" class="pass-status">
<SvgIcon name="no-pass-icon" style="width:52;height:24px" /> <SvgIcon name="no-pass-icon" style="width:52;height:24px" />
</div> </div>
<div v-show="overTask && overTask.id === item.id" class="action"> <div v-show="overTask && overTask.id === item.id" class="action">
@ -612,6 +657,19 @@ defineExpose({
<SvgIcon style="cursor: pointer;margin-left: 40px;" name="t2" @click.stop="singleRejectHandler(item)" /> <SvgIcon style="cursor: pointer;margin-left: 40px;" name="t2" @click.stop="singleRejectHandler(item)" />
</div> </div>
</div> </div>
<n-back-top :listen-to="wrapperListRef" :bottom="220" :visibility-height="10">
<div
style="
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 14px;
"
>
回到顶部
</div>
</n-back-top>
</div> </div>
</div> </div>
</n-spin> </n-spin>
@ -885,7 +943,6 @@ defineExpose({
padding: 24px; padding: 24px;
// background: lime; // background: lime;
.task-name { .task-name {
display: inline-block; display: inline-block;
width: 100%; width: 100%;
@ -1077,7 +1134,6 @@ defineExpose({
} }
} }
.action { .action {
position: absolute; position: absolute;
z-index: 5; z-index: 5;
@ -1092,7 +1148,6 @@ defineExpose({
background-color: rgba(0, 0, 0, 0.48); background-color: rgba(0, 0, 0, 0.48);
} }
} }
} }
} }

Loading…
Cancel
Save