feat(oa): add initiator system field to condition branches

Allow __initiator__ contains matching in publish validation and the
flow designer candidate list, excluding it from form useInCondition locks.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zlwuandCursor committed 2026-07-30 13:07:44 +08:00
1 parent 3d88f52e2e
commit 22be6d8b36
7 files changed
+103 -23

No files matched your search

@@ -48,7 +48,7 @@
/>
</el-select>
<el-select
v-if="isPersonField(rule.field)"
v-if="isPersonLikeField(rule.field)"
:model-value="personValueIds(rule.value)"
multiple
filterable
@@ -152,8 +152,9 @@
return props.candidates.find((c) => c.field === field)
}
function isPersonField(field: string) {
return meta(field)?.type === 'person'
function isPersonLikeField(field: string) {
const t = meta(field)?.type
return t === 'person' || t === 'initiator'
}
function personValueIds(v: unknown): string[] {
@@ -163,7 +164,7 @@
}
function defaultValueForType(type: string, opts?: ConditionCandidate['options']) {
if (type === 'person') return [] as string[]
if (type === 'person' || type === 'initiator') return [] as string[]
return opts?.[0]?.value ?? ''
}
@@ -285,13 +286,13 @@
}
onMounted(() => {
if (props.candidates.some((c) => c.type === 'person')) {
if (props.candidates.some((c) => c.type === 'person' || c.type === 'initiator')) {
loadUsers()
}
})
watch(
() => props.candidates.some((c) => c.type === 'person'),
() => props.candidates.some((c) => c.type === 'person' || c.type === 'initiator'),
(need) => {
if (need && !userOptions.value.length) loadUsers()
}
@@ -11,6 +11,15 @@ export const CONDITION_ELIGIBLE_TYPES = new Set([
'date'
])
/** 系统条件伪字段:发起人(非常驻表单控件) */
export const INITIATOR_CONDITION_FIELD = '__initiator__'
export const INITIATOR_CONDITION_CANDIDATE: ConditionCandidate = {
field: INITIATOR_CONDITION_FIELD,
title: '发起人',
type: 'initiator'
}
export type ConditionOp = '>' | '>=' | '<' | '<=' | '==' | '!=' | 'contains'
export interface ConditionCandidate {
@@ -22,7 +31,7 @@ export interface ConditionCandidate {
}
export function opsForFieldType(type: string): Array<{ value: ConditionOp; label: string }> {
if (type === 'person') {
if (type === 'person' || type === 'initiator') {
return [{ value: 'contains', label: '包含' }]
}
// 单选/下拉为离散选项,仅等于/不等于;输入框常填数字参与区间比较,与数字/金额/日期同套运算符
@@ -66,9 +75,9 @@ export function flattenFormRules(schema: unknown): any[] {
return out
}
/** 勾选了 useInCondition 的合格字段 */
/** 勾选了 useInCondition 的合格字段 + 系统「发起人」 */
export function listConditionCandidates(schema: unknown): ConditionCandidate[] {
const out: ConditionCandidate[] = []
const out: ConditionCandidate[] = [INITIATOR_CONDITION_CANDIDATE]
for (const rule of flattenFormRules(schema)) {
const type = String(rule.type || '')
if (!CONDITION_ELIGIBLE_TYPES.has(type)) continue
@@ -115,6 +124,13 @@ export function collectConditionReferencedFields(flow: unknown): Set<string> {
return refs
}
/** 会锁定表单「参与条件」勾选的引用字段(排除系统伪字段) */
export function collectFormConditionReferencedFields(flow: unknown): Set<string> {
const refs = collectConditionReferencedFields(flow)
refs.delete(INITIATOR_CONDITION_FIELD)
return refs
}
/** 发布/保存前:useInCondition ⇒ $required / required = true;写回顶层 useInCondition */
export function normalizeSchemaConditionRequired(schema: unknown): {
rule: unknown[]
@@ -46,9 +46,6 @@
上传
</el-button>
</el-upload>
<el-button class="btn-ghost" @click="basic.iconUrl = pickRandomOaAppIconUrl()">
换默认
</el-button>
</div>
</el-form-item>
<el-form-item label="应用名称">
@@ -126,11 +123,11 @@
import { createDefaultFlow, ensureFlowRoot } from '@/components/oa-approval/flow-tree/types'
import OaFormDesignerEmbed from '@/components/oa-approval/OaFormDesignerEmbed.vue'
import {
collectConditionReferencedFields,
collectFormConditionReferencedFields,
listConditionCandidates,
normalizeSchemaConditionRequired
} from '@/components/oa-approval/oa-condition-fields'
import { pickRandomOaAppIconUrl, resolveOaAppIconUrl } from '@/utils/oa-app-icons'
import { resolveOaAppIconUrl } from '@/utils/oa-app-icons'
defineOptions({ name: 'OaApprovalDesigner' })
@@ -175,7 +172,7 @@
const flowTreeJson = ref(createDefaultFlow())
const flowConditionFields = computed(() =>
Array.from(collectConditionReferencedFields(flowTreeJson.value))
Array.from(collectFormConditionReferencedFields(flowTreeJson.value))
)
const conditionCandidates = computed(() => listConditionCandidates(formSchema.value))
@@ -447,10 +444,10 @@
.oa-designer__icon-preview {
display: block;
width: 48px;
height: 48px;
width: 80px;
height: 80px;
overflow: hidden;
border-radius: 10px;
border-radius: 16px;
img {
display: block;