刘释隆 2 years ago
commit a2ff6c65dd

2
components.d.ts vendored

@ -17,7 +17,6 @@ declare module 'vue' {
NCollapse: typeof import('naive-ui')['NCollapse']
NCollapseItem: typeof import('naive-ui')['NCollapseItem']
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
NDataTable: typeof import('naive-ui')['NDataTable']
NDatePicker: typeof import('naive-ui')['NDatePicker']
NDialogProvider: typeof import('naive-ui')['NDialogProvider']
NDivider: typeof import('naive-ui')['NDivider']
@ -28,7 +27,6 @@ declare module 'vue' {
NGi: typeof import('naive-ui')['NGi']
NGrid: typeof import('naive-ui')['NGrid']
NGridItem: typeof import('naive-ui')['NGridItem']
NIcon: typeof import('naive-ui')['NIcon']
NImage: typeof import('naive-ui')['NImage']
NInput: typeof import('naive-ui')['NInput']
NMessageProvider: typeof import('naive-ui')['NMessageProvider']

@ -1,9 +1,9 @@
import { pickBy } from 'lodash-es'
import { http } from '@/utils/http/axios'
import type { CheckParam, PageParam, QueryPictureParam, UploadParam } from '/#/api'
import { ContentTypeEnum } from '@/enums/httpEnum'
import { notEmpty } from '@/utils'
import { formatToDate2 } from '@/utils/dateUtil'
import { http } from '@/utils/http/axios'
import { pickBy } from 'lodash-es'
import type { CheckParam, PageParam, QueryPictureParam, UploadParam } from '/#/api'
/**
*
@ -103,6 +103,104 @@ export async function oneClickCheck(params: Partial<CheckParam> = { search_histo
})
}
/**
*
* @param note
* @returns
*/
export async function oneClickCheckTaskPackage(params: Partial<CheckParam> = { search_history: '0' }) {
const notEmptyParams = pickBy(params, notEmpty)
Object.keys(notEmptyParams).forEach((key) => {
const val = notEmptyParams[key]
if (Array.isArray(val))
notEmptyParams[key] = val.join(',')
})
return http.request({
url: `/ocr/checkDuplicate/openCheckDuplicate`,
method: 'get',
params: notEmptyParams,
headers: { 'Content-Type': ContentTypeEnum.FORM_DATA },
})
}
/**
*
* @param note
* @returns
*/
export async function getLastCheckNo() {
return http.request({
url: `/ocr/checkDuplicate/getLastCheckNo`,
method: 'get',
headers: { 'Content-Type': ContentTypeEnum.FORM_DATA },
})
}
/**
*
* @param note
* @returns
*/
export async function getCheckDuplicateStatus(checkDuplicateNo) {
return http.request({
url: `/ocr/checkDuplicate/getCheckDuplicateStatus`,
method: 'get',
params: { checkDuplicateNo },
headers: { 'Content-Type': ContentTypeEnum.FORM_DATA },
})
}
/**
*
* @param
* @returns
*/
export async function createPackage(params) {
return http.request({
url: `/ocr/ocrTaskPackage/createPackage`,
method: 'post',
params
})
}
/**
*
* @param
* @returns
*/
export async function queryPageListByCheckNo(params: any): Promise<any> {
const notEmptyParams = pickBy(params, notEmpty)
Object.keys(notEmptyParams).forEach((key) => {
const val = notEmptyParams[key]
if (key === 'izyear') {
const start = formatToDate2(val[0])
const end = formatToDate2(val[1])
notEmptyParams[key] = `${start}-${end}`
}
if (Array.isArray(notEmptyParams[key]))
notEmptyParams[key] = val.join(',')
})
const res = await http.request({
url: `/ocr/checkDuplicate/queryPageListByCheckNo`,
method: 'get',
params: notEmptyParams,
headers: { 'Content-Type': ContentTypeEnum.FORM_DATA },
})
const { data: { records, pages, total } } = res
return {
pageCount: pages,
data: records,
total,
}
}
/**
*
* @param params

@ -1,5 +1,5 @@
<script lang="ts" setup>
import { getPictureList, oneClickCheck } from '@/api/home/main'
import { createPackage, getCheckDuplicateStatus, getLastCheckNo, getPictureList, oneClickCheckTaskPackage, queryPageListByCheckNo } from '@/api/home/main'
import avatar from '@/assets/images/avatar.jpg'
import { timeOptions, viewOptions } from '@/config/home'
import { useWindowSizeFn } from '@/hooks/event/useWindowSizeFn'
@ -9,14 +9,17 @@ import { hideDownload } from '@/utils/image'
import emitter from '@/utils/mitt'
import { getImgUrl } from '@/utils/urlUtils'
import { useInfiniteScroll } from '@vueuse/core'
import dayjs from 'dayjs'
import imagesloaded from 'imagesloaded'
import { debounce } from 'lodash-es'
import { cloneDeep, debounce } from 'lodash-es'
import Masonry from 'masonry-layout'
import { useMessage } from 'naive-ui'
import { computed, nextTick, onMounted, onUnmounted, onUpdated, reactive, ref, unref, watch } from 'vue'
import FinishPackageModal from './modal/FinishPackageModal.vue'
import GeneratePackageModal from './modal/GeneratePackageModal.vue'
import LoginSuccessModal from './modal/LoginSuccessModal.vue'
import PackageSettingsModal from './modal/PackageSettingsModal.vue'
import QueryRepeatedTasksModal from './modal/QueryRepeatedTasksModal.vue'
import type { PictureSortParam } from "/#/api"
const deviceHeight = ref(600)
@ -32,7 +35,9 @@ const pagination = reactive({
const configStore = useConfig()
const packageModalRef = ref(null)
const generateModalRef = ref(null)
const queryRepeatedTasksModalRef = ref(null)
const LoginSuccessModalRef = ref(null)
const finishPackageModal = ref(null)
const loading = ref(false)
const message = useMessage()
const totalCount = ref(0)
@ -41,6 +46,10 @@ const sortBy: PictureSortParam = {
orderbyvalue: "pictureResult",
};
const imageRef = ref<ComponentElRef | null>()
const checkDuplicateNo = ref('')
const checkTaskStatus = ref(null) // 1. 2. 3.
const isRefresh = ref(true) //
let canloadMore = true
let filterId = null
@ -132,7 +141,16 @@ async function featchList() {
const asideParams = unref(configStore.getAsideValue)
const params = filterId ? { userSearchId: filterId } : asideParams
const result = await getPictureList({ ...pagination, ...contentParams, ...params, ...sortBy })
let result = {
pageCount: 0,
data: [],
total: 0,
}
if (checkTaskStatus.value === 2 && isRefresh) {
result = await queryPageListByCheckNo({ ...pagination, ...contentParams, ...params, ...sortBy, checkDuplicateNo: checkDuplicateNo.value })
} else {
result = await getPictureList({ ...pagination, ...contentParams, ...params, ...sortBy })
}
const { data, pageCount, total } = result
totalCount.value = total
canloadMore = pageCount >= pagination.pageNo && pageCount > 0
@ -180,8 +198,41 @@ const gridHeight = computed(() => {
})
async function oneCheck() {
const modal = packageModalRef.value as any
modal.showModal()
const asideVal = cloneDeep(configStore.getAsideValue)
asideVal.izyear = dayjs(asideVal.izyear[0]).format("YYYY/MM/DD") + '-' + dayjs(asideVal.izyear[1]).format("YYYY/MM/DD")
const tasksLoadingModal = queryRepeatedTasksModalRef.value as any
delete asideVal.izsimilarity
if (checkDuplicateNo.value) {
getCheckDuplicateStatus(checkDuplicateNo.value).then((res) => {
if (res.code === "OK") {
checkTaskStatus.value = res.data.status // 1. 2.
if (isRefresh.value === false) {
const modal = packageModalRef.value as any
modal.showModal()
return
}
if (checkTaskStatus.value === 2 && isRefresh) {
isRefresh.value = false
message.success('任务执行完毕,正在刷新数据...');
reset()
loadMore()
} else if (checkTaskStatus.value === 1) {
tasksLoadingModal.showModal()
return
}
}
})
return
}
tasksLoadingModal.showModal()
oneClickCheckTaskPackage(asideVal).then((res) => {
if (res.code === "OK") {
checkDuplicateNo.value = res.data.checkDuplicateNo
} else {
message.error(res.message || '查重失败')
}
})
}
async function showLoginSuccessModal() {
@ -190,28 +241,35 @@ async function showLoginSuccessModal() {
}
async function commitHandler(settingParam) {
const contentParams = {
search_month: timeRange.value,
const params = {
name: settingParam.packagename,
checkDuplicateNo: checkDuplicateNo.value
}
const modal = generateModalRef.value as any
const finishModal = finishPackageModal.value as any
modal.showModal()
createPackage(params).then((res) => {
if (res.code === "OK") {
message.success(res.data);
modal.closeModal()
finishModal.showModal()
}
})
const asideVal = configStore.getAsideValue
const finalParam = { ...contentParams, ...asideVal }
const finalParam = { ...asideVal }
finalParam.buessinessno = settingParam.packagename
finalParam.search_history = settingParam.comparehistory ? 1 : 0
const modal = generateModalRef.value as any
modal.showModal()
oneClickCheck(finalParam).then(() => {
modal.closeModal()
}, () => {
modal.closeModal()
})
}
onMounted(() => {
emitter.on('filter', refreshHandler)
//
getLastCheckNo().then((res) => {
if (res.code === "OK") {
checkDuplicateNo.value = res.data
}
})
nextTick(() => {
computeListHeight()
//
@ -310,7 +368,7 @@ async function downloadImage(item) {
}
}
function previewHandler(index: number,event: MouseEvent) {
function previewHandler(index: number, event: MouseEvent) {
event.stopImmediatePropagation();
event.stopPropagation();
if (imageRef.value?.[index] && (imageRef.value[index] as any).src)
@ -325,7 +383,11 @@ function previewHandler(index: number,event: MouseEvent) {
<SvgIcon size="32" name="magnifying" />
<span class="font">AI一键查重</span>
</div>
<SvgIcon style="cursor: pointer;" size="105" name="yijianchachong" @click="oneCheck" />
<SvgIcon v-show="checkTaskStatus !== 2" style="cursor: pointer;" size="105" name="yijianchachong"
@click="oneCheck" />
<div v-show="checkTaskStatus === 2" style="cursor: pointer;" size="105" name="magnifying" @click="oneCheck">
生成任务包
</div>
</div>
<div class="wrapper-content">
<div style="display: flex;justify-content: space-between;">
@ -352,7 +414,8 @@ function previewHandler(index: number,event: MouseEvent) {
<SvgIcon style="margin-left: 8px;" name="sort" size="12" />
</div>
</div>
<span style="font-size: 16px;color:#494949"> <span style="color:#7899fd;font-weight: 500;">{{ totalCount }}</span> </span>
<span style="font-size: 16px;color:#494949"> <span style="color:#7899fd;font-weight: 500;">{{ totalCount
}}</span> </span>
</div>
<n-spin :show="loading">
<div ref="el" class="scroll" :style="listStyle">
@ -402,7 +465,9 @@ function previewHandler(index: number,event: MouseEvent) {
</div>
<PackageSettingsModal ref="packageModalRef" @commit="commitHandler" />
<GeneratePackageModal ref="generateModalRef" />
<QueryRepeatedTasksModal ref="queryRepeatedTasksModalRef" />
<LoginSuccessModal ref="LoginSuccessModalRef" />
<FinishPackageModal ref="finishPackageModal" />
</div>
</template>
@ -508,7 +573,7 @@ function previewHandler(index: number,event: MouseEvent) {
flex-direction: row;
align-items: center;
margin-right: 24px;
color:#323233;
color: #323233;
.gap {
margin-left: 5px;
@ -546,6 +611,7 @@ function previewHandler(index: number,event: MouseEvent) {
padding: 0 10px;
background: rgba(0, 0, 0, .35);
border-radius: 7px;
.img-name {
width: 70%;
color: #FFF;

@ -0,0 +1,81 @@
<script lang="ts" setup>
import { defineOptions, ref } from 'vue';
import { useRouter } from 'vue-router';
defineOptions({ name: 'ShortcutModal' })
const show = ref(false)
const router = useRouter()
const cardStyle = {
'width': '29vw',
'--n-padding-bottom': '10px',
'--n-padding-left': '10px',
}
function showModal() {
show.value = true
}
function closeModal(path) {
show.value = false
router.push(path)
}
defineExpose({
showModal,
})
</script>
<template>
<div>
<n-modal v-model:show="show" transform-origin="center" style="padding: 8px;">
<n-card :style="cardStyle" :bordered="false" size="huge" role="dialog" aria-modal="true">
<div style="display: flex;">
<div><svg-icon size="80" name="robot2" /></div>
<div style="height: 130px;text-align: center;margin-left: 20px;">
<div class="msg-title">生成任务提示</div>
<div class="msg-text">AI已根据您的配置要求生成任务包</div>
</div>
</div>
<template #footer>
<div class="wrapper-footer">
<n-button type="info" @click="closeModal('/worksheet')">
进入AI工单
</n-button>
<n-button style="margin-left:10px;color: #666666;" @click="closeModal('/task')">
进入任务审批
</n-button>
</div>
</template>
</n-card>
</n-modal>
</div>
</template>
<style lang="less" scoped>
.wrapper-footer {
margin-top: -20px;
text-align: right;
}
.msg-title {
font-size: 16px;
font-family: PingFang SC, PingFang SC-Medium;
font-weight: Medium;
text-align: left;
color: #333333;
line-height: 24px;
margin: 12px 0;
}
.msg-text {
font-size: 14px;
font-family: PingFang SC, PingFang SC-Regular;
font-weight: Regular;
text-align: left;
color: #666666;
line-height: 22px;
}
</style>

@ -1,7 +1,7 @@
<script lang="ts" setup>
import type { FormInst, FormRules } from 'naive-ui'
import { ref } from 'vue'
import { useMessage } from 'naive-ui'
import type { FormInst, FormRules } from 'naive-ui';
import { useMessage } from 'naive-ui';
import { ref } from 'vue';
const emit = defineEmits<{
(e: 'commit', value: any)
@ -42,7 +42,7 @@ const rules: FormRules = {
const model = ref({
packagename: '',
comparehistory: false,
// comparehistory: false,
mark: false,
})
@ -66,7 +66,6 @@ const formItemStyle = {
function afterLeave() {
model.value.packagename = ''
model.value.comparehistory = false
model.value.mark = false
}
</script>
@ -85,11 +84,6 @@ function afterLeave() {
<n-form-item path="packagename" label="任务包名称">
<n-input v-model:value="model.packagename" max="12" @keydown.enter.prevent />
</n-form-item>
<n-form-item path="comparehistory" :style="formItemStyle">
<n-checkbox v-model:checked="model.comparehistory">
是否对比历史数据
</n-checkbox>
</n-form-item>
<n-form-item path="mark" :style="formItemStyle">
<n-checkbox v-model:checked="model.mark">
是否给重复图片添加重复标识

@ -0,0 +1,50 @@
<script lang="ts" setup>
import { ref } from 'vue'
const show = ref(false)
const stys = {
'width': '424px',
'height': '192px',
'--n-padding-bottom': '0px',
'--n-padding-left': '0px',
'background': 'linear-gradient(132deg, rgba(255, 255, 255, 0.32) 21%, rgba(152, 172, 255, 0.14) 100%)',
'border-radius': '4px',
'box-shadow': '0px 12px 48px 16px rgba(0, 0, 0, 0.03)',
'backdrop-filter': ' blur(10px)',
}
function showModal() {
show.value = true
}
function closeModal() {
show.value = false
}
defineExpose({
showModal,
closeModal,
})
</script>
<template>
<n-modal v-model:show="show" :mask-closable="false" transform-origin="center">
<n-card :style="stys" :bordered="false" role="dialog" aria-modal="true">
<div class="wrapper">
<svg-icon size="90" name="robot2" />
<span style="margin-top: 24px;">正在查重中</span>
</div>
</n-card>
</n-modal>
</template>
<style lang="less" scoped>
.wrapper {
display: flex;
height: 100%;
flex-direction: column;
justify-content: center;
align-items: center;
}
</style>

@ -582,6 +582,15 @@ function getPercent(pictureid: string) {
</template>
<style lang="less" scoped>
::v-deep(.n-tabs-tab__label) {
font-size: 14px;
font-family: PingFang SC, PingFang SC-Regular;
font-weight: 400;
color: #666666;
}
::v-deep(.n-tabs-tab--active .n-tabs-tab__label) {
color: #507AFD;
}
.wrapper {
display: flex;
flex: 1;

@ -92,14 +92,16 @@ onMounted(() => {
<div class="card">
<n-collapse arrow-placement="right" :default-expanded-names="['1']">
<template #header-extra>
审批结果{{ getLabel(props.data.states) }}
<div class="status">
审批结果{{ getLabel(props.data.states) }}
</div>
</template>
<n-collapse-item title="收起" name="1">
<div v-for="items in props.data.userapproveList" :key="items.nodeName" class="item">
<div class="header">
<SvgIcon class="icon" name="approve" size="16" />
<div class="title">
<div class="item-title">
{{ items.nodeName }}
</div>
</div>
@ -131,11 +133,23 @@ onMounted(() => {
</template>
<style lang="less" scoped>
::v-deep(.n-timeline-item-timeline__line) {
width: 1px!important;
}
::v-deep(.n-collapse-item__header) {
flex-direction: row-reverse;
}
::v-deep(.n-collapse-item__header-main) {
flex: none!important;
}
::v-deep(.n-collapse-item__header-extra) {
flex: 1;
}
.info-header {
display: flex;
padding: 6px 0 15px 0;
align-items: center;
justify-content: space-between;
margin-bottom: 18px;
.left_box {
display: flex;
align-items: center;
@ -144,15 +158,13 @@ onMounted(() => {
align-items: center;
font-size: 16px;
font-family: PingFang SC, PingFang SC-Medium;
font-weight: Medium;
text-align: left;
font-weight: 500;
color: #333333;
line-height: 22px;
&:before {
content: "";
width: 4px;
height: 18px;
height: 12px;
background: #507afd;
border-radius: 3px;
display: inline-block;
@ -160,6 +172,18 @@ onMounted(() => {
}
}
}
.right_box {
display: flex;
align-items: center;
cursor: pointer;
font-size: 14px;
font-family: PingFang SC, PingFang SC-Regular;
color: #666666;
.icon{
margin-left: 7px
}
}
}
.point-line{
@ -210,6 +234,14 @@ onMounted(() => {
padding: 16px;
}
.status{
font-size: 14px;
font-family: PingFang SC, PingFang SC-Medium;
font-weight: 500;
text-align: center;
color: #333333;
}
.point{
width: 4px;
height: 4px;
@ -218,6 +250,13 @@ onMounted(() => {
margin-right: 6px;
}
.item-title{
font-size: 14px;
font-family: PingFang SC, PingFang SC-Medium;
font-weight: 500;
color: #333333;
}
.header{
display: flex;
align-items: center;

@ -8,6 +8,13 @@ defineProps({
</script>
<template>
<div class="info-header">
<div class="left_box">
<div class="title">
基本信息
</div>
</div>
</div>
<table class="description">
<tr>
<th>图片名称</th>
@ -15,15 +22,13 @@ defineProps({
{{ data?.ocrPicture?.imgname }}
</td>
<th>图片格式</th>
<td class="blue">
</td>
<td class="blue" />
</tr>
<tr>
<th>图片大小</th>
<td></td>
<td />
<th>图片尺寸</th>
<td></td>
<td />
</tr>
<tr>
<th>上传时间</th>
@ -33,18 +38,62 @@ defineProps({
</tr>
<tr>
<th>标记时间</th>
<td> </td>
<td />
<th>色彩空间</th>
<td>{{ data?.ocrPicture?.space }}</td>
</tr>
<tr>
<th>来源</th>
<td> {{ data?.ocrPicture?.source }}</td>
<th>
来源
</th>
<td colspan="3">
{{ data?.ocrPicture?.source }}
</td>
</tr>
</table>
</template>
<style lang="less" scoped>
.info-header {
display: flex;
padding: 6px 0 15px 0;
align-items: center;
justify-content: space-between;
.left_box {
display: flex;
align-items: center;
.title {
display: flex;
align-items: center;
font-size: 16px;
font-family: PingFang SC, PingFang SC-Medium;
font-weight: 500;
color: #333333;
&:before {
content: "";
width: 4px;
height: 12px;
background: #507afd;
border-radius: 3px;
display: inline-block;
margin-right: 10px;
}
}
}
.right_box {
display: flex;
align-items: center;
cursor: pointer;
font-size: 14px;
font-family: PingFang SC, PingFang SC-Regular;
color: #666666;
.icon{
margin-left: 7px
}
}
}
.description {
width: 100%;
font-size: 14px;
@ -54,16 +103,24 @@ th {
width: 20%;
background-color: #fafafa;
color: #666666;
font-size: 14px;
font-family: PingFang SC, PingFang SC-Regular;
font-weight: 400;
line-height: 22px;
}
td {
width: 30%;
font-size: 14px;
font-family: PingFang SC, PingFang SC-Regular;
font-weight: 400;
color: #666666;
}
th,
td {
border: 1px solid #ebebeb;
padding: 12px 24px;
padding: 10px 24px;
text-align: left;
}

Loading…
Cancel
Save