Merge branch 'main' into shen

bak
Dragon 2 years ago
commit 1a3466072e

1
components.d.ts vendored

@ -20,6 +20,7 @@ declare module 'vue' {
NDialogProvider: typeof import('naive-ui')['NDialogProvider']
NDivider: typeof import('naive-ui')['NDivider']
NDropdown: typeof import('naive-ui')['NDropdown']
NEmpty: typeof import('naive-ui')['NEmpty']
NForm: typeof import('naive-ui')['NForm']
NFormItem: typeof import('naive-ui')['NFormItem']
NGi: typeof import('naive-ui')['NGi']

@ -15,7 +15,7 @@
},
"dependencies": {
"@vueup/vue-quill": "^1.2.0",
"@vueuse/core": "^10.7.0",
"@vueuse/core": "10.9.0",
"axios": "^1.4.0",
"date-fns": "^2.30.0",
"esno": "^0.16.3",

@ -9,8 +9,8 @@ dependencies:
specifier: ^1.2.0
version: 1.2.0(vue@3.3.10)
'@vueuse/core':
specifier: ^10.7.0
version: 10.7.0(vue@3.3.10)
specifier: 10.9.0
version: 10.9.0(vue@3.3.10)
axios:
specifier: ^1.4.0
version: 1.6.2
@ -1640,26 +1640,26 @@ packages:
vue: 3.3.10(typescript@4.9.5)
dev: false
/@vueuse/core@10.7.0(vue@3.3.10):
resolution: {integrity: sha512-4EUDESCHtwu44ZWK3Gc/hZUVhVo/ysvdtwocB5vcauSV4B7NiGY5972WnsojB3vRNdxvAt7kzJWE2h9h7C9d5w==}
/@vueuse/core@10.9.0(vue@3.3.10):
resolution: {integrity: sha512-/1vjTol8SXnx6xewDEKfS0Ra//ncg4Hb0DaZiwKf7drgfMsKFExQ+FnnENcN6efPen+1kIzhLQoGSy0eDUVOMg==}
dependencies:
'@types/web-bluetooth': 0.0.20
'@vueuse/metadata': 10.7.0
'@vueuse/shared': 10.7.0(vue@3.3.10)
vue-demi: 0.14.6(vue@3.3.10)
'@vueuse/metadata': 10.9.0
'@vueuse/shared': 10.9.0(vue@3.3.10)
vue-demi: 0.14.7(vue@3.3.10)
transitivePeerDependencies:
- '@vue/composition-api'
- vue
dev: false
/@vueuse/metadata@10.7.0:
resolution: {integrity: sha512-GlaH7tKP2iBCZ3bHNZ6b0cl9g0CJK8lttkBNUX156gWvNYhTKEtbweWLm9rxCPIiwzYcr/5xML6T8ZUEt+DkvA==}
/@vueuse/metadata@10.9.0:
resolution: {integrity: sha512-iddNbg3yZM0X7qFY2sAotomgdHK7YJ6sKUvQqbvwnf7TmaVPxS4EJydcNsVejNdS8iWCtDk+fYXr7E32nyTnGA==}
dev: false
/@vueuse/shared@10.7.0(vue@3.3.10):
resolution: {integrity: sha512-kc00uV6CiaTdc3i1CDC4a3lBxzaBE9AgYNtFN87B5OOscqeWElj/uza8qVDmk7/U8JbqoONLbtqiLJ5LGRuqlw==}
/@vueuse/shared@10.9.0(vue@3.3.10):
resolution: {integrity: sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw==}
dependencies:
vue-demi: 0.14.6(vue@3.3.10)
vue-demi: 0.14.7(vue@3.3.10)
transitivePeerDependencies:
- '@vue/composition-api'
- vue
@ -7116,6 +7116,21 @@ packages:
vue: 3.3.10(typescript@4.9.5)
dev: false
/vue-demi@0.14.7(vue@3.3.10):
resolution: {integrity: sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==}
engines: {node: '>=12'}
hasBin: true
requiresBuild: true
peerDependencies:
'@vue/composition-api': ^1.0.0-rc.1
vue: ^3.0.0-0 || ^2.6.0
peerDependenciesMeta:
'@vue/composition-api':
optional: true
dependencies:
vue: 3.3.10(typescript@4.9.5)
dev: false
/vue-draggable-plus@0.3.5(@types/sortablejs@1.15.7):
resolution: {integrity: sha512-HqIxV4Wr4U5LRPLRi2oV+EJ4g6ibyRKhuaiH4ZQo+LxK4zrk2XcBk9UyXC88OXp4SAq0XYH4Wco/T3LX5kJ79A==}
peerDependencies:

@ -1,15 +1,33 @@
import type { FinalParam, ResetParam } from '/#/api'
import { http } from '@/utils/http/axios'
import { notEmpty } from '@/utils'
import { pickBy } from 'lodash-es'
import { formatToDate2 } from '@/utils/dateUtil'
/**
*
* @returns
*/
export async function getFinalList(params: FinalParam) {
const notEmptyParams = pickBy(params, notEmpty)
Object.keys(notEmptyParams).forEach((key) => {
const val = notEmptyParams[key]
if (key === 'izuptime') {
const start = formatToDate2(val[0])
const end = formatToDate2(val[1])
notEmptyParams[key] = `${start}-${end}`
}
if (Array.isArray(notEmptyParams[key]))
notEmptyParams[key] = val.join(',')
})
const res = await http.request({
url: `/flow/task/listfinal`,
method: 'get',
params,
params: notEmptyParams,
})
const { data: { list, totalPage } } = res

@ -126,3 +126,52 @@ export async function sort(searchid: string, reorder: number): Promise<void> {
params: { searchid, reorder },
})
}
/**
*
*
* @param reviewType
* @param userId
* @returns
*/
export async function getfieldList(reviewType: number, userId: number): Promise<void> {
return http.request({
url: `/ocr/user/field/queryFields`,
method: 'get',
params: { reviewType, userId },
})
}
/**
*
*
* @param reviewType
* @returns
*/
export async function getAllfieldList(reviewType: number): Promise<void> {
return http.request({
url: `/ocr/field/list`,
method: 'get',
params: { reviewType},
})
}
/**
*
*
* @param reviewType
* @param userId
* @param userField
*
* @returns
*/
export async function savefield(reviewType: number,userId:string,userFieldFixed:string,userFieldUnFixed:string=''): Promise<void> {
return http.request({
url: `/ocr/user/field/saveOrUpdate`,
method: 'POST',
params: { reviewType,userId,userFieldFixed,userFieldUnFixed},
})
}

@ -117,9 +117,10 @@ export async function getPictureList(params: any): Promise<any> {
headers: { 'Content-Type': ContentTypeEnum.FORM_DATA },
})
const { data: { records, pages } } = res
const { data: { records, pages, total } } = res
return {
pageCount: pages,
data: records,
total,
}
}

