bak
Dragon 1 year ago
parent e7c37bc426
commit a0e518ab24

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B

@ -0,0 +1,42 @@
import type { RouteRecordRaw } from 'vue-router'
import { Layout } from '@/router/constant'
/**
* @param name , ,
* @param meta
* @param redirect , 访,
* @param meta.disabled
* @param meta.title
* @param meta.icon
* @param meta.keepAlive
* @param meta.sort
*
*/
const routes: Array<RouteRecordRaw> = [
{
path: '/',
name: 'message',
redirect: '/message',
component: Layout,
meta: {
title: '消息通知',
permissions: ['worksheet-main'],
svgname: 'worksheet',
svgsize: 22,
sort: 2,
disabled: true,
},
children: [
{
path: 'message',
name: 'message-main',
meta: {
title: 'message',
},
component: () => import('@/views/message/index.vue'),
},
],
},
]
export default routes

@ -29,7 +29,7 @@ const router = useRouter()
const route = useRoute() const route = useRoute()
const show = ref(true) const show = ref(true)
const showForget = ref(true) const showForget = ref(true)
const ifLogin = ref(false) const ifLogin = ref(true)
const formInline: FormState = reactive({ const formInline: FormState = reactive({
enterprisecode: '三方系统标识8', enterprisecode: '三方系统标识8',
@ -38,77 +38,10 @@ const formInline: FormState = reactive({
captcha: '', captcha: '',
}) })
const rules = {
enterprisecode: { required: true, message: '请输入企业编码', trigger: 'blur' },
username: { required: true, message: '请输入用户名', trigger: 'blur' },
password: { required: true, message: '请输入密码', trigger: 'blur' },
captcha: { required: true, message: '请输入验证码', trigger: 'blur' },
}
function handleSubmit(e) {
e.preventDefault()
formRef.value.validate(async (errors) => {
if (!errors) {
const { username, password, enterprisecode, captcha } = formInline
message.loading('登录中...')
loading.value = true
const params = {
logincode: captcha,
username,
password,
codetoken: userStore.getCapToken,
agentcode: enterprisecode,
}
try {
const { code, message: msg } = await userStore.login(params)
await userStore.getInformation()
const response = await getFilter()
//
if (response.data === null) {
const systemConfig = await getConfig()
const onList: string[] = []
Object.keys(systemConfig.data).forEach((key) => {
//
if (key.startsWith('iz') && systemConfig.data[key] === 'Y' && asideMap[key]?.isDefaultFilter)
onList.push(key)
})
await setFilter({ searchcount: onList.join(',') })
}
message.destroyAll()
if (code === ResultEnum.SUCCESS) {
const toPath = decodeURIComponent((route.query?.redirect || '/') as string)
message.success('登录成功,即将进入系统')
if (route.name === LOGIN_NAME)
router.replace('/')
else router.replace(toPath)
}
else {
message.info(msg || '登录失败')
}
}
finally {
loading.value = false
}
}
else {
message.error('请填写完整信息,并且进行验证码校验')
}
})
}
function showLogin() { function showLogin() {
show.value = true show.value = true
} }
function forget() {
show.value = false
showForget.value = true
}
function close() { function close() {
show.value = false show.value = false
ifLogin.value = true ifLogin.value = true

@ -0,0 +1,163 @@
<script lang="ts" setup>
import { computed, defineOptions, nextTick, onBeforeMount, onMounted, reactive, ref, unref } from 'vue'
import CustomFieldModalVue from '../modal/CustomFieldModal.vue'
import WorkSheetList from './WorkSheetList.vue'
import { useWindowSizeFn } from '@/hooks/event/useWindowSizeFn'
import { getViewportOffset } from '@/utils/domUtils'
import type { PackageListItem } from '/#/workorder'
import { useWorkOrder } from '@/store/modules/workOrder'
defineOptions({ name: 'AsideContent' })
const collapse = ref(false)
const workStore = useWorkOrder()
const filterModalRef = ref(null)
function collapseHandler() {
collapse.value = !collapse.value
}
const asideWidth = computed(() => {
return collapse.value ? 0 : 308
})
const asideStyle = computed(() => {
return {
width: `${asideWidth.value}px`,
}
})
const collapseIcon = computed(() => {
return collapse.value ? 'expand-cir' : 'collapse-cir'
})
const listHeight = ref(700)
function computeListHeight() {
const listEl = document.querySelector('.work-sheet-list')!
const { bottomIncludeBody } = getViewportOffset(listEl)
const height = bottomIncludeBody
listHeight.value = height - 25
}
const listStyle = computed(() => {
return {
height: `${listHeight.value}px`,
}
})
useWindowSizeFn(computeListHeight, 280)
onMounted(() => {
nextTick(() => {
computeListHeight()
})
})
const data = ref<PackageListItem[]>([])
const pagination = reactive({
pageNo: 1,
pageSize: 10,
})
onBeforeMount(async () => {
const orderList = await workStore.fetchOrderList(pagination)
data.value = orderList
})
const asideEnter = ref(false)
const showCollapse = computed(() => {
return collapse.value ? true : asideEnter.value
})
function showFilter() {
const modal = unref(filterModalRef)! as any
modal.showModal()
}
</script>
<template>
<div class="aside" :style="asideStyle" @mouseenter="asideEnter = true" @mouseleave="asideEnter = false">
111fsfsf发送到发
<div v-show="showCollapse" class="aside-collapse">
<div class="aside-collapse-btn" @click="collapseHandler">
<SvgIcon :name="collapseIcon" size="40" />
</div>
</div>
<div class="aside-header">
<div class="aside-header-left">
<svg-icon name="all-worksheet" size="32" />
<span style="margin-left: 8px;">所有工单</span>
</div>
<div class="aside-header-right">
<SvgIcon style="cursor: pointer;margin-left: 10px;" size="18" name="magnifying-1" />
<SvgIcon style="cursor: pointer;margin-left: 10px;" size="18" name="filter" @click="showFilter" />
</div>
</div>
<WorkSheetList :style="listStyle" class="work-sheet-list" :data="data" :active-id="workStore.getActiveId" />
<CustomFieldModalVue ref="filterModalRef" />
</div>
</template>
<style lang="less" scoped>
.aside {
display: flex;
position: relative;
flex-direction: column;
background: #FFF;
border: 1px solid rgb(239, 239, 245);
border-radius: 3px;
box-sizing: border-box;
&-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 16px;
width: 100%;
overflow: hidden;
&-left {
display: flex;
align-items: center;
overflow: hidden;
}
&-right {
display: flex;
align-items: center;
overflow: hidden;
}
}
&-divider {
margin-left: 16px;
width: 292px;
height: 1px;
background-color: #e8e8e8;
}
&-collapse {
width: 2px;
height: 100%;
background: #507afd;
position: absolute;
right: 0;
top: 0;
}
&-collapse-btn {
position: absolute;
cursor: pointer;
width: 40px;
height: 40px;
top: calc(15%);
right: -20px;
z-index: 10;
}
}
</style>
../types

@ -0,0 +1,90 @@
<script lang="ts" setup>
import { computed } from 'vue'
import type { PackageListItem } from '/#/workorder'
defineOptions({ name: 'ListItem' })
const props = defineProps({
selected: {
type: Boolean,
default: false,
},
listItem: {
type: Object as PropType<PackageListItem>,
required: true,
},
})
const svgName = computed(() => {
return props.selected ? 'taskpack-select' : 'taskpack'
})
</script>
<template>
<div class="list-item" :class="{ 'list-item-selected': selected }">
<div class="list-item-header">
<div style="display: flex;">
<SvgIcon :name="svgName" size="28" />
<span class="list-item-header-name" :class="{ 'list-item-header-selected': selected }">
{{ listItem.packagename }}
</span>
<span class="list-item-header-selected">({{ listItem.pictureno }})</span>
</div>
<SvgIcon v-show="selected" size="14" name="more-ver" />
</div>
<ul class="list-item-detail">
<li>筛选时间{{ listItem.createTime }}</li>
<li>执行人{{ listItem.createBy }}</li>
</ul>
<div class="list-item-divider" />
</div>
</template>
<style lang="less" scoped>
.list-item {
padding: 12px 0px 12px 16px;
position: relative;
&-header {
display: flex;
align-items: center;
&-name {
font-size: 16px;
font-weight: bold;
color: #333333;
line-height: 22px;
margin: 0px 0px 8px 8px;
}
&-selected {
color: #507AFD;
}
}
&-selected {
background-color: #f2f5fe;
}
&-detail {
margin-left: 36px;
li {
font-size: 13px;
color: #666666;
line-height: 18px;
margin-bottom: 8px;
}
}
&-divider {
width: 100%;
height: 1px;
background-color: #e8e8e8;
position: absolute;
bottom: 0px;
}
}
</style>
../types

@ -0,0 +1,37 @@
<script lang="ts" setup>
import type { PackageListItem } from '/#/workorder'
import ListItem from './ListItem.vue'
import { useWorkOrder } from '@/store/modules/workOrder'
defineOptions({ name: 'WorkSheetList' })
defineProps({
activeId: {
type: String,
required: true,
},
data: {
type: Object as PropType<PackageListItem[]>,
required: true,
},
})
const workStore = useWorkOrder()
function selectHandler(id: string, index: number) {
workStore.setActive(index)
}
</script>
<template>
<n-scrollbar>
<ListItem
v-for="(item, index) in data" :key="item.id" :selected="activeId === item.id" :list-item="item"
@click="selectHandler(item.id, index)"
/>
</n-scrollbar>
</template>
<style lang="less" scoped>
</style>
../types

@ -0,0 +1,515 @@
<script lang="ts" setup>
import { computed, onUnmounted, reactive, ref, unref, watch } from 'vue'
import { useDialog, useMessage } from 'naive-ui'
import { clone, pickBy } from 'lodash-es'
import ConfrimModal from '../modal/ConfrimModal.vue'
import type { PictureSortParam, SetTFParam } from '/#/api'
import { useWorkOrder } from '@/store/modules/workOrder'
import { clearTF, getPackageTaskList, getTaskDetailInfo, getTaskDetailPictureList, setTF } from '@/api/work/work'
import { fieldMap } from '@/config/workorder'
const batch = ref(false)
const selectItems = ref<any[]>([])
const message = useMessage()
const dialog = useDialog()
const totalCount = ref(0)
function setBatch(value: boolean) {
batch.value = value
if (value === false) {
selectItems.value.forEach(item => item.checked = false)
selectItems.value.length = 0
}
}
function onCheckChange(checked: any, item: any) {
const index = selectItems.value.indexOf(item)
item.checked = checked
if (index === -1 && checked)
selectItems.value.push(item)
else
selectItems.value.splice(index, 1)
}
const showActions = computed(() => {
return selectItems.value.length > 0 && batch
})
const packagepagination = reactive({
pageNo: 1,
pageSize: 10,
})
const taskpagination = reactive({
pageNo: 1,
pageSize: 10,
})
const sortBy: PictureSortParam = {
orderbyname: 'desc',
orderbyvalue: 'fromuptime',
}
const workStore = useWorkOrder()
const selectTask = ref<any>(null)
const overTask = ref<any>(null)
const taskList = ref<any[]>([])
const taskDetailInfo = ref<any>({})
const taskDetailPictureList = ref<any[]>([])
const confrimModalRef = ref(null)
let processItems: any[] = []
const tab = ref(0)
function validate(items: any[]) {
if (items.length === 0)
return '至少选中一个任务'
for (const item of items) {
const { iztrueorfalse, history, states } = item
if (iztrueorfalse !== null)
return '存在已经辨识过的任务'
else if (history)
return '包含历史数据'
else if (states !== 1 && states !== 2)
return '审批状态不合法'
}
return null
}
function falseHandler() {
let cloneItem: any
if (batch.value) { processItems = selectItems.value }
else if (overTask.value) {
cloneItem = clone(overTask.value)
processItems = [cloneItem]
}
const msg = validate(processItems)
if (msg !== null) {
message.error(msg)
return
}
const modal = unref(confrimModalRef)! as any
modal.showModal()
}
function trueHandler() {
let cloneItem: any
if (batch.value) { processItems = selectItems.value }
else if (overTask.value) {
cloneItem = clone(overTask.value)
processItems = [cloneItem]
}
const msg = validate(processItems)
if (msg !== null) {
message.error(msg)
return
}
dialog.info({
title: '确认提示',
content: '确认给该任务图判真吗?',
positiveText: '确定',
negativeText: '取消',
onPositiveClick: () => {
setTrue()
},
onNegativeClick: () => { },
})
}
function setTrue() {
const ids: any[] = processItems.map(item => item.id)
const param: SetTFParam = {
taskchildpictureids: ids.join(','),
iztrueorfalse: 1,
packageid: workStore.getActiveId,
judgeid: '0',
}
doSetTF(param)
}
function setFalse(id: string, desc: null | string) {
const ids: any[] = processItems.map(item => item.id)
const param: SetTFParam = {
taskchildpictureids: ids.join(','),
iztrueorfalse: 0,
packageid: workStore.getActiveId,
judgeid: id,
}
if (desc)
param.judgedesc = desc
doSetTF(param)
}
function doSetTF(param: SetTFParam) {
setTF(param).then((res) => {
const { code } = res
processItems.length = 0
if (code === 'OK')
updateList(param)
else
message.error(res.message)
})
}
function updateList(param: SetTFParam) {
const list = taskDetailPictureList.value
const ids = param.taskchildpictureids.split(',')
for (const item of list) {
if (ids.includes(item.id))
item.iztrueorfalse = param.iztrueorfalse
}
}
function forwardHandler() {
workStore.forward()
}
function backHandler() {
workStore.back()
}
watch(() => workStore.activeId, async (newValue, oldValue) => {
const res = await getPackageTaskList(newValue, packagepagination)
const { data } = res
taskList.value = data
if (taskList.value.length > 0)
handleSelect(taskList.value[0])
})
const packageName = computed(() => {
const index = workStore.getCurrentIndex
return workStore.getOrderList[index]?.packagename || ''
})
async function handleSelect(item: any) {
selectTask.value = item
const taskId = item.id
taskDetailInfo.value = await getTaskDetailInfo(taskId, workStore.activeId)
const { data, total } = await getTaskDetailPictureList(workStore.activeId, taskId, { ...taskpagination, ...sortBy })
taskDetailPictureList.value = data
totalCount.value = total
}
async function sortHandler(orderby: 'pictureResult' | 'fromuptime') {
if (!selectTask.value)
return
taskpagination.pageNo = 1
taskpagination.pageSize = 10
sortBy.orderbyvalue = orderby
const res = await getTaskDetailPictureList(workStore.activeId, selectTask.value.id, { ...taskpagination, ...sortBy })
taskDetailPictureList.value = res.data
}
const propertys = computed(() => {
const { ocrPicture } = taskDetailInfo.value
const v = pickBy(ocrPicture, (value, key: string) => {
return key.startsWith('field') && value !== null
})
return v
})
async function clearMark() {
const res = await clearTF(workStore.activeId, selectTask.value.id)
if (res.code === 'OK') {
taskDetailInfo.value.iztrueorfalse = null
message.info('清除标记成功')
}
else { message.error(res.message) }
}
function overTaskHandelr(item: any) {
if (validate([item]) == null && batch.value === false)
overTask.value = item
}
function leaveTaskHandler() {
overTask.value = null
}
onUnmounted(() => {
workStore.reset()
})
function getPercent(pictureid: string) {
const { ocpictureid, pictureresult } = taskDetailInfo.value
const index = ocpictureid.split(',').indexOf(String(pictureid))
const results = pictureresult.split(',')
const percent = results[index] || '0'
const val = Number.parseFloat(percent)
return `${val}%`
}
const mark = computed(() => {
return taskDetailInfo.value.iztrueorfalse === null ? '未标记' : '已标记'
})
function switchTab(type: number) {
tab.value = type
}
</script>
<template>
<div class="wrapper-message">
<div class="header flex justify-between">
<div class="header-title">
消息通知
</div>
<div class="clear">
清除未读
</div>
</div>
<div class="content">
<div class="slider">
<div :class="{ 'item-active': tab === 0 }" class="item flex" @click="switchTab(0)">
<div class="item-left flex align-center">
<img class="icon" src="@/assets/images/login/logo.png" alt="">
<div class="text">
审批通知
</div>
</div>
<img class="icon-arrow" src="@/assets/images/login/arrow-active.png" alt="">
<div v-if="tab === 0" class="line" />
</div>
<div :class="{ 'item-active': tab === 1 }" class="item flex" @click="switchTab(1)">
<div class="item-left flex align-center">
<img class="icon" src="@/assets/images/login/logo.png" alt="">
<div class="text">
系统消息
</div>
</div>
<img class="icon-arrow" src="@/assets/images/login/arrow-active.png" alt="">
<div v-if="tab === 1" class="line" />
</div>
</div>
<div class="list">
<div class="item">
<div class="left left">
<div class="num">
23
<div class="point" />
</div>
<div class="date">
2024.01
</div>
</div>
<div class="middle">
<div class="title">
系统升级通知占位符占位占位系统升级通知占位符占位占位系统升级通知占位符占位占位
</div>
<div class="subtitle">
<span class="name">系统管理员</span>
<span class="time">2024-01-31 23:12:00</span>
</div>
</div>
<div class="look">
查看
</div>
</div>
</div>
</div>
</div>
</template>
<style lang="less" scoped>
.wrapper-message {
display: flex;
flex: 1;
flex-direction: column;
box-sizing: border-box;
background: #FFF;
border-radius: 3px;
border: 1px solid rgb(239, 239, 245);
height: calc(100vh - 88px);
overflow-y: scroll;
.header{
padding: 24px;
&-title{
font-size: 20px;
font-family: PingFang SC, PingFang SC-Medium;
font-weight: Medium;
color: #333333;
line-height: 28px;
}
.clear{
font-size: 14px;
font-family: PingFang SC, PingFang SC-Regular;
font-weight: Regular;
color: #666666;
line-height: 20px;
}
}
.content{
display: flex;
padding-right: 24px;
.slider{
.icon{
width: 17px;
height: 17px;
}
.icon-arrow{
width: 14px;
height: 14px;
}
.item{
width: 200px;
height: 44px;
position: relative;
padding: 0 24px;
box-sizing: border-box;
align-items: center;
justify-content: space-between;
&-active{
background: rgba(80,122,253,.1);
}
}
.item-left{
align-items: center;
}
.text{
font-size: 14px;
font-family: PingFang SC, PingFang SC-Medium;
font-weight: 600;
color: #333333;
margin-left: 12px;
&-text{
color: #507AFD;
}
}
.line{
position: absolute;
width: 3px;
height: 44px;
background: #5376ff;
left: 0;
top: 0;
}
}
.list{
margin-left: 24px;
flex: 1;
.item{
display: flex;
align-items: center;
justify-content: space-between;
flex: 1;
height: 96px;
border-bottom: 1px solid #eeeeee;
padding-right: 25px;
}
.num{
font-size: 32px;
font-family: HarmonyOS Sans SC, HarmonyOS Sans SC-Medium;
font-weight: Medium;
text-align: left;
color: #507afd;
line-height: 46px;
position: relative;
}
.date{
font-size: 12px;
font-family: PingFang SC, PingFang SC-Regular;
font-weight: Regular;
text-align: left;
color: #999999;
line-height: 17px;
}
.point{
position: absolute;
right: -2px;
top: 5px;
width: 8px;
height: 8px;
border-radius: 50%;
background: #ff4e4f;
}
.left{
width: 80px;
height: 64px;
border-right: 1px solid #e8e8e8;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.middle{
flex: 1;
padding-left: 20px;
}
.title{
font-size: 16px;
font-family: PingFang SC, PingFang SC-Medium;
font-weight: Medium;
text-align: left;
color: #666666;
line-height: 25px;
}
.subtitle{
font-size: 12px;
font-family: PingFang SC, PingFang SC-Regular;
font-weight: Regular;
text-align: left;
color: #999999;
line-height: 19px;
margin-top: 8px;
}
.name{
margin-right: 16px;
}
.look{
font-size: 14px;
font-family: PingFang SC, PingFang SC-Regular;
font-weight: Regular;
text-align: left;
color: #5376ff;
line-height: 20px;
}
}
}
}
// ::v-deep(.n-divider:not(.n-divider--vertical)) {
// margin-top: 12px;
// margin-bottom: 12px;
// }
</style>

@ -0,0 +1,345 @@
<script lang="ts" setup>
import { computed, onUnmounted, reactive, ref, unref, watch } from 'vue'
import { useDialog, useMessage } from 'naive-ui'
import { clone, pickBy } from 'lodash-es'
import ConfrimModal from '../modal/ConfrimModal.vue'
import type { PictureSortParam, SetTFParam } from '/#/api'
import { useWorkOrder } from '@/store/modules/workOrder'
import { clearTF, getPackageTaskList, getTaskDetailInfo, getTaskDetailPictureList, setTF } from '@/api/work/work'
import { fieldMap } from '@/config/workorder'
const batch = ref(false)
const selectItems = ref<any[]>([])
const message = useMessage()
const dialog = useDialog()
const totalCount = ref(0)
function setBatch(value: boolean) {
batch.value = value
if (value === false) {
selectItems.value.forEach(item => item.checked = false)
selectItems.value.length = 0
}
}
function onCheckChange(checked: any, item: any) {
const index = selectItems.value.indexOf(item)
item.checked = checked
if (index === -1 && checked)
selectItems.value.push(item)
else
selectItems.value.splice(index, 1)
}
const showActions = computed(() => {
return selectItems.value.length > 0 && batch
})
const packagepagination = reactive({
pageNo: 1,
pageSize: 10,
})
const taskpagination = reactive({
pageNo: 1,
pageSize: 10,
})
const sortBy: PictureSortParam = {
orderbyname: 'desc',
orderbyvalue: 'fromuptime',
}
const workStore = useWorkOrder()
const selectTask = ref<any>(null)
const overTask = ref<any>(null)
const taskList = ref<any[]>([])
const taskDetailInfo = ref<any>({})
const taskDetailPictureList = ref<any[]>([])
const confrimModalRef = ref(null)
let processItems: any[] = []
const tab = ref(0)
function validate(items: any[]) {
if (items.length === 0)
return '至少选中一个任务'
for (const item of items) {
const { iztrueorfalse, history, states } = item
if (iztrueorfalse !== null)
return '存在已经辨识过的任务'
else if (history)
return '包含历史数据'
else if (states !== 1 && states !== 2)
return '审批状态不合法'
}
return null
}
function falseHandler() {
let cloneItem: any
if (batch.value) { processItems = selectItems.value }
else if (overTask.value) {
cloneItem = clone(overTask.value)
processItems = [cloneItem]
}
const msg = validate(processItems)
if (msg !== null) {
message.error(msg)
return
}
const modal = unref(confrimModalRef)! as any
modal.showModal()
}
function trueHandler() {
let cloneItem: any
if (batch.value) { processItems = selectItems.value }
else if (overTask.value) {
cloneItem = clone(overTask.value)
processItems = [cloneItem]
}
const msg = validate(processItems)
if (msg !== null) {
message.error(msg)
return
}
dialog.info({
title: '确认提示',
content: '确认给该任务图判真吗?',
positiveText: '确定',
negativeText: '取消',
onPositiveClick: () => {
setTrue()
},
onNegativeClick: () => { },
})
}
function setTrue() {
const ids: any[] = processItems.map(item => item.id)
const param: SetTFParam = {
taskchildpictureids: ids.join(','),
iztrueorfalse: 1,
packageid: workStore.getActiveId,
judgeid: '0',
}
doSetTF(param)
}
function setFalse(id: string, desc: null | string) {
const ids: any[] = processItems.map(item => item.id)
const param: SetTFParam = {
taskchildpictureids: ids.join(','),
iztrueorfalse: 0,
packageid: workStore.getActiveId,
judgeid: id,
}
if (desc)
param.judgedesc = desc
doSetTF(param)
}
function doSetTF(param: SetTFParam) {
setTF(param).then((res) => {
const { code } = res
processItems.length = 0
if (code === 'OK')
updateList(param)
else
message.error(res.message)
})
}
function updateList(param: SetTFParam) {
const list = taskDetailPictureList.value
const ids = param.taskchildpictureids.split(',')
for (const item of list) {
if (ids.includes(item.id))
item.iztrueorfalse = param.iztrueorfalse
}
}
function forwardHandler() {
workStore.forward()
}
function backHandler() {
workStore.back()
}
watch(() => workStore.activeId, async (newValue, oldValue) => {
const res = await getPackageTaskList(newValue, packagepagination)
const { data } = res
taskList.value = data
if (taskList.value.length > 0)
handleSelect(taskList.value[0])
})
const packageName = computed(() => {
const index = workStore.getCurrentIndex
return workStore.getOrderList[index]?.packagename || ''
})
async function handleSelect(item: any) {
selectTask.value = item
const taskId = item.id
taskDetailInfo.value = await getTaskDetailInfo(taskId, workStore.activeId)
const { data, total } = await getTaskDetailPictureList(workStore.activeId, taskId, { ...taskpagination, ...sortBy })
taskDetailPictureList.value = data
totalCount.value = total
}
async function sortHandler(orderby: 'pictureResult' | 'fromuptime') {
if (!selectTask.value)
return
taskpagination.pageNo = 1
taskpagination.pageSize = 10
sortBy.orderbyvalue = orderby
const res = await getTaskDetailPictureList(workStore.activeId, selectTask.value.id, { ...taskpagination, ...sortBy })
taskDetailPictureList.value = res.data
}
const propertys = computed(() => {
const { ocrPicture } = taskDetailInfo.value
const v = pickBy(ocrPicture, (value, key: string) => {
return key.startsWith('field') && value !== null
})
return v
})
async function clearMark() {
const res = await clearTF(workStore.activeId, selectTask.value.id)
if (res.code === 'OK') {
taskDetailInfo.value.iztrueorfalse = null
message.info('清除标记成功')
}
else { message.error(res.message) }
}
function overTaskHandelr(item: any) {
if (validate([item]) == null && batch.value === false)
overTask.value = item
}
function leaveTaskHandler() {
overTask.value = null
}
onUnmounted(() => {
workStore.reset()
})
function getPercent(pictureid: string) {
const { ocpictureid, pictureresult } = taskDetailInfo.value
const index = ocpictureid.split(',').indexOf(String(pictureid))
const results = pictureresult.split(',')
const percent = results[index] || '0'
const val = Number.parseFloat(percent)
return `${val}%`
}
const mark = computed(() => {
return taskDetailInfo.value.iztrueorfalse === null ? '未标记' : '已标记'
})
function switchTab(type: number) {
tab.value = type
}
</script>
<template>
<div class="wrapper-message">
<div class="left-card">
dd
</div>
<div class="right-card">
<img class="icon-set" src="@/assets/images/login/logo.png" alt="">
<div class="title">
系统消息
</div>
<div class="form">
<div class="form-item">
<div class="label">
任务名称
</div>
<div class="value">
dd
</div>
</div>
</div>
</div>
</div>
</template>
<style lang="less" scoped>
.wrapper-message {
display: flex;
flex: 1;
box-sizing: border-box;
border-radius: 3px;
border: 1px solid rgb(239, 239, 245);
height: calc(100vh - 88px);
overflow-y: auto;
.left-card{
height: 100%;
background: #ffffff;
border-radius: 4px;
flex: 1;
}
.right-card{
width: 280px;
height: 100%;
box-sizing: border-box;
background: #ffffff;
border-radius: 4px;
margin-left: 16px;
padding-top: 48px;
.title{
width: 80px;
height: 22px;
font-size: 20px;
font-family: PingFang SC, PingFang SC-Medium;
font-weight: Medium;
text-align: center;
color: #333333;
line-height: 22px;
}
.line{
width: 232px;
height: 1px;
border: 1px solid #eeeeee;
margin: 0 auto;
}
}
.icon-set{
width: 80px;
height: 80px;
margin: 0 auto;
margin-bottom: 24px;
}
}
</style>

@ -0,0 +1,25 @@
<script lang="ts" setup>
import Aside from './aside/Aside.vue'
import Content from './content/Content.vue'
import Detail from './content/Detail.vue'
</script>
<template>
<div class="main">
<!-- 侧边 -->
<!-- <Aside /> -->
<!-- 内容 -->
<!-- <Content /> -->
<Detail />
</div>
</template>
<style lang="less" scoped>
.main {
display: flex;
flex-direction: row;
box-sizing: border-box;
width: 100%;
}
</style>

@ -0,0 +1,167 @@
<script lang="ts" setup>
import { computed, onBeforeMount, ref } from 'vue'
import { useDictionary } from '@/store/modules/dictonary'
const emit = defineEmits<{
(e: 'commit', id: any, desc: null | string)
}>()
const dictonaryStore = useDictionary()
const show = ref(false)
const cardStyle = {
'width': '520px',
'--n-padding-bottom': '10px',
'--n-padding-left': '0px',
}
function showModal() {
show.value = true
}
function closeModal() {
show.value = false
}
defineExpose({
showModal,
})
const options = ref<any[]>([])
const selectId = ref(null)
const otherValue = ref(null)
const showOther = computed(() => {
for (const item of options.value) {
if (item.value === selectId.value && item.label === '其他')
return true
}
return false
})
async function handleSumbit(e: MouseEvent) {
e.preventDefault()
closeModal()
emit('commit', selectId.value, otherValue.value)
}
onBeforeMount(async () => {
const tfList = await dictonaryStore.fetchTFList()
options.value = tfList
})
</script>
<template>
<n-modal v-model:show="show" transform-origin="center">
<n-card :style="cardStyle" :bordered="false" size="huge" role="dialog" aria-modal="true">
<div class="wrapper">
<div class="wrapper-header">
<span class="wrapper-left">选择判假原因</span>
<div class="wrapper-right">
<div class="wrapper-right-close" @pointerdown="closeModal">
<div class="wrapper-right-icon" />
</div>
</div>
</div>
<div class="wrapper-content">
<span>判假原因</span>
<n-select v-model:value="selectId" style="margin-top: 10px;" :options="options" />
<n-input v-show="showOther" v-model:value="otherValue" style="margin-top: 10px;" type="textarea" />
</div>
</div>
<template #footer>
<div class="wrapper-footer">
<n-button type="info" @click="handleSumbit">
确认
</n-button>
<n-button secondary style="margin-left:15px" @click="closeModal">
取消
</n-button>
</div>
</template>
</n-card>
</n-modal>
</template>
<style lang="less" scoped>
.wrapper {
&-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
}
&-left {
font-weight: bold;
font-size: 16px;
}
&-right {
&-close {
width: 18px;
height: 18px;
cursor: pointer;
}
&-icon {
background: #000;
display: inline-block;
width: 18px;
height: 1px;
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
margin-bottom: 8px;
&:after {
content: '';
display: block;
width: 18px;
height: 1px;
background: #000;
transform: rotate(-90deg);
-webkit-transform: rotate(-90deg);
}
}
}
&-content {
padding: 18px 10px;
}
&-footer {
display: flex;
justify-content: flex-end;
}
&-info {
font-weight: bold;
position: relative;
&:before {
background-color: #1980ff;
content: '';
width: 5px;
border-radius: 2px;
top: 0;
bottom: 0;
position: absolute;
}
}
}
::v-deep(.n-card.n-card--content-segmented > .n-card__content:not(:first-child)) {
border: 0px;
}
::v-deep(.n-card > .n-card-header) {
--n-padding-top: 0px;
--n-padding-bottom: 12px;
}
::v-deep(.n-divider:not(.n-divider--vertical)) {
margin-top: 0px;
margin-bottom: 0px;
}
</style>

@ -0,0 +1,384 @@
<script lang="ts" setup>
import { computed, ref, watch } from 'vue'
import { difference } from 'lodash-es'
import { VueDraggable } from 'vue-draggable-plus'
import { workPackageMap } from '@/config/workorder'
//
const offList = ref<any[]>([])
//
const onList = ref<any[]>([])
const allCount = computed(() => {
return `全部筛选(共${offList.value.length - 1}个)`
})
const selectCount = computed(() => {
return `全部筛选(共${onList.value.length}个)`
})
function generatList() {
const keys = Object.keys(workPackageMap)
let showList: object[] = []
const hideList: object[] = []
const showStr = 'status'
const showKeys = showStr.split(',').map((key: string) => key.toLowerCase())
for (const key of keys) {
const name = workPackageMap[key]?.label
const isDefault = workPackageMap[key]?.isDefault
// Y
if (!isDefault) {
hideList.push({
id: key,
name: name || '未配置',
fix: isDefault,
checked: workPackageMap[key].isDefault,
})
}
}
showList = showKeys.reduce((acc, key) => {
const config = {
id: key,
name: workPackageMap[key].label || '未配置',
fix: workPackageMap[key].isDefault,
}
return [...acc, config]
}, [])
const fixedList = generateDefaultList()
hideList.unshift(...fixedList)
showList.unshift(...fixedList)
onList.value = showList
offList.value = hideList
return { showList, hideList }
}
function generateDefaultList() {
return Object.keys(workPackageMap).reduce((acc, key) => {
const { label, isDefault } = workPackageMap[key]
if (isDefault) {
const config = {
id: key,
name: label || '未配置',
fix: true,
checked: true,
}
return [...acc, config]
}
else {
return acc
}
}, [])
}
const show = ref(false)
const checkAll = ref(false)
function showModal() {
show.value = true
}
function closeModal() {
show.value = false
}
async function handleSumbit(e: MouseEvent) {
e.preventDefault()
closeModal()
}
defineExpose({
showModal,
})
generatList()
const selectIds = ref<string[]>([])
function onCheckAllChange(value) {
const ids: string[] = []
for (const item of offList.value) {
if (!item.fix) {
item.checked = value
ids.push(item.id)
}
}
selectIds.value = value ? ids : []
}
function onCheckChange(checked: any, item: any) {
const index = selectIds.value.indexOf(item.id)
item.checked = checked
if (index === -1 && checked)
selectIds.value.push(item.id)
else
selectIds.value.splice(index, 1)
}
const showIds = computed(() => {
return onList.value.map((item) => {
return item.id
})
})
watch(
() => selectIds.value.length,
(newVal, oldVal) => {
if (newVal === oldVal)
return
const action = newVal > oldVal ? 'add' : 'remove'
const diff = action === 'add' ? difference(selectIds.value, showIds.value) : difference(showIds.value, selectIds.value)
if (diff.length === 0)
return
if (action === 'add') {
for (const item of offList.value) {
if (!item.fix && diff.includes(item.id)) {
onList.value.push({
id: item.id,
name: item.name || '未配置',
fix: item.fix || false,
})
}
}
}
else {
const list = onList.value
for (let index = 0; index < list.length; index++) {
const item = list[index]
if (!item.fix && diff.includes(item.id)) {
list.splice(index, 1)
index--
}
}
}
},
)
watch(
() => showIds.value.length,
(newVal, oldVal) => {
if (newVal === oldVal)
return
const diff = difference(selectIds.value, showIds.value)
if (diff.length === 0)
return
for (const item of offList.value) {
if (!item.fix && diff.includes(item.id)) {
const index = selectIds.value.indexOf(item.id)
item.checked = false
selectIds.value.splice(index, 1)
}
}
},
)
function clearDragSource() {
onList.value = onList.value.filter((item) => {
return item.fix === true
})
}
function removeHandler(id: string) {
const index = onList.value.findIndex((item) => {
return item.id === id
})
if (index !== -1)
onList.value.splice(index, 1)
}
</script>
<template>
<n-modal v-model:show="show" transform-origin="center">
<n-card class="cardstyle" :bordered="false" size="huge" role="dialog" aria-modal="true">
<div class="wrapper">
<span class="wrapper-title">自定义任务包字段</span>
<div class="wrapper-bar">
<div class="wrapper-info">
<span :style="{ 'margin-left': '18px' }">字段信息</span>
</div>
</div>
<n-grid cols="4" class="mt-4 proCard" responsive="screen" :x-gap="24">
<n-grid-item span="3">
<NCard
:title="allCount" class="dragcardStyle" :segmented="{ content: true, footer: true }" size="small"
:bordered="false"
>
<div>
<n-input placeholder="搜索关键字">
<template #suffix>
<SvgIcon size="14px" name="magnifying-1" />
</template>
</n-input>
<div class="draggable-ul">
<div class="draggable-li">
<n-checkbox v-model:checked="checkAll" label="全部" @update:checked="onCheckAllChange" />
</div>
<div class="content">
<div
v-for="item in offList" :key="item.id" style="width: 170px;"
:class="{ 'disable-check': item.fix }" class="draggable-li"
>
<n-checkbox
v-model:checked="item.checked" :label="item.name" :disabled="item.fix"
@update:checked="onCheckChange($event, item)"
/>
</div>
</div>
</div>
</div>
</NCard>
</n-grid-item>
<n-grid-item>
<NCard
:title="selectCount" class="dragcardStyle" :segmented="{ content: true, footer: true }" size="small"
:bordered="false"
>
<template #header-extra>
<span class="textbtnStyle" @click="clearDragSource"></span>
</template>
<div>
<n-input placeholder="搜索关键字">
<template #suffix>
<SvgIcon size="14px" name="magnifying-1" />
</template>
</n-input>
<VueDraggable v-model="onList" class="draggable-ul" :animation="150" group="shared">
<div
v-for="item in onList" :key="item.id" :class="{ fix: item.fix }"
class="cursor-move draggable-item"
>
<span class="ml-2">{{ item.name }}</span>
<SvgIcon
v-if="!item.fix" size="16px" style="display: block; margin-left: auto; cursor: pointer"
name="clear" @click="removeHandler(item.id)"
/>
</div>
</VueDraggable>
</div>
</NCard>
</n-grid-item>
</n-grid>
</div>
<template #footer>
<div class="wrapper-footer">
<n-button type="info" @click="handleSumbit">
确认
</n-button>
<n-button secondary style="margin-left:15px" @click="closeModal">
取消
</n-button>
</div>
</template>
</n-card>
</n-modal>
</template>
<style lang="less" scoped>
.wrapper {
display: flex;
flex-direction: column;
&-title {
font-weight: bold;
font-size: 16px;
}
&-bar {
background-color: #e8e8e8;
width: 100%;
margin-top: 20px;
}
&-footer {
display: flex;
justify-content: flex-end;
}
&-info {
font-weight: bold;
position: relative;
&:before {
background-color: #1980ff;
content: '';
width: 5px;
border-radius: 2px;
top: 0;
bottom: 0;
position: absolute;
}
}
}
.dragcardStyle {
--n-padding-bottom: 0px !important;
--n-padding-left: 0px !important;
}
.cardstyle {
width: 820px;
--n-padding-bottom: 20px;
--n-padding-left: 24px;
}
.textbtnStyle {
cursor: pointer;
color: #1980ff;
}
.draggable-ul {
width: 100%;
overflow: hidden;
border: 1px solid #cad2dd;
border-top: 0px;
border-radius: 2px;
display: block;
.content {
display: flex;
flex-wrap: wrap;
}
.draggable-li {
padding: 10px 16px;
color: #333;
}
.draggable-item {
padding: 10px 16px;
color: #333;
display: flex;
align-items: center;
}
.disable-check {
color: gainsboro;
}
}
::v-deep(.n-card.n-card--content-segmented > .n-card__content:not(:first-child)) {
border: 0px;
}
::v-deep(.n-card > .n-card-header) {
--n-padding-top: 0px;
--n-padding-bottom: 12px;
}
</style>
Loading…
Cancel
Save