fix: 冲突解决

pull/90/head
wendong551 1 year ago
commit 098c277914

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>形状</title>
<g id="登录" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="登录_1.2未输入密码提示" transform="translate(-537.000000, -488.000000)" fill="#FF4E4F">
<g id="编组-11" transform="translate(510.000000, 165.000000)">
<g id="登录" transform="translate(0.000000, 44.000000)">
<g id="Group-10" transform="translate(27.000000, 276.000000)">
<g id="警示" transform="translate(0.000000, 3.000000)">
<path d="M7,0.875 C3.61757813,0.875 0.875,3.61757813 0.875,7 C0.875,10.3824219 3.61757813,13.125 7,13.125 C10.3824219,13.125 13.125,10.3824219 13.125,7 C13.125,3.61757813 10.3824219,0.875 7,0.875 Z M6.5625,4.046875 C6.5625,3.98671875 6.61171875,3.9375 6.671875,3.9375 L7.328125,3.9375 C7.38828125,3.9375 7.4375,3.98671875 7.4375,4.046875 L7.4375,7.765625 C7.4375,7.82578125 7.38828125,7.875 7.328125,7.875 L6.671875,7.875 C6.61171875,7.875 6.5625,7.82578125 6.5625,7.765625 L6.5625,4.046875 Z M7,10.0625 C6.63769531,10.0625 6.34375,9.76855469 6.34375,9.40625 C6.34375,9.04394531 6.63769531,8.75 7,8.75 C7.36230469,8.75 7.65625,9.04394531 7.65625,9.40625 C7.65625,9.76855469 7.36230469,10.0625 7,10.0625 Z" id="形状"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="64px" height="64px" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>右箭头</title>
<defs>
<rect id="path-1" x="0" y="0" width="64" height="64"></rect>
</defs>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="PrevailCloud-Design-图标集" transform="translate(-2504.000000, -8416.000000)">
<g id="右箭头" transform="translate(2536.000000, 8448.000000) scale(-1, 1) translate(-2536.000000, -8448.000000) translate(2504.000000, 8416.000000)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<g id="蒙版"></g>
<path d="M28.2032063,13.8205721 C28.5937306,13.4300478 29.2268955,13.4300478 29.6174198,13.8205721 L29.6174198,13.8205721 L31.7387402,15.9418924 C32.1292645,16.3324167 32.1292645,16.9655817 31.7387402,17.356106 L31.7387402,17.356106 L20.0942055,28.9996789 L52.663654,29 C53.2159388,29 53.663654,29.4477153 53.663654,30 L53.663654,33 C53.663654,33.5522847 53.2159388,34 52.663654,34 L20.0952055,33.9996789 L31.7387402,45.643894 C32.1292645,46.0344183 32.1292645,46.6675833 31.7387402,47.0581076 L29.6174198,49.1794279 C29.2268955,49.5699522 28.5937306,49.5699522 28.2032063,49.1794279 L11.9379919,32.9142136 C11.1569433,32.133165 11.1569433,30.866835 11.9379919,30.0857864 L13.3522055,28.6715729 L13.3592055,28.6636789 Z" id="形状结合" fill="#FFFFFF" mask="url(#mask-2)"></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

