feat:优化 bpm 相关代码,重点处理 back 逻辑,search 表单

This commit is contained in:
YunaiV
2025-12-15 20:40:37 +08:00
parent b15f2327db
commit 8807caa3eb
12 changed files with 412 additions and 348 deletions

View File

@@ -1,54 +1,55 @@
<template>
<view class="bpm-list">
<view
v-for="item in list"
:key="item.id"
class="bpm-card"
@click="handleDetail(item)"
>
<view class="bpm-card-content">
<view class="bpm-card-header">
<view class="bpm-card-title">
{{ item.processInstanceName }}
</view>
<wd-tag type="primary" plain>
查看详情
</wd-tag>
</view>
<view v-if="item.summary?.length" class="bpm-summary">
<view v-for="(s, idx) in item.summary" :key="idx" class="bpm-summary-item">
<text class="text-[#999]">{{ s.key }}</text>
<text>{{ s.value }}</text>
</view>
</view>
<view class="bpm-card-info">
<view class="bpm-user">
<view class="bpm-avatar">
{{ item.startUser.nickname?.[0] || '?' }}
</view>
<text class="bpm-nickname">{{ item.startUser.nickname }}</text>
</view>
<text class="bpm-time">{{ formatDateTime(item.createTime) }}</text>
</view>
</view>
</view>
<view v-if="loadMoreState !== 'loading' && list.length === 0" class="bpm-empty">
<wd-status-tip image="content" tip="暂无抄送任务" />
</view>
<wd-loadmore
v-if="list.length > 0"
:state="loadMoreState"
@reload="loadMore"
/>
<!-- 搜索弹窗 -->
<view>
<!-- 搜索组件 -->
<CopySearchForm
v-model="searchPopupVisible"
:search-params="queryParams"
@search="handleSearch"
@reset="handleReset"
/>
<view class="bpm-list">
<view
v-for="item in list"
:key="item.id"
class="bpm-card"
@click="handleDetail(item)"
>
<view class="bpm-card-content">
<view class="bpm-card-header">
<view class="bpm-card-title">
{{ item.processInstanceName }}
</view>
<wd-tag type="primary" plain>
查看详情
</wd-tag>
</view>
<view v-if="item.summary?.length" class="bpm-summary">
<view v-for="(s, idx) in item.summary" :key="idx" class="bpm-summary-item">
<text class="text-[#999]">{{ s.key }}</text>
<text>{{ s.value }}</text>
</view>
</view>
<view class="bpm-card-info">
<view class="bpm-user">
<view class="bpm-avatar">
{{ item.startUser.nickname?.[0] || '?' }}
</view>
<text class="bpm-nickname">{{ item.startUser.nickname }}</text>
</view>
<text class="bpm-time">{{ formatDateTime(item.createTime) }}</text>
</view>
</view>
</view>
<view v-if="loadMoreState !== 'loading' && list.length === 0" class="bpm-empty">
<wd-status-tip image="content" tip="暂无抄送任务" />
</view>
<wd-loadmore
v-if="list.length > 0"
:state="loadMoreState"
@reload="loadMore"
/>
</view>
</view>
</template>
@@ -64,17 +65,13 @@ import CopySearchForm from './copy-search-form.vue'
import './index.scss'
const props = defineProps<{
searchVisible?: boolean
}>()
const emit = defineEmits<{
'update:searchVisible': [value: boolean]
active?: boolean
}>()
const total = ref(0)
const list = ref<ProcessInstanceCopy[]>([])
const loadMoreState = ref<LoadMoreState>('loading')
const searchPopupVisible = ref(false)
const isFirstLoad = ref(true)
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
@@ -133,16 +130,18 @@ onReachBottom(() => {
loadMore()
})
watch(() => props.searchVisible, (val) => {
searchPopupVisible.value = val ?? false
})
watch(searchPopupVisible, (val) => {
emit('update:searchVisible', val)
/** 监听激活状态,刷新数据 */
watch(() => props.active, (val) => {
if (val && !isFirstLoad.value) {
queryParams.pageNo = 1
list.value = []
getList()
}
})
/** 初始化 */
onMounted(() => {
getList()
isFirstLoad.value = false
})
</script>

View File

@@ -1,4 +1,13 @@
<template>
<!-- 搜索框入口 -->
<wd-search
:placeholder="searchPlaceholder"
:hide-cancel="true"
disabled
@click="visible = true"
/>
<!-- 搜索弹窗 -->
<wd-popup
v-model="visible"
position="top"
@@ -93,19 +102,26 @@ export interface CopySearchFormData {
}
const props = defineProps<{
modelValue: boolean
searchParams?: Partial<CopySearchFormData>
}>()
const emit = defineEmits<{
'update:modelValue': [value: boolean]
'search': [data: CopySearchFormData]
'reset': []
search: [data: CopySearchFormData]
reset: []
}>()
const visible = computed({
get: () => props.modelValue,
set: (val: boolean) => emit('update:modelValue', val),
const visible = ref(false)
/** 搜索条件 placeholder 拼接 */
const searchPlaceholder = computed(() => {
const conditions: string[] = []
if (props.searchParams?.processInstanceName) {
conditions.push(`名称:${props.searchParams.processInstanceName}`)
}
if (props.searchParams?.createTime?.[0] && props.searchParams?.createTime?.[1]) {
conditions.push(`时间:${formatDate(props.searchParams.createTime[0])}~${formatDate(props.searchParams.createTime[1])}`)
}
return conditions.length > 0 ? conditions.join(' | ') : '搜索抄送任务'
})
const formData = reactive<CopySearchFormData>({
@@ -141,7 +157,7 @@ function handleEndCancel() {
}
/** 监听弹窗打开,同步外部参数 */
watch(() => props.modelValue, (val) => {
watch(visible, (val) => {
if (val && props.searchParams) {
formData.processInstanceName = props.searchParams.processInstanceName
formData.createTime = props.searchParams.createTime ?? [undefined, undefined]

View File

@@ -1,52 +1,53 @@
<template>
<view class="bpm-list">
<view
v-for="item in list"
:key="item.id"
class="bpm-card"
@click="handleDetail(item)"
>
<view class="bpm-card-content">
<view class="bpm-card-header">
<view class="bpm-card-title">
{{ item.processInstance?.name }}
</view>
<dict-tag :type="DICT_TYPE.BPM_TASK_STATUS" :value="item.status" />
</view>
<view v-if="item.processInstance?.summary?.length" class="bpm-summary">
<view v-for="(s, idx) in item.processInstance.summary" :key="idx" class="bpm-summary-item">
<text class="text-[#999]">{{ s.key }}</text>
<text>{{ s.value }}</text>
</view>
</view>
<view class="bpm-card-info">
<view class="bpm-user">
<view class="bpm-avatar">
{{ item.processInstance?.startUser?.nickname?.[0] || '?' }}
</view>
<text class="bpm-nickname">{{ item.processInstance?.startUser?.nickname }}</text>
</view>
<text class="bpm-time">{{ formatDateTime(item.createTime) }}</text>
</view>
</view>
</view>
<view v-if="loadMoreState !== 'loading' && list.length === 0" class="bpm-empty">
<wd-status-tip image="content" tip="暂无已办任务" />
</view>
<wd-loadmore
v-if="list.length > 0"
:state="loadMoreState"
@reload="loadMore"
/>
<!-- 搜索弹窗 -->
<view>
<!-- 搜索组件 -->
<DoneSearchForm
v-model="searchPopupVisible"
:search-params="queryParams"
@search="handleSearch"
@reset="handleReset"
/>
<view class="bpm-list">
<view
v-for="item in list"
:key="item.id"
class="bpm-card"
@click="handleDetail(item)"
>
<view class="bpm-card-content">
<view class="bpm-card-header">
<view class="bpm-card-title">
{{ item.processInstance?.name }}
</view>
<dict-tag :type="DICT_TYPE.BPM_TASK_STATUS" :value="item.status" />
</view>
<view v-if="item.processInstance?.summary?.length" class="bpm-summary">
<view v-for="(s, idx) in item.processInstance.summary" :key="idx" class="bpm-summary-item">
<text class="text-[#999]">{{ s.key }}</text>
<text>{{ s.value }}</text>
</view>
</view>
<view class="bpm-card-info">
<view class="bpm-user">
<view class="bpm-avatar">
{{ item.processInstance?.startUser?.nickname?.[0] || '?' }}
</view>
<text class="bpm-nickname">{{ item.processInstance?.startUser?.nickname }}</text>
</view>
<text class="bpm-time">{{ formatDateTime(item.createTime) }}</text>
</view>
</view>
</view>
<view v-if="loadMoreState !== 'loading' && list.length === 0" class="bpm-empty">
<wd-status-tip image="content" tip="暂无已办任务" />
</view>
<wd-loadmore
v-if="list.length > 0"
:state="loadMoreState"
@reload="loadMore"
/>
</view>
</view>
</template>
@@ -63,17 +64,13 @@ import DoneSearchForm from './done-search-form.vue'
import './index.scss'
const props = defineProps<{
searchVisible?: boolean
}>()
const emit = defineEmits<{
'update:searchVisible': [value: boolean]
active?: boolean
}>()
const total = ref(0)
const list = ref<Task[]>([])
const loadMoreState = ref<LoadMoreState>('loading')
const searchPopupVisible = ref(false)
const isFirstLoad = ref(true)
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
@@ -132,16 +129,18 @@ onReachBottom(() => {
loadMore()
})
watch(() => props.searchVisible, (val) => {
searchPopupVisible.value = val ?? false
})
watch(searchPopupVisible, (val) => {
emit('update:searchVisible', val)
/** 监听激活状态,刷新数据 */
watch(() => props.active, (val) => {
if (val && !isFirstLoad.value) {
queryParams.pageNo = 1
list.value = []
getList()
}
})
/** 初始化 */
onMounted(() => {
getList()
isFirstLoad.value = false
})
</script>

View File

@@ -1,4 +1,13 @@
<template>
<!-- 搜索框入口 -->
<wd-search
:placeholder="searchPlaceholder"
:hide-cancel="true"
disabled
@click="visible = true"
/>
<!-- 搜索弹窗 -->
<wd-popup
v-model="visible"
position="top"
@@ -126,7 +135,7 @@ import type { ProcessDefinition } from '@/api/bpm/definition'
import { computed, onMounted, reactive, ref, watch } from 'vue'
import { getCategorySimpleList } from '@/api/bpm/category'
import { getProcessDefinitionList } from '@/api/bpm/definition'
import { getIntDictOptions } from '@/hooks/useDict'
import { getDictLabel, getIntDictOptions } from '@/hooks/useDict'
import { DICT_TYPE } from '@/utils/constants'
import { formatDate } from '@/utils/date'
@@ -140,19 +149,29 @@ export interface DoneSearchFormData {
}
const props = defineProps<{
modelValue: boolean
searchParams?: Partial<DoneSearchFormData>
}>()
const emit = defineEmits<{
'update:modelValue': [value: boolean]
'search': [data: DoneSearchFormData]
'reset': []
search: [data: DoneSearchFormData]
reset: []
}>()
const visible = computed({
get: () => props.modelValue,
set: (val: boolean) => emit('update:modelValue', val),
const visible = ref(false)
/** 搜索条件 placeholder 拼接 */
const searchPlaceholder = computed(() => {
const conditions: string[] = []
if (props.searchParams?.name) {
conditions.push(`名称:${props.searchParams.name}`)
}
if (props.searchParams?.status !== undefined && props.searchParams.status !== -1) {
conditions.push(`状态:${getDictLabel(DICT_TYPE.BPM_TASK_STATUS, props.searchParams.status)}`)
}
if (props.searchParams?.createTime?.[0] && props.searchParams?.createTime?.[1]) {
conditions.push(`时间:${formatDate(props.searchParams.createTime[0])}~${formatDate(props.searchParams.createTime[1])}`)
}
return conditions.length > 0 ? conditions.join(' | ') : '搜索已办任务'
})
const categoryList = ref<Category[]>([])
@@ -211,7 +230,7 @@ async function getProcessDefinitions() {
}
/** 监听弹窗打开,同步外部参数 */
watch(() => props.modelValue, (val) => {
watch(visible, (val) => {
if (val && props.searchParams) {
formData.name = props.searchParams.name
formData.processDefinitionKey = props.searchParams.processDefinitionKey

View File

@@ -1,61 +1,63 @@
<template>
<view class="bpm-list">
<view
v-for="item in list"
:key="item.id"
class="bpm-card"
@click="handleDetail(item)"
>
<view class="bpm-card-content">
<view class="bpm-card-header">
<view class="bpm-card-title">
{{ item.name }}
</view>
<dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS" :value="item.status" />
</view>
<view v-if="item.summary?.length" class="bpm-summary">
<view v-for="(s, idx) in item.summary" :key="idx" class="bpm-summary-item">
<text class="text-[#999]">{{ s.key }}</text>
<text>{{ s.value }}</text>
</view>
</view>
<view class="bpm-card-info">
<view class="bpm-user">
<view class="bpm-avatar">
{{ userNickname?.[0] }}
</view>
<text class="bpm-nickname">{{ userNickname }}</text>
</view>
<text class="bpm-time">{{ formatDateTime(item.startTime) }}</text>
</view>
</view>
</view>
<!-- 空状态 -->
<view v-if="loadMoreState !== 'loading' && list.length === 0" class="bpm-empty">
<wd-status-tip image="content" tip="暂无发起的流程" />
</view>
<!-- 加载更多 -->
<wd-loadmore
v-if="list.length > 0"
:state="loadMoreState"
@reload="loadMore"
/>
<!-- 搜索弹窗 -->
<view>
<!-- 搜索组件 -->
<MySearchForm
v-model="searchPopupVisible"
:search-params="queryParams"
@search="handleSearch"
@reset="handleReset"
/>
<!-- 新增按钮 -->
<view
class="fixed bottom-100rpx right-32rpx z-10 h-100rpx w-100rpx flex items-center justify-center rounded-full bg-[#1890ff] shadow-lg"
@click="handleCreate"
>
<wd-icon name="add" size="24px" color="#fff" />
<view class="bpm-list">
<view
v-for="item in list"
:key="item.id"
class="bpm-card"
@click="handleDetail(item)"
>
<view class="bpm-card-content">
<view class="bpm-card-header">
<view class="bpm-card-title">
{{ item.name }}
</view>
<dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS" :value="item.status" />
</view>
<view v-if="item.summary?.length" class="bpm-summary">
<view v-for="(s, idx) in item.summary" :key="idx" class="bpm-summary-item">
<text class="text-[#999]">{{ s.key }}</text>
<text>{{ s.value }}</text>
</view>
</view>
<view class="bpm-card-info">
<view class="bpm-user">
<view class="bpm-avatar">
{{ userNickname?.[0] }}
</view>
<text class="bpm-nickname">{{ userNickname }}</text>
</view>
<text class="bpm-time">{{ formatDateTime(item.startTime) }}</text>
</view>
</view>
</view>
<!-- 空状态 -->
<view v-if="loadMoreState !== 'loading' && list.length === 0" class="bpm-empty">
<wd-status-tip image="content" tip="暂无发起的流程" />
</view>
<!-- 加载更多 -->
<wd-loadmore
v-if="list.length > 0"
:state="loadMoreState"
@reload="loadMore"
/>
<!-- 新增按钮 -->
<!-- TODO @AI换成 wd-fat要注意可能高度不对晚点在改 -->
<view
class="fixed bottom-100rpx right-32rpx z-10 h-100rpx w-100rpx flex items-center justify-center rounded-full bg-[#1890ff] shadow-lg"
@click="handleCreate"
>
<wd-icon name="add" size="24px" color="#fff" />
</view>
</view>
</view>
</template>
@@ -74,11 +76,7 @@ import MySearchForm from './my-search-form.vue'
import './index.scss'
const props = defineProps<{
searchVisible?: boolean
}>()
const emit = defineEmits<{
'update:searchVisible': [value: boolean]
active?: boolean
}>()
const userStore = useUserStore()
@@ -87,7 +85,7 @@ const userNickname = computed(() => userStore.userInfo?.nickname || '')
const total = ref(0)
const list = ref<ProcessInstance[]>([])
const loadMoreState = ref<LoadMoreState>('loading')
const searchPopupVisible = ref(false)
const isFirstLoad = ref(true)
const queryParams = reactive({
pageNo: 1,
@@ -157,16 +155,18 @@ onReachBottom(() => {
loadMore()
})
watch(() => props.searchVisible, (val) => {
searchPopupVisible.value = val ?? false
})
watch(searchPopupVisible, (val) => {
emit('update:searchVisible', val)
/** 监听激活状态,刷新数据 */
watch(() => props.active, (val) => {
if (val && !isFirstLoad.value) {
queryParams.pageNo = 1
list.value = []
getList()
}
})
/** 初始化 */
onMounted(() => {
getList()
isFirstLoad.value = false
})
</script>

View File

@@ -1,4 +1,13 @@
<template>
<!-- 搜索框入口 -->
<wd-search
:placeholder="searchPlaceholder"
:hide-cancel="true"
disabled
@click="visible = true"
/>
<!-- 搜索弹窗 -->
<wd-popup
v-model="visible"
position="top"
@@ -126,7 +135,7 @@ import type { ProcessDefinition } from '@/api/bpm/definition'
import { computed, onMounted, reactive, ref, watch } from 'vue'
import { getCategorySimpleList } from '@/api/bpm/category'
import { getProcessDefinitionList } from '@/api/bpm/definition'
import { getIntDictOptions } from '@/hooks/useDict'
import { getDictLabel, getIntDictOptions } from '@/hooks/useDict'
import { DICT_TYPE } from '@/utils/constants'
import { formatDate } from '@/utils/date'
@@ -140,19 +149,29 @@ export interface MySearchFormData {
}
const props = defineProps<{
modelValue: boolean
searchParams?: Partial<MySearchFormData>
}>()
const emit = defineEmits<{
'update:modelValue': [value: boolean]
'search': [data: MySearchFormData]
'reset': []
search: [data: MySearchFormData]
reset: []
}>()
const visible = computed({
get: () => props.modelValue,
set: (val: boolean) => emit('update:modelValue', val),
const visible = ref(false)
/** 搜索条件 placeholder 拼接 */
const searchPlaceholder = computed(() => {
const conditions: string[] = []
if (props.searchParams?.name) {
conditions.push(`名称:${props.searchParams.name}`)
}
if (props.searchParams?.status !== undefined && props.searchParams.status !== -1) {
conditions.push(`状态:${getDictLabel(DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS, props.searchParams.status)}`)
}
if (props.searchParams?.createTime?.[0] && props.searchParams?.createTime?.[1]) {
conditions.push(`时间:${formatDate(props.searchParams.createTime[0])}~${formatDate(props.searchParams.createTime[1])}`)
}
return conditions.length > 0 ? conditions.join(' | ') : '搜索我的流程'
})
const categoryList = ref<Category[]>([])
@@ -211,7 +230,7 @@ async function getProcessDefinitions() {
}
/** 监听弹窗打开,同步外部参数 */
watch(() => props.modelValue, (val) => {
watch(visible, (val) => {
if (val && props.searchParams) {
formData.name = props.searchParams.name
formData.processDefinitionId = props.searchParams.processDefinitionId

View File

@@ -1,63 +1,64 @@
<template>
<view class="bpm-list">
<view
v-for="item in list"
:key="item.id"
class="bpm-card"
@click="handleDetail(item)"
>
<view class="bpm-card-content">
<view class="bpm-card-header">
<view class="bpm-card-title">
{{ item.processInstance?.name }}
</view>
<wd-tag type="primary" plain>
待审批
</wd-tag>
</view>
<view v-if="item.processInstance?.summary?.length" class="bpm-summary">
<view v-for="(s, idx) in item.processInstance.summary" :key="idx" class="bpm-summary-item">
<text class="text-[#999]">{{ s.key }}</text>
<text>{{ s.value }}</text>
</view>
</view>
<view class="bpm-card-info">
<view class="bpm-user">
<view class="bpm-avatar">
{{ item.processInstance?.startUser?.nickname?.[0] || '?' }}
</view>
<text class="bpm-nickname">{{ item.processInstance?.startUser?.nickname }}</text>
</view>
<text class="bpm-time--warning">{{ formatPast(item.createTime) }}</text>
</view>
</view>
<view class="bpm-actions">
<view class="bpm-action-btn" @click.stop="handleReject(item)">
<text>拒绝</text>
</view>
<view class="bpm-action-btn" @click.stop="handleApprove(item)">
<text>同意</text>
</view>
</view>
</view>
<!-- 加载更多 -->
<view v-if="loadMoreState !== 'loading' && list.length === 0" class="bpm-empty">
<wd-status-tip image="content" tip="暂无待办任务" />
</view>
<wd-loadmore
v-if="list.length > 0"
:state="loadMoreState"
@reload="loadMore"
/>
<!-- 搜索弹窗 -->
<view>
<!-- 搜索组件 -->
<TodoSearchForm
v-model="searchPopupVisible"
:search-params="queryParams"
@search="handleSearch"
@reset="handleReset"
/>
<view class="bpm-list">
<view
v-for="item in list"
:key="item.id"
class="bpm-card"
@click="handleDetail(item)"
>
<view class="bpm-card-content">
<view class="bpm-card-header">
<view class="bpm-card-title">
{{ item.processInstance?.name }}
</view>
<wd-tag type="primary" plain>
待审批
</wd-tag>
</view>
<view v-if="item.processInstance?.summary?.length" class="bpm-summary">
<view v-for="(s, idx) in item.processInstance.summary" :key="idx" class="bpm-summary-item">
<text class="text-[#999]">{{ s.key }}</text>
<text>{{ s.value }}</text>
</view>
</view>
<view class="bpm-card-info">
<view class="bpm-user">
<view class="bpm-avatar">
{{ item.processInstance?.startUser?.nickname?.[0] || '?' }}
</view>
<text class="bpm-nickname">{{ item.processInstance?.startUser?.nickname }}</text>
</view>
<text class="bpm-time--warning">{{ formatPast(item.createTime) }}</text>
</view>
</view>
<view class="bpm-actions">
<view class="bpm-action-btn" @click.stop="handleReject(item)">
<text>拒绝</text>
</view>
<view class="bpm-action-btn" @click.stop="handleApprove(item)">
<text>同意</text>
</view>
</view>
</view>
<!-- 加载更多 -->
<view v-if="loadMoreState !== 'loading' && list.length === 0" class="bpm-empty">
<wd-status-tip image="content" tip="暂无待办任务" />
</view>
<wd-loadmore
v-if="list.length > 0"
:state="loadMoreState"
@reload="loadMore"
/>
</view>
</view>
</template>
@@ -73,17 +74,13 @@ import TodoSearchForm from './todo-search-form.vue'
import './index.scss'
const props = defineProps<{
searchVisible?: boolean
}>()
const emit = defineEmits<{
'update:searchVisible': [value: boolean]
active?: boolean
}>()
const total = ref(0)
const list = ref<Task[]>([])
const loadMoreState = ref<LoadMoreState>('loading')
const searchPopupVisible = ref(false)
const isFirstLoad = ref(true)
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
@@ -152,16 +149,18 @@ onReachBottom(() => {
loadMore()
})
watch(() => props.searchVisible, (val) => {
searchPopupVisible.value = val ?? false
})
watch(searchPopupVisible, (val) => {
emit('update:searchVisible', val)
/** 监听激活状态,刷新数据 */
watch(() => props.active, (val) => {
if (val && !isFirstLoad.value) {
queryParams.pageNo = 1
list.value = []
getList()
}
})
/** 初始化 */
onMounted(() => {
getList()
isFirstLoad.value = false
})
</script>

View File

@@ -1,4 +1,13 @@
<template>
<!-- 搜索框入口 -->
<wd-search
:placeholder="searchPlaceholder"
:hide-cancel="true"
disabled
@click="visible = true"
/>
<!-- 搜索弹窗 -->
<wd-popup
v-model="visible"
position="top"
@@ -126,7 +135,7 @@ import type { ProcessDefinition } from '@/api/bpm/definition'
import { computed, onMounted, reactive, ref, watch } from 'vue'
import { getCategorySimpleList } from '@/api/bpm/category'
import { getProcessDefinitionList } from '@/api/bpm/definition'
import { getIntDictOptions } from '@/hooks/useDict'
import { getDictLabel, getIntDictOptions } from '@/hooks/useDict'
import { DICT_TYPE } from '@/utils/constants'
import { formatDate } from '@/utils/date'
@@ -140,19 +149,29 @@ export interface TodoSearchFormData {
}
const props = defineProps<{
modelValue: boolean
searchParams?: Partial<TodoSearchFormData>
}>()
const emit = defineEmits<{
'update:modelValue': [value: boolean]
'search': [data: TodoSearchFormData]
'reset': []
search: [data: TodoSearchFormData]
reset: []
}>()
const visible = computed({
get: () => props.modelValue,
set: (val: boolean) => emit('update:modelValue', val),
const visible = ref(false)
/** 搜索条件 placeholder 拼接 */
const searchPlaceholder = computed(() => {
const conditions: string[] = []
if (props.searchParams?.name) {
conditions.push(`名称:${props.searchParams.name}`)
}
if (props.searchParams?.status !== undefined && props.searchParams.status !== -1) {
conditions.push(`状态:${getDictLabel(DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS, props.searchParams.status)}`)
}
if (props.searchParams?.createTime?.[0] && props.searchParams?.createTime?.[1]) {
conditions.push(`时间:${formatDate(props.searchParams.createTime[0])}~${formatDate(props.searchParams.createTime[1])}`)
}
return conditions.length > 0 ? conditions.join(' | ') : '搜索待办任务'
})
const categoryList = ref<Category[]>([])
@@ -211,7 +230,7 @@ async function getProcessDefinitions() {
}
/** 监听弹窗打开,同步外部参数 */
watch(() => props.modelValue, (val) => {
watch(visible, (val) => {
if (val && props.searchParams) {
formData.name = props.searchParams.name
formData.processDefinitionKey = props.searchParams.processDefinitionKey

View File

@@ -4,13 +4,7 @@
<wd-navbar
title="审批"
placeholder safe-area-inset-top fixed
>
<template #right>
<view class="flex items-center" @click="searchVisible = !searchVisible">
<wd-icon name="search" size="20px" />
</view>
</template>
</wd-navbar>
/>
<!-- Tabs 区域 -->
<view class="bg-white">
@@ -22,26 +16,10 @@
</wd-tabs>
</view>
<!-- 列表内容 -->
<TodoList
v-show="tabType === 'todo'"
:search-visible="searchVisible && tabType === 'todo'"
@update:search-visible="searchVisible = $event"
/>
<DoneList
v-show="tabType === 'done'"
:search-visible="searchVisible && tabType === 'done'"
@update:search-visible="searchVisible = $event"
/>
<MyList
v-show="tabType === 'my'"
:search-visible="searchVisible && tabType === 'my'"
@update:search-visible="searchVisible = $event"
/>
<CopyList
v-show="tabType === 'copy'"
:search-visible="searchVisible && tabType === 'copy'"
@update:search-visible="searchVisible = $event"
/>
<TodoList v-show="tabType === 'todo'" :active="tabType === 'todo'" />
<DoneList v-show="tabType === 'done'" :active="tabType === 'done'" />
<MyList v-show="tabType === 'my'" :active="tabType === 'my'" />
<CopyList v-show="tabType === 'copy'" :active="tabType === 'copy'" />
</view>
</template>
@@ -63,12 +41,10 @@ definePage({
const tabTypes: string[] = ['todo', 'done', 'my', 'copy']
const tabIndex = ref(0)
const tabType = computed<string>(() => tabTypes[tabIndex.value])
const searchVisible = ref(false)
/** Tab 切换 */
function handleTabChange({ index }: { index: number }) {
tabIndex.value = index
searchVisible.value = false
}
/** 初始化:根据 tab 参数设置默认 tab */