feat(oa): confirmation kit defaults and confirmation-date linkage on start form
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
898a337f96
commit
493ce698df
3 files changed
+470
-4
No files matched your search
@@ -0,0 +1,291 @@
|
||||
import { addMonthsYmd } from '@/utils/oa-confirmation-date'
|
||||
import {
|
||||
CONFIRMATION_KIT_FIELD_DEFS,
|
||||
type ConfirmationKitFieldKey
|
||||
} from '@/utils/oa-confirmation-kit-rule'
|
||||
import { resolveCurrentOwnerDept } from '@/utils/oa-owner-field-defaults'
|
||||
|
||||
export const CONFIRMATION_MANUAL_PREFIX = '__manual_'
|
||||
|
||||
export type ConfirmationKitBinding = {
|
||||
fields: Partial<Record<ConfirmationKitFieldKey, string>>
|
||||
visible: Record<ConfirmationKitFieldKey, boolean>
|
||||
confirmationDateField?: string
|
||||
hireDateField?: string
|
||||
probationMonthsField?: string
|
||||
}
|
||||
|
||||
function asRules(schema: unknown): Record<string, unknown>[] {
|
||||
if (Array.isArray(schema)) return schema.filter((r) => r && typeof r === 'object') as any
|
||||
if (schema && typeof schema === 'object') {
|
||||
const s = schema as any
|
||||
const rules = s.rule || s.rules || s.fields
|
||||
if (Array.isArray(rules)) return rules.filter((r: any) => r && typeof r === 'object')
|
||||
if (s.type || s.field) return [s]
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
function walk(rules: Record<string, unknown>[], out: Record<string, unknown>[]) {
|
||||
for (const r of rules) {
|
||||
out.push(r)
|
||||
const children = r.children
|
||||
if (Array.isArray(children)) {
|
||||
walk(
|
||||
children.filter((c) => c && typeof c === 'object') as Record<string, unknown>[],
|
||||
out
|
||||
)
|
||||
}
|
||||
const props = r.props as Record<string, unknown> | undefined
|
||||
if (props && Array.isArray(props.rule)) {
|
||||
walk(
|
||||
props.rule.filter((c) => c && typeof c === 'object') as Record<string, unknown>[],
|
||||
out
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function kitChildren(kit: Record<string, unknown>): Record<string, any>[] {
|
||||
const props = (kit.props && typeof kit.props === 'object' ? kit.props : {}) as Record<
|
||||
string,
|
||||
any
|
||||
>
|
||||
if (Array.isArray(kit.children)) return kit.children as any
|
||||
if (Array.isArray(props.rule)) return props.rule as any
|
||||
return []
|
||||
}
|
||||
|
||||
function resolveBinding(kit: Record<string, unknown>): ConfirmationKitBinding {
|
||||
const props = (kit.props && typeof kit.props === 'object' ? kit.props : {}) as Record<
|
||||
string,
|
||||
any
|
||||
>
|
||||
const fields: Partial<Record<ConfirmationKitFieldKey, string>> = {}
|
||||
const propFieldMap: Record<string, ConfirmationKitFieldKey> = {
|
||||
hireDateField: 'hireDate',
|
||||
probationMonthsField: 'probationMonths',
|
||||
confirmationDateField: 'confirmationDate',
|
||||
postField: 'post',
|
||||
jobLevelField: 'jobLevel',
|
||||
nameField: 'name',
|
||||
emailField: 'email',
|
||||
deptField: 'dept',
|
||||
phoneField: 'phone'
|
||||
}
|
||||
for (const [propKey, sem] of Object.entries(propFieldMap)) {
|
||||
const f = props[propKey]
|
||||
if (f) fields[sem] = String(f)
|
||||
}
|
||||
|
||||
for (const c of kitChildren(kit)) {
|
||||
if (!c?.field) continue
|
||||
const sem = String(c.props?._fc_kit_field || '') as ConfirmationKitFieldKey
|
||||
if (CONFIRMATION_KIT_FIELD_DEFS.some((d) => d.key === sem) && !fields[sem]) {
|
||||
fields[sem] = String(c.field)
|
||||
}
|
||||
}
|
||||
|
||||
const visible = {} as Record<ConfirmationKitFieldKey, boolean>
|
||||
for (const d of CONFIRMATION_KIT_FIELD_DEFS) {
|
||||
const v = props[d.showProp]
|
||||
visible[d.key] = v === undefined || v === null ? true : !!v
|
||||
}
|
||||
|
||||
return {
|
||||
fields,
|
||||
visible,
|
||||
confirmationDateField: fields.confirmationDate,
|
||||
hireDateField: fields.hireDate,
|
||||
probationMonthsField: fields.probationMonths
|
||||
}
|
||||
}
|
||||
|
||||
export function listConfirmationKitBindings(schema: unknown): ConfirmationKitBinding[] {
|
||||
const flat: Record<string, unknown>[] = []
|
||||
walk(asRules(schema), flat)
|
||||
const out: ConfirmationKitBinding[] = []
|
||||
for (const r of flat) {
|
||||
if (String(r.type || '') !== 'confirmationKit') continue
|
||||
out.push(resolveBinding(r))
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
function isEmptyValue(raw: unknown): boolean {
|
||||
if (raw == null || raw === '') return true
|
||||
if (Array.isArray(raw)) return raw.length === 0
|
||||
if (typeof raw === 'object') {
|
||||
const o = raw as Record<string, unknown>
|
||||
return !String(o.id || '').trim()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/** 按 show* props 同步子字段 hidden,并去掉隐藏字段的前端必填 */
|
||||
export function ensureConfirmationKitVisibility(rules: unknown): any[] {
|
||||
if (!Array.isArray(rules)) return []
|
||||
return rules.map((raw) => {
|
||||
if (!raw || typeof raw !== 'object') return raw
|
||||
const rule: any = { ...(raw as object) }
|
||||
if (String(rule.type || '') === 'confirmationKit') {
|
||||
const binding = resolveBinding(rule)
|
||||
const patchChildren = (list: any[]): any[] =>
|
||||
list.map((c) => {
|
||||
if (!c || typeof c !== 'object') return c
|
||||
const child: any = { ...c }
|
||||
const sem = String(child.props?._fc_kit_field || '') as ConfirmationKitFieldKey
|
||||
const show =
|
||||
sem && CONFIRMATION_KIT_FIELD_DEFS.some((d) => d.key === sem)
|
||||
? binding.visible[sem] !== false
|
||||
: true
|
||||
child.hidden = !show
|
||||
if (!show) {
|
||||
child.$required = false
|
||||
if (child.validate) child.validate = []
|
||||
}
|
||||
if (Array.isArray(child.children)) {
|
||||
child.children = patchChildren(child.children)
|
||||
}
|
||||
return child
|
||||
})
|
||||
if (Array.isArray(rule.children)) {
|
||||
rule.children = patchChildren(rule.children)
|
||||
}
|
||||
if (Array.isArray(rule.props?.rule)) {
|
||||
rule.props = {
|
||||
...rule.props,
|
||||
rule: patchChildren(rule.props.rule)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Array.isArray(rule.children)) {
|
||||
rule.children = ensureConfirmationKitVisibility(rule.children)
|
||||
}
|
||||
if (Array.isArray(rule.props?.rule)) {
|
||||
rule.props = {
|
||||
...rule.props,
|
||||
rule: ensureConfirmationKitVisibility(rule.props.rule)
|
||||
}
|
||||
}
|
||||
return rule
|
||||
})
|
||||
}
|
||||
|
||||
export async function applyConfirmationKitDefaults(
|
||||
schema: unknown,
|
||||
formData: Record<string, unknown>,
|
||||
user: Record<string, unknown> | null | undefined
|
||||
): Promise<Record<string, unknown>> {
|
||||
const data = { ...formData }
|
||||
const kits = listConfirmationKitBindings(schema)
|
||||
if (!kits.length || !user) return data
|
||||
|
||||
const name = String(user.realName || user.nickName || user.userName || '').trim()
|
||||
const email = String(user.email || '').trim()
|
||||
const phone = String(user.phone || user.phoneNo || '').trim()
|
||||
const hireDate = String(user.hireDate || '').trim()
|
||||
const probationRaw = user.probationMonths
|
||||
const probationMonths =
|
||||
probationRaw === null || probationRaw === undefined || probationRaw === ''
|
||||
? null
|
||||
: Number(probationRaw)
|
||||
|
||||
const dept = await resolveCurrentOwnerDept(user as any)
|
||||
|
||||
for (const kit of kits) {
|
||||
const setIfEmpty = (sem: ConfirmationKitFieldKey, value: unknown) => {
|
||||
const field = kit.fields[sem]
|
||||
if (!field) return
|
||||
if (!isEmptyValue(data[field])) return
|
||||
if (value === null || value === undefined || value === '') return
|
||||
data[field] = value
|
||||
}
|
||||
|
||||
setIfEmpty('hireDate', hireDate || null)
|
||||
if (probationMonths !== null && Number.isFinite(probationMonths) && probationMonths >= 0) {
|
||||
setIfEmpty('probationMonths', Math.trunc(probationMonths))
|
||||
}
|
||||
setIfEmpty('name', name || null)
|
||||
setIfEmpty('email', email || null)
|
||||
setIfEmpty('phone', phone || null)
|
||||
if (dept) setIfEmpty('dept', dept)
|
||||
|
||||
const confField = kit.confirmationDateField
|
||||
const hireField = kit.hireDateField
|
||||
const probField = kit.probationMonthsField
|
||||
if (confField && isEmptyValue(data[confField]) && hireField && probField) {
|
||||
const suggested = addMonthsYmd(
|
||||
String(data[hireField] || ''),
|
||||
Number(data[probField])
|
||||
)
|
||||
if (suggested) data[confField] = suggested
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
export function applyConfirmationKitDateLinkage(
|
||||
schema: unknown,
|
||||
formData: Record<string, unknown>
|
||||
): { data: Record<string, unknown>; changed: boolean } {
|
||||
const data = { ...formData }
|
||||
let changed = false
|
||||
for (const kit of listConfirmationKitBindings(schema)) {
|
||||
const confField = kit.confirmationDateField
|
||||
const hireField = kit.hireDateField
|
||||
const probField = kit.probationMonthsField
|
||||
if (!confField || !hireField || !probField) continue
|
||||
if (data[CONFIRMATION_MANUAL_PREFIX + confField]) continue
|
||||
const suggested = addMonthsYmd(String(data[hireField] || ''), Number(data[probField]))
|
||||
if (suggested == null) continue
|
||||
if (data[confField] !== suggested) {
|
||||
data[confField] = suggested
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
return { data, changed }
|
||||
}
|
||||
|
||||
export function markConfirmationDateManual(
|
||||
formData: Record<string, unknown>,
|
||||
confirmationDateField: string,
|
||||
manual = true
|
||||
) {
|
||||
const data = { ...formData }
|
||||
const key = CONFIRMATION_MANUAL_PREFIX + confirmationDateField
|
||||
if (manual) data[key] = true
|
||||
else delete data[key]
|
||||
return data
|
||||
}
|
||||
|
||||
export function clearConfirmationDateManualAndRelink(
|
||||
schema: unknown,
|
||||
formData: Record<string, unknown>,
|
||||
confirmationDateField: string
|
||||
) {
|
||||
let data = markConfirmationDateManual(formData, confirmationDateField, false)
|
||||
const linked = applyConfirmationKitDateLinkage(schema, data)
|
||||
return linked.data
|
||||
}
|
||||
|
||||
export function listManualConfirmationDateFields(schema: unknown, formData: Record<string, unknown>) {
|
||||
return listConfirmationKitBindings(schema)
|
||||
.map((k) => k.confirmationDateField)
|
||||
.filter((f): f is string => !!f && !!formData[CONFIRMATION_MANUAL_PREFIX + f])
|
||||
}
|
||||
|
||||
export function isConfirmationDateField(schema: unknown, field: string): boolean {
|
||||
return listConfirmationKitBindings(schema).some((k) => k.confirmationDateField === field)
|
||||
}
|
||||
|
||||
export function findConfirmationKitByHireOrProbation(
|
||||
schema: unknown,
|
||||
field: string
|
||||
): ConfirmationKitBinding | null {
|
||||
return (
|
||||
listConfirmationKitBindings(schema).find(
|
||||
(k) => k.hireDateField === field || k.probationMonthsField === field
|
||||
) || null
|
||||
)
|
||||
}
|
||||
@@ -210,6 +210,9 @@
|
||||
OA_FC_DEFAULT_GUTTER,
|
||||
ensureOaUploadRuleProps
|
||||
} from '@/utils/oa-form-create-upload'
|
||||
import { ensureLeaveKitRuleProps } from '@/utils/oa-leave-kit-runtime'
|
||||
import { ensureConfirmationKitVisibility } from '@/utils/oa-confirmation-kit-runtime'
|
||||
import { ensureOwnerFieldRuleProps } from '@/utils/oa-owner-field-defaults'
|
||||
|
||||
defineOptions({ name: 'OaApprovalInstanceDetail' })
|
||||
|
||||
@@ -340,7 +343,9 @@
|
||||
function applySchema(schema: any, data: any) {
|
||||
viewFormData.value = { ...(data || {}) }
|
||||
const rule = Array.isArray(schema?.rule) ? schema.rule : Array.isArray(schema) ? schema : []
|
||||
viewRule.value = ensureOaUploadRuleProps(rule)
|
||||
viewRule.value = ensureConfirmationKitVisibility(
|
||||
ensureOwnerFieldRuleProps(ensureLeaveKitRuleProps(ensureOaUploadRuleProps(rule)))
|
||||
)
|
||||
const savedGutter = Number(schema?.option?.row?.gutter)
|
||||
viewOption.value = {
|
||||
...(schema?.option || {}),
|
||||
|
||||
@@ -105,7 +105,17 @@
|
||||
:rule="formRule"
|
||||
:option="formOption"
|
||||
/>
|
||||
<p v-else-if="!detailLoading" class="oa-start__tip">该模板暂无表单字段,仍可直接提交。</p>
|
||||
<p
|
||||
v-if="confirmationDateManualFields.length"
|
||||
class="oa-start__tip oa-start__confirm-relink"
|
||||
>
|
||||
<el-button link type="primary" @click="restoreConfirmationDateAuto">
|
||||
恢复转正日期自动计算
|
||||
</el-button>
|
||||
</p>
|
||||
<p v-else-if="!formRule.length && !detailLoading" class="oa-start__tip">
|
||||
该模板暂无表单字段,仍可直接提交。
|
||||
</p>
|
||||
<OaFlowPreview
|
||||
v-if="!detailLoading"
|
||||
v-model:select-by-node="initiatorSelectByNode"
|
||||
@@ -154,11 +164,34 @@
|
||||
OA_FC_DEFAULT_GUTTER,
|
||||
ensureOaUploadRuleProps
|
||||
} from '@/utils/oa-form-create-upload'
|
||||
import {
|
||||
applyLeaveKitDurationsToFormData,
|
||||
ensureLeaveKitRuleProps,
|
||||
LEAVE_MANUAL_PREFIX,
|
||||
listLeaveKitBindings,
|
||||
markLeaveDurationManual
|
||||
} from '@/utils/oa-leave-kit-runtime'
|
||||
import {
|
||||
applyConfirmationKitDateLinkage,
|
||||
applyConfirmationKitDefaults,
|
||||
clearConfirmationDateManualAndRelink,
|
||||
CONFIRMATION_MANUAL_PREFIX,
|
||||
ensureConfirmationKitVisibility,
|
||||
listConfirmationKitBindings,
|
||||
listManualConfirmationDateFields,
|
||||
markConfirmationDateManual
|
||||
} from '@/utils/oa-confirmation-kit-runtime'
|
||||
import {
|
||||
applyOwnerFieldDefaults,
|
||||
ensureOwnerFieldRuleProps
|
||||
} from '@/utils/oa-owner-field-defaults'
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
|
||||
defineOptions({ name: 'OaApprovalStart' })
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const userStore = useUserStore()
|
||||
const loading = ref(false)
|
||||
const templates = ref<any[]>([])
|
||||
const groupOptions = ref<Array<{ id: string; groupName: string }>>([])
|
||||
@@ -184,6 +217,15 @@
|
||||
const flowPendingMessage = ref('必填信息填写后,流程将自动显示')
|
||||
const previewLoading = ref(false)
|
||||
let previewTimer: ReturnType<typeof setTimeout> | null = null
|
||||
/** 避免时长自动回写再次触发手改判定 */
|
||||
let leaveKitSyncing = false
|
||||
let leaveKitPrevSnapshot: Record<string, unknown> = {}
|
||||
let confirmationKitSyncing = false
|
||||
let confirmationKitPrevSnapshot: Record<string, unknown> = {}
|
||||
|
||||
const confirmationDateManualFields = computed(() =>
|
||||
listManualConfirmationDateFields({ rule: formRule.value }, formData.value)
|
||||
)
|
||||
|
||||
const displayGroups = computed(() => {
|
||||
const kw = (searchKeyword.value || '').trim().toLowerCase()
|
||||
@@ -288,6 +330,8 @@
|
||||
picked.value = t
|
||||
formData.value = {}
|
||||
formRule.value = []
|
||||
leaveKitPrevSnapshot = {}
|
||||
confirmationKitPrevSnapshot = {}
|
||||
needInitiatorSelect.value = false
|
||||
initiatorSelectByNode.value = {}
|
||||
flowSteps.value = []
|
||||
@@ -304,7 +348,11 @@
|
||||
: Array.isArray(schema)
|
||||
? schema
|
||||
: []
|
||||
formRule.value = ensureOaUploadRuleProps(rawRule)
|
||||
formRule.value = ensureConfirmationKitVisibility(
|
||||
ensureOwnerFieldRuleProps(
|
||||
ensureLeaveKitRuleProps(ensureOaUploadRuleProps(rawRule))
|
||||
)
|
||||
)
|
||||
const savedGutter = Number(schema.option?.row?.gutter)
|
||||
formOption.value = {
|
||||
...(schema.option || {}),
|
||||
@@ -320,6 +368,19 @@
|
||||
submitBtn: false,
|
||||
resetBtn: false
|
||||
}
|
||||
let data = await applyOwnerFieldDefaults(
|
||||
formRule.value,
|
||||
{},
|
||||
(userStore.info || userStore.getUserInfo) as any
|
||||
)
|
||||
data = await applyConfirmationKitDefaults(
|
||||
{ rule: formRule.value },
|
||||
data,
|
||||
(userStore.info || userStore.getUserInfo) as any
|
||||
)
|
||||
const linked = applyConfirmationKitDateLinkage({ rule: formRule.value }, data)
|
||||
formData.value = linked.data
|
||||
confirmationKitPrevSnapshot = { ...linked.data }
|
||||
const flow = detail?.flowTreeJson || {}
|
||||
const root = flow.root || flow
|
||||
needInitiatorSelect.value = flowNeedsInitiatorSelect(root)
|
||||
@@ -337,9 +398,114 @@
|
||||
}
|
||||
}
|
||||
|
||||
function syncLeaveKitDurations() {
|
||||
if (leaveKitSyncing) return
|
||||
if (!formRule.value.length) return
|
||||
const schema = { rule: formRule.value }
|
||||
const bindings = listLeaveKitBindings(schema)
|
||||
if (!bindings.length) return
|
||||
|
||||
const curr = { ...formData.value }
|
||||
for (const kit of bindings) {
|
||||
const prevDur = leaveKitPrevSnapshot[kit.durationField]
|
||||
const currDur = curr[kit.durationField]
|
||||
const startChanged =
|
||||
leaveKitPrevSnapshot[kit.startField] !== curr[kit.startField]
|
||||
const endChanged = leaveKitPrevSnapshot[kit.endField] !== curr[kit.endField]
|
||||
const durChanged = prevDur !== currDur
|
||||
if (durChanged && !startChanged && !endChanged && currDur !== undefined && currDur !== '') {
|
||||
Object.assign(curr, markLeaveDurationManual(curr, kit.durationField, true))
|
||||
}
|
||||
}
|
||||
|
||||
const { data, changed } = applyLeaveKitDurationsToFormData(schema, curr)
|
||||
leaveKitPrevSnapshot = { ...data }
|
||||
const manualKeysChanged = bindings.some(
|
||||
(k) =>
|
||||
!!data[LEAVE_MANUAL_PREFIX + k.durationField] !==
|
||||
!!formData.value[LEAVE_MANUAL_PREFIX + k.durationField]
|
||||
)
|
||||
const durationChanged = bindings.some(
|
||||
(k) => data[k.durationField] !== formData.value[k.durationField]
|
||||
)
|
||||
if (changed || manualKeysChanged || durationChanged) {
|
||||
leaveKitSyncing = true
|
||||
formData.value = data
|
||||
queueMicrotask(() => {
|
||||
leaveKitSyncing = false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function syncConfirmationKitDates() {
|
||||
if (confirmationKitSyncing) return
|
||||
if (!formRule.value.length) return
|
||||
const schema = { rule: formRule.value }
|
||||
const kits = listConfirmationKitBindings(schema)
|
||||
if (!kits.length) return
|
||||
|
||||
let curr = { ...formData.value }
|
||||
for (const kit of kits) {
|
||||
const confField = kit.confirmationDateField
|
||||
const hireField = kit.hireDateField
|
||||
const probField = kit.probationMonthsField
|
||||
if (!confField || !hireField || !probField) continue
|
||||
const confChanged =
|
||||
confirmationKitPrevSnapshot[confField] !== curr[confField]
|
||||
const hireChanged = confirmationKitPrevSnapshot[hireField] !== curr[hireField]
|
||||
const probChanged = confirmationKitPrevSnapshot[probField] !== curr[probField]
|
||||
if (
|
||||
confChanged &&
|
||||
!hireChanged &&
|
||||
!probChanged &&
|
||||
curr[confField] !== undefined &&
|
||||
curr[confField] !== ''
|
||||
) {
|
||||
curr = markConfirmationDateManual(curr, confField, true)
|
||||
}
|
||||
}
|
||||
|
||||
const { data, changed } = applyConfirmationKitDateLinkage(schema, curr)
|
||||
confirmationKitPrevSnapshot = { ...data }
|
||||
const anyDiff =
|
||||
changed ||
|
||||
kits.some((k) => {
|
||||
const f = k.confirmationDateField
|
||||
if (!f) return false
|
||||
return (
|
||||
data[f] !== formData.value[f] ||
|
||||
!!data[CONFIRMATION_MANUAL_PREFIX + f] !==
|
||||
!!formData.value[CONFIRMATION_MANUAL_PREFIX + f]
|
||||
)
|
||||
})
|
||||
if (anyDiff) {
|
||||
confirmationKitSyncing = true
|
||||
formData.value = data
|
||||
queueMicrotask(() => {
|
||||
confirmationKitSyncing = false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function restoreConfirmationDateAuto() {
|
||||
const schema = { rule: formRule.value }
|
||||
let data = { ...formData.value }
|
||||
for (const field of listManualConfirmationDateFields(schema, data)) {
|
||||
data = clearConfirmationDateManualAndRelink(schema, data, field)
|
||||
}
|
||||
confirmationKitSyncing = true
|
||||
formData.value = data
|
||||
confirmationKitPrevSnapshot = { ...data }
|
||||
queueMicrotask(() => {
|
||||
confirmationKitSyncing = false
|
||||
})
|
||||
}
|
||||
|
||||
watch(
|
||||
formData,
|
||||
() => {
|
||||
syncLeaveKitDurations()
|
||||
syncConfirmationKitDates()
|
||||
scheduleFlowPreview()
|
||||
},
|
||||
{ deep: true }
|
||||
@@ -403,7 +569,11 @@
|
||||
if (qCopyFrom) {
|
||||
try {
|
||||
const old = await fetchOaInstanceDetail(qCopyFrom)
|
||||
formData.value = { ...(old?.formDataJson || {}) }
|
||||
formData.value = await applyOwnerFieldDefaults(
|
||||
formRule.value,
|
||||
{ ...(old?.formDataJson || {}) },
|
||||
(userStore.info || userStore.getUserInfo) as any
|
||||
)
|
||||
} catch {
|
||||
/* 预填失败仍可手工填 */
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user