@ -31,7 +31,7 @@ async function handlerSearch(value) {
if (res.code === 'OK') {
state.resultList = [
{
title: 'AI工单管理',
title: '图检审批',
path: 'worksheet',
data: res.data.ai,
},

@ -173,15 +173,14 @@ function imUpdateSelectIds(x: number, y: number, w: number, h: number) {
items.forEach((item: HTMLDivElement) => {
const rect = item.getBoundingClientRect()
const index = selectIds.value.indexOf(item.dataset.id!)
if (rect.right > x && rect.bottom > y && rect.left < x + w && rect.top < y + h)
index === -1 && selectIds.value.push(item.dataset.id!)
else index !== -1 && selectIds.value.splice(index, 1)
})
}
function isSelected(id: number) {
return selectIds.value.includes(String(id))
function isSelected(pictureId: number) {
return selectIds.value.includes(String(pictureId))
}
function moveHandler(e: MouseEvent) {
@ -241,6 +240,7 @@ onMounted(() => {
async function showModal() {
show.value = true
reset()
pagination.pageNo = 1
const list = await featchList()
listData.value = list
@ -296,7 +296,6 @@ defineExpose({
const notPassModalRef = ref(null)
const showActions = computed(() => {
console.log('selectedApproveItems', selectedApproveItems)
return selectedApproveItems.value.length > 0 && batch;
});
@ -318,6 +317,7 @@ function reset() {
batch.value = false;
pagination.pageNo = 1;
pagination.pageSize = 20;
selectIds.value = [];
selectedApproveItems.value.length = 0;
loading = false;
canloadMore = true;
@ -457,8 +457,8 @@ async function refreshHandler() {
<div ref="el" class="scroll">
<!-- <n-scrollbar :on-scroll="scrollHandler"> -->
<div ref="masonryRef" class="grid">
<div v-for="(item, index) in listData" :key="item.id" :data-id="item.id"
:class="{ 'grid-item-selected': isSelected(item.id) }" :style="{ height: gridHeight }"
<div v-for="(item, index) in listData" :key="item.pictureId" :data-id="item.pictureId"
:class="{ 'grid-item-selected': isSelected(item.pictureId) }" :style="{ height: gridHeight }"
class="grid-item">
<n-image :src="item.imgUrl" class="img "
:class="{ 'img-fit': viewMode === 'horizontalVersion', 'img-full': viewMode === '3:4' || viewMode === 'verticalVersion' }" />

@ -38,7 +38,7 @@ const routes: Array<RouteRecordRaw> = [
path: 'final-detail',
name: 'final-detail',
meta: {
title: '任务终审详情',
title: '任务详情',
},
component: () => import('@/views/task/content/Content.vue'),
},

@ -108,12 +108,12 @@ export const useDictionaryStore = defineStore({
},
actions: {
initData(){
this.fetchRegionList();
// this.fetchRegionList(); //废弃
this.fetchPictureTypeList();
this.fetchPersionList();
this.fetchPlanList();
this.fetchTFList();
this.fetchIzShowList();
// this.fetchIzShowList(); //废弃
this.fetchIzProjectList();
this.fetchIztaskrromList();
this.fetchIztaskstatusList();

@ -138,6 +138,9 @@ const showSearch = ref(false);
function setShowSearch(value: boolean) {
showSearch.value = value;
if(!value){
inputChange('')
}
}
// key
@ -161,7 +164,6 @@ watch(asideValue, (newVal) => {
});
const inputChange = (keyword) => {
console.log("Search Component", keyword);
emit("inputChange", keyword);
};
</script>

@ -433,13 +433,13 @@ const indeterminate = computed(() => {
>
<SvgIcon name="drag" size="14" color="#666666" />
<span class="ml-2">{{ item.name }}</span>
<SvgIcon
<!-- <SvgIcon
v-if="!item.fix"
size="16px"
style="display: block; margin-left: auto; cursor: pointer"
name="clear"
@click="removeHandler(item.id, 'fix')"
/>
/> -->
</div>
</VueDraggable>
<div>不固定</div>

@ -299,6 +299,7 @@ const showSearch = computed(() => {
transform-origin="center"
display-directive="if"
@after-leave="afterLeave"
:mask-closable="false"
>
<n-card
:style="cardStyle"

@ -28,19 +28,25 @@ const actions = computed(() => {
</script>
<template>
<div :data-id="id">
<n-button
v-for="(action, index) in actions" :key="index" class="normal"
<div :data-id="id" class="wrap">
<div
v-for="(action, index) in actions" :key="index"
class="normal"
:class="{ gap: index !== 0, reject: action.key === 'reject' }" text @click="(trigger(action) as any)"
>
{{ action.label }}
</n-button>
</div>
</div>
</template>
<style scoped>
.wrap{
display: flex;
align-items: center;
}
.normal {
color: #507AFD
color: #507AFD;
cursor: pointer;
}
.gap {

@ -255,7 +255,7 @@ defineExpose({
</script>
<template>
<n-modal v-model:show="show" transform-origin="center" @after-leave="leaveHandler">
<n-modal v-model:show="show" transform-origin="center" @after-leave="leaveHandler" :mask-closable="false">
<n-card :style="cardStyle" :bordered="false" size="huge" role="dialog" aria-modal="true">
<div class="wrapper">
<span class="wrapper-title">{{ modalTitle }}</span>
@ -308,7 +308,7 @@ defineExpose({
<template #footer>
<div class="wrapper-footer">
<n-button type="info" @click="handleSumbit">
保存
确定
</n-button>
<n-button secondary style="margin-left:15px" @click="closeModal">
取消

@ -1,7 +1,8 @@
<script lang="ts" setup>
import { reactive, ref, toRefs } from 'vue'
import { repetitionTask } from '@/api/final/index'
import listDark from 'naive-ui/lib/mention/styles/dark'
import { getRepeatList, repetitionTask } from '@/api/final/index'
const emit = defineEmits<{
(e: 'reject', params: any)
@ -45,17 +46,30 @@ function closeModal() {
show.value = false
}
async function reject() {
const list = []
state.detail.forEach((items) => {
items.repeatedTaskList.forEach((item) => {
list.push(item)
})
async function query() {
const result = await getRepeatList({
sortorder: 'asc',
pageSize: 300,
pageNo: 1,
sortname: '',
})
emit('reject', list)
const { data } = result
// console.log(data)
// // const list = []
// // data.forEach((items) => {
// // items.repeatedTaskList.forEach((item) => {
// // list.push(item)
// // })
// // })
// console.log(data)
emit('reject', data)
closeModal()
}
async function reject() {
query()
}
async function viewRepeat(e: MouseEvent) {
emit('viewrepeat')
e.preventDefault()

@ -68,6 +68,9 @@ const columns: DataTableColumns<RowData> = [
ellipsis: {
tooltip: true,
},
render(row: any) {
return row.fromtaskname
},
},
{
title: '任务名称',
@ -356,6 +359,7 @@ function showModal() {
function reload() {
selectionIds.value = []
checkedRowKeys.value = []
query(pagination.page, pagination.pageSize)
}
function goDetail(row) {
@ -397,25 +401,21 @@ defineExpose({
</div>
</div>
<div class="batch">
<div v-show="!showActions" style="display: flex; align-items: center">
<div class="btn-batch">
<SvgIcon style="margin-right: 6px" size="22" name="batch" />
批量审批
</div>
</div>
<div v-show="showActions" style="display: flex; align-items: center">
<NButton text @click="switchBatch()">
<template #icon>
<SvgIcon name="revoke" />
</template>
取消
</NButton>
<div v-show="showActions" class="batch">
<div style="display: flex; align-items: center">
<img class="btn-approval btn-left" style="margin-left: 16px" src="@/assets/images/task/btn-not-pass.png" alt="" @click.stop="batchReject">
<SvgIcon size="24" name="vs" />
<img class="btn-approval" src="@/assets/images/task/btn-pass.png" alt="" @click.stop="batchApproval">
</div>
<div class="batch-right">
<div class="select">
已选中 <span class="num">{{ selectionIds.length }}</span>
</div>
<div class="line" />
<div class="clear" @click="switchBatch">
清空
</div>
</div>
</div>
<div class="wrapper-content">
<NDataTable
@ -454,6 +454,7 @@ defineExpose({
.batch {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 27px;
.btn-approval{
@ -462,6 +463,34 @@ defineExpose({
cursor: pointer;
}
.batch-right {
display: flex;
align-items: center;
.select{
font-size: 14px;
font-family: PingFang SC, PingFang SC-Regular;
font-weight: 500;
text-align: center;
color: #666666;
}
.num{
color: #507AFD;
}
.line{
width: 1px;
height: 14px;
background: #d8d8d8;
margin: 0 16px;
}
.clear{
color: #507AFD;
cursor: pointer;
}
}
}
.wrapper {
display: flex;

@ -184,10 +184,8 @@ async function getColumns() {
const useList = res.data
const userFieldFixed = useList.userFieldFixed?.split(',')
const userFieldUnFixed = useList.userFieldUnFixed?.split(',')
console.log(userFieldFixed, userFieldUnFixed, 'userFieldUnFixed')
console.log(allList, 'allList')
allList?.map((v) => {
if (!userFieldFixed?.length && !userFieldUnFixed?.length) {
if (!userFieldFixed?.length && !userFieldUnFixed?.length) {
allList?.map((v) => {
if (v.isrequired == 2) {
columnsRef.value.push({
title: v.fieldDesc,
@ -196,27 +194,63 @@ async function getColumns() {
width: 120,
})
}
}
if (userFieldFixed?.find(v2 => v2 == v.name)) {
})
}
else {
userFieldFixed.map((v) => {
const item = allList.find(v2 => v2.name == v)
columnsRef.value.push({
title: v.fieldDesc,
key: v.name,
title: item.fieldDesc,
key: item.name,
fixed: 'left',
width: 120,
})
}
if (userFieldUnFixed?.find(v2 => v2 == v.name)) {
})
userFieldUnFixed.map((v) => {
const item = allList.find(v2 => v2.name == v)
columnsRef.value.push({
title: v.fieldDesc,
key: v.name,
title: item.fieldDesc,
key: item.name,
width: 120,
})
}
})
})
}
// TODO:
// #region
// allList?.map((v) => {
// if (!userFieldFixed?.length && !userFieldUnFixed?.length) {
// if (v.isrequired == 2) {
// columnsRef.value.push({
// title: v.fieldDesc,
// fixed: "left",
// key: v.name,
// width: 120,
// });
// }
// }
// if (userFieldFixed?.find((v2) => v2 == v.name)) {
// columnsRef.value.push({
// title: v.fieldDesc,
// key: v.name,
// fixed: "left",
// width: 120,
// });
// }
// if (userFieldUnFixed?.find((v2) => v2 == v.name)) {
// columnsRef.value.push({
// title: v.fieldDesc,
// key: v.name,
// width: 120,
// });
// }
// });
// #endregion
columnsRef.value.push(actionsColumns as any)
console.log(columnsRef.value, 'columnsRef111')
formatColumns()
console.log(columnsRef.value, 'columnsRef')
console.log(columnsRef.value, 'columnsRef222')
}
async function formatColumns() {
@ -244,7 +278,7 @@ async function formatColumns() {
'text-color': '#507AFD',
'onClick': () => goDetail(row),
},
{ default: () => row.id },
{ default: () => row.fromtaskname },
)
},
}
@ -437,7 +471,7 @@ async function query(page: number, pageSize: number, filterId?: any) {
sortorder: 'asc',
pageSize,
currPage: page,
sortname: '',
sortname: 'states',
...params,
})
const { data, pageCount, totalCount } = result
@ -767,7 +801,10 @@ async function refreshHandler(searchId?: any) {
}
function filterTableData(keyword) {
tableData.value = tableData.value.filter(item => item.id.includes(keyword))
if (keyword)
tableData.value = tableData.value.filter(item => item.id.includes(keyword))
else
query(pagination.page, pagination.pageSize)
}
defineExpose({
filterTableData,
@ -782,7 +819,12 @@ defineExpose({
<SvgIcon size="32" name="magnifying" @click="changeContent" />
</div>
<div>
<SvgIcon style="margin-right: 6px;" size="13" name="summary" @click="showModal(repeatModalRef)" />
<SvgIcon
style="margin-right: 6px"
size="13"
name="summary"
@click="showModal(repeatModalRef)"
/>
<NButton class="xjcc" text @click="showModal(repeatModalRef)">
小结查重
</NButton>
@ -801,7 +843,12 @@ defineExpose({
取消
</NButton>
<img class="btn-approval btn-left" src="@/assets/images/task/btn-not-pass.png" alt="" @click.stop="batchReject">
<img
class="btn-approval btn-left"
src="@/assets/images/task/btn-not-pass.png"
alt=""
@click.stop="batchReject"
>
<SvgIcon size="24" name="vs" />
<img
class="btn-approval"
@ -834,9 +881,9 @@ defineExpose({
<li>
<SvgIcon size="20" name="download" /><span style="margin-left: 5px">导出全部数据</span>
</li>
<!-- <li>
<li>
<SvgIcon size="20" name="look" /><span style="margin-left: 5px">查看导入记录</span>
</li> -->
</li>
</ul>
</n-popover>
</div>
@ -1076,4 +1123,10 @@ defineExpose({
:deep(.n-data-table .n-data-table-td.n-data-table-td--fixed-right) {
z-index: 100 !important;
}
:deep(.n-data-table-th__title) {
color: #333;
}
:deep(.n-data-table .n-data-table-td) {
color: #666;
}
</style>

@ -92,14 +92,6 @@ onBeforeMount(async () => {
configStore.$subscribe(() => {
const config = configStore.getConfig
const customConfig = configStore.getCustomConfig
console.log("config", config);
console.log("customConfig", customConfig);
console.log("customObjRef.value", customObjRef.value);
console.log("customTempObjRef.value", customTempObjRef.value, );
console.log("getFilterConfig", configStore.getFilterConfig,);
console.log("isEqual(asideValue, configStore.getAsideValue)", isEqual(asideValue, configStore.getAsideValue), );
console.log("configStore的getAsideValue", configStore.getAsideValue, );
console.log( "getAsideValue", asideValue);
if((configFilterRef.value.length > 0 && isEqual(configFilterRef.value, configStore.getFilterConfig)) && customObjRef.value && isEqual(customObjRef.value, customTempObjRef.value)) {
return
}
@ -157,6 +149,7 @@ configStore.$subscribe(() => {
console.log("asideValue直接处理后的结果", asideValue);
console.log("customTempObjRef.value", customTempObjRef.value);
let tempobj = cloneDeep(asideValue);
console.log("tempObj", tempobj);
configStore.setAsideValue(tempobj);
}
// console.log("showKeys", showKeys);
@ -235,7 +228,9 @@ function updateComponent(key, e) {
console.log("tempAsideValue跟新值", configStore.getAsideValue, asideValue);
// let tempAsideValue = configStore.getAsideValue || asideValue;
let tempobj = cloneDeep(asideValue);
console.log(tempobj,'tempobj')
tempobj[key] = e;
console.log(tempobj, 'tempobj After')
customObjRef.value = tempobj;
// asideValue = Object.assign({}, asideValue, tempobj);
console.log("asideValue跟新值", tempobj);

@ -58,6 +58,7 @@ const searchName = () => {
const close = () => {
searchKeyword.value = "";
configStore.setSearchValue(searchKeyword.value);
emit('close');
}

@ -332,6 +332,7 @@ const showSearch = computed(() => {
transform-origin="center"
display-directive="if"
@after-leave="afterLeave"
:mask-closable="false"
>
<n-card
:style="cardStyle"

@ -153,8 +153,7 @@ function unformatValue(searchfield: string, searchvalue: any) {
}
// 80,90
if (searchfield === 'izsimilarity')
return searchvalue.split(',')
// if (searchfield === "izsimilarity") return searchvalue.split(",");
return searchvalue
}
@ -192,16 +191,16 @@ const logicOptions = ref([])
const similarityOptions = [
{
label: '80%-90%',
value: [80, 90],
label: "80%-90%",
value: '80,90',
},
{
label: '95%-100%',
value: [95, 100],
label: "95%-100%",
value: '95,100',
},
{
label: '100%-100%',
value: [100, 100],
label: "100%-100%",
value: '100,100',
},
]
@ -257,12 +256,10 @@ watch(
)
function getOptions(key: string) {
if (key === 'izsimilarity')
return similarityOptions
const getterName = `get${key}`
const options = unref(dicStore[getterName])
return options || []
if (key === "izsimilarity") return similarityOptions;
const getterName = `get${key}`;
const options = unref(dicStore[getterName]);
return options || [];
}
function leaveHandler() {
@ -280,11 +277,11 @@ function leaveHandler() {
}
function edit(editFilter: any) {
currentStatus.value = 'edit'
const { searchname, ocrUsersearchchildList, id } = editFilter
currentEditId = id
formValue.name = searchname
currentStatus.value = "edit";
console.log(editFilter,'editFilter')
const { searchname, ocrUsersearchchildList, id } = editFilter;
currentEditId = id;
formValue.name = searchname;
formValue.conditions = ocrUsersearchchildList.map((item) => {
return {
type: item.searchfield,
@ -301,7 +298,7 @@ defineExpose({
</script>
<template>
<n-modal v-model:show="show" transform-origin="center" @after-leave="leaveHandler">
<n-modal v-model:show="show" transform-origin="center" @after-leave="leaveHandler" :mask-closable="false">
<n-card
:style="cardStyle"
:bordered="false"

File diff suppressed because it is too large Load Diff

@ -84,11 +84,11 @@ function afterLeave() {
<n-form-item class="wrapper-task-package-name" path="packagename" label="任务包名称">
<n-input v-model:value="model.packagename" maxlength="12" @keydown.enter.prevent />
</n-form-item>
<n-form-item path="mark" :style="formItemStyle">
<n-checkbox v-model:checked="model.mark">
<!-- <n-form-item path="mark" :style="formItemStyle">
<n-checkbox v-model:checked="model.mark" >
是否给重复图片增加重复标识
</n-checkbox>
</n-form-item>
</n-form-item> -->
</n-form>
</div>
<template #footer>

@ -62,7 +62,7 @@ function close() {
</div>
<div class="text">企业级 SaaS 智能审批解决方案</div>
<img class="img-icon-2" src="../../assets/images/login/img-icon-2.png" alt="" />
<div class="btn-login-2 f-c-c" @click="showLogin"> -></div>
<div class="flex btn-login-2 f-c-c" @click="showLogin"> <SvgIcon name="right_arrow" class="right_arrow"/></div>
<div class="item-wrap f-c">
<div class="item">
<img class="item-img" src="../../assets/images/login/item-1.png" alt="" />
@ -300,5 +300,9 @@ function close() {
color: #FF4E4F !important;
font-size: .75rem !important;
}
.right_arrow{
height: 1.25rem !important;
width: 1.25rem !important;
margin-top: .2rem;
}
</style>

@ -1,32 +1,32 @@
<script lang="ts" setup>
import { reactive, ref, toRefs } from "vue";
import { format } from "date-fns";
import { useRoute, useRouter } from "vue-router";
import { getMessageList, readAllMsg, readMsg } from "@/api/message/message";
import iconApproveActive from "@/assets/images/message/approve-active.png";
import iconApprove from "@/assets/images/message/approve.png";
import iconSystemActive from "@/assets/images/message/system-active.png";
import iconSystem from "@/assets/images/message/system.png";
import iconArrowActive from "@/assets/images/message/arrow-active.png";
import iconArrow from "@/assets/images/message/arrow.png";
import iconClear from "@/assets/images/message/clear.png";
import iconArrowDown from "@/assets/images/message/arrow-down.png";
const emit = defineEmits(["goDetail"]);
const router = useRouter();
const route = useRoute();
const hasNextPage = ref(false);
import { reactive, ref, toRefs } from 'vue'
import { format } from 'date-fns'
import { useRoute, useRouter } from 'vue-router'
import { getMessageList, readAllMsg, readMsg } from '@/api/message/message'
import iconApproveActive from '@/assets/images/message/approve-active.png'
import iconApprove from '@/assets/images/message/approve.png'
import iconSystemActive from '@/assets/images/message/system-active.png'
import iconSystem from '@/assets/images/message/system.png'
import iconArrowActive from '@/assets/images/message/arrow-active.png'
import iconArrow from '@/assets/images/message/arrow.png'
import iconClear from '@/assets/images/message/clear.png'
import iconArrowDown from '@/assets/images/message/arrow-down.png'
const emit = defineEmits(['goDetail'])
const router = useRouter()
const route = useRoute()
const hasNextPage = ref(false)
const state = reactive({
tabList: [
{
name: "审批通知",
name: '审批通知',
icon: iconApprove,
activeIcon: iconApproveActive,
value: 1,
},
{
name: "系统消息",
name: '系统消息',
icon: iconSystem,
activeIcon: iconSystemActive,
value: 2,
@ -34,102 +34,105 @@ const state = reactive({
],
list: [] as any,
pageNo: 1,
});
})
const { list, tabList } = toRefs(state);
const { list, tabList } = toRefs(state)
const tab = ref(1);
const tab = ref(1)
async function getList(type = "") {
async function getList(type = '') {
let res = await getMessageList({
pageNo: state.pageNo,
pageSize: "7",
pageSize: '7',
msgCategory: tab.value,
});
if (type == "more") {
})
if (type == 'more') {
while (res.data.endRow > 0) {
if (res.code == "OK") {
if (res.code == 'OK') {
if (tab.value === 1) {
res.data.list.forEach((item) => {
item.tag = JSON.parse(item.busJson);
});
item.tag = JSON.parse(item.busJson)
})
}
state.list = state.list.concat(res.data.list);
state.pageNo++;
state.list = state.list.concat(res.data.list)
state.pageNo++
res = await getMessageList({
pageNo: state.pageNo,
pageSize: "7",
pageSize: '7',
msgCategory: tab.value,
});
})
}
}
hasNextPage.value = res.data.hasNextPage;
} else {
if (res.code === "OK") {
hasNextPage.value = res.data.hasNextPage;
hasNextPage.value = res.data.hasNextPage
}
else {
if (res.code === 'OK') {
hasNextPage.value = res.data.hasNextPage
if (tab.value === 1) {
res.data.list.forEach((item) => {
item.tag = JSON.parse(item.busJson);
});
item.tag = JSON.parse(item.busJson)
})
}
state.list = state.list.concat(res.data.list);
state.list = state.list.concat(res.data.list)
}
}
}
getList();
getList()
async function clearMsg() {
const res = await readAllMsg({ msgCategory: tab.value });
if (res.code === "OK") {
state.list = [];
state.pageNo = 1;
getList();
const res = await readAllMsg({ msgCategory: tab.value })
if (res.code === 'OK') {
state.list = []
state.pageNo = 1
getList()
}
}
function switchTab(type: number) {
tab.value = type;
state.list = [];
state.pageNo = 1;
getList();
tab.value = type
state.list = []
state.pageNo = 1
getList()
}
function goFinalDetail(row) {
console.log(row);
console.log(row)
router.push({
name: "final-detail",
query: { id: row.tag.taskId, packageid: row.packageid },
});
name: 'final-detail',
query: { id: row.tag.fromId, packageid: row.packageid },
})
}
function goDetail(item) {
if (tab.value === 1) {
clearMsgOne(item.id);
goFinalDetail(item);
clearMsgOne(item.id)
goFinalDetail(item)
}
// emit('goDetail', item.id)
else {
router.push({ name: "message-detail", query: { id: item.id } });
router.push({ name: 'message-detail', query: { id: item.id } })
}
}
async function clearMsgOne(id) {
const res = await readMsg({ msgid: id });
const res = await readMsg({ msgid: id })
}
function getMore() {
state.pageNo += 1;
getList("more");
state.pageNo += 1
getList('more')
}
</script>
<template>
<div class="wrapper-message">
<div class="flex justify-between header">
<div class="header-title">消息通知</div>
<div class="header-title">
消息通知
</div>
<div class="clear" @click="clearMsg">
<img class="icon-clear" :src="iconClear" alt="" />
<img class="icon-clear" :src="iconClear" alt="">
清除未读
</div>
</div>
@ -147,7 +150,7 @@ function getMore() {
class="icon"
:src="tab === item.value ? item.activeIcon : item.icon"
alt=""
/>
>
<div :class="{ 'text-active': tab === item.value }" class="text">
{{ item.name }}
</div>
@ -156,7 +159,7 @@ function getMore() {
class="icon-arrow"
:src="tab === item.value ? iconArrowActive : iconArrow"
alt=""
/>
>
<div v-if="tab === item.value" class="line" />
</div>
</div>
@ -164,7 +167,7 @@ function getMore() {
<div
v-for="(item, index) in list"
:key="item.id"
:class="{ pt0: index === 0, 'item-disabled': item.readFlag }"
:class="{ 'pt0': index === 0, 'item-disabled': item.readFlag }"
class="item"
@click="goDetail(item)"
>
@ -185,7 +188,9 @@ function getMore() {
{{ item.titile }}
</div>
<div v-if="tab === 1" class="status">
<div class="tag tag-blue">审批节点{{ item.tag.nodeName }}</div>
<div class="tag tag-blue">
审批节点{{ item.tag.nodeName }}
</div>
<div :class="item.tag.states === 5 ? 'tag-red' : 'tag-green'" class="tag">
审批状态{{ item.tag.states }}
</div>
@ -199,11 +204,13 @@ function getMore() {
<span class="time">{{ format(item.sendTime, "yyyy-MM-dd HH:mm:ss") }}</span>
</div>
</div>
<div class="look">查看</div>
<div class="look">
查看
</div>
</div>
<div v-if="hasNextPage" class="more" @click="getMore">
查看更多<img class="icon-more" :src="iconArrowDown" alt="" />
查看更多<img class="icon-more" :src="iconArrowDown" alt="">
</div>
</div>
</div>

@ -70,10 +70,8 @@ const showSearch = ref(false)
function setShowSearch(value: boolean) {
if (!value) {
console.log('setShowSearch', value)
search.value = ''
taskListRef.value.search('')
return
}
showSearch.value = value
}

@ -240,7 +240,9 @@ async function handleDragEnd(event, item) {
const res = await dubiousfileyd({ pictureid: item.pictureId })
if (res.code === 'OK') {
message.success('加入成功')
setBatch(false)
getTableData()
getImgList()
}
else {
message.error(res.message)
@ -355,6 +357,11 @@ async function getDetail() {
getImgList()
}
function notPassSuccess(param) {
batchModalRef.value.reload()
reloadList(param, '不通过')
}
function reloadList(param, text) {
//
const id = currentTaskId()
@ -574,7 +581,7 @@ function switchBatch() {
<div
draggable="true"
class="img-wrapper"
:style="{ 'background-image': `url(${item.imgUrl})` }"
:style="{ 'background-image': `url(${item.serverThumbnailUrl})` }"
@dragend="
(event) => {
handleDragEnd(event, item);
@ -643,10 +650,8 @@ function switchBatch() {
</n-tab-pane>
</n-tabs>
<NotPassed
ref="notPassModalRef" @success="(param) => {
batchModalRef.value.reload()
reloadList(param, '不通过')
}"
ref="notPassModalRef"
@success="notPassSuccess"
/>
<BatchModal
ref="batchModalRef"

@ -5,8 +5,10 @@ import { useInfiniteScroll } from '@vueuse/core'
import { debounce } from 'lodash-es'
import imagesloaded from 'imagesloaded'
import { useMessage } from 'naive-ui'
import { useWindowSizeFn } from '@/hooks/event/useWindowSizeFn'
import { getViewportOffset, off, on } from '@/utils/domUtils'
import { timeOptions, viewOptions } from '@/config/home'
import { off, on } from '@/utils/domUtils'
import { useTask } from '@/store/modules/task'
import { TASK_STATUS_OBJ } from '@/enums/index'
import { formatToDateHMS } from '@/utils/dateUtil'
@ -43,6 +45,7 @@ const viewLabel = computed(() => {
return item?.label
})
const deviceHeight = ref(600)
const taskStore = useTask()
const masonryRef = ref<ComponentRef>(null)
@ -64,6 +67,14 @@ const sortBy: any = {
const batch = ref(false)
let _imagesload: any
const message = useMessage()
async function computeListHeight() {
const headEl = document.querySelector('.wrapper-content')!
const { bottomIncludeBody } = getViewportOffset(headEl)
const height = bottomIncludeBody
deviceHeight.value = height - 40 - 16 - 24
}
useWindowSizeFn(computeListHeight)
const layout = debounce(() => {
if (!show.value)
@ -74,6 +85,7 @@ const layout = debounce(() => {
_masonry = new Masonry(masonryRef.value as any, {
itemSelector: '.grid-item',
gutter: 17,
columnWidth: 214,
percentPosition: true,
stagger: 10,
@ -100,15 +112,17 @@ watch(viewMode, () => {
let canloadMore = true
useInfiniteScroll(
el as any,
() => {
loadMore()
},
{ distance: 10, canLoadMore: () => canloadMore },
)
// useInfiniteScroll(
// el as any,
// () => {
// console.log(123456)
// loadMore()
// },
// { distance: 10, canLoadMore: () => canloadMore },
// )
async function loadMore() {
console.log('loadMore')
if (loading.value || el.value == null)
return
@ -206,9 +220,9 @@ function upHandler(event: MouseEvent) {
start = null
}
const gridHeight = computed(() => {
return viewMode.value !== 'masonry' ? '157px' : ''
})
// const gridHeight = computed(() => {
// return viewMode.value !== 'masonry' ? '157px' : ''
// })
function addListeners() {
selectionBox = document.querySelector('.selection-box') as HTMLDivElement
@ -234,6 +248,7 @@ async function afterEnter() {
}
function afterLeave() {
reload()
removeListeners()
}
@ -285,8 +300,12 @@ const showActions = computed(() => {
function setBatch(value: boolean) {
batch.value = value
if (value === false)
selectIds.value.length = 0
if (value === false) {
selectIds.value = []
listData.value.forEach((item) => {
item.checked = false
})
}
}
function reject() {
@ -321,13 +340,15 @@ async function refreshHandler() {
taskDetailInfo.value = await getTaskDetailInfo(taskId.value, '')
nextTick(() => {
useInfiniteScroll(
el as any,
() => {
loadMore()
},
{ distance: 10, canLoadMore: () => canloadMore },
)
setTimeout(() => {
useInfiniteScroll(
el as any,
() => {
loadMore()
},
{ distance: 10, canLoadMore: () => canloadMore },
)
}, 300)
})
}
@ -337,14 +358,43 @@ watch(() => taskStore.activeId, async (newValue, oldValue) => {
refreshHandler()
})
const listStyle = computed(() => {
return {
height: `${deviceHeight.value}px`,
}
})
function switchBatch() {
setBatch(!batch.value)
}
function reload() {
selectIds.value = []
setBatch(false)
refreshHandler()
}
function sortHandler(orderby: 'similarityScore' | 'createdate') {
sortBy.orderName = orderby
sortBy.orderType = sortBy.orderType === 'asc' ? 'desc' : 'asc'
refreshHandler()
}
const gridHeight = computed(() => {
let height = ''
if (viewMode.value === 'masonry')
height = ''
else if (viewMode.value === 'horizontalVersion')
height = '122px'
else if (viewMode.value === 'verticalVersion')
height = '300px'
else if (viewMode.value === '3:4')
height = '240px'
return height
})
defineExpose({
showModal,
reload,
@ -364,10 +414,10 @@ defineExpose({
<div class="wrapper">
<div class="wrapper-m32">
<SvgIcon name="task-batch" size="16" />
<span style="margin-left: 8px;">任务审批</span>
<span style="margin-left: 8px;color: #666;">任务审批</span>
</div>
<div class="wrapper-title wrapper-m32">
<span>任务ID:{{ taskDetailInfo.fromtaskname }}</span>
<span style="color: #333;">任务ID:{{ taskDetailInfo.fromtaskname }}</span>
<SvgIcon size="22" class="forward" name="arrow-left" @click="backHandler" />
<SvgIcon size="22" class="back" name="arrow-right" @click="forwardHandler" />
</div>
@ -422,7 +472,7 @@ defineExpose({
<div class="wrapper-content">
<div class="wrapper-content-form wrapper-m32">
<div>
<n-popselect v-model:value="timeRange" :options="timeOptions" trigger="click" @change="onChange">
<!-- <n-popselect v-model:value="timeRange" :options="timeOptions" trigger="click" @change="onChange">
<div class="wrapper-content-form-dropdown">
<span>{{ timeLabel || '时间模式' }}</span>
<SvgIcon class="wrapper-content-form-dropdown-gap" name="arrow-botton" size="14" />
@ -433,7 +483,22 @@ defineExpose({
<span>{{ viewLabel || '视图模式' }}</span>
<SvgIcon class="wrapper-content-form-gap" name="arrow-botton" size="14" />
</div>
</n-popselect> -->
<n-popselect v-model:value="viewMode" :options="viewOptions" trigger="click">
<div class="dropdown">
<!-- <span>{{ viewLabel || '请选择' }}</span> -->
<span>视图</span>
<SvgIcon class="gap" name="arrow-botton" size="14" />
</div>
</n-popselect>
<div style="margin-left: 15px;cursor: pointer;color:#323233" @click="sortHandler('createdate')">
<span>时间排序</span>
<SvgIcon style="margin-left: 8px;" name="sort" size="12" />
</div>
<div style="margin-left: 15px;cursor: pointer;color:#323233" @click="sortHandler('similarityScore')">
<span>相似度排序</span>
<SvgIcon style="margin-left: 8px;" name="sort" size="12" />
</div>
</div>
<div>
<div v-show="!showActions" class="wrapper-content-form-button" @click="switchBatch()">
@ -458,46 +523,57 @@ defineExpose({
</div>
</div>
<div ref="el" class="scroll">
<!-- <n-scrollbar :on-scroll="scrollHandler"> -->
<div ref="masonryRef" class="grid">
<div
v-for="(item, index) in listData" :key="index" :data-id="item.id" :style="{ height: gridHeight }"
class="grid-item"
>
<div class="img-wrap">
<img
class="wrapper-content-item-img"
:class="{ 'wrapper-content-item-img-fit': viewMode !== 'masonry' }" :src="item.imgUrl"
>
<div class="small-mark" />
<div class="time">
<div v-if="item.photoDateTimestamp" class="time-item">
<SvgIcon class="svg-time" color="#FFF" size="14" name="camera-time" />
<span>{{ formatToDateHMS(Number(item.photoDateTimestamp) || 0) }}</span>
<n-spin :show="loading">
<div ref="el" class="scroll" :style="listStyle">
<!-- <n-scrollbar :on-scroll="scrollHandler"> -->
<div ref="masonryRef" class="grid">
<div
v-for="(item, index) in listData"
:key="index"
:style="{ height: gridHeight }"
class="grid-item"
>
<div>
<n-image
ref="imageRef"
class="img"
:class="{
'img-fit': viewMode === 'horizontalVersion',
'img-full': viewMode === '3:4' || viewMode === 'verticalVersion',
}"
:src="item.serverThumbnailUrl"
/>
<div class="small-mark" />
<div class="time">
<div v-if="item.photoDateTimestamp" class="time-item">
<SvgIcon class="svg-time" color="#FFF" size="14" name="camera-time" />
<span>{{ formatToDateHMS(Number(item.photoDateTimestamp) || 0) }}</span>
</div>
<div v-if="item.submitDateTimestamp" class="time-item time-item2">
<SvgIcon class="svg-time" color="#FFF" size="14" name="submit-time" />
<span>{{ formatToDateHMS(Number(item.submitDateTimestamp) || 0) }}</span>
</div>
</div>
<div v-if="item.submitDateTimestamp" class="time-item time-item2">
<SvgIcon class="svg-time" color="#FFF" size="14" name="submit-time" />
<span>{{ formatToDateHMS(Number(item.submitDateTimestamp) || 0) }}</span>
<img v-if="item.historyStates === 2" class="tag-status" src="@/assets/images/task/tag-pass.png" alt="">
<img v-if="item.historyStates === 3" class="tag-status" src="@/assets/images/task/tag-not-pass.png" alt="">
<div class="check">
<n-checkbox
v-show="batch && item.historyStates === 1"
v-model:checked="item.checked" @click.prevent
@update:checked="onCheckChange($event, item)"
/>
</div>
<div :class="{ 'percent-red': item.similarityScore === 100 }" class="percent">
{{ item.similarityScore }}<span class="percent-unit">%</span>
</div>
</div>
<img v-if="item.historyStates === 2" class="tag-status" src="@/assets/images/task/tag-pass.png" alt="">
<img v-if="item.historyStates === 3" class="tag-status" src="@/assets/images/task/tag-not-pass.png" alt="">
<div class="check">
<n-checkbox
v-show="batch && item.historyStates === 1"
v-model:checked="item.checked" @click.prevent
@update:checked="onCheckChange($event, item)"
/>
</div>
<div :class="{ 'percent-red': item.similarityScore === 100 }" class="percent">
{{ item.similarityScore }}<span class="percent-unit">%</span>
</div>
</div>
</div>
<!-- </n-scrollbar> -->
</div>
<!-- </n-scrollbar> -->
</div>
</n-spin>
</div>
<div class="close" @pointerdown="closeModal">
@ -659,7 +735,7 @@ defineExpose({
margin-bottom: 10px;
th {
color: #d7d7d7;
color: #999999;
text-align: left;
}
@ -676,7 +752,7 @@ defineExpose({
}
&-m32 {
margin-left: 19px;
// margin-left: 19px;
}
&-content {
@ -726,17 +802,40 @@ defineExpose({
display: block;
height: 100%;
}
}
.img-fit {
width: 100%;
object-fit: cover;
overflow: hidden;
}
&-img-fit {
.img {
border-radius: 7px;
display: block;
// height: calc(100% - 25px);
height: 100%;
width: 100%;
}
.img-full {
width: 100%;
overflow: hidden;
::v-deep(img) {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.grid-item {
width: 214px;
padding: 16px;
// padding: 16px;
// width: 182px;
position: relative;
margin-bottom: 32px;
transition: 0.5s;
.check{
position: absolute;
@ -782,4 +881,7 @@ defineExpose({
}
}
}
::v-deep(.n-image img) {
width: 100%!important;
}
</style>

@ -1,25 +1,22 @@
<script lang="ts" setup>
import { debounce } from 'lodash-es'
import {
computed,
defineOptions,
inject,
nextTick,
onMounted,
ref,
toRaw,
unref,
watch,
} from 'vue'
import CustomFieldModalVue from '../modal/CustomFieldModal.vue'
import WorkSheetList from './WorkSheetList.vue'
import { getAllfieldList, getfieldList } from '@/api/home/filter'
import { useWindowSizeFn } from '@/hooks/event/useWindowSizeFn'
import { useUser } from '@/store/modules/user'
import { useWorkOrder } from '@/store/modules/workOrder'
import { getViewportOffset } from '@/utils/domUtils'
computed,
defineOptions,
inject,
nextTick,
onMounted,
ref,
unref,
toRaw,
watch,
defineEmits
} from "vue";
import CustomFieldModalVue from "../modal/CustomFieldModal.vue";
import WorkSheetList from "./WorkSheetList.vue";
defineOptions({ name: 'AsideContent' })
defineOptions({ name: "AsideContent" });
const emit = defineEmits(["ApprovalOver"]);
const collapse = ref(false)
const workStore = useWorkOrder()
@ -150,8 +147,12 @@ function setShowSearch(value: boolean) {
const inputHandler = debounce((word) => {
searchKeyword.value = word;
(packageListRef.value as any).search(word)
}, 500)
(packageListRef.value as any).search(word);
}, 500);
const ApprovalOver = (packageId)=>{
emit('ApprovalOver',packageId)
}
</script>
<template>
@ -212,12 +213,9 @@ const inputHandler = debounce((word) => {
class="work-sheet-list"
:show-field-list="showFieldList"
:dicts="dicts"
@ApprovalOver="ApprovalOver"
/>
<CustomFieldModalVue
ref="filterModalRef"
:review-type="1"
@on-ok="getshowFieldList"
/>
<CustomFieldModalVue ref="filterModalRef" :review-type="1" @onOk="getshowFieldList" />
</div>
</template>

@ -10,6 +10,8 @@ import ApprovalModal from "../modal/ApprovalModal.vue";
import ListItem from "./ListItem.vue";
import type { PackageListItem } from "/#/workorder";
const emit = defineEmits(["ApprovalOver"]);
defineProps({
showFieldList: {
type: Array,
@ -136,13 +138,17 @@ function dismisClick(packageId: string) {
}
});
}
const ApprovalOver = (packageId) => {
emit("ApprovalOver",packageId);
};
defineExpose({
search,
});
</script>
<template>
<ApprovalModal ref="approvalModalRef" @not-pass="notPass" />
<ApprovalModal ref="approvalModalRef" @not-pass="notPass" @reject="ApprovalOver" />
<NotPassed ref="notPassedRef" />
<n-spin :show="isLoading">
<div ref="el" class="list">

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

@ -0,0 +1,489 @@
<script lang="ts" setup>
import { audit } from '@/api/task/task';
import {
getPictureSimilarityList
} from "@/api/work/work";
import NotPassed from '@/components/Approval/NotPassed.vue';
import { useWorkOrder } from "@/store/modules/workOrder";
import { isEmpty } from "@/utils";
import { formatToDateHMS } from "@/utils/dateUtil";
import emitter from '@/utils/mitt';
import { useInfiniteScroll } from "@vueuse/core";
import imagesloaded from "imagesloaded";
import { clone, debounce } from "lodash-es";
import { useDialog, useMessage } from "naive-ui";
import { onMounted, onUnmounted, onUpdated, reactive, ref, toRefs, unref, watch } from "vue";
import ConfrimModal from "../modal/ConfrimModal.vue";
import type { ApprovalParam, SimilarityPictureSortParam } from "/#/api";
const props = defineProps({
taskDetailInfo: {
type: Object,
default: () => ({}),
},
});
const { taskDetailInfo } = toRefs(props)
const batch = ref(false); //
const selectItems = ref<any[]>([]);
const message = useMessage();
const dialog = useDialog();
const totalCount = ref(0);
let _imagesload: any;
function setBatch(value: boolean) {
if (value && batch.value) {
batch.value = !value;
} else {
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 taskpagination = reactive({
pageNo: 1,
pageSize: 10,
});
const sortBy: SimilarityPictureSortParam = {
orderType: "desc",
orderName: "similarityScore",
};
const workStore = useWorkOrder();
const selectTask = ref<any>(null);
const overTask = ref<any>(null);
const confrimModalRef = ref(null);
const listData = ref<any[]>([]);
const loading = ref(false);
const el = ref<HTMLDivElement | null>(null);
const selectedSortName = ref('');
const notPassModalRef = ref(null)
let canloadMore = true;
let processItems: any[] = [];
function validate(items: any[]) {
if (items.length === 0) return "至少选中一个任务";
return null;
}
function reset() {
taskpagination.pageNo = 0;
taskpagination.pageSize = 20;
listData.value.length = 0;
loading.value = false;
canloadMore = true;
}
async function refreshHandler() {
reset();
useInfiniteScroll(
el as any,
() => {
loadMore();
},
{ distance: 10, canLoadMore: () => canloadMore }
);
}
async function loadMore() {
if (loading.value || el.value == null) return;
const more = await featchList();
listData.value.push(...more);
}
async function featchList() {
loading.value = true;
try {
taskpagination.pageNo += 1;
const { data, total, pageCount } = await getPictureSimilarityList(
{ ...taskpagination, ...sortBy, checkDuplicateId: workStore.activeId, pictureId: taskDetailInfo.value.id }
);
totalCount.value = total;
canloadMore = pageCount >= taskpagination.pageNo && pageCount > 0;
return data;
} catch (error) {
canloadMore = false;
return [];
}
}
const layout = debounce(() => {
if (el.value == null) return;
_imagesload = imagesloaded(".grid-item");
_imagesload.on("done", (instance) => {
if (!el.value) return;
loading.value = false;
});
_imagesload.on("fail", (instance) => {
message.error("图片错误");
loading.value = false;
});
}, 300);
watch(
() => taskDetailInfo.value.id,
async (newValue, oldValue) => {
if (newValue !== oldValue) {
if (isEmpty(taskDetailInfo.value.id)) {
listData.value.length = 0;
totalCount.value = 0;
return;
}
reset();
const more = await featchList();
listData.value.push(...more);
}
}, { deep: true, immediate: true }
);
//
async function handleSelect(item: any) {
const packageid = workStore.getActiveId;
if (isEmpty(packageid)) {
listData.value.length = 0;
totalCount.value = 0;
return;
}
}
async function sortHandler(orderby: "similarityScore" | "createdate") {
selectedSortName.value = orderby;
sortBy.orderName = orderby;
sortBy.orderType = sortBy.orderType === "asc" ? "desc" : "asc";
refreshHandler();
}
function overTaskHandelr(item: any) {
if (item?.historyStates === 2 || item?.historyStates == 3) {
overTask.value = null;
return;
}
if (validate([item]) == null && batch.value === false) overTask.value = item;
}
function leaveTaskHandler() {
overTask.value = null;
}
function singleRejectHandler(item) {
const modal = unref(notPassModalRef)! as any
modal.showModal([item])
}
function approvalHandler(items?: any) {
let cloneItem: any
if (batch.value) {
processItems = selectItems.value
}
else if (overTask.value) {
cloneItem = clone(overTask.value)
processItems = [cloneItem]
}
// => => /
if (items !== undefined && !(items instanceof PointerEvent))
processItems = [items]
const msg = validate(processItems)
if (msg !== null) {
message.error(msg)
return
}
const list: any = []
processItems.forEach((item) => {
list.push({
formId: item.id,
taskId: item.taskId,
taskName: item.fromTaskName,
})
})
const param = {
result: true,
comment: '',
disposeType: '',
disposeTypeId: '',
failCauseId: '',
failCauseName: '',
flowTaskInfoList: list,
}
dialog.info({
title: '确认提示',
content: '确认给该任务审批为【通过】吗?',
positiveText: '确定',
negativeText: '取消',
onPositiveClick: () => {
doAudit(param)
},
onNegativeClick: () => { },
})
}
function doAudit(param: any) {
audit(param).then((res) => {
const { code } = res
setBatch(false)
if (code === 'OK') {
message.info(res.message)
emitter.emit('refresh')
refreshHandler()
}
else message.error(res.message)
})
}
function reloadList() {
setBatch(false)
refreshHandler()
}
function reject(idOrDesc: string, backId: string, isOther: boolean) {
const formIds: string[] = processItems.map(item => item.id)
const taskIds: string[] = processItems.map(item => item.taskId)
const tasknames: string[] = processItems.map(item => item.taskname)
const param: ApprovalParam = {
formid: formIds,
taskId: taskIds,
approvd: false,
taskComment: idOrDesc,
taskname: isOther ? tasknames : ['其他'],
}
doAudit(param)
}
onMounted(async () => {
})
onUpdated(() => {
layout();
});
onUnmounted(() => {
workStore.reset();
});
</script>
<template>
<div>
<div style="display: flex; justify-content: space-between; padding: 12px 0px 3px 0">
<div>
<span
style="font-size: 18px; font-weight: Medium;color: #333333;font-family: PingFang SC, PingFang SC-Medium;">任务包图片</span>
</div>
<div style="display: flex; align-items: center;font-size: 14px;margin-right: 25px;color:#323233">
<div style="cursor: pointer" @click="sortHandler('createdate')">
<span>时间排序</span>
<SvgIcon style="margin-left: 5px" name="sort" size="12" v-show="selectedSortName !== 'createdate'" />
<SvgIcon style="margin-left: 5px" name="active-sort" size="12" v-show="selectedSortName === 'createdate'" />
</div>
<div style="margin-left: 15px; cursor: pointer" @click="sortHandler('similarityScore')">
<span>相似度排序</span>
<SvgIcon style="margin-left: 5px" name="sort" size="12" v-show="selectedSortName !== 'similarityScore'" />
<SvgIcon style="margin-left: 5px" name="active-sort" size="12"
v-show="selectedSortName === 'similarityScore'" />
</div>
</div>
</div>
<div class="wrapper-list">
<div v-for="(item, index) in listData" :key="index" :class="{ 'item-selected': item === selectTask }"
class="grid-item" @click="handleSelect(item)" @mouseover="overTaskHandelr(item)" @mouseleave="leaveTaskHandler">
<div class="img-wrapper" :style="{ 'background-image': `url(${item.imgurl})` }" />
<div class="time-wrapper">
<div class="time">
<SvgIcon color="#FFF" size="16" name="camera" />
<span class="current-time">{{ item.photoDateTimestamp ? formatToDateHMS(Number(item.photoDateTimestamp) ||
0) : '-'
}}</span>
</div>
<div class="time">
<SvgIcon color="#FFF" size="16" name="save" />
<span class="current-time">{{ item.submitDateTimestamp ? formatToDateHMS(Number(item.submitDateTimestamp)
|| 0) : '-'
}}</span>
</div>
</div>
<div class="check">
<n-checkbox v-show="batch && item.historyStates !== 2 && item.historyStates !== 3"
v-model:checked="item.checked" @click.stop @update:checked="onCheckChange($event, item)" />
</div>
<div class="percent" :class="{ 'percent-red': item?.maxSimilarity >= 100 }">
<div class="val">
{{ item?.maxSimilarity && Number(item?.maxSimilarity).toFixed(0) }}<span class="percent-unit">%</span>
</div>
</div>
<div class="pass-status" v-if="item.historyStates === 2">
<SvgIcon name="pass-icon" style="width:52;height:24px" />
</div>
<div class="pass-status" v-else-if="item.historyStates === 3">
<SvgIcon name="no-pass-icon" style="width:52;height:24px" />
</div>
<div v-show="overTask && overTask.id === item.id" class="action">
<SvgIcon style="cursor: pointer" name="t1" @click.stop="approvalHandler" />
<SvgIcon style="cursor: pointer;margin-left: 40px;" name="t2" @click.stop="singleRejectHandler(item)" />
</div>
</div>
</div>
<NotPassed ref="notPassModalRef" @success="reloadList" />
<ConfrimModal ref="confrimModalRef" @commit="reject" />
</div>
</template>
<style lang="less" scoped>
.wrapper-list {
display: flex;
flex-wrap: wrap;
flex-direction: row;
justify-content: flex-start;
flex-shrink: 0;
.item-selected {
box-shadow: 0px 2px 8px 0px rgba(0, 65, 207, 0.28);
background-color: #fff;
}
.grid-item {
box-sizing: border-box;
border-radius: 8px;
padding: 9px 5px;
position: relative;
.img-wrapper {
width: 230px;
height: 130px;
overflow: hidden;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
border-radius: 8px;
}
.time-wrapper {
position: absolute;
bottom: 9px;
width: calc(100% - 11px);
height: 58px;
background: linear-gradient(180deg, rgba(0, 0, 0, 0.01), rgba(0, 0, 0, 0.71) 100%);
border-radius: 8px;
display: flex;
flex-direction: column;
justify-content: center;
font-weight: Medium;
padding-left: 12px;
color: white;
.time .current-time {
margin-left: 9px;
font-weight: Medium;
}
}
.check {
position: absolute;
z-index: 3;
left: 12px;
top: 12px;
}
.percent {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
width: 35px;
height: 18px;
opacity: 0.9;
background: #6f92fd;
border-radius: 6px 0px 6px 0px;
z-index: 5;
right: 12px;
top: 15px;
color: #fff;
font-size: 14px;
}
.percent-unit {
font-size: 8px;
margin-top: 4px;
}
.percent-red {
background: #ff4e4f;
}
.pass-status {
position: absolute;
left: 0px;
top: 15px;
}
.mark {
position: absolute;
z-index: 3;
right: 62px;
top: 9px;
width: 64px;
height: 40px;
overflow: hidden;
overflow: hidden;
svg {
position: absolute;
top: -20px;
}
}
.action {
position: absolute;
z-index: 5;
left: 4px;
top: 9px;
width: 230px;
height: 130px;
display: flex;
border-radius: 8px;
align-items: center;
justify-content: center;
background-color: rgba(0, 0, 0, 0.48);
}
}
}
::v-deep(.n-divider:not(.n-divider--vertical)) {
margin-top: 12px;
margin-bottom: 12px;
}
</style>

@ -13,7 +13,7 @@ import emitter from '@/utils/mitt';
import { useInfiniteScroll } from "@vueuse/core";
import { format } from 'date-fns';
import imagesloaded from "imagesloaded";
import { clone, debounce, pickBy } from "lodash-es";
import { clone, cloneDeep, debounce, pickBy } from "lodash-es";
import { useDialog, useMessage } from "naive-ui";
import { computed, onUnmounted, onUpdated, reactive, ref, unref, watch } from "vue";
import PictureInfo from "../components/PictureInfo.vue";
@ -71,6 +71,7 @@ const el = ref<HTMLDivElement | null>(null);
const selectedSortName = ref('');
const isFullScreen = ref(false);
const notPassModalRef = ref(null)
const mainImageModalRef = ref(null)
let canloadMore = true;
@ -188,8 +189,6 @@ watch(
() => workStore.activeId,
async (newValue, oldValue) => {
const packageid = workStore.getActiveId;
if (isEmpty(packageid)) {
listData.value.length = 0;
totalCount.value = 0;
@ -272,7 +271,7 @@ function immersionHandler() {
}
function showAction() {
const item = taskDetailInfo.value;
const item = taskDetailInfo.value;
if (item.historyStates === 2 || item.historyStates === 3) {
return
}
@ -294,6 +293,7 @@ function rejectHandler() {
const modal = unref(notPassModalRef)! as any
modal.showModal(selectItems.value)
}
function singleRejectHandler(item) {
const modal = unref(notPassModalRef)! as any
modal.showModal([item])
@ -313,6 +313,67 @@ function reject(idOrDesc: string, backId: string, isOther: boolean) {
doAudit(param)
}
function handleRejectMainImage() {
const modal = unref(mainImageModalRef)! as any
const params = cloneDeep(taskDetailInfo.value)
params.id = params.taskchildpictureid
modal.showModal([params])
}
async function reloadDetailInfo(){
const packageid = workStore.getActiveId;
taskDetailInfo.value = await getTaskDetailInfo(packageid);
}
function handleApproveMainImage(items?: any) {
let cloneItem: any
if (overTask.value) {
cloneItem = clone(overTask.value)
cloneItem.id = cloneItem.taskchildpictureid
processItems = [cloneItem]
}
const msg = validate(processItems)
if (msg !== null) {
message.error(msg)
return
}
const list: any = []
processItems.forEach((item) => {
list.push({
formId: item.id,
taskId: item.taskId,
taskName: item.fromTaskName,
})
})
const param = {
result: true,
comment: '',
disposeType: '',
disposeTypeId: '',
failCauseId: '',
failCauseName: '',
flowTaskInfoList: list,
}
dialog.info({
title: '确认提示',
content: '确认给该任务审批为【通过】吗?',
positiveText: '确定',
negativeText: '取消',
onPositiveClick: () => {
audit(param).then(async(res) => {
const { code } = res
if (code === 'OK') {
message.info(res.message)
const packageid = workStore.getActiveId;
taskDetailInfo.value = await getTaskDetailInfo(packageid);
}
else message.error(res.message)
})
},
onNegativeClick: () => { },
})
}
function approvalHandler(items?: any) {
let cloneItem: any
if (batch.value) {
@ -381,6 +442,9 @@ function reloadList() {
setBatch(false)
refreshHandler()
}
defineExpose({
queryDetail
})
</script>
<template>
@ -398,8 +462,8 @@ function reloadList() {
批量审批
</div>
<div class="icon-wrap">
<SvgIcon size="20" v-if="isFullScreen" name="power-off" @click="immersionHandler" style="cursor: pointer;"/>
<SvgIcon size="20" v-else name="immersion-model" @click="immersionHandler" style="cursor: pointer;"/>
<SvgIcon size="20" v-if="isFullScreen" name="power-off" @click="immersionHandler" style="cursor: pointer;" />
<SvgIcon size="20" v-else name="immersion-model" @click="immersionHandler" style="cursor: pointer;" />
</div>
</div>
@ -430,19 +494,21 @@ function reloadList() {
<div class="footer-times">
<div class="time" style="margin-bottom: 4px;">
<SvgIcon color="#FFF" size="16" name="camera" />
<span class="time-value">{{ taskDetailInfo?.submitDateTimestamp ? format(
taskDetailInfo.submitDateTimestamp, 'yyyy-MM-dd HH:mm:ss') : '-' }} </span>
<span class="time-value">{{ taskDetailInfo?.photoDateTimestamp ? format(
taskDetailInfo.photoDateTimestamp, 'yyyy-MM-dd HH:mm:ss') : '-' }} </span>
</div>
<div class="time">
<SvgIcon color="#FFF" size="16" name="save" />
<span class="time-value">{{
taskDetailInfo?.photoDateTimestamp ? format(taskDetailInfo?.photoDateTimestamp, 'yyyy-MM-dd HH:mm:ss') :
taskDetailInfo?.submitDateTimestamp ? format(taskDetailInfo?.submitDateTimestamp, 'yyyy-MM-dd HH:mm:ss')
:
'-'
}} </span>
</div>
</div>
<div class="status">
<img v-show="taskDetailInfo?.historyStates === 2" class="img-status" src="@/assets/images/task/pass.png" alt="">
<img v-show="taskDetailInfo?.historyStates === 2" class="img-status" src="@/assets/images/task/pass.png"
alt="">
<img v-show="taskDetailInfo?.historyStates === 3" class="img-status" src="@/assets/images/task/not_pass.png"
alt="">
</div>
@ -481,8 +547,8 @@ function reloadList() {
</div>
<!-- 操作 -->
<div v-show="overTask && overTask.id === taskDetailInfo.id" class="action" @click.stop="hideAction">
<SvgIcon style="cursor: pointer" name="t1" @click.stop="approvalHandler" />
<SvgIcon style="cursor: pointer; margin-left: 30px" name="t2" @click.stop="rejectHandler" />
<SvgIcon style="cursor: pointer" name="t1" @click.stop="handleApproveMainImage" />
<SvgIcon style="cursor: pointer; margin-left: 30px" name="t2" @click.stop="handleRejectMainImage" />
</div>
</div>
<PictureInfo :taskDetailInfo="taskDetailInfo"></PictureInfo>
@ -526,13 +592,12 @@ function reloadList() {
</div>
</div>
<div class="check">
<n-checkbox v-show="batch && item.historyStates !== 2 && item.historyStates !== 3" v-model:checked="item.checked" @click.stop
@update:checked="onCheckChange($event, item)" />
<n-checkbox v-show="batch && item.historyStates !== 2 && item.historyStates !== 3"
v-model:checked="item.checked" @click.stop @update:checked="onCheckChange($event, item)" />
</div>
<div class="percent">
<SvgIcon size="42" name="tag" />
<div class="percent" :class="{ 'percent-red': item?.maxSimilarity >= 100 }">
<div class="val">
{{ item?.maxSimilarity && Number(item?.maxSimilarity).toFixed(0) }}%
{{ item?.maxSimilarity && Number(item?.maxSimilarity).toFixed(0) }}<span class="percent-unit">%</span>
</div>
</div>
@ -552,6 +617,7 @@ function reloadList() {
</n-spin>
<ConfrimModal ref="confrimModalRef" @commit="reject" />
<NotPassed ref="notPassModalRef" @success="reloadList" />
<NotPassed ref="mainImageModalRef" @success="reloadDetailInfo" />
</div>
</template>
@ -604,6 +670,7 @@ function reloadList() {
margin-left: 6px;
}
}
.right {
display: flex;
align-items: center;
@ -862,6 +929,7 @@ function reloadList() {
color: #507AFD;
border: 1px solid #507AFD;
}
.tag-submiting {
color: #FFB800;
border: 1px solid #FFB800;
@ -963,29 +1031,28 @@ function reloadList() {
.percent {
position: absolute;
text-align: center;
z-index: 3;
right: 17px;
top: 2px;
display: flex;
align-items: center;
justify-content: center;
width: 35px;
height: 18px;
opacity: 0.9;
background: #6f92fd;
border-radius: 6px 0px 6px 0px;
z-index: 5;
right: 12px;
top: 15px;
color: #fff;
font-size: 14px;
}
.val {
position: absolute;
left: 0;
top: 0;
display: block;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-family: PingFang SC, PingFang SC-Semibold;
font-weight: Semibold;
text-align: left;
color: #ffffff;
line-height: 24px;
}
.percent-unit {
font-size: 8px;
margin-top: 4px;
}
.percent-red {
background: #ff4e4f;
}
.pass-status {

@ -1,22 +1,30 @@
<script lang="ts" setup>
import DataHeader from '@/components/DataHeader/index.vue';
import Aside from './aside/Aside.vue';
import Content from './content/Content.vue';
import DataHeader from "@/components/DataHeader/index.vue";
import { ref } from "vue";
import Aside from "./aside/Aside.vue";
import Content from "./content/Content.vue";
import { useWorkOrder } from "@/store/modules/workOrder";
const workStore = useWorkOrder();
const contentRef: any = ref(null);
const ApprovalOver = (packageId) => {
const id: string = workStore.getActiveId;
contentRef.value.queryDetail(id);
};
</script>
<template>
<div style="width: 100%;">
<div style="width: 100%">
<div class="header">
<DataHeader v-show="false"/>
<DataHeader v-show="false" />
</div>
<div class="main">
<!-- 侧边 -->
<Aside />
<div class="main">
<!-- 侧边 -->
<Aside @ApprovalOver="ApprovalOver" />
<!-- 内容 -->
<Content />
<!-- 内容 -->
<Content ref="contentRef" />
</div>
</div>
</div>
</template>
<style lang="less" scoped>

@ -8,7 +8,7 @@ import { getToolsCount } from "@/api/home/main";
import { storage } from "@/utils/Storage";
import { CURRENT_USER } from "@/store/mutation-types";
const emit = defineEmits<{
(e: "reject", params: any);
(e: "reject", params?: any);
(e: "notPass", params: any);
}>();
const message = useMessage()
@ -62,6 +62,7 @@ const handleReject = async () => {
}else{
message.error(res.message)
}
emit('reject',state.packageid)
closeModal();
};
@ -139,10 +140,10 @@ defineExpose({
<div class="item">
<div class="imgwrapper" />
<div class="content">
<div class="task_id">#AI任务包{{ detail.packageId }}</div>
<div class="task_id">{{ detail.packageName }}</div>
<div class="tag_box">
<div class="tag_item error">
<span style="color: red">error</span> 重复图片({{
<span style="color: red"><SvgIcon name="error_icon" size="14"/></span> 重复图片({{
detail.similarComplete || 0
}})
</div>

Loading…
Cancel
Save