feat(pl): 证书齐备默认只看待安排前的跟进状态。

Web 列筛选和移动端跟进状态下拉默认勾选草稿中、等通知、待安排。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
wuzilongandCursor committed 2026-11-05 21:14:18 +08:00
1 parent da3ec62719
commit 421332cad4
5 files changed
+114 -1

No files matched your search

@@ -4,6 +4,7 @@ import test from 'node:test'
import { effectScope } from 'vue'
import { useServerColumnFilters } from '../src/composables/useServerColumnFilters'
import { certReadyDefaultPlanDates } from '../src/utils/cert-ready-plan-date'
import { PL_PLAN_CERT_READY_DEFAULT_FOLLOW_STATUSES } from '../src/utils/pl-display'
test('incomplete certificate filter is sent as quotaCertWaivedIn=0', () => {
const scope = effectScope()
@@ -39,6 +40,48 @@ test('web funnel and miniprogram status dropdown default to incomplete', () => {
)
assert.match(mobile, /certReadyDefaultPlanDates\(\)/)
assert.match(mobile, /:plan-date-from="readyDateFrom"/)
assert.match(
web,
/followStatus:\s*\{\s*text:\s*'',\s*selected:\s*\[\.\.\.PL_PLAN_CERT_READY_DEFAULT_FOLLOW_STATUSES\]\s*\}/
)
assert.match(
mobile,
/const readyFollow = ref<string\[\]>\(\[\.\.\.PL_PLAN_CERT_READY_DEFAULT_FOLLOW_STATUSES\]\)/
)
assert.match(mobile, /text:\s*'全部跟进状态'/)
assert.match(mobile, /:follow-status="readyFollowQuery"/)
const ready = readFileSync(
new URL('../src/views/m/pl/plan-cert/ReadyTab.vue', import.meta.url),
'utf8'
)
assert.match(ready, /followStatusIn: props\.followStatus/)
})
test('certificate ready follow status defaults to drafting, waiting and pending', () => {
assert.deepEqual(
[...PL_PLAN_CERT_READY_DEFAULT_FOLLOW_STATUSES],
['drafting', 'wait_notice', 'pending_arrange']
)
const scope = effectScope()
const params = scope.run(() =>
useServerColumnFilters(
[
{
prop: 'followStatus',
label: '跟进状态',
type: 'enum',
queryKey: 'followStatus'
}
],
{
initialFilters: {
followStatus: { text: '', selected: [...PL_PLAN_CERT_READY_DEFAULT_FOLLOW_STATUSES] }
}
}
).toQueryParams()
)
scope.stop()
assert.deepEqual(params, { followStatusIn: 'drafting,wait_notice,pending_arrange' })
})
test('default plan dates run from yesterday through seven days later', () => {
+7
View File
@@ -452,6 +452,13 @@ export const PL_PLAN_DEFAULT_FOLLOW_STATUSES = PL_PLAN_FOLLOW_STATUS_OPTIONS.fil
(opt) => opt.value !== 'cancelled'
).map((opt) => opt.value)
/** 证书齐备列表默认勾选:草稿中、等通知、待安排 */
export const PL_PLAN_CERT_READY_DEFAULT_FOLLOW_STATUSES = [
'drafting',
'wait_notice',
'pending_arrange'
] as const
export function getPlPlanFollowStatusTagType(status?: string) {
const map: Record<string, string> = {
drafting: 'info',
@@ -55,6 +55,7 @@
const props = defineProps<{
keyword: string
waived: string
followStatus: string
planDateFrom: string
planDateTo: string
}>()
@@ -85,6 +86,7 @@
pageSize: 20,
keyword: props.keyword || undefined,
waived: props.waived || undefined,
followStatusIn: props.followStatus || undefined,
planDateFrom: props.planDateFrom || undefined,
planDateTo: props.planDateTo || undefined
})
@@ -126,7 +128,10 @@
}
watch(
() => [props.keyword, props.waived, props.planDateFrom, props.planDateTo].join('\0'),
() =>
[props.keyword, props.waived, props.followStatus, props.planDateFrom, props.planDateTo].join(
'\0'
),
() => reload()
)
</script>
@@ -47,6 +47,23 @@
</van-dropdown-menu>
<van-dropdown-menu v-else-if="tab === 'ready'" class="mp-customer-dd">
<van-dropdown-item v-model="readyState" :options="readyStateOptions" />
<van-dropdown-item :title="readyFollowTitle">
<van-cell
v-for="option in readyFollowOptions"
:key="option.value || 'all'"
clickable
:title="option.text"
class="van-dropdown-item__option"
:class="{ 'van-dropdown-item__option--active': readyFollowActive(option.value) }"
role="menuitemcheckbox"
:aria-checked="readyFollowActive(option.value)"
@click="toggleReadyFollow(option.value)"
>
<template v-if="readyFollowActive(option.value)" #right-icon>
<van-icon name="success" class="van-dropdown-item__icon" />
</template>
</van-cell>
</van-dropdown-item>
<van-dropdown-item
ref="readyDateFilter"
:title="readyDateTitle"
@@ -118,6 +135,7 @@
:key="session + committed"
:keyword="committed"
:waived="readyState"
:follow-status="readyFollowQuery"
:plan-date-from="readyDateFrom"
:plan-date-to="readyDateTo"
/>
@@ -130,6 +148,10 @@
import { useUserStore } from '@/store/modules/user'
import { goToMiniWorkbench } from '@/utils/mp-webview'
import { certReadyDefaultPlanDates } from '@/utils/cert-ready-plan-date'
import {
PL_PLAN_CERT_READY_DEFAULT_FOLLOW_STATUSES,
PL_PLAN_FOLLOW_STATUS_OPTIONS
} from '@/utils/pl-display'
import PlanDateField from '../plan/PlanDateField.vue'
import ArchiveTab from './ArchiveTab.vue'
import ContractTab from './ContractTab.vue'
@@ -164,6 +186,40 @@
const showAllPlans = computed(() => planScope.value === '1')
const defaultReadyDates = certReadyDefaultPlanDates()
const readyState = ref('0')
const readyFollow = ref<string[]>([...PL_PLAN_CERT_READY_DEFAULT_FOLLOW_STATUSES])
const readyFollowOptions = [
{ text: '全部跟进状态', value: '' },
...PL_PLAN_FOLLOW_STATUS_OPTIONS.filter((item) => item.value !== 'cancelled').map((item) => ({
text: item.label,
value: item.value
}))
]
const readyFollowQuery = computed(() =>
readyFollowOptions
.filter((item) => item.value && readyFollow.value.includes(item.value))
.map((item) => item.value)
.join(',')
)
const readyFollowTitle = computed(() => {
const labels = readyFollowOptions
.filter((item) => item.value && readyFollow.value.includes(item.value))
.map((item) => item.text)
if (labels.length === 1) return labels[0]
if (labels.length > 1) return `${labels[0]}等${labels.length}项`
return '全部跟进状态'
})
function readyFollowActive(value: string) {
return value ? readyFollow.value.includes(value) : readyFollow.value.length === 0
}
function toggleReadyFollow(value: string) {
if (!value) {
readyFollow.value = []
return
}
readyFollow.value = readyFollow.value.includes(value)
? readyFollow.value.filter((item) => item !== value)
: [...readyFollow.value, value]
}
const readyDateFrom = ref(defaultReadyDates.from)
const readyDateTo = ref(defaultReadyDates.to)
const readyDateFromDraft = ref(defaultReadyDates.from)
@@ -112,6 +112,7 @@
import { certReadyDefaultPlanDates } from '@/utils/cert-ready-plan-date'
import { certReadyErrorText, formatCertReadyTime } from '@/utils/pl-quota-cert-waiver'
import {
PL_PLAN_CERT_READY_DEFAULT_FOLLOW_STATUSES,
PL_PLAN_FOLLOW_STATUS_OPTIONS,
getPlPlanFollowStatusLabel,
getPlPlanFollowStatusTagType
@@ -193,6 +194,7 @@
} = useServerColumnFilters(columns, {
initialFilters: {
quotaCertWaived: { text: '', selected: ['0'] },
followStatus: { text: '', selected: [...PL_PLAN_CERT_READY_DEFAULT_FOLLOW_STATUSES] },
planDate: { from: defaultPlanDates.from, to: defaultPlanDates.to }
},
onChange: search