@ -7,16 +7,16 @@ import { ContentTypeEnum } from '@/enums/httpEnum'
*
* @returns
*/
export async function getApprovalList(page: PageParam, assigneeId: string) {
export async function getApprovalList(page: PageParam) {
const res = await http.request({
url: `/flow/task/listalldata`,
method: 'get',
params: { pageSize: page.pageSize, currPage: page.pageNo, assigneeId },
params: { pageSize: page.pageSize, currPage: page.pageNo },
})
const { data: { list, totalPage } } = res
const { data: { list, totalCount } } = res
return {
pageCount: totalPage,
pageCount: Math.ceil(totalCount / page.pageSize!),
data: list,
}
}

@ -28,8 +28,10 @@ export async function getPackageList(params: PageParam, packagename: string) {
* @returns
*/
export async function getPackageTaskList(packageid: string, params: PageParam) {
const pid = packageid || 0
const res = await http.request({
url: `/backstage/jifen/ocrtaskchildpicture/listbypackageid/${packageid}`,
url: `/backstage/jifen/ocrtaskchildpicture/listbypackageid/${pid}`,
method: 'get',
params,
})
@ -48,8 +50,10 @@ export async function getPackageTaskList(packageid: string, params: PageParam) {
* @returns
*/
export async function getTaskDetailInfo(taskId: string, packageid: string) {
const pid = packageid || 0
const res = await http.request({
url: `/backstage/jifen/ocrtaskchildpicture/getdata/${taskId}/${packageid}`,
url: `/backstage/jifen/ocrtaskchildpicture/getdata/${taskId}/${pid}`,
method: 'get',
})
@ -64,8 +68,10 @@ export async function getTaskDetailInfo(taskId: string, packageid: string) {
* @returns
*/
export async function getTaskDetailPictureList(packageid: string, taskchildpictureid: string, params: PageParam & PictureSortParam) {
const pid = packageid || 0
const res = await http.request({
url: `/backstage/jifen/ocrtaskchildpicture/listbypictureid/${packageid}/${taskchildpictureid}`,
url: `/backstage/jifen/ocrtaskchildpicture/listbypictureid/${pid}/${taskchildpictureid}`,
method: 'get',
params,
})
@ -81,6 +87,7 @@ export async function getTaskDetailPictureList(packageid: string, taskchildpictu
assignee: item.assignee,
pictureid: item.pictureid,
imgurl: item.ocrPicture.imgurl,
thumburl: item.ocrPicture.serverThumbnailUrl || item.ocrPicture.imgurl,
iztrueorfalse: item.iztrueorfalse,
states: item.states,
history: hasHistory(item.ocpictureid, item.picturecompare),

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 230 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 230 KiB

@ -5,7 +5,7 @@ export interface AsideEntity {
label: string
defaultValue?: any
isDefaultFilter?: boolean// 是否为默认显示选项(不能隐藏)
inFilterList?: boolean// 是否出现在过滤配置选项中
inFilterList?: boolean// 是否出现在过滤配置选项中(这个名字不好为false代表只用于客户端的显示配置不作为参数传递给服务器端)
render?: boolean// 是否作为单独组件渲染
key: string
component: Component

@ -157,16 +157,17 @@ export const fieldMap = {
field2: '拜访客户类型',
field3: '拜访客户名称',
field4: '任务来源',
field5: '厂商1',
field5: '厂商',
field6: '拜访客户级别',
field7: '科室名称',
field8: '拜访小结',
field9: '产品名称',
field10: '定位信息',
field11: 2002,
field11: '拜访日期',
field12: '定位距离',
field13: '病历号',
field14: '是否重复',
field15: '任务类型',
field16: '任务状态',
field17: '项目类别',
}

@ -18,7 +18,7 @@ export interface DictionaryState {
izCustomtypeList: any
izcustomnameList: any
izcustomlevelList: any
izizprojecttypeList: any
izprojecttypeList: any
izvisitcityList: any
rejectList: any
backList: any
@ -44,7 +44,7 @@ export const useDictionaryStore = defineStore({
izcustomnameList: null,
izCustomtypeList: null,
izcustomlevelList: null,
izizprojecttypeList: null,
izprojecttypeList: null,
izvisitcityList: null,
rejectList: null,
backList: null,
@ -94,8 +94,11 @@ export const useDictionaryStore = defineStore({
getizcustomlevel: (state) => {
return state.izcustomlevelList
},
getizizprojecttype: (state) => {
return state.izizprojecttypeList
getizprojecttype: (state) => {
return state.izprojecttypeList
},
getizstatus: (state) => {
return state.izstatusList
},
},
actions: {
@ -195,8 +198,8 @@ export const useDictionaryStore = defineStore({
// 项目类别
async fetchizizprojecttypeList() {
const list = await getBusinessList('izprojecttype')
this.izizprojecttypeList = list
return this.izizprojecttypeList
this.izprojecttypeList = list
return this.izprojecttypeList
},
// 发布地区
async fetchizvisitcityList() {

@ -10,7 +10,6 @@ export const useTaskStore = defineStore({
activeId: '',
approvalList: [],
packageid: '',
refresh: false,
immersion: false,
}),
getters: {
@ -26,7 +25,7 @@ export const useTaskStore = defineStore({
setActive(index: number, taskId?: string) {
this.currentIndex = index
const task = this.approvalList[index]
this.activeId = taskId || task?.formid
this.activeId = taskId || task?.id
this.packageid = task.packageid
},
forward() {
@ -43,14 +42,12 @@ export const useTaskStore = defineStore({
this.setActive(--this.currentIndex)
},
async fetchApprovalList(pagination, id, refresh?: boolean) {
const res = await getApprovalList(pagination, id)
async fetchApprovalList(pagination) {
const res = await getApprovalList(pagination)
if (res.data.length > 0) {
this.setApprovalList(res.data)
this.setActive(0)
// 审批操作完成后需要刷新为防止activeId在刷新后值不变通过此值刷新
this.refresh = !this.refresh
this.approvalList.push(...res.data)
if (!this.activeId)
this.setActive(0)
}
return res

@ -45,10 +45,11 @@ export const useWorkOrderStore = defineStore({
},
async fetchOrderList(pagination, keyword) {
const res = await getPackageList(pagination, keyword)
if (res.data.length > 0) {
this.setOrderList(res.data)
this.setActive(0)
this.packageList.push(...res.data)
if (!this.activeId)
this.setActive(0)
}
return res

@ -1,4 +1,4 @@
import { format } from 'date-fns'
import { format, parse } from 'date-fns'
const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm'
const DATE_FORMAT = 'YYYY-MM-DD '
@ -20,3 +20,9 @@ export function formatToDate2(date: Date | number, formatStr = DATA_FORMAT_2): s
export function formatToDateHMS(date: Date | number, formatStr = DATE_FORMAT_HMS) {
return format(date, formatStr)
}
// 将yyyy/mm/dd转换为时间戳
export function formatToDate3(dateString: string) {
const dateObject = parse(dateString, 'yyyy/MM/dd', new Date())
return dateObject.getTime()
}

@ -275,3 +275,12 @@ export function arrayEquals(a, b) {
export function notEmpty(value: any) {
return !(value === undefined || value === '' || value === null || (Array.isArray(value) && value.length === 0))
}
/**
*
* @param value
* @returns
*/
export function isEmpty(value: any) {
return (value === undefined || value === '' || value === null)
}

@ -1,6 +1,6 @@
<script lang="ts" setup>
import { computed, nextTick, onBeforeMount, onMounted, reactive, ref, shallowRef, unref, watch } from 'vue'
import { CustomFilterModalVue } from '@/views/final/comp'
import { CustomFilterModalVue, FilterModal, NewFilterModal } from '@/views/final/comp'
import Search from '@/views/home/aside/comp/Search.vue'
import AdvanceFilter from '@/views/home/aside/comp/AdvanceFilter.vue'
import { getViewportOffset } from '@/utils/domUtils'
@ -10,6 +10,7 @@ import type { Filter } from '/#/home'
import type { AsideEntity } from '@/config/aside'
import { asideMap } from '@/config/final'
import type { AsideConfig } from '/#/api'
import emitter from '@/utils/mitt'
const finalStore = useFinal()
@ -21,9 +22,9 @@ const asideVisible: Partial<Record<keyof AsideConfig, boolean>> = reactive({})
const showItems = shallowRef<{ key: string, config: AsideEntity }[]>([])
Object.keys(asideMap).forEach((key) => {
const entity = asideMap[key]
const { defaultValue } = entity
asideValue[key] = defaultValue
const { defaultValue, inFilterList } = asideMap[key]
if (inFilterList !== false)
asideValue[key] = defaultValue
})
const filterModalRef = ref(null)
@ -133,16 +134,8 @@ function scrollHandler(key: string) {
element?.scrollIntoView(true)
}
//
function filterHandler(filterList: Filter[]) {
const filerMap: Record<string, any> = {}
for (const filter of filterList) {
const { key, value } = filter
filerMap[key] = value
}
// TODO:
function filterHandler(searchId: string) {
emitter.emit('filter-final', searchId)
}
function editFilter(filter: any) {
@ -169,7 +162,7 @@ watch(asideValue, (newVal) => {
<Search v-show="showSearch" @select="scrollHandler" @close="setShowSearch(false)" />
<!-- 高级筛选 -->
<AdvanceFilter
v-show="!showSearch" @select="filterHandler" @update:search="setShowSearch(true)"
v-show="!showSearch" :type="1" @select="filterHandler" @update:search="setShowSearch(true)"
@show-custom="showModal(customModalRef)" @show-filter="showModal(filterModalRef)"
/>
</div>
@ -181,6 +174,10 @@ watch(asideValue, (newVal) => {
<!-- 筛选 -->
<CustomFilterModalVue ref="customModalRef" />
<!-- 过滤列表 -->
<FilterModal ref="filterModalRef" @edit-filter="editFilter" @show-new-filter="showModal(newFilterModalRef)" />
<!-- 新增过滤 -->
<NewFilterModal ref="newFilterModalRef" />
</n-scrollbar>
</div>
</template>

@ -17,7 +17,9 @@ const props = defineProps({
})
const actionConfig = {
1: [{ label: '查看', key: 'view' }, { label: '重置审批', key: 'reset' }],
3: [{ label: '查看', key: 'view' }, { label: '重置审批', key: 'reset' }],
4: [{ label: '查看', key: 'view' }, { label: '重置审批', key: 'reset' }],
2: [{ label: '通过', key: 'approval' }, { label: '不通过', key: 'reject' }, { label: '重置审批', key: 'reset' }],
5: [{ label: '通过', key: 'approval' }, { label: '不通过', key: 'reject' }, { label: '重置审批', key: 'reset' }],
}

@ -1,10 +1,10 @@
<script lang="ts" setup>
import { computed, ref, watch } from 'vue'
import { VueDraggable } from 'vue-draggable-plus'
import { debounce, difference } from 'lodash-es'
import { setFilter } from '@/api/home/filter'
import { asideMap } from '@/config/final'
import { useFinal } from '@/store/modules/final'
import { debounce, difference } from 'lodash-es'
import { computed, ref, watch } from 'vue'
import { VueDraggable } from 'vue-draggable-plus'
const show = ref(false)
const checkAll = ref(false)

@ -1,8 +1,10 @@
<script lang="ts" setup>
import { computed, ref, watch } from 'vue'
import { difference } from 'lodash-es'
import { VueDraggable } from 'vue-draggable-plus'
import { ColumnsMap } from '@/config/final'
import { getAllfieldList, getfieldList } from "@/api/home/filter";
import { ColumnsMap } from '@/config/final';
import { useUser } from "@/store/modules/user";
import { difference } from 'lodash-es';
import { computed, onMounted, ref, watch } from 'vue';
import { VueDraggable } from 'vue-draggable-plus';
const emit = defineEmits<{
(e: 'commit', columns: any[])
@ -13,6 +15,41 @@ const offList = ref<any[]>([])
//
const fixLeftList = ref<any[]>([])
const onList = ref<any[]>([])
const props = defineProps({
reviewType: {
type: Number,
default: () => 0,
require: true,
},
})
onMounted(async()=>{
const userStore = useUser();
const userInfo = userStore.getUserInfo;
let res;
res = await getAllfieldList(props.reviewType); //
const allList = res.data;
res = await getfieldList(props.reviewType, userInfo.id); //
const useList = res.data;
/**
* name 标题
* id 键值
* fix 是否默认
* checked 是否选中
*/
allList.map((v) => {
let item = {
name: v.fieldDesc,
id: v.name,
fix: v.isrequired == 2,
checked:
v.isrequired == 2 ||
Boolean(useList.userFieldFixed?.toLowerCase().indexOf(v.name)>-1) || Boolean(useList.userFieldUnFixed?.toLowerCase().indexOf(v.name)>-1),
};
offList.value.push(item)
});
})
const allCount = computed(() => {
return `全部字段(共${offList.value.length - 1}个)`
@ -129,7 +166,7 @@ defineExpose({
showModal,
})
generatList()
// generatList()
const selectIds = ref<string[]>([])

@ -0,0 +1,347 @@
<script lang="ts" setup>
import { defineOptions, h, nextTick, onUnmounted, reactive, ref, unref } from 'vue'
import { NDataTable } from 'naive-ui'
import type { DataTableColumns, DataTableRowKey } from 'naive-ui'
import type { SortableEvent } from 'sortablejs'
import Sortable from 'sortablejs'
import { debounce } from 'lodash-es'
import Action from '@/views/home/aside/comp/Action.vue'
import { deleteCondition, getConditionList, sort } from '@/api/home/filter'
import type { FilterSearchParam } from '/#/api'
defineOptions({ name: 'FilterModal' })
const emit = defineEmits<{
(e: 'showNewFilter'): void
(e: 'editFilter', filter: any): void
}>()
const show = ref(false)
const cardStyle = {
'width': '800px',
'height': '800px',
'--n-padding-bottom': '10px',
'--n-padding-left': '10px',
}
interface RowData {
id: string
searchname: string
createby: string
createtime: string
updateby: string
updatetime: string
}
const columns: DataTableColumns<RowData> = [
{
type: 'selection',
},
{
title: '操作',
key: 'action',
render(row) {
return h(
Action,
{
options: [
{ label: '编辑', key: 1 },
{ label: '删除', key: 2 },
],
id: row.id,
select,
},
)
},
},
{
title: '名称',
key: 'searchname',
},
{
title: '创建者',
key: 'createby',
},
{
title: '创建时间',
key: 'createtime',
},
{
title: '更新者',
key: 'updateby',
},
{
title: '更新时间',
key: 'updatetime',
},
]
const loading = ref(true)
const pagination = reactive({
page: 1,
pageCount: 1,
pageSize: 10,
})
const tableData = ref<Array<RowData>>([])
const keyword = ref('')
async function query(page: number, pageSize: number) {
const searchParam: FilterSearchParam = { search_searchname: { value: keyword.value, op: 'like', type: 'string' } }
const result = await getConditionList({ pageNo: page, pageSize }, searchParam, 1)
const { data, pageCount } = result
tableData.value = data
pagination.page = page
pagination.pageCount = pageCount
loading.value = false
}
function afterLeave() {
pagination.page = 1
pagination.pageCount = 1
pagination.pageSize = 10
}
const selectionIds = ref<DataTableRowKey[]>([])
const rowKey = (row: RowData) => row.id
function rowProps(row: RowData) {
return {
'data-id': row.id,
}
}
function handleCheck(rowKeys: DataTableRowKey[]) {
selectionIds.value = rowKeys
}
function select(key: number) {
switch (key) {
case 1:
editSelection()
break
case 2:
deleteSelection()
break
default:
break
}
}
function editSelection() {
// eslint-disable-next-line dot-notation
const $message = window['$message']
if (selectionIds.value.length === 0 || selectionIds.value.length > 1) {
$message.error('请选中一条过滤')
return
}
const selectedId = selectionIds.value[0]
const selectedFilter = tableData.value.find((item: any) => {
return item.id === selectedId
})
emit('editFilter', selectedFilter)
closeModal()
}
function deleteSelection() {
// eslint-disable-next-line dot-notation
const $message = window['$message']
if (selectionIds.value.length === 0) {
$message.error('至少选中一条过滤')
return
}
deleteCondition({ ids: selectionIds.value.join(',') }).then(() => {
query(pagination.page, pagination.pageSize)
})
}
async function handlePageChange(currentPage) {
if (loading.value)
return
const { pageSize } = pagination
await query(currentPage, pageSize)
}
function handleClick() {
emit('showNewFilter')
show.value = false
}
let sortTable: Sortable | null = null
const tableRef = ref<InstanceType<typeof NDataTable>>()
async function showModal() {
show.value = true
const { page, pageSize } = pagination
await query(page, pageSize)
nextTick(() => {
if (sortTable !== null)
destory()
const el: HTMLDivElement = tableRef.value?.$el
const tbody: HTMLElement | null = el.querySelector('tbody.n-data-table-tbody')!
if (tbody)
sortTable = Sortable.create(tbody, { onEnd, onMove })
})
}
let relatedId = ''
let insertafter = false
// TODO: bug
function onEnd(event: SortableEvent) {
const data = unref(tableData)
const oldElem = data[event.oldIndex!]
data.splice(event.oldIndex!, 1)
data.splice(event.newIndex!, 0, oldElem)
const dragId = oldElem.id
const index = data.findIndex((item) => {
return item.id === relatedId
})
// -1+1
const order = insertafter ? index - 1 : index + 1
// console.log('dragid:', dragId, 'order:', order)
sort(dragId, order)
}
function onMove(evt: any) {
relatedId = evt.related?.dataset?.id
insertafter = evt.willInsertAfter
// console.log(`${evt.dragged.dataset.id},${evt.related}`, 'insertafter', evt.willInsertAfter)
}
function destory() {
sortTable && sortTable.destroy()
sortTable = null
}
onUnmounted(() => {
destory()
})
function closeModal() {
show.value = false
}
defineExpose({
showModal,
})
const inputHandler = debounce((word) => {
keyword.value = word
query(1, 5)
}, 300)
</script>
<template>
<div>
<n-modal
v-model:show="show" transform-origin="center" display-directive="if"
@after-leave="afterLeave"
>
<n-card :style="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>
<div class="wrapper-form">
<n-input :style="{ width: '360px', border: '1px solid #cad2dd' }" placeholder="请输入过滤条件名称搜索" @input="inputHandler">
<template #suffix>
<SvgIcon size="14px" name="magnifying-1" />
</template>
</n-input>
<n-button type="info" @click="handleClick">
创建
<template #icon>
<SvgIcon size="14px" name="magnifying-1" />
</template>
</n-button>
</div>
<div class="wrapper-table">
<NDataTable
ref="tableRef" remote :row-props="rowProps as any" :columns="columns" :data="tableData" :loading="loading"
:pagination="pagination" :row-key="rowKey" @update:page="handlePageChange"
@update:checked-row-keys="handleCheck"
/>
</div>
</div>
<template #footer>
<div class="wrapper-footer">
<n-button type="info" @click="closeModal">
确认
</n-button>
<n-button secondary style="margin-left:15px" @click="closeModal">
取消
</n-button>
</div>
</template>
</n-card>
</n-modal>
</div>
</template>
<style lang="less" scoped>
.wrapper {
display: flex;
flex-direction: column;
&-title {
font-weight: bold;
font-size: 16px;
}
&-bar {
background-color: #f8f8f8;
width: 100%;
margin-top: 20px;
}
&-form {
display: flex;
justify-content: space-between;
margin-top: 20px;
.n-input {
width: 300px;
border: 1px solid gray
}
}
&-table {
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;
}
}
}
</style>

@ -0,0 +1,380 @@
<script lang="ts" setup>
import type { FormInst, FormItemRule, FormRules } from 'naive-ui'
import { computed, onBeforeMount, reactive, ref, unref, watch } from 'vue'
import { asideMap } from '@/config/final'
import { useDictionary } from '@/store/modules/dictonary'
import { useConfig } from '@/store/modules/asideConfig'
import type { FilterCondition } from '/#/api'
import { addCondition, updateCondition } from '@/api/home/filter'
import { formatToDate2, formatToDate3 } from '@/utils/dateUtil'
type Status = 'edit' | 'new'
const show = ref(false)
const configStore = useConfig()
const dicStore = useDictionary()
const currentStatus = ref<Status>('new')
let currentEditId: string | null = null
const modalTitle = computed(() => {
return currentStatus.value === 'new' ? '新建过滤条件' : '编辑过滤条件'
})
const cardStyle = {
'width': '800px',
'--n-padding-bottom': '10px',
'--n-padding-left': '10px',
}
const noBorderInput = {
'--n-border': '0px',
'--n-border-hover': '0px',
'--n-border-pressed': '0px',
}
const formItemStyle = {
'--n-label-height': '0px',
'--n-feedback-height': '8px',
}
interface FormType {
name: string | null
logic: string | null
conditions: Condition[]
}
interface Condition {
type: string | null
operator: string | null
result: any
}
interface Option {
label: string
value: string
}
const rules: FormRules = {
name: {
required: true,
message: '请输入过滤条件名称',
trigger: 'blur',
},
logic: {
required: true,
message: '请选择逻辑关系',
trigger: 'blur',
},
conditions: {
required: true,
validator(rule: FormItemRule, value: Condition[]) {
for (const item of value) {
const { type, operator, result } = item
if (type === null || operator === null || result === null)
return new Error('请选择过滤条件')
}
return true
},
trigger: ['input', 'blur'],
},
}
const formRef = ref<FormInst | null>(null)
const formValue = reactive<FormType>({
name: null,
logic: null,
conditions: [{
type: null,
operator: null,
result: null,
}],
})
function handleSumbit(e: MouseEvent) {
e.preventDefault()
formRef.value?.validate((errors) => {
if (errors)
return
const list = formValue.conditions.map((item, index) => {
const { type, operator, result } = item
return {
searchfield: type!,
searchtype: operator!,
searchvalue: formatValue(type!, result),
searchRelationType: formValue.logic!,
orderNum: index + 1,
}
})
const param: FilterCondition = {
searchname: formValue.name!,
type: 1,
ocrUsersearchchildList: list,
}
if (currentStatus.value === 'new')
addCondition(param)
else
updateCondition({ id: currentEditId!, ...param })
closeModal()
})
}
function formatValue(searchfield: string, searchvalue: any) {
if (searchfield === 'izuptime') {
const start = formatToDate2(searchvalue[0])
const end = formatToDate2(searchvalue[1])
return `${start}-${end}`
}
return searchvalue
}
//
function unformatValue(searchfield: string, searchvalue: any) {
// 2022/01/03-2023/02/04
if (searchfield === 'izuptime') {
const dataStrs = searchvalue.split('-')
const start = formatToDate3(dataStrs[0])
const end = formatToDate3(dataStrs[1])
return [start, end]
}
return searchvalue
}
function createCondition() {
formValue.conditions.push({
type: null,
operator: null,
result: null,
})
}
function removeCondition(index: number) {
formValue.conditions.splice(index, 1)
}
function formLabel(index: number) {
return index === 0 ? '筛选条件' : ''
}
const typeOptions = ref<Option[]>([])
const operatorOptions = [
{
label: '等于',
value: 'eq',
},
{
label: '不等于',
value: 'notEq',
},
]
const logicOptions = ref([])
onBeforeMount(() => {
dicStore.fetchRelationTypeList()
})
watch(() => dicStore.relationTypeList, (newval) => {
logicOptions.value = newval
})
function showModal() {
show.value = true
}
function closeModal() {
show.value = false
}
function generateAllData(): Option[] {
const initVal: Option[] = []
const list = Object.keys(asideMap).reduce((acc, value) => {
if (value.startsWith('iz') && asideMap[value]?.inFilterList !== false) {
const name = asideMap[value]?.label
name && acc.push({
value,
label: name || '未配置',
})
}
return acc
}, initVal)
return list
}
typeOptions.value = generateAllData()
function getOptions(key: string) {
const getterName = `get${key}`
const options = unref(dicStore[getterName])
return options || []
}
function leaveHandler() {
currentStatus.value = 'new'
currentEditId = null
formValue.name = null
formValue.conditions = [
{
type: null,
operator: null,
result: null,
},
]
}
function edit(editFilter: any) {
currentStatus.value = 'edit'
const { searchname, ocrUsersearchchildList, id } = editFilter
currentEditId = id
formValue.name = searchname
formValue.conditions = ocrUsersearchchildList.map((item) => {
return {
type: item.searchfield,
operator: item.searchtype,
result: unformatValue(item.searchfield, item.searchvalue),
}
})
}
defineExpose({
showModal,
edit,
})
</script>
<template>
<n-modal v-model:show="show" transform-origin="center" @after-leave="leaveHandler">
<n-card :style="cardStyle" :bordered="false" size="huge" role="dialog" aria-modal="true">
<div class="wrapper">
<span class="wrapper-title">{{ modalTitle }}</span>
<div class="wrapper-bar">
<div class="wrapper-info">
<span :style="{ 'margin-left': '18px' }">基本信息</span>
</div>
</div>
<div class="wrapper-form">
<n-form ref="formRef" :model="formValue" :rules="rules">
<n-form-item path="name" label="标题">
<n-input v-model:value="formValue.name" :style="{ width: '780px' }" @keydown.enter.prevent />
</n-form-item>
<n-form-item path="logic" label="逻辑关系">
<n-select v-model:value="formValue.logic" placeholder="请选择逻辑关系" :options="logicOptions" />
</n-form-item>
<n-form-item
v-for="(item, index) in formValue.conditions" :key="index" :style="formItemStyle"
path="conditions" :label="formLabel(index)"
>
<n-select
v-model:value="item.type" placeholder="请选择筛选项名称" :options="typeOptions"
/>
<n-select
v-model:value="item.operator" style="margin-left: 8px;" placeholder="请选择"
:options="operatorOptions"
/>
<n-space v-if="item.type === 'izuptime'">
<n-date-picker
v-model:value="item.result" style="margin-left: 8px;width: 240px;" type="daterange"
clearable
/>
</n-space>
<n-select
v-else v-model:value="item.result" style="margin-left: 8px;" placeholder="请选择" :options="getOptions(item.type!)"
/>
<n-button :style="noBorderInput" icon-placement="right" @click="removeCondition(index)">
<template #icon>
<SvgIcon size="24" name="close" />
</template>
</n-button>
</n-form-item>
</n-form>
</div>
<div class="wrapper-new" @click="createCondition">
<span>+</span>
<span style="margin-left:8px">添加筛选条件</span>
</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 {
display: flex;
flex-direction: column;
&-title {
font-weight: bold;
font-size: 16px;
}
&-bar {
background-color: #e8e8e8;
width: 100%;
margin-top: 20px;
}
&-form {
display: flex;
justify-content: space-between;
margin-top: 20px;
}
&-new {
display: flex;
width: 110px;
color: #507afd;
line-height: 22px;
cursor: pointer;
&:hover {
color: #507aac;
}
}
&-table {
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;
}
}
}
</style>

@ -5,5 +5,7 @@ import RepeatTaskTableModal from './RepeatTaskTableModal.vue'
import Action from './Action.vue'
import RejectModal from './RejectModal.vue'
import CustomFilterModalVue from './CustomFilterModalVue.vue'
import FilterModal from './FilterModal.vue'
import NewFilterModal from './NewFilterModal.vue'
export { CustomTabelModal, ImportExcelModal, RepeatModal, RepeatTaskTableModal, Action, RejectModal, CustomFilterModalVue }
export { CustomTabelModal, ImportExcelModal, RepeatModal, RepeatTaskTableModal, Action, RejectModal, CustomFilterModalVue, FilterModal, NewFilterModal }

@ -1,19 +1,21 @@
<script lang="ts" setup>
import { computed, h, nextTick, onMounted, reactive, ref, unref } from 'vue'
import { NDataTable, useDialog, useMessage } from 'naive-ui'
import type { DataTableColumns, DataTableRowKey, PaginationProps } from 'naive-ui'
import { NDataTable, useDialog, useMessage } from 'naive-ui'
import { computed, h, nextTick, onMounted, onUnmounted, reactive, ref, unref, watch } from 'vue'
import { Action, CustomTabelModal, ImportExcelModal, RepeatModal, RepeatTaskTableModal } from '../comp'
import ConfrimModal from '@/views/task/modal/ConfrimModal.vue'
import { useWindowSizeFn } from '@/hooks/event/useWindowSizeFn'
import { getViewportOffset } from '@/utils/domUtils'
import { getFinalList } from '@/api/final'
import { audit } from '@/api/task/task'
import SvgIcon from '@/components/Icon/SvgIcon.vue'
import type { RowData } from '@/config/final'
import { findKey, headRules } from '@/config/final'
import { getFinalList } from '@/api/final'
import { isBoolean } from '@/utils/is'
import { useWindowSizeFn } from '@/hooks/event/useWindowSizeFn'
import { useUser } from '@/store/modules/user'
import { useFinal } from '@/store/modules/final'
import { getViewportOffset } from '@/utils/domUtils'
import { isBoolean } from '@/utils/is'
import ConfrimModal from '@/views/task/modal/ConfrimModal.vue'
import type { ApprovalParam } from '/#/api'
import { audit } from '@/api/task/task'
import SvgIcon from '@/components/Icon/SvgIcon.vue'
import emitter from '@/utils/mitt'
const columns: DataTableColumns<RowData> = [
{
@ -106,11 +108,17 @@ const columns: DataTableColumns<RowData> = [
const deviceHeight = ref(600)
onMounted(() => {
emitter.on('filter-final', refreshHandler)
nextTick(() => {
computeListHeight()
})
})
onUnmounted(() => {
emitter.off('filter-final', refreshHandler)
})
const columnsRef = ref(columns)
const tableRef = ref<InstanceType<typeof NDataTable>>()
const rowKey = (row: RowData) => row.id
@ -122,12 +130,15 @@ const pagination = reactive({
})
const tableData = ref<Array<RowData>>([])
const selectionIds = ref<DataTableRowKey[]>([])
const userStore = useUser()
const dialog = useDialog()
const message = useMessage()
const finalStore = useFinal()
async function query(page: number, pageSize: number) {
const result = await getFinalList({ sortorder: 'asc', pageSize, currPage: page, sortname: '' })
async function query(page: number, pageSize: number, filterId?: any) {
const asideParmas = unref(finalStore.getAsideValue)
// 使使
const params = filterId ? { userSearchId: filterId } : asideParmas
const result = await getFinalList({ sortorder: 'asc', pageSize, currPage: page, sortname: '', ...params })
const { data, pageCount } = result
tableData.value = data
pagination.page = page
@ -265,20 +276,20 @@ function validate(items: any[]) {
if (items.length === 0)
return '至少选中一个任务'
const useInfo = userStore.getUserInfo
const username = useInfo.loginname
// const useInfo = userStore.getUserInfo
// const username = useInfo.loginname
for (const item of items) {
const { iztrueorfalse, states, assignee } = item
if (iztrueorfalse === null)
return '未判别真假'
// for (const item of items) {
// const { iztrueorfalse, states, assignee } = item
// if (iztrueorfalse === null)
// return ''
else if (states !== 2)
return '审批状态不合法'
// else if (states !== 2)
// return ''
else if (assignee !== username)
return '审批人不一致'
}
// else if (assignee !== username)
// return ''
// }
return null
}
@ -381,6 +392,21 @@ function reload() {
const { page, pageSize } = unref(tableRef.value?.pagination) as PaginationProps
query(page!, pageSize!)
}
watch(() => finalStore.asideValue, (newVal, oldVal) => {
refreshHandler()
}, { deep: true })
function reset() {
pagination.page = 1
pagination.pageCount = 1
pagination.pageSize = 1
}
async function refreshHandler(searchId?: any) {
reset()
query(pagination.page, pagination.pageSize, searchId)
}
</script>
<template>

@ -82,7 +82,7 @@ configStore.$subscribe(() => {
const config = configStore.getConfig
const customConfig = configStore.getCustomConfig
if (config === null || customConfig === null)
if (config == null || customConfig == null)
return
const showKeys = [...customConfig].filter(key => !asideMap[key].isDefaultFilter)
@ -133,15 +133,8 @@ function scrollHandler(key: string) {
}
//
function filterHandler(filterList: Filter[]) {
const filerMap: Record<string, any> = {}
for (const filter of filterList) {
const { key, value } = filter
filerMap[key] = value
}
emitter.emit('filter', filerMap)
function filterHandler(searchId: string) {
emitter.emit('filter', searchId)
}
function editFilter(filter: any) {
@ -168,7 +161,7 @@ watch(asideValue, (newVal) => {
<Search v-show="showSearch" @select="scrollHandler" @close="setShowSearch(false)" />
<!-- 高级筛选 -->
<AdvanceFilter
v-show="!showSearch" @select="filterHandler" @update:search="setShowSearch(true)"
v-show="!showSearch" :type="0" @select="filterHandler" @update:search="setShowSearch(true)"
@show-custom="showModal(customModalRef)" @show-filter="showModal(filterModalRef)"
/>
</div>

@ -1,19 +1,27 @@
<script lang="ts" setup>
import { onMounted, reactive, ref } from 'vue'
import { favorite, getConditionList, unfavorite } from '@/api/home/filter'
import { asideMap } from '@/config/aside'
import { useInfiniteScroll } from '@vueuse/core'
import { debounce } from 'lodash-es'
import { asideMap } from '@/config/aside'
import { favorite, getConditionList, unfavorite } from '@/api/home/filter'
import type { Filter, FilterEntity } from '/#/home'
import { onMounted, reactive, ref } from 'vue'
import type { FilterSearchParam } from '/#/api'
import type { Filter, FilterEntity } from '/#/home'
defineOptions({ name: 'AdvanceFilter' })
const props = defineProps({
type: {
type: Number,
default: 0,
required: true,
},
})
const emit = defineEmits<{
(e: 'show-filter'): void
(e: 'show-custom'): void
(e: 'update:search'): void
(e: 'select', filterList: Filter[])
(e: 'select', id: string)
}>()
const data = ref<FilterEntity[]>([])
@ -38,6 +46,7 @@ function generateDefaultConfig(): FilterEntity[] {
if (isDefaultFilter === true) {
const config = {
id: '',
name: label,
favorite: false,
isDefaultFilter,
@ -78,7 +87,7 @@ async function featchList() {
loading = true
try {
const searchParam: FilterSearchParam = { search_searchname: { value: keyword.value, op: 'like', type: 'string' } }
const result = await getConditionList(pagination, searchParam, 0)
const result = await getConditionList(pagination, searchParam, props.type)
const { data } = result
// pagination.pageNo += 1
// canloadMore = pageCount >= pagination.pageNo
@ -124,7 +133,7 @@ function generateFilterEntityList(data) {
function selectHandler(item: FilterEntity) {
(popover.value as any).setShow(false)
emit('select', item.filterList)
emit('select', item.id)
}
const inputHandler = debounce((word) => {

@ -23,6 +23,10 @@ const inputHandler = debounce((keyword) => {
configStore.$subscribe(() => {
const customConfig = configStore.getCustomConfig
if (customConfig == null)
return
const keys = customConfig ? [...customConfig] : []
if (keys.length === 0)

@ -19,14 +19,8 @@ const formValue = ref({
const rules: FormRules = {
plans: [
{
required: true,
required: false,
type: 'array',
validator(rule: FormItemRule, value: string[]) {
if (value == null || value.length === 0)
return new Error('请选择拜访客户级别')
return true
},
trigger: ['blur', 'change'],
},
],

@ -19,14 +19,8 @@ const formValue = ref({
const rules: FormRules = {
plans: [
{
required: true,
required: false,
type: 'array',
validator(rule: FormItemRule, value: string[]) {
if (value == null || value.length === 0)
return new Error('请选择拜访客户名称')
return true
},
trigger: ['blur', 'change'],
},
],

@ -19,14 +19,8 @@ const formValue = ref({
const rules: FormRules = {
plans: [
{
required: true,
required: false,
type: 'array',
validator(rule: FormItemRule, value: string[]) {
if (value == null || value.length === 0)
return new Error('请选择拜访客户类型')
return true
},
trigger: ['blur', 'change'],
},
],

@ -19,14 +19,8 @@ const formValue = ref({
const rules: FormRules = {
plans: [
{
required: true,
required: false,
type: 'array',
validator(rule: FormItemRule, value: string[]) {
if (value == null || value.length === 0)
return new Error('请选择产品名称')
return true
},
trigger: ['blur', 'change'],
},
],

@ -19,14 +19,8 @@ const formValue = ref({
const rules: FormRules = {
plans: [
{
required: true,
required: false,
type: 'array',
validator(rule: FormItemRule, value: string[]) {
if (value == null || value.length === 0)
return new Error('请选择所属项目')
return true
},
trigger: ['blur', 'change'],
},
],

@ -19,14 +19,8 @@ const formValue = ref({
const rules: FormRules = {
plans: [
{
required: true,
required: false,
type: 'array',
validator(rule: FormItemRule, value: string[]) {
if (value == null || value.length === 0)
return new Error('请选择拜访项目类别')
return true
},
trigger: ['blur', 'change'],
},
],

@ -19,14 +19,8 @@ const formValue = ref({
const rules: FormRules = {
plans: [
{
required: true,
required: false,
type: 'array',
validator(rule: FormItemRule, value: string[]) {
if (value == null || value.length === 0)
return new Error('请选择分类')
return true
},
trigger: ['blur', 'change'],
},
],

@ -19,14 +19,8 @@ const formValue = ref({
const rules: FormRules = {
plans: [
{
required: true,
required: false,
type: 'array',
validator(rule: FormItemRule, value: string[]) {
if (value == null || value.length === 0)
return new Error('请选择发布地区')
return true
},
trigger: ['blur', 'change'],
},
],

@ -19,14 +19,8 @@ const formValue = ref({
const rules: FormRules = {
plans: [
{
required: true,
required: false,
type: 'array',
validator(rule: FormItemRule, value: string[]) {
if (value == null || value.length === 0)
return new Error('请选择厂商')
return true
},
trigger: ['blur', 'change'],
},
],

@ -1,6 +1,6 @@
<script lang="ts" setup>
import { onBeforeMount, ref } from 'vue'
import type { FormItemRule, FormRules } from 'naive-ui'
import { type FormItemRule, type FormRules, faIR } from 'naive-ui'
import { useDictionary } from '@/store/modules/dictonary'
const props = defineProps<{
@ -19,14 +19,8 @@ const formValue = ref({
const rules: FormRules = {
plans: [
{
required: true,
required: false,
type: 'array',
validator(rule: FormItemRule, value: string[]) {
if (value == null || value.length === 0)
return new Error('请选择任务来源')
return true
},
trigger: ['blur', 'change'],
},
],

@ -19,14 +19,8 @@ const formValue = ref({
const rules: FormRules = {
plans: [
{
required: true,
required: false,
type: 'array',
validator(rule: FormItemRule, value: string[]) {
if (value == null || value.length === 0)
return new Error('请选择任务状态')
return true
},
trigger: ['blur', 'change'],
},
],

@ -19,14 +19,8 @@ const formValue = ref({
const rules: FormRules = {
plans: [
{
required: true,
required: false,
type: 'array',
validator(rule: FormItemRule, value: string[]) {
if (value == null || value.length === 0)
return new Error('请选择省份')
return true
},
trigger: ['blur', 'change'],
},
],

@ -19,14 +19,8 @@ const formValue = ref({
const rules: FormRules = {
plans: [
{
required: true,
required: false,
type: 'array',
validator(rule: FormItemRule, value: string[]) {
if (value == null || value.length === 0)
return new Error('请选择计划')
return true
},
trigger: ['blur', 'change'],
},
],

@ -19,14 +19,8 @@ const formValue = ref({
const rules: FormRules = {
users: [
{
required: true,
required: false,
type: 'array',
validator(rule: FormItemRule, value: string[]) {
if (value == null || value.length === 0)
return new Error('请选择提报人')
return true
},
trigger: ['blur', 'change'],
},
],

@ -1,10 +1,12 @@
<script lang="ts" setup>
import { computed, defineOptions, ref, watch } from 'vue'
import { VueDraggable } from 'vue-draggable-plus'
import { clone, debounce, difference } from 'lodash-es'
import { setFilter } from '@/api/home/filter'
import { getAllfieldList, getfieldList, setFilter } from '@/api/home/filter'
import { asideMap } from '@/config/aside'
import { useConfig } from '@/store/modules/asideConfig'
import { useUser } from "@/store/modules/user"
import { debounce, difference } from 'lodash-es'
import { computed, defineOptions, onMounted, ref, watch } from 'vue'
import { VueDraggable } from 'vue-draggable-plus'
defineOptions({ name: 'CustomFilterModal' })
@ -113,7 +115,7 @@ configStore.$subscribe(() => {
const config = configStore.getConfig
const customConfig = configStore.getCustomConfig
if (config === null || customConfig === null)
if (config == null || customConfig == null)
return
const { showList, hideList } = generatList(config, customConfig)
@ -245,6 +247,19 @@ const leftInputHandler = debounce((keyword) => {
const rightInputHandler = debounce((keyword) => {
onKeyword.value = keyword
}, 300)
async function getfield(){
let res;
res = await getAllfieldList(3)
const userStore = useUser();
const userInfo = userStore.getUserInfo;
res = await getfieldList(3,userInfo.id)
}
onMounted(()=>{
getfield();
})
</script>
<template>

@ -6,9 +6,7 @@ import { useDictionary } from '@/store/modules/dictonary'
import { useConfig } from '@/store/modules/asideConfig'
import type { FilterCondition } from '/#/api'
import { addCondition, updateCondition } from '@/api/home/filter'
import { formatToDate2 } from '@/utils/dateUtil'
defineOptions({ name: 'NewFilterModal' })
import { formatToDate2, formatToDate3 } from '@/utils/dateUtil'
type Status = 'edit' | 'new'
@ -96,7 +94,6 @@ const formValue = reactive<FormType>({
function handleSumbit(e: MouseEvent) {
e.preventDefault()
const v = formRef.value
formRef.value?.validate((errors) => {
if (errors)
return
@ -127,6 +124,7 @@ function handleSumbit(e: MouseEvent) {
})
}
//
function formatValue(searchfield: string, searchvalue: any) {
if (searchfield === 'izyear') {
const start = formatToDate2(searchvalue[0])
@ -134,12 +132,29 @@ function formatValue(searchfield: string, searchvalue: any) {
return `${start}-${end}`
}
if (Array.isArray(searchvalue))
if (searchfield === 'izsimilarity' && Array.isArray(searchvalue))
return searchvalue.join(',')
return searchvalue
}
//
function unformatValue(searchfield: string, searchvalue: any) {
// 2022/01/03-2023/02/04
if (searchfield === 'izyear') {
const dataStrs = searchvalue.split('-')
const start = formatToDate3(dataStrs[0])
const end = formatToDate3(dataStrs[1])
return [start, end]
}
// 80,90
if (searchfield === 'izsimilarity')
return searchvalue.split(',')
return searchvalue
}
function createCondition() {
formValue.conditions.push({
type: null,
@ -194,8 +209,6 @@ watch(() => dicStore.relationTypeList, (newval) => {
logicOptions.value = newval
})
const resultOptions = ref<Option[]>([])
function showModal() {
show.value = true
}
@ -206,6 +219,7 @@ function closeModal() {
function generateAllData(config): Option[] {
const initVal: Option[] = []
const list = Object.keys(config).reduce((acc, value) => {
if (value.startsWith('iz') && asideMap[value]?.inFilterList !== false) {
const name = asideMap[value]?.label
@ -222,19 +236,20 @@ function generateAllData(config): Option[] {
}
watch(() => configStore.systemConfig, (newVal) => {
if (!newVal)
return
const list = generateAllData(newVal)
typeOptions.value = list
})
function handleTypeUpate(value: string) {
if (value === 'izsimilarity') {
resultOptions.value = similarityOptions as any
return
}
function getOptions(key: string) {
if (key === 'izsimilarity')
return similarityOptions
const key = `get${value}`
const options = unref(dicStore[key])
resultOptions.value = options || []
const getterName = `get${key}`
const options = unref(dicStore[getterName])
return options || []
}
function leaveHandler() {
@ -261,7 +276,7 @@ function edit(editFilter: any) {
return {
type: item.searchfield,
operator: item.searchtype,
result: item.searchvalue,
result: unformatValue(item.searchfield, item.searchvalue),
}
})
}
@ -296,7 +311,6 @@ defineExpose({
>
<n-select
v-model:value="item.type" placeholder="请选择筛选项名称" :options="typeOptions"
@update:value="handleTypeUpate"
/>
<n-select
v-model:value="item.operator" style="margin-left: 8px;" placeholder="请选择"
@ -309,7 +323,7 @@ defineExpose({
/>
</n-space>
<n-select
v-else v-model:value="item.result" style="margin-left: 8px;" placeholder="请选择" :options="resultOptions"
v-else v-model:value="item.result" style="margin-left: 8px;" placeholder="请选择" :options="getOptions(item.type!)"
/>
<n-button :style="noBorderInput" icon-placement="right" @click="removeCondition(index)">
<template #icon>

@ -26,7 +26,7 @@ const el = ref<HTMLDivElement | null>(null)
const viewMode = ref('masonry')
const pagination = reactive({
pageNo: 0,
pageSize: 50,
pageSize: 30,
})
const configStore = useConfig()
const packageModalRef = ref(null)
@ -34,6 +34,9 @@ const generateModalRef = ref(null)
const LoginSuccessModalRef = ref(null)
const loading = ref(false)
const message = useMessage()
const totalCount = ref(0)
let canloadMore = true
let filterId = null
async function computeListHeight() {
const headEl = document.querySelector('.wrapper-content')!
@ -71,10 +74,10 @@ const layout = debounce(() => {
(_masonry as any).layout()
if (!el.value)
return
const scrollHeight = el.value!.scrollHeight
const clientHeight = el.value!.clientHeight
const top = scrollHeight - clientHeight - 100
el.value!.scrollTo({ top, behavior: 'instant' })
// const scrollHeight = el.value!.scrollHeight
// const clientHeight = el.value!.clientHeight
// const top = scrollHeight - clientHeight - 100
// el.value!.scrollTo({ top, behavior: 'instant' })
loading.value = false
})
@ -82,19 +85,8 @@ const layout = debounce(() => {
message.error('图片错误')
loading.value = false
})
// imagesloaded('.grid-item', () => {
// (_masonry as any).layout()
// const scrollHeight = el.value!.scrollHeight
// const clientHeight = el.value!.clientHeight
// const top = scrollHeight - clientHeight - 20
// el.value!.scrollTo({ top, behavior: 'instant' })
// loading.value = false
// })
}, 300)
let canloadMore = true
useInfiniteScroll(
el as any,
() => {
@ -136,14 +128,17 @@ async function featchList() {
pagination.pageNo += 1
const filterParams = unref(configStore.getAsideValue)
const result = await getPictureList({ ...pagination, ...contentParams, ...filterParams })
const { data, pageCount } = result
const asideParams = unref(configStore.getAsideValue)
const params = filterId ? { userSearchId: filterId } : asideParams
const result = await getPictureList({ ...pagination, ...contentParams, ...params })
const { data, pageCount, total } = result
totalCount.value = total
canloadMore = pageCount >= pagination.pageNo && pageCount > 0
const list = data.map((item) => {
return {
imgUrl: item.imgurl,
thumburl: item.serverThumbnailUrl || item.imgurl,
upname: item.upname,
ocrPictureclass: item.ocrPictureclass,
uphead: item.uphead,
@ -190,8 +185,6 @@ async function commitHandler(settingParam) {
finalParam.buessinessno = settingParam.packagename
finalParam.search_history = settingParam.comparehistory ? 1 : 0
// TODO
const modal = generateModalRef.value as any
modal.showModal()
@ -224,33 +217,31 @@ watch(() => configStore.asideValue, (newVal, oldVal) => {
refreshHandler()
}, { deep: true })
async function refreshHandler() {
function reset() {
pagination.pageNo = 0
pagination.pageSize = 50
pagination.pageSize = 30
listData.value.length = 0
loading.value = true
loading.value = false
canloadMore = true
filterId = null
layout()
}
const contentParams = {
search_month: timeRange.value,
search_history: 0,
}
async function refreshHandler(filtersearchId?: any) {
reset()
const filterParams = unref(configStore.getAsideValue)
const result = await getPictureList({ ...pagination, ...contentParams, ...filterParams })
const { data, pageCount } = result
pagination.pageNo += 1
canloadMore = pageCount >= pagination.pageNo
const list = data.map((item) => {
return {
imgUrl: item.imgurl,
upname: item.upname,
ocrPictureclass: item.ocrPictureclass,
uphead: item.uphead,
}
})
if (filtersearchId)
filterId = filtersearchId
listData.value = list
nextTick(() => {
useInfiniteScroll(
el as any,
() => {
loadMore()
},
{ distance: 10, canLoadMore: () => canloadMore },
)
})
}
function getAvatar(url: string): string {
@ -268,19 +259,22 @@ function getAvatar(url: string): string {
<SvgIcon style="cursor: pointer;" size="105" name="yijianchachong" @click="oneCheck" />
</div>
<div class="wrapper-content">
<div class="form">
<n-popselect v-model:value="timeRange" :options="timeOptions" trigger="click">
<div class="dropdown">
<span>{{ timeLabel || '请选择' }}</span>
<SvgIcon class="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>
<SvgIcon class="gap" name="arrow-botton" size="14" />
</div>
</n-popselect>
<div style="display: flex;justify-content: space-between;">
<div class="form">
<n-popselect v-model:value="timeRange" :options="timeOptions" trigger="click">
<div class="dropdown">
<span>{{ timeLabel || '请选择' }}</span>
<SvgIcon class="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>
<SvgIcon class="gap" name="arrow-botton" size="14" />
</div>
</n-popselect>
</div>
<span>{{ totalCount }}</span>
</div>
<n-spin :show="loading">
<div ref="el" class="scroll" :style="listStyle">
@ -293,8 +287,8 @@ function getAvatar(url: string): string {
:src="item.imgUrl"
> -->
<n-image
class="img" :img-props="{ onClick: hideDownload }"
:class="{ 'img-fit': viewMode !== 'masonry' }" :src="item.imgUrl"
class="img" :img-props="{ onClick: hideDownload }" :class="{ 'img-fit': viewMode !== 'masonry' }"
:src="item.thumburl"
/>
<div class="info">
<div class="left">

@ -35,9 +35,9 @@ const show = ref(false)
const flag = ref(true)
const formInline: FormState = reactive({
enterprisecode: '三方系统标识8',
username: '13311111111',
password: '12345678l',
enterprisecode: '演示公司',
username: 'yanshi01',
password: '123456',
})
const formSms: FormSms = reactive({

@ -1,9 +1,11 @@
<script lang="ts" setup>
import { computed, onBeforeMount, onMounted, onUnmounted, reactive, ref, unref, watch } from 'vue'
import { debounce } from 'lodash-es'
import TaskList from './TaskList.vue'
import { useTaskStore } from '@/store/modules/task'
import { useUser } from '@/store/modules/user'
import { useTaskStore } from '@/store/modules/task';
import { debounce } from 'lodash-es';
import { computed, ref, unref, watch } from 'vue';
import CustomFieldModal from '../../worksheet/modal/CustomFieldModal.vue';
import TaskList from './TaskList.vue';
const CustomFieldModalRef = ref(null)
const collapse = ref(false)
@ -85,7 +87,7 @@ const inputHandler = debounce((word) => {
</div>
</div>
<TaskList ref="taskListRef" style="height: calc(100vh - 146px);" class="work-sheet-list" />
<CustomFieldModal ref="CustomFieldModalRef" />
<CustomFieldModal ref="CustomFieldModalRef" :reviewType="2" />
</div>
</template>

@ -1,5 +1,6 @@
<script lang="ts" setup>
import { computed } from 'vue'
import { format } from 'date-fns';
import { computed } from 'vue';
defineOptions({ name: 'ListItem' })
@ -25,15 +26,17 @@ const svgName = computed(() => {
<div style="display: flex;">
<SvgIcon :name="svgName" size="28" />
<span class="list-item-header-name" :class="{ 'list-item-header-selected': selected }">
任务ID:{{ listItem.formid }}
任务ID:{{ listItem.fromtaskname }}
</span>
</div>
<SvgIcon v-show="selected" size="14" name="more-ver" />
</div>
<ul class="list-item-detail">
<li>审批状态<span class="list-item-status">{{ listItem.states }}</span></li>
<li>审批节点{{ listItem.createdate }}</li>
<li>提交时间{{ listItem.createdate }}</li>
<li>审批状态<span class="list-item-status">{{ listItem.statshisText }}</span></li>
<li>审批节点{{ listItem.tasknamehis }}</li>
<li>提交时间{{ format(new Date(), 'yyyy-MM-dd HH:mm:ss') }}</li>
<li>提报人{{ listItem.fromUserName }}</li>
</ul>
<div class="list-item-divider" />
</div>

@ -1,12 +1,9 @@
<script lang="ts" setup>
import { onMounted, onUnmounted, reactive, ref, watch } from 'vue'
import { useInfiniteScroll } from '@vueuse/core'
import ListItem from './ListItem.vue'
import { useTaskStore } from '@/store/modules/task'
import { useUser } from '@/store/modules/user'
import emitter from '@/utils/mitt'
defineOptions({ name: 'WorkSheetList' })
import { useInfiniteScroll } from '@vueuse/core'
import { onMounted, onUnmounted, reactive, ref, watch } from 'vue'
import ListItem from './ListItem.vue'
const taskStore = useTaskStore()
const data = ref<any[]>([])
@ -14,11 +11,10 @@ const activeId = ref('')
const el = ref<HTMLDivElement | null>(null)
const keyword = ref('')
const canloadMore = ref(true)
const userStore = useUser()
const pagination = reactive({
pageNo: 0,
pageSize: 10,
pageSize: 30,
})
function selectHandler(id: string, index: number) {
@ -30,10 +26,7 @@ const { isLoading } = useInfiniteScroll(
() => {
loadMore()
},
{ distance: 10, interval: 300, canLoadMore: () => {
// console.log('canloadmore excuted!')
return canloadMore.value
} },
{ distance: 10, interval: 300, canLoadMore: () => canloadMore.value },
)
async function loadMore() {
@ -47,10 +40,9 @@ async function loadMore() {
async function fetchList() {
try {
pagination.pageNo += 1
const id = userStore.getUserInfo.id
const result = await taskStore.fetchApprovalList(pagination, id)
const result = await taskStore.fetchApprovalList(pagination)
const { data, pageCount } = result
canloadMore.value = pageCount >= pagination.pageNo && pageCount !== 0
canloadMore.value = pageCount >= pagination.pageNo
return data || []
}
catch (error) {
@ -65,9 +57,11 @@ watch(() => taskStore.activeId, (newVal) => {
function reset() {
pagination.pageNo = 0
pagination.pageSize = 10
pagination.pageSize = 30
canloadMore.value = true
data.value.length = 0
taskStore.reset()
}
async function search(word: string) {
@ -91,7 +85,6 @@ onUnmounted(() => {
})
async function refreshHandler() {
reset()
search('')
}
@ -101,17 +94,29 @@ defineExpose({
</script>
<template>
<n-scrollbar>
<n-spin :show="isLoading">
<div ref="el">
<ListItem
v-for="(item, index) in data" :key="item.id" :selected="activeId === item.formid" :list-item="item"
@click="selectHandler(item.id, index)"
/>
</div>
</n-spin>
</n-scrollbar>
<n-spin :show="isLoading">
<div ref="el" class="list">
<ListItem
v-for="(item, index) in data" :key="item.id" :selected="activeId === item.id" :list-item="item"
@click="selectHandler(item.id, index)"
/>
</div>
</n-spin>
</template>
<style lang="less" scoped>
.list {
height: calc(100vh - 146px);
overflow-y: scroll;
overflow-x: hidden;
scrollbar-width: none;
/* firefox */
-ms-overflow-style: none;
/* IE 10+ */
&::-webkit-scrollbar {
display: none;
}
}
</style>

@ -1,10 +1,13 @@
<script lang="ts" setup>
import { getAllfieldList, getfieldList } from '@/api/home/filter'
import { audit } from '@/api/task/task'
import { getTaskDetailInfo, getTaskDetailPictureList } from '@/api/work/work'
import { useTask } from '@/store/modules/task'
import { useUser } from '@/store/modules/user'
import { isEmpty } from '@/utils'
import { hideDownload } from '@/utils/image'
import emitter from '@/utils/mitt'
import _ from 'lodash'
import { clone } from 'lodash-es'
import { useDialog, useMessage } from 'naive-ui'
import { computed, onUnmounted, reactive, ref, unref, watch } from 'vue'
@ -13,7 +16,17 @@ import ConfrimModal from '../modal/ConfrimModal.vue'
import CustomSettingModal from '../modal/CustomSettingModal.vue'
import PictureTable from './PictureTable.vue'
import TaskTable from './TaskTable.vue'
import { getAllfieldList } from '@/api/home/filter'
import { audit } from '@/api/task/task'
import { getTaskDetailInfo, getTaskDetailPictureList } from '@/api/work/work'
import { useTask } from '@/store/modules/task'
import { useUser } from '@/store/modules/user'
import { isEmpty } from '@/utils'
import { hideDownload } from '@/utils/image'
import emitter from '@/utils/mitt'
import type { ApprovalParam, PictureSortParam } from '/#/api'
import { formatToDateHMS } from '@/utils/dateUtil'
const batch = ref(false)
const selectItems = ref<any[]>([])
@ -23,49 +36,50 @@ const confrimModalRef = ref(null)
const batchModalRef = ref(null)
const totalCount = ref(0)
const CustomSettingModalRef = ref(null)
const taskTableData = ref<any[]>([])
const sortBy: PictureSortParam = {
orderbyname: 'asc',
orderbyvalue: 'fromuptime',
}
orderbyname: "asc",
orderbyvalue: "fromuptime",
};
function setBatch(value: boolean) {
batch.value = value
if (totalCount.value === 0) return;
batch.value = value;
if (value === false) {
selectItems.value.forEach(item => (item.checked = false))
selectItems.value.length = 0
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
const index = selectItems.value.indexOf(item);
item.checked = checked;
if (index === -1 && checked)
selectItems.value.push(item)
else selectItems.value.splice(index, 1)
if (index === -1 && checked) selectItems.value.push(item);
else selectItems.value.splice(index, 1);
}
const showActions = computed(() => {
return selectItems.value.length > 0 && batch
})
return selectItems.value.length > 0 && batch;
});
const taskpagination = reactive({
pageNo: 1,
pageSize: 10,
})
const taskStore = useTask()
const overTask = ref<any>(null)
const taskDetailInfo = ref<any>({})
const taskDetailPictureList = ref<any[]>([])
const userStore = useUser()
const imageRef = ref<ComponentElRef | null>()
let processItems: any[] = []
});
const taskStore = useTask();
const overTask = ref<any>(null);
const taskDetailInfo = ref<any>({});
const taskDetailPictureList = ref<any[]>([]);
const userStore = useUser();
const imageRef = ref<ComponentElRef | null>();
let processItems: any[] = [];
// states:1234
function validate(items: any[]) {
if (items.length === 0)
return '至少选中一个任务'
if (items.length === 0) return "至少选中一个任务";
// const useInfo = userStore.getUserInfo
// const username = useInfo.loginname
@ -82,170 +96,225 @@ function validate(items: any[]) {
// return ''
// }
return null
return null;
}
function approvalHandler(items?: any) {
let cloneItem: any
if (batch.value) { processItems = selectItems.value }
else if (overTask.value) {
cloneItem = clone(overTask.value)
processItems = [cloneItem]
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
processItems = items;
const msg = validate(processItems)
const msg = validate(processItems);
if (msg !== null) {
message.error(msg)
return
message.error(msg);
return;
}
dialog.info({
title: '确认提示',
content: '确认给该任务审批为【通过】吗?',
positiveText: '确定',
negativeText: '取消',
title: "确认提示",
content: "确认给该任务审批为【通过】吗?",
positiveText: "确定",
negativeText: "取消",
onPositiveClick: () => {
approval()
approval();
},
onNegativeClick: () => { },
})
onNegativeClick: () => {},
});
}
function rejectHandler(items?: any) {
let cloneItem: any
if (batch.value) { processItems = selectItems.value }
else if (overTask.value) {
cloneItem = clone(overTask.value)
processItems = [cloneItem]
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
processItems = items;
const msg = validate(processItems)
const msg = validate(processItems);
if (msg !== null) {
message.error(msg)
return
message.error(msg);
return;
}
const modal = unref(confrimModalRef)! as any
modal.showModal()
const modal = unref(confrimModalRef)! as any;
modal.showModal();
}
function approval() {
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 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: true,
taskComment: 'approval',
taskComment: "approval",
taskname: tasknames,
}
};
doAudit(param)
doAudit(param);
}
function doAudit(param: any) {
audit(param).then((res) => {
const { code } = res
processItems.length = 0
if (code === 'OK')
emitter.emit('refresh')
else message.error(res.message)
})
const { code } = res;
processItems.length = 0;
if (code === "OK") emitter.emit("refresh");
else message.error(res.message);
});
}
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 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 : ['其他'],
}
taskname: isOther ? tasknames : ["其他"],
};
doAudit(param)
doAudit(param);
}
function showModal(modalRef: any) {
const modal = unref(modalRef)! as any
modal.showModal()
const modal = unref(modalRef)! as any;
modal.showModal();
}
function forwardHandler() {
taskStore.forward()
taskStore.forward();
}
function backHandler() {
taskStore.back()
taskStore.back();
}
watch(() => [taskStore.activeId, taskStore.refresh], async (newValue, oldValue) => {
const packageid = taskStore.getPackageid
const taskId = taskStore.getActiveId
if (taskId === '' || packageid === '')
return
taskDetailInfo.value = await getTaskDetailInfo(taskId, packageid)
const { data, total } = await getTaskDetailPictureList(packageid, taskId, { ...taskpagination, ...sortBy })
taskDetailPictureList.value = data
totalCount.value = total
})
watch(
() => [taskStore.activeId],
async (newValue, oldValue) => {
const packageid = taskStore.getPackageid
const taskId = taskStore.getActiveId
if (isEmpty(taskId)) return;
const useInfo = userStore.getUserInfo;
let listData = [];
taskDetailInfo.value = await getTaskDetailInfo(taskId, packageid);
const reviewType = 3; //
let res = await getAllfieldList(reviewType);
let fieldList = (res as any)?.data;
res = await getfieldList(reviewType, useInfo.id);
let userFieldList = (res as any)?.data.userFieldFixed;
console.log(userFieldList,'userFieldList')
fieldList.map((v) => {
if (userFieldList.indexOf(v.name) > -1) {
let item = {
label: v.fieldDesc,
value: taskDetailInfo.value.ocrPicture[v.name],
key: v.name,
};
listData.push(item);
}
});
// TODO mock
// let showFieldData = taskDetailInfo.value.ocrPicture;
// let showFieldKeys = Object.keys(showFieldData);
// for (let i in showFieldKeys) {
// let key = showFieldKeys[i];
// let hasKey = userFieldList.indexOf(key) > -1;
// if (hasKey) {
// let currentData = fieldList.find((v) => v.name == key);
// if (currentData) {
// console.log(fieldList, key, "currentData");
// console.log(currentData, "currentData222");
// let item = {
// label: currentData.fieldDesc,
// value: taskDetailInfo.value.ocrPicture[key],
// key: currentData.name,
// };
// listData.push(item);
// }
// }
// }
taskTableData.value = _.chunk(listData, 2);
if (!isEmpty(packageid)) {
const { data, total } = await getTaskDetailPictureList(
packageid,
taskId,
{ ...taskpagination, ...sortBy },
)
taskDetailPictureList.value = data
totalCount.value = total
}
}
);
const currentTaskId = computed(() => {
const index = taskStore.getCurrentIndex
return taskStore.getApprovalList[index]?.formid || ''
})
const index = taskStore.getCurrentIndex;
return taskStore.getApprovalList[index]?.formid || "";
});
function overTaskHandle() {
const item = taskDetailInfo.value
const item = taskDetailInfo.value;
if (validate([item]) == null && batch.value === false)
overTask.value = item
if (validate([item]) == null && batch.value === false) overTask.value = item;
}
function leaveTaskHandler() {
overTask.value = null
overTask.value = null;
}
function showActionsModal() {
const modal = unref(CustomSettingModalRef)! as any
modal.showModal()
const modal = unref(CustomSettingModalRef)! as any;
modal.showModal();
}
onUnmounted(() => {
taskStore.reset()
})
taskStore.reset();
});
const mark = computed(() => {
return taskDetailInfo.value.iztrueorfalse === null ? '未标记' : '已标记'
})
return taskDetailInfo.value.iztrueorfalse === null ? "未标记" : "已标记";
});
function immersionHandler() {
taskStore.updateImmersion()
taskStore.updateImmersion();
}
function previewHandler(event: MouseEvent) {
event.stopImmediatePropagation()
event.stopPropagation()
event.stopImmediatePropagation();
event.stopPropagation();
if (imageRef.value)
if (imageRef.value && (imageRef.value as any).src)
(imageRef.value as any).mergedOnClick()
}
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}%`;
}
</script>
<template>
@ -267,12 +336,21 @@ function previewHandler(event: MouseEvent) {
/>
</div>
<div class="right">
<div v-show="!showActions" style="display: flex;align-items: center;" @click="setBatch(true)">
<div
v-show="!showActions"
style="display: flex; align-items: center"
@click="setBatch(true)"
>
<div class="btn">
<SvgIcon style="margin-right: 6px;" size="14" name="tf" />
<SvgIcon style="margin-right: 6px" size="14" name="tf" />
批量审批
</div>
<SvgIcon style="cursor: pointer;" size="20" name="immersion-model" @click="immersionHandler" />
<SvgIcon
style="cursor: pointer"
size="20"
name="immersion-model"
@click="immersionHandler"
/>
</div>
<div v-show="showActions" class="batch">
<n-button text @click="setBatch(false)">
@ -281,11 +359,14 @@ function previewHandler(event: MouseEvent) {
</template>
返回
</n-button>
<div style="cursor: pointer;margin-left: 16px;" @click.stop="rejectHandler">
<div
style="cursor: pointer; margin-left: 16px"
@click.stop="rejectHandler"
>
<SvgIcon width="64" height="28" name="a1" />
</div>
<SvgIcon size="24" name="vs" />
<div style="cursor: pointer;" @click.stop="approvalHandler">
<div style="cursor: pointer" @click.stop="approvalHandler">
<SvgIcon width="64" height="28" name="a2" />
</div>
</div>
@ -293,21 +374,55 @@ function previewHandler(event: MouseEvent) {
</div>
<div class="wrapper-detail">
<div
class="left" :style="{ 'background-image': `url(${taskDetailInfo?.ocrPicture?.imgurl})` }"
@mouseover="overTaskHandle" @mouseleave="leaveTaskHandler" @click="previewHandler"
class="left"
:style="{
'background-image': `url(${taskDetailInfo?.ocrPicture?.imgurl})`,
}"
@mouseover="overTaskHandle"
@mouseleave="leaveTaskHandler"
@click="previewHandler"
>
<div v-show="overTask" class="action">
<SvgIcon style="cursor: pointer;" width="168" height="48" name="r6" @click.stop="approvalHandler" />
<SvgIcon
style="cursor: pointer;margin-left: 30px;" width="168" height="48" name="r7"
style="cursor: pointer"
width="168"
height="48"
name="r6"
@click.stop="approvalHandler"
/>
<SvgIcon
style="cursor: pointer; margin-left: 30px"
width="168"
height="48"
name="r7"
@click.stop="rejectHandler"
/>
</div>
<div class="check">
<n-checkbox
v-show="batch"
v-model:checked="taskDetailInfo.checked"
@click.stop
@update:checked="onCheckChange($event, taskDetailInfo)"
/>
</div>
<div class="status">
<SvgIcon v-show="taskDetailInfo?.states === 4" width="134" height="129" name="p1" />
<SvgIcon v-show="taskDetailInfo?.states === 3" width="134" height="129" name="p2" />
</div>
<div class="mark">
<SvgIcon v-show="taskDetailInfo?.iztrueorfalse === 0" size="128" name="jia" />
<SvgIcon
v-show="taskDetailInfo?.iztrueorfalse === 0"
size="128"
name="jia"
/>
</div>
<div class="mark">
<SvgIcon v-show="taskDetailInfo?.iztrueorfalse === 1" size="128" name="zhen" />
<SvgIcon
v-show="taskDetailInfo?.iztrueorfalse === 1"
size="128"
name="zhen"
/>
</div>
<div class="info">
<n-grid x-gap="12" y-gap="10" :cols="12">
@ -317,7 +432,7 @@ function previewHandler(event: MouseEvent) {
</span>
</n-gi>
<n-gi span="8" class="gi2">
<span style="font-size: bold;font-size: 18px;">{{ mark }}</span>
<span style="font-size: bold; font-size: 18px">{{ mark }}</span>
<span>审批状态</span>
</n-gi>
<n-gi span="4" class="gi1">
@ -326,31 +441,46 @@ function previewHandler(event: MouseEvent) {
</span>
</n-gi>
<n-gi span="8" class="gi2">
<span style="font-size: bold;font-size: 18px;">{{ totalCount }}</span>
<span style="font-size: bold; font-size: 18px">{{
totalCount
}}</span>
<span>相似匹配</span>
</n-gi>
</n-grid>
</div>
<div class="time">
<SvgIcon color="#FFF" size="16" name="time" />
<span>2023-09-17 13:09:10</span>
<span>{{ formatToDateHMS(taskDetailInfo.createdate || 0) }}</span>
</div>
<div style="display: none;">
<n-image ref="imageRef" :img-props="{ onClick: hideDownload }" :src="taskDetailInfo?.ocrPicture?.imgurl" />
<div style="display: none">
<n-image
ref="imageRef"
:img-props="{ onClick: hideDownload }"
:src="taskDetailInfo?.ocrPicture?.imgurl"
/>
</div>
</div>
<div class="right">
<n-scrollbar style="max-height: 100%">
<n-scrollbar v-if="totalCount > 0" style="max-height: 100%">
<div class="header">
<span>相似图片(9)</span>
<span>相似图片({{ totalCount }})</span>
<SvgIcon
style="margin-right: 20px;cursor: pointer;" name="max" size="24"
style="margin-right: 20px; cursor: pointer"
name="max"
size="24"
@click="showModal(batchModalRef)"
/>
</div>
<div class="list">
<div v-for="(item, index) in taskDetailPictureList" :key="index" class="item">
<div class="img-wrapper" :style="{ 'background-image': `url(${item.imgurl})` }" />
<div
v-for="(item, index) in taskDetailPictureList"
:key="index"
class="item"
>
<div
class="img-wrapper"
:style="{ 'background-image': `url(${item.thumburl})` }"
/>
<div class="check">
<n-checkbox
v-show="batch"
@ -360,19 +490,18 @@ function previewHandler(event: MouseEvent) {
/>
</div>
<div class="percent">
96%
{{ getPercent(item.pictureid) }}
</div>
</div>
</div>
</n-scrollbar>
<n-empty v-else description="暂无数据" />
</div>
</div>
<div class="info-header">
<div class="left_box">
<div class="title">
填报信息
</div>
<div class="title">填报信息</div>
<SvgIcon size="12" name="collapse" />
</div>
<div class="right_box" @click="showActionsModal">
@ -382,7 +511,7 @@ function previewHandler(event: MouseEvent) {
</div>
<n-tabs type="line" animated>
<n-tab-pane name="task-info" tab="任务信息">
<TaskTable :data="taskDetailInfo" />
<TaskTable :data="taskDetailInfo" :taskTableData="taskTableData" />
</n-tab-pane>
<n-tab-pane name="picture-info" tab="图片信息">
<PictureTable :data="taskDetailInfo" />
@ -390,8 +519,12 @@ function previewHandler(event: MouseEvent) {
<n-tab-pane name="history" tab="历史审查" />
</n-tabs>
<ConfrimModal ref="confrimModalRef" @commit="reject" />
<BatchModal ref="batchModalRef" @reject="rejectHandler" @approval="approvalHandler" />
<CustomSettingModal ref="CustomSettingModalRef" />
<BatchModal
ref="batchModalRef"
@reject="rejectHandler"
@approval="approvalHandler"
/>
<CustomSettingModal ref="CustomSettingModalRef" :review-type="3" />
</div>
</template>
@ -448,7 +581,7 @@ function previewHandler(event: MouseEvent) {
display: flex;
align-items: center;
justify-content: center;
color: #FFF;
color: #fff;
margin-right: 6px;
cursor: pointer;
}
@ -518,7 +651,7 @@ function previewHandler(event: MouseEvent) {
background: rgba(216, 216, 216, 0.4);
border-radius: 7px;
padding: 10px;
color: #FFF;
color: #fff;
}
.time {
@ -526,7 +659,7 @@ function previewHandler(event: MouseEvent) {
z-index: 3;
left: 2%;
bottom: 2%;
color: #FFF;
color: #fff;
display: flex;
align-items: center;
}
@ -540,7 +673,21 @@ function previewHandler(event: MouseEvent) {
display: flex;
align-items: left;
flex-direction: column;
justify-content: center
justify-content: center;
}
.check{
position: absolute;
z-index: 3;
left: 2%;
top: 2%;
}
.status{
position: absolute;
z-index: 3;
left: 3%;
top: 3%;
}
}

@ -16,14 +16,14 @@ defineProps({
</td>
<th>图片格式</th>
<td class="blue">
???
</td>
</tr>
<tr>
<th>图片大小</th>
<td> ???</td>
<td></td>
<th>图片尺寸</th>
<td> ???</td>
<td></td>
</tr>
<tr>
<th>上传时间</th>
@ -33,7 +33,7 @@ defineProps({
</tr>
<tr>
<th>标记时间</th>
<td> ???</td>
<td> </td>
<th>色彩空间</th>
<td>{{ data?.ocrPicture?.space }}</td>
</tr>

@ -1,55 +1,28 @@
<script lang="ts" setup>
defineProps({
import { onMounted } from "vue";
const props = defineProps({
data: {
type: Object as PropType<any>,
required: true,
},
taskTableData: {
type: Array,
default: () => [[]],
},
});
onMounted(()=>{
console.log(props.taskTableData,'taskTableData')
})
</script>
<template>
<table class="description">
<tr>
<th>拜访终端名称</th>
<td class="blue">
{{ data?.ocrPicture?.field3 }}
</td>
<th>定位信息</th>
<td class="blue">
{{ data?.ocrPicture?.field10 }}
</td>
</tr>
<tr>
<th>拜访日期</th>
<td> {{ data?.ocrPicture?.field1 }}</td>
<th>定位距离</th>
<td> {{ data?.ocrPicture?.field12 }}</td>
</tr>
<tr>
<th>拜访小结</th>
<td> {{ data?.ocrPicture?.field8 }}</td>
<th>拜访项目类别</th>
<td> {{ data?.ocrPicture?.field17 }}</td>
</tr>
<tr>
<th>科室名称</th>
<td> {{ data?.ocrPicture?.field7 }}</td>
<th>病例号</th>
<td></td>
</tr>
<tr>
<th>拜访级别</th>
<td> {{ data?.ocrPicture?.field6 }}</td>
<th>下阶段计划</th>
<td>?</td>
</tr>
<tr>
<th>是否为重复图片</th>
<td> {{ data?.ocrPicture?.field14 }}</td>
<th>附件信息</th>
<td>
<a href="data?.fileannex" download>????</a>
</td>
<tr v-for="(item, index) in taskTableData" :key="index">
<th v-if="item&&item[0]">{{ item[0]["label"] }}</th>
<td v-if="item&&item[0]">{{ item[0]["value"] }}</td>
<th v-if="item&&item.length>1">{{ item[1]["label"] }}</th>
<td v-if="item&&item.length>1">{{ item[1]["value"] }}</td>
</tr>
</table>
</template>

@ -1,9 +1,10 @@
<script lang="ts" setup>
import { computed, onMounted, onUpdated, reactive, ref, watch } from 'vue'
import { computed, nextTick, onMounted, onUpdated, reactive, ref, watch } from 'vue'
import Masonry from 'masonry-layout'
import { useInfiniteScroll } from '@vueuse/core'
import { debounce } from 'lodash-es'
import imagesloaded from 'imagesloaded'
import { useMessage } from 'naive-ui'
import { timeOptions, viewOptions } from '@/config/home'
import { off, on } from '@/utils/domUtils'
import { useTask } from '@/store/modules/task'
@ -46,10 +47,10 @@ const el = ref<HTMLDivElement | null>(null)
const listData = ref<any[]>([])
const taskDetailInfo = ref<any>({})
const pagination = reactive({
pageNo: 1,
pageNo: 0,
pageSize: 30,
})
let loading = false
const loading = ref(false)
let _masonry: null | Masonry = null
const show = ref(false)
const sortBy: PictureSortParam = {
@ -57,6 +58,8 @@ const sortBy: PictureSortParam = {
orderbyvalue: 'fromuptime',
}
const batch = ref(false)
let _imagesload: any
const message = useMessage()
const layout = debounce(() => {
if (!show.value)
@ -72,13 +75,18 @@ const layout = debounce(() => {
stagger: 10,
})
imagesloaded('.grid-item', () => {
_imagesload = imagesloaded('.grid-item')
_imagesload.on('done', (instance) => {
(_masonry as any).layout()
const scrollHeight = el.value!.scrollHeight
const clientHeight = el.value!.clientHeight
const top = scrollHeight - clientHeight - 20
el.value!.scrollTo({ top, behavior: 'instant' })
loading = false
if (!el.value)
return
loading.value = false
})
_imagesload.on('fail', (instance) => {
message.error('图片错误')
loading.value = false
})
}, 300)
@ -96,27 +104,8 @@ useInfiniteScroll(
{ distance: 10, canLoadMore: () => canloadMore },
)
async function featchList() {
loading = true
try {
const packageid = taskStore.getPackageid
const taskId = taskStore.getActiveId
const res = await getTaskDetailPictureList(packageid, taskId, { ...pagination, ...sortBy })
const { data, pageCount } = res
pagination.pageNo += 1
canloadMore = pageCount >= pagination.pageNo
return data
}
catch (error) {
return []
}
}
async function loadMore() {
if (loading || el.value == null)
if (loading.value || el.value == null)
return
const packageid = taskStore.getPackageid
@ -127,11 +116,28 @@ async function loadMore() {
const more = await featchList()
listData.value.push(...more)
nextTick(() => {
layout()
})
}
onUpdated(() => {
layout()
})
async function featchList() {
loading.value = true
try {
const packageid = taskStore.getPackageid
const taskId = taskStore.getActiveId
pagination.pageNo += 1
const { data, pageCount } = await getTaskDetailPictureList(packageid, taskId, { ...pagination, ...sortBy })
canloadMore = pageCount >= pagination.pageNo && pageCount > 0
return data
}
catch (error) {
canloadMore = false
return []
}
}
let start: { x: number, y: number } | null = null
let selectionBox: HTMLDivElement | null
@ -292,18 +298,34 @@ function getSelectItems() {
return listData.value.filter(item => selectIds.value.includes(item.id))
}
function reset() {
pagination.pageNo = 0
pagination.pageSize = 30
listData.value.length = 0
loading.value = false
canloadMore = true
layout()
}
async function refreshHandler() {
reset()
const packageid = taskStore.getPackageid
const taskId = taskStore.getActiveId
taskDetailInfo.value = await getTaskDetailInfo(taskId, packageid)
pagination.pageNo = 1
pagination.pageSize = 30
listData.value.length = 0
if (!packageid || !taskId)
return
const list = await featchList()
listData.value = list
layout()
taskDetailInfo.value = await getTaskDetailInfo(taskId, packageid)
nextTick(() => {
useInfiniteScroll(
el as any,
() => {
loadMore()
},
{ distance: 10, canLoadMore: () => canloadMore },
)
})
}
watch(() => taskStore.activeId, async (newValue, oldValue) => {
@ -414,7 +436,7 @@ watch(() => taskStore.activeId, async (newValue, oldValue) => {
>
<img
class="wrapper-content-item-img"
:class="{ 'wrapper-content-item-img-fit': viewMode !== 'masonry' }" :src="item.imgurl"
:class="{ 'wrapper-content-item-img-fit': viewMode !== 'masonry' }" :src="item.thumburl"
>
<div class="top">
<n-checkbox
@ -610,7 +632,7 @@ watch(() => taskStore.activeId, async (newValue, oldValue) => {
.scroll {
overflow-y: scroll;
height: calc(100vh - 320px);
height: calc(100vh - 420px);
}
}
}

@ -1,8 +1,8 @@
<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'
import { workPackageMap } from '@/config/workorder';
import { difference } from 'lodash-es';
import { computed, ref, watch } from 'vue';
import { VueDraggable } from 'vue-draggable-plus';
//
const offList = ref<any[]>([])

@ -1,6 +1,44 @@
<script lang="ts" setup>
import { getAllfieldList, getfieldList, savefield } from "@/api/home/filter";
import { ReportInfoConfig } from "@/config/workorder";
import { ref } from "vue";
import { useUser } from "@/store/modules/user";
import { defineProps, onMounted, ref } from "vue";
const props = defineProps({
reviewType: {
type: Number,
default: () => 3,
require: true,
},
})
onMounted(async () => {
const userStore = useUser();
const userInfo = userStore.getUserInfo;
let res;
res = await getAllfieldList(props.reviewType); //
const allList = res.data;
res = await getfieldList(props.reviewType, userInfo.id); //
const useList = res.data;
/**
* name 标题
* id 键值
* fix 是否默认
* checked 是否选中
*/
allList.map((v) => {
let item = {
name: v.fieldDesc,
id: v.name,
fix: v.isrequired == 2,
checked:
v.isrequired == 2 ||
Boolean(useList.userFieldFixed?.toLowerCase().indexOf(v.name)>-1) || Boolean(useList.userFieldUnFixed?.toLowerCase().indexOf(v.name)>-1),
};
offList.value.push(item)
});
});
const offList = ref<any[]>([]);
function generatList() {
@ -59,15 +97,28 @@ function closeModal() {
}
async function handleSumbit(e: MouseEvent) {
const userStore = useUser();
const userInfo = userStore.getUserInfo;
let userField = "";
offList.value.map((v) => {
if(v.checked){
userField += `${v.id},`;
}
});
userField = userField.slice(0,userField.length-1);
savefield(props.reviewType, userInfo.id, userField);
e.preventDefault();
closeModal();
setTimeout(()=>{
window.location.reload();
},3000)
}
defineExpose({
showModal,
});
generatList();
// generatList();
const selectIds = ref<string[]>([]);

@ -1,11 +1,11 @@
<script lang="ts" setup>
import { computed, defineOptions, nextTick, onBeforeMount, onMounted, reactive, ref, unref, watch } from 'vue'
import { debounce } from 'lodash-es'
import { computed, defineOptions, nextTick, onMounted, ref, unref, watch } 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 { useWorkOrder } from '@/store/modules/workOrder'
import { useWindowSizeFn } from '@/hooks/event/useWindowSizeFn'
defineOptions({ name: 'AsideContent' })
@ -114,8 +114,8 @@ const inputHandler = debounce((word) => {
<SvgIcon size="16px" style="margin-left: 6px;cursor: pointer;" name="clear" @click="setShowSearch(false)" />
</div>
</div>
<WorkSheetList ref="packageListRef" :style="listStyle" class="work-sheet-list" />
<CustomFieldModalVue ref="filterModalRef" />
<WorkSheetList ref="packageListRef" class="work-sheet-list" />
<CustomFieldModalVue ref="filterModalRef" :review-type="1" />
</div>
</template>

@ -1,9 +1,10 @@
<script lang="ts" setup>
import type { PackageListItem } from '/#/workorder'
import ListItem from './ListItem.vue'
import { useWorkOrder } from '@/store/modules/workOrder'
import { reactive, ref, watch } from 'vue'
import { isEmpty } from '@/utils'
import { useInfiniteScroll } from '@vueuse/core'
import { reactive, ref, watch } from 'vue'
import ListItem from './ListItem.vue'
import type { PackageListItem } from '/#/workorder'
const workStore = useWorkOrder()
const data = ref<PackageListItem[]>([])
@ -26,7 +27,7 @@ const { isLoading } = useInfiniteScroll(
() => {
loadMore()
},
{ distance: 10, interval: 300, canLoadMore: () => {
{ distance: 10, interval: 800, canLoadMore: () => {
// console.log('canloadmore excuted!')
return canloadMore.value
} },
@ -56,6 +57,9 @@ async function fetchList() {
}
watch(() => workStore.activeId, (newVal) => {
if (isEmpty(newVal))
return
activeId.value = newVal
})
@ -64,6 +68,8 @@ function reset() {
pagination.pageSize = 10
canloadMore.value = true
data.value.length = 0
workStore.reset()
}
async function search(word: string) {
@ -84,17 +90,29 @@ defineExpose({
</script>
<template>
<n-scrollbar>
<n-spin :show="isLoading">
<div ref="el">
<ListItem
v-for="(item, index) in data" :key="item.id" :selected="activeId === item.id" :list-item="item"
@click="selectHandler(item.id, index)"
/>
</div>
</n-spin>
</n-scrollbar>
<n-spin :show="isLoading">
<div ref="el" class="list">
<ListItem
v-for="(item, index) in data" :key="item.id" :selected="activeId === item.id" :list-item="item"
@click="selectHandler(item.id, index)"
/>
</div>
</n-spin>
</template>
<style lang="less" scoped>
.list {
height: calc(100vh - 146px);
overflow-y: scroll;
overflow-x: hidden;
scrollbar-width: none;
/* firefox */
-ms-overflow-style: none;
/* IE 10+ */
&::-webkit-scrollbar {
display: none;
}
}
</style>

@ -1,19 +1,23 @@
<script lang="ts" setup>
import { computed, onUnmounted, reactive, ref, unref, watch } from 'vue'
import { computed, onUnmounted, onUpdated, reactive, ref, unref, watch } from 'vue'
import { useDialog, useMessage } from 'naive-ui'
import { clone, pickBy } from 'lodash-es'
import { clone, debounce, pickBy } from 'lodash-es'
import { useInfiniteScroll } from '@vueuse/core'
import imagesloaded from 'imagesloaded'
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'
import { hideDownload } from '@/utils/image'
import { isEmpty } from '@/utils'
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) {
batch.value = value
@ -47,17 +51,21 @@ const taskpagination = reactive({
pageSize: 10,
})
const sortBy: PictureSortParam = {
orderbyname: 'desc',
orderbyvalue: 'fromuptime',
orderbyname: 'asc',
orderbyvalue: 'pictureResult',
}
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)
const imageRef = ref<ComponentElRef | null>()
const listData = ref<any[]>([])
const loading = ref(false)
const el = ref<HTMLDivElement | null>(null)
let canloadMore = true
let processItems: any[] = []
@ -166,13 +174,16 @@ function doSetTF(param: SetTFParam) {
}
function updateList(param: SetTFParam) {
const list = taskDetailPictureList.value
const list = listData.value
const ids = param.taskchildpictureids.split(',')
for (const item of list) {
if (ids.includes(item.id))
item.iztrueorfalse = param.iztrueorfalse
}
if (ids.includes(taskDetailInfo.value.id))
taskDetailInfo.value.iztrueorfalse = param.iztrueorfalse
}
function forwardHandler() {
@ -183,11 +194,82 @@ function backHandler() {
workStore.back()
}
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 taskId = selectTask.value.id
const { data, total, pageCount } = await getTaskDetailPictureList(workStore.activeId, taskId, { ...taskpagination, ...sortBy })
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)
onUpdated(() => {
layout()
})
watch(() => workStore.activeId, async (newValue, oldValue) => {
const packageid = workStore.getActiveId
if (isEmpty(packageid))
return
const res = await getPackageTaskList(newValue, packagepagination)
const { data } = res
taskList.value = data
if (taskList.value.length > 0)
handleSelect(taskList.value[0])
})
@ -202,21 +284,21 @@ async function handleSelect(item: any) {
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
const packageid = workStore.getActiveId
if (isEmpty(packageid))
return
refreshHandler()
}
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
sortBy.orderbyname = sortBy.orderbyname === 'asc' ? 'desc' : 'asc'
refreshHandler()
}
const propertys = computed(() => {
@ -267,7 +349,7 @@ function getPercent(pictureid: string) {
const index = ocpictureid.split(',').indexOf(String(pictureid))
const results = pictureresult.split(',')
const percent = results[index] || '0'
const val = Number.parseFloat(percent)
const val = Math.floor(Number.parseFloat(percent))
return `${val}%`
}
@ -279,15 +361,23 @@ function immersionHandler() {
workStore.updateImmersion()
}
function showAction() {
const item = taskDetailInfo.value
if (batch.value === false)
overTask.value = item
}
function hideAction() {
overTask.value = null
}
function previewHandler(event: MouseEvent) {
event.stopImmediatePropagation()
event.stopPropagation()
if (imageRef.value)
if (imageRef.value && (imageRef.value as any).src)
(imageRef.value as any).mergedOnClick()
}
const count = computed(() => taskDetailPictureList.value.length)
</script>
<template>
@ -328,110 +418,130 @@ const count = computed(() => taskDetailPictureList.value.length)
</div>
</div>
</div>
<div class="wrapper-detail">
<div
class="left" :style="{ 'background-image': `url(${taskDetailInfo?.ocrPicture?.imgurl})` }"
@click="previewHandler"
>
<div class="mark">
<SvgIcon v-show="taskDetailInfo?.iztrueorfalse === 0" size="128" name="jia" />
</div>
<div class="mark">
<SvgIcon v-show="taskDetailInfo?.iztrueorfalse === 1" size="128" name="zhen" />
</div>
<div class="info">
<n-grid x-gap="16" y-gap="0" :cols="12">
<n-gi span="4">
<span style="color:#8b8d8f;">
<SvgIcon name="m1" />
</span>
</n-gi>
<n-gi span="8" style="display: flex;align-items: left;flex-direction: column;justify-content: center;">
<span>{{ mark }}</span>
<span>图片标记</span>
</n-gi>
<n-gi span="4">
<span style="color:#8b8d8f;">
<SvgIcon name="m2" />
</span>
</n-gi>
<n-gi span="8" style="display: flex;align-items: left;flex-direction: column;justify-content: center;">
<span>{{ totalCount }}</span>
<span>相似匹配</span>
</n-gi>
</n-grid>
</div>
<div style="display: none;">
<n-image ref="imageRef" :img-props="{ onClick: hideDownload }" :src="taskDetailInfo?.ocrPicture?.imgurl" />
</div>
</div>
<div class="right">
<n-scrollbar style="max-height: 100%;">
<span class="name">图片名称</span>
<div class="tags">
<div class="tag tag-actived">
重复图片
<n-spin :show="loading">
<div ref="el" class="scroll">
<div class="wrapper-detail">
<div
class="left" :style="{ 'background-image': `url(${taskDetailInfo?.ocrPicture?.imgurl})` }"
@click="showAction" @mouseleave="leaveTaskHandler"
>
<!-- 真假标记 -->
<div class="mark">
<SvgIcon v-show="taskDetailInfo?.iztrueorfalse === 0" size="128" name="jia" />
</div>
<div class="tag">
基线任务
<div class="mark">
<SvgIcon v-show="taskDetailInfo?.iztrueorfalse === 1" size="128" name="zhen" />
</div>
<!-- 右下信息 -->
<div class="info">
<n-grid x-gap="16" y-gap="0" :cols="12">
<n-gi span="4">
<span style="color:#8b8d8f;">
<SvgIcon name="m1" />
</span>
</n-gi>
<n-gi span="8" style="display: flex;align-items: left;flex-direction: column;justify-content: center;">
<span>{{ mark }}</span>
<span>图片标记</span>
</n-gi>
<n-gi span="4">
<span style="color:#8b8d8f;">
<SvgIcon name="m2" />
</span>
</n-gi>
<n-gi span="8" style="display: flex;align-items: left;flex-direction: column;justify-content: center;">
<span>{{ totalCount }}</span>
<span>相似匹配</span>
</n-gi>
</n-grid>
</div>
<!-- 右上点击大图 -->
<div class="preview" @click="previewHandler">
<SvgIcon size="30" name="zoom-out" />
</div>
<!-- 预览大图组件 -->
<div style="display: none;">
<n-image
ref="imageRef" :img-props="{ onClick: hideDownload }"
:src="taskDetailInfo?.ocrPicture?.imgurl"
/>
</div>
<!-- 操作 -->
<div v-show="overTask && overTask.id === taskDetailInfo.id" class="action" @click.stop="hideAction">
<SvgIcon style="cursor: pointer;" name="t1" @click.stop="trueHandler" />
<SvgIcon style="cursor: pointer;margin-left: 30px;" name="t2" @click.stop="falseHandler" />
</div>
</div>
<n-divider />
<div class="property">
<span class="property-name top" style="font-weight: bold;color: #333333;">拜访终端
</span>
<span style="font-weight: bold;color: #333333;font-size: 16px;">拜访终端</span>
</div>
<div v-for="(key) in Object.keys(propertys)" :key="key" class="property">
<span class="property-name">{{ fieldMap[key] }}</span>
<span class="property-content ">{{ propertys[key] }}</span>
<div class="right">
<n-scrollbar style="max-height: 100%;">
<span class="name">图片名称</span>
<div class="tags">
<div class="tag tag-actived">
重复图片
</div>
<div class="tag">
基线任务
</div>
</div>
<n-divider />
<div class="property">
<span class="property-name top" style="font-weight: bold;color: #333333;">拜访终端
</span>
<span style="font-weight: bold;color: #333333;font-size: 16px;">拜访终端</span>
</div>
<div v-for="(key) in Object.keys(propertys)" :key="key" class="property">
<span class="property-name">{{ fieldMap[key] }}</span>
<span class="property-content ">{{ propertys[key] }}</span>
</div>
</n-scrollbar>
</div>
</n-scrollbar>
</div>
</div>
<div style="display: flex;justify-content: space-between;padding: 12px 0px;">
<div><span style="font-size: 21px;font-weight: bold;">相似图片</span><span>({{ count }})</span></div>
<div style="display: flex;align-items: center;" @click="sortHandler('fromuptime')">
<div style="cursor: pointer;">
<span>按时间排序</span>
<SvgIcon style="margin-left: 8px;" name="sort" size="12" />
</div>
<div style="margin-left: 15px;cursor: pointer" @click="sortHandler('pictureResult')">
<span>相似度排序</span>
<SvgIcon style="margin-left: 8px;" name="sort" size="12" />
</div>
</div>
</div>
<div class="wrapper-list">
<div
v-for="(item, index) in taskDetailPictureList" :key="index" :class="{ 'item-selected': item === selectTask }"
class="item" @click="handleSelect(item)" @mouseover="overTaskHandelr(item)" @mouseleave="leaveTaskHandler"
>
<div class="img-wrapper" :style="{ 'background-image': `url(${item.imgurl})` }" />
<div class="check">
<n-checkbox
v-show="batch" v-model:checked="item.checked" @click.stop
@update:checked="onCheckChange($event, item)"
/>
</div>
<div class="percent">
<SvgIcon size="42" name="tag" />
<div class="val">
{{ getPercent(item.pictureid) }}
<div style="display: flex;justify-content: space-between;padding: 12px 0px;">
<div><span style="font-size: 21px;font-weight: bold;">相似图片</span><span>({{ totalCount }})</span></div>
<div style="display: flex;align-items: center;">
<div style="cursor: pointer;" @click="sortHandler('fromuptime')">
<span>按时间排序</span>
<SvgIcon style="margin-left: 8px;" name="sort" size="12" />
</div>
<div style="margin-left: 15px;cursor: pointer" @click="sortHandler('pictureResult')">
<span>相似度排序</span>
<SvgIcon style="margin-left: 8px;" name="sort" size="12" />
</div>
</div>
</div>
<div class="mark">
<SvgIcon v-show="item.iztrueorfalse === 0" name="jia" />
</div>
<div class="mark">
<SvgIcon v-show="item.iztrueorfalse === 1" name="zhen" />
</div>
<div v-show="overTask && overTask.id === item.id" class="action">
<SvgIcon style="cursor: pointer;" name="t1" @click.stop="trueHandler" />
<SvgIcon style="cursor: pointer;" name="t2" @click.stop="falseHandler" />
<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.thumburl})` }" />
<div class="check">
<n-checkbox
v-show="batch" v-model:checked="item.checked" @click.stop
@update:checked="onCheckChange($event, item)"
/>
</div>
<div class="percent">
<SvgIcon size="42" name="tag" />
<div class="val">
{{ getPercent(item.pictureid) }}
</div>
</div>
<div class="mark">
<SvgIcon v-show="item.iztrueorfalse === 0" name="jia" />
</div>
<div class="mark">
<SvgIcon v-show="item.iztrueorfalse === 1" name="zhen" />
</div>
<div v-show="overTask && overTask.id === item.id" class="action">
<SvgIcon style="cursor: pointer;" name="t1" @click.stop="trueHandler" />
<SvgIcon style="cursor: pointer;" name="t2" @click.stop="falseHandler" />
</div>
</div>
</div>
</div>
</div>
</n-spin>
<ConfrimModal ref="confrimModalRef" @commit="setFalse" />
</div>
</template>
@ -447,8 +557,11 @@ const count = computed(() => taskDetailPictureList.value.length)
background: #FFF;
border-radius: 3px;
border: 1px solid rgb(239, 239, 245);
height: calc(100vh - 88px);
overflow-y: scroll;
.scroll {
height: calc(100vh - 88px - 72px);
overflow-y: scroll;
}
&-header {
display: flex;
@ -520,6 +633,21 @@ const count = computed(() => taskDetailPictureList.value.length)
border-radius: 8px;
position: relative;
.preview {
position: absolute;
z-index: 3;
right: 10px;
top: 10px;
width: 50px;
height: 50px;
background-color: rgba(255, 255, 255, 0.6);
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.mark {
position: absolute;
z-index: 3;
@ -547,6 +675,18 @@ const count = computed(() => taskDetailPictureList.value.length)
background: rgba(216, 216, 216, 0.4);
border-radius: 7px;
}
.action {
position: absolute;
z-index: 3;
width: 100%;
height: 100%;
display: flex;
border-radius: 8px;
align-items: center;
justify-content: center;
background-color: rgba(102, 102, 102, 0.5);
}
}
.right {
@ -629,7 +769,7 @@ const count = computed(() => taskDetailPictureList.value.length)
background-color: #FFF;
}
.item {
.grid-item {
box-sizing: border-box;
border-radius: 8px;
padding: 9px 10px;

@ -1,212 +1,268 @@
<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'
import { getAllfieldList, getfieldList, savefield } from "@/api/home/filter";
import { workPackageMap } from "@/config/workorder";
import { useUser } from "@/store/modules/user";
import { difference } from "lodash-es";
import { computed, defineProps, onMounted, ref, watch } from "vue";
import { VueDraggable } from "vue-draggable-plus";
const props = defineProps({
reviewType: {
type: Number,
default: () => 1,
require: true,
},
});
//
const offList = ref<any[]>([])
const offList = ref<any[]>([]);
//
const onList = ref<any[]>([])
const onList = ref<any[]>([]);
const allCount = computed(() => {
return `全部筛选(共${offList.value.length - 1}个)`
})
return `全部筛选(共${offList.value.length - 1}个)`;
});
const selectCount = computed(() => {
return `全部筛选(共${onList.value.length}个)`
})
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())
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
const name = workPackageMap[key]?.label;
const isDefault = workPackageMap[key]?.isDefault;
// Y
if (!isDefault) {
hideList.push({
id: key,
name: name || '未配置',
name: name || "未配置",
fix: isDefault,
checked: workPackageMap[key].isDefault,
})
});
}
}
showList = showKeys.reduce((acc, key) => {
const config = {
id: key,
name: workPackageMap[key].label || '未配置',
name: workPackageMap[key].label || "未配置",
fix: workPackageMap[key].isDefault,
}
return [...acc, config]
}, [])
};
return [...acc, config];
}, []);
const fixedList = generateDefaultList()
const fixedList = generateDefaultList();
hideList.unshift(...fixedList)
showList.unshift(...fixedList)
hideList.unshift(...fixedList);
showList.unshift(...fixedList);
onList.value = showList
offList.value = hideList
return { showList, hideList }
onList.value = showList;
offList.value = hideList;
return { showList, hideList };
}
function generateDefaultList() {
return Object.keys(workPackageMap).reduce((acc, key) => {
const { label, isDefault } = workPackageMap[key]
const { label, isDefault } = workPackageMap[key];
if (isDefault) {
const config = {
id: key,
name: label || '未配置',
name: label || "未配置",
fix: true,
checked: true,
}
return [...acc, config]
}
else {
return acc
};
return [...acc, config];
} else {
return acc;
}
}, [])
}, []);
}
const show = ref(false)
const checkAll = ref(false)
const show = ref(false);
const checkAll = ref(false);
function showModal() {
show.value = true
show.value = true;
}
function closeModal() {
show.value = false
show.value = false;
}
async function handleSumbit(e: MouseEvent) {
e.preventDefault()
closeModal()
const userStore = useUser();
const userInfo = userStore.getUserInfo;
let userField = "";
onList.value.map((v) => {
userField += `${v.id},`;
});
userField = userField.slice(0,userField.length-1);
savefield(props.reviewType, userInfo.id, userField);
e.preventDefault();
closeModal();
}
defineExpose({
showModal,
})
});
generatList()
// generatList();
const selectIds = ref<string[]>([])
const selectIds = ref<string[]>([]);
function onCheckAllChange(value) {
const ids: string[] = []
const ids: string[] = [];
for (const item of offList.value) {
if (!item.fix) {
item.checked = value
ids.push(item.id)
item.checked = value;
ids.push(item.id);
}
}
selectIds.value = value ? ids : []
selectIds.value = value ? ids : [];
}
function onCheckChange(checked: any, item: any) {
const index = selectIds.value.indexOf(item.id)
const index = selectIds.value.indexOf(item.id);
item.checked = checked
item.checked = checked;
if (index === -1 && checked)
selectIds.value.push(item.id)
else
selectIds.value.splice(index, 1)
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
})
})
return item.id;
});
});
watch(
() => selectIds.value.length,
(newVal, oldVal) => {
if (newVal === oldVal)
return
if (newVal === oldVal) return;
const action = newVal > oldVal ? 'add' : 'remove'
const diff = action === 'add' ? difference(selectIds.value, showIds.value) : difference(showIds.value, selectIds.value)
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 (diff.length === 0) return;
if (action === 'add') {
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 || '未配置',
name: item.name || "未配置",
fix: item.fix || false,
})
});
}
}
}
else {
const list = onList.value
} else {
const list = onList.value;
for (let index = 0; index < list.length; index++) {
const item = list[index]
const item = list[index];
if (!item.fix && diff.includes(item.id)) {
list.splice(index, 1)
index--
list.splice(index, 1);
index--;
}
}
}
},
)
}
);
watch(
() => showIds.value.length,
(newVal, oldVal) => {
if (newVal === oldVal)
return
if (newVal === oldVal) return;
const diff = difference(selectIds.value, showIds.value)
const diff = difference(selectIds.value, showIds.value);
if (diff.length === 0)
return
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)
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
})
return item.fix === true;
});
}
function removeHandler(id: string) {
const index = onList.value.findIndex((item) => {
return item.id === id
})
return item.id === id;
});
if (index !== -1)
onList.value.splice(index, 1)
if (index !== -1) onList.value.splice(index, 1);
}
onMounted(async () => {
const userStore = useUser();
const userInfo = userStore.getUserInfo;
let res;
res = await getAllfieldList(props.reviewType); //
const allList = res.data;
res = await getfieldList(props.reviewType, userInfo.id); //
const useList = res.data;
/**
* name 标题
* id 键值
* fix 是否默认
* checked 是否选中
*/
let fixList = [];
allList.map((v) => {
let item = {
name: v.fieldDesc,
id: v.name,
fix: v.isrequired == 2,
checked:
v.isrequired == 2 ||
Boolean(useList.userFieldFixed?.toLowerCase().indexOf(v.name)>-1) || Boolean(useList.userFieldUnFixed?.toLowerCase().indexOf(v.name)>-1),
};
if (item.checked) {
onList.value.push(item);
} else {
offList.value.push(item);
}
if (item.fix) {
fixList.push(item);
}
});
offList.value.unshift(...fixList);
});
</script>
<template>
<n-modal v-model:show="show" transform-origin="center">
<n-card class="cardstyle" :bordered="false" size="huge" role="dialog" aria-modal="true">
<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">
@ -217,7 +273,10 @@ function removeHandler(id: string) {
<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"
:title="allCount"
class="dragcardStyle"
:segmented="{ content: true, footer: true }"
size="small"
:bordered="false"
>
<div>
@ -228,15 +287,24 @@ function removeHandler(id: string) {
</n-input>
<div class="draggable-ul">
<div class="draggable-li">
<n-checkbox v-model:checked="checkAll" label="全部" @update:checked="onCheckAllChange" />
<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"
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"
v-model:checked="item.checked"
:label="item.name"
:disabled="item.fix"
@update:checked="onCheckChange($event, item)"
/>
</div>
@ -247,7 +315,10 @@ function removeHandler(id: string) {
</n-grid-item>
<n-grid-item>
<NCard
:title="selectCount" class="dragcardStyle" :segmented="{ content: true, footer: true }" size="small"
:title="selectCount"
class="dragcardStyle"
:segmented="{ content: true, footer: true }"
size="small"
:bordered="false"
>
<template #header-extra>
@ -259,15 +330,25 @@ function removeHandler(id: string) {
<SvgIcon size="14px" name="magnifying-1" />
</template>
</n-input>
<VueDraggable v-model="onList" class="draggable-ul" :animation="150" group="shared">
<VueDraggable
v-model="onList"
class="draggable-ul"
:animation="150"
group="shared"
>
<div
v-for="item in onList" :key="item.id" :class="{ fix: item.fix }"
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)"
v-if="!item.fix"
size="16px"
style="display: block; margin-left: auto; cursor: pointer"
name="clear"
@click="removeHandler(item.id)"
/>
</div>
</VueDraggable>
@ -278,10 +359,8 @@ function removeHandler(id: string) {
</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 type="info" @click="handleSumbit"> </n-button>
<n-button secondary style="margin-left: 15px" @click="closeModal">
取消
</n-button>
</div>
@ -317,7 +396,7 @@ function removeHandler(id: string) {
&:before {
background-color: #1980ff;
content: '';
content: "";
width: 5px;
border-radius: 2px;
top: 0;
@ -373,7 +452,9 @@ function removeHandler(id: string) {
}
}
::v-deep(.n-card.n-card--content-segmented > .n-card__content:not(:first-child)) {
::v-deep(
.n-card.n-card--content-segmented > .n-card__content:not(:first-child)
) {
border: 0px;
}

1
types/home.d.ts vendored

@ -6,6 +6,7 @@ export interface Filter {
// 过滤
export interface FilterEntity {
id: string
name: string // 过滤名称
favorite: boolean// 是否收藏
isDefaultFilter: boolean// 默认筛选

1
types/task.d.ts vendored

@ -10,7 +10,6 @@ export interface TaskState {
packageid: string
currentIndex: number
approvalList: any[]
refresh: boolean
immersion: boolean
}

Loading…
Cancel
Save