feat(mobile-oa-h5): add kit shells, trip itinerary, and camera-friendly upload
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
d5e61a1162
commit
834b1a59a7
6 files changed
+526
-35
No files matched your search
@@ -24,7 +24,18 @@
|
||||
|
||||
- `person` / `dept` / `post`:底部选择弹层,值 `{ id, name }`(部门展示全路径)
|
||||
- `ownerPerson` / `ownerDept`:单选封装,`allowModify` 控制可否改选
|
||||
- 仍为 stub:各 Kit(请假/加班/转正/离职/差旅)
|
||||
|
||||
## P2 套件(已落地)
|
||||
|
||||
- `leaveKit` / `overtimeKit` / `confirmationKit` / `resignationKit` / `tripKit`:与 Web 相同为 **slot 容器**,子字段由 `children` 渲染
|
||||
- `tripItinerary`:行程多段编辑(交通/城市/日期时段)
|
||||
- 说明:Web 端「时长自动计算 / 节假日联动」等运行时逻辑尚未移植,真模板联调时再对齐
|
||||
|
||||
## 附件拍照(真机 / 微信 web-view)
|
||||
|
||||
- **支持**:`van-uploader` 在微信内打开图片时,系统选择器通常提供「拍照」和「从相册选择」
|
||||
- 默认**不**写死 `capture="camera"`,以便同时保留相册;若业务只要拍照可传 `props.capture = 'camera'`
|
||||
- 非图片附件走文件选择;需 HTTPS 业务域名与有效 `token`
|
||||
|
||||
## 本地联调提示
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<!-- 与 Web 套件一致:仅组合容器,子字段由 form-create children + slot 渲染 -->
|
||||
<template>
|
||||
<div class="oa-kit-shell" v-bind="$attrs">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
defineOptions({ inheritAttrs: false })
|
||||
defineProps({
|
||||
formCreateInject: { type: Object, default: null }
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.oa-kit-shell {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,267 @@
|
||||
<template>
|
||||
<div class="oa-trip">
|
||||
<div v-for="(leg, idx) in inner" :key="idx" class="oa-trip__leg">
|
||||
<div class="oa-trip__head">
|
||||
<strong>行程 {{ idx + 1 }}</strong>
|
||||
<van-button
|
||||
v-if="!disabled && inner.length > 1"
|
||||
size="mini"
|
||||
type="danger"
|
||||
plain
|
||||
@click="remove(idx)"
|
||||
>
|
||||
删除
|
||||
</van-button>
|
||||
</div>
|
||||
<van-field
|
||||
:model-value="leg.transport"
|
||||
label="交通工具"
|
||||
readonly
|
||||
is-link
|
||||
:disabled="disabled"
|
||||
placeholder="请选择"
|
||||
@click="!disabled && openSelect(idx, 'transport', transportOpts)"
|
||||
/>
|
||||
<van-field
|
||||
:model-value="leg.tripType"
|
||||
label="单程往返"
|
||||
readonly
|
||||
is-link
|
||||
:disabled="disabled"
|
||||
placeholder="请选择"
|
||||
@click="!disabled && openSelect(idx, 'tripType', tripTypeOpts)"
|
||||
/>
|
||||
<van-field
|
||||
:model-value="leg.fromCity"
|
||||
label="出发城市"
|
||||
:disabled="disabled"
|
||||
placeholder="请输入"
|
||||
@update:model-value="(v) => patch(idx, { fromCity: v })"
|
||||
/>
|
||||
<van-field
|
||||
:model-value="leg.toCity"
|
||||
label="目的城市"
|
||||
:disabled="disabled"
|
||||
placeholder="请输入"
|
||||
@update:model-value="(v) => patch(idx, { toCity: v })"
|
||||
/>
|
||||
<van-field
|
||||
:model-value="leg.startDate"
|
||||
label="开始日期"
|
||||
readonly
|
||||
is-link
|
||||
:disabled="disabled"
|
||||
placeholder="选择日期"
|
||||
@click="!disabled && openDate(idx, 'startDate')"
|
||||
/>
|
||||
<van-field
|
||||
:model-value="leg.startHalf"
|
||||
label="开始时段"
|
||||
readonly
|
||||
is-link
|
||||
:disabled="disabled"
|
||||
@click="!disabled && openSelect(idx, 'startHalf', halfOpts)"
|
||||
/>
|
||||
<van-field
|
||||
:model-value="leg.endDate"
|
||||
label="结束日期"
|
||||
readonly
|
||||
is-link
|
||||
:disabled="disabled"
|
||||
placeholder="选择日期"
|
||||
@click="!disabled && openDate(idx, 'endDate')"
|
||||
/>
|
||||
<van-field
|
||||
:model-value="leg.endHalf"
|
||||
label="结束时段"
|
||||
readonly
|
||||
is-link
|
||||
:disabled="disabled"
|
||||
@click="!disabled && openSelect(idx, 'endHalf', halfOpts)"
|
||||
/>
|
||||
<van-field
|
||||
:model-value="leg.duration == null ? '' : String(leg.duration)"
|
||||
label="时长(天)"
|
||||
type="number"
|
||||
:disabled="disabled"
|
||||
@update:model-value="(v) => patch(idx, { duration: v === '' ? null : Number(v) })"
|
||||
/>
|
||||
</div>
|
||||
<van-button v-if="!disabled" block type="primary" plain size="small" @click="add">
|
||||
添加行程
|
||||
</van-button>
|
||||
|
||||
<van-popup v-model:show="pickerShow" position="bottom" round>
|
||||
<van-picker
|
||||
:columns="pickerColumns"
|
||||
@confirm="onPickerConfirm"
|
||||
@cancel="pickerShow = false"
|
||||
/>
|
||||
</van-popup>
|
||||
<van-popup v-model:show="dateShow" position="bottom" round>
|
||||
<van-date-picker
|
||||
v-model="dateValue"
|
||||
title="选择日期"
|
||||
@confirm="onDateConfirm"
|
||||
@cancel="dateShow = false"
|
||||
/>
|
||||
</van-popup>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, ref, watch } from 'vue'
|
||||
|
||||
defineOptions({ name: 'tripItinerary' })
|
||||
|
||||
const DEFAULT_TRANSPORT = [
|
||||
{ text: '飞机', value: '飞机' },
|
||||
{ text: '火车', value: '火车' },
|
||||
{ text: '汽车', value: '汽车' },
|
||||
{ text: '其他', value: '其他' }
|
||||
]
|
||||
const DEFAULT_TRIP_TYPE = [
|
||||
{ text: '单程', value: '单程' },
|
||||
{ text: '往返', value: '往返' }
|
||||
]
|
||||
const halfOpts = [
|
||||
{ text: '上午', value: '上午' },
|
||||
{ text: '下午', value: '下午' }
|
||||
]
|
||||
|
||||
function emptyLeg() {
|
||||
return {
|
||||
transport: '',
|
||||
tripType: '',
|
||||
fromCity: '',
|
||||
toCity: '',
|
||||
startDate: '',
|
||||
startHalf: '上午',
|
||||
endDate: '',
|
||||
endHalf: '下午',
|
||||
duration: null,
|
||||
durationManual: false
|
||||
}
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: { type: Array, default: () => [] },
|
||||
disabled: { type: Boolean, default: false },
|
||||
transportOptions: { type: Array, default: () => [] },
|
||||
tripTypeOptions: { type: Array, default: () => [] },
|
||||
formCreateInject: { type: Object, default: null }
|
||||
})
|
||||
const emit = defineEmits(['update:modelValue', 'change'])
|
||||
|
||||
const inner = ref(
|
||||
Array.isArray(props.modelValue) && props.modelValue.length
|
||||
? props.modelValue.map((x) => ({ ...emptyLeg(), ...x }))
|
||||
: [emptyLeg()]
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(v) => {
|
||||
if (!Array.isArray(v)) return
|
||||
const next = v.length ? v.map((x) => ({ ...emptyLeg(), ...x })) : [emptyLeg()]
|
||||
if (JSON.stringify(next) !== JSON.stringify(inner.value)) inner.value = next
|
||||
}
|
||||
)
|
||||
|
||||
const transportOpts = computed(() => {
|
||||
const raw = props.transportOptions?.length
|
||||
? props.transportOptions
|
||||
: DEFAULT_TRANSPORT.map((o) => ({ label: o.text, value: o.value }))
|
||||
return raw.map((o) => ({ text: o.label || o.text, value: o.value }))
|
||||
})
|
||||
const tripTypeOpts = computed(() => {
|
||||
const raw = props.tripTypeOptions?.length
|
||||
? props.tripTypeOptions
|
||||
: DEFAULT_TRIP_TYPE.map((o) => ({ label: o.text, value: o.value }))
|
||||
return raw.map((o) => ({ text: o.label || o.text, value: o.value }))
|
||||
})
|
||||
|
||||
function sync() {
|
||||
emit('update:modelValue', inner.value.map((x) => ({ ...x })))
|
||||
emit('change', inner.value.map((x) => ({ ...x })))
|
||||
}
|
||||
|
||||
function patch(idx, patchObj) {
|
||||
const next = inner.value.slice()
|
||||
next[idx] = { ...next[idx], ...patchObj }
|
||||
inner.value = next
|
||||
sync()
|
||||
}
|
||||
|
||||
function add() {
|
||||
inner.value = [...inner.value, emptyLeg()]
|
||||
sync()
|
||||
}
|
||||
|
||||
function remove(idx) {
|
||||
if (inner.value.length <= 1) return
|
||||
inner.value = inner.value.filter((_, i) => i !== idx)
|
||||
sync()
|
||||
}
|
||||
|
||||
const pickerShow = ref(false)
|
||||
const pickerColumns = ref([])
|
||||
const editIdx = ref(0)
|
||||
const editKey = ref('')
|
||||
const dateShow = ref(false)
|
||||
const dateValue = ref(['2026', '01', '01'])
|
||||
|
||||
function openSelect(idx, key, opts) {
|
||||
editIdx.value = idx
|
||||
editKey.value = key
|
||||
pickerColumns.value = opts
|
||||
pickerShow.value = true
|
||||
}
|
||||
|
||||
function onPickerConfirm({ selectedOptions }) {
|
||||
const v = selectedOptions?.[0]?.value ?? ''
|
||||
patch(editIdx.value, { [editKey.value]: v })
|
||||
pickerShow.value = false
|
||||
}
|
||||
|
||||
function openDate(idx, key) {
|
||||
editIdx.value = idx
|
||||
editKey.value = key
|
||||
const cur = String(inner.value[idx]?.[key] || '')
|
||||
if (/^\d{4}-\d{2}-\d{2}$/.test(cur)) {
|
||||
dateValue.value = cur.split('-')
|
||||
} else {
|
||||
const d = new Date()
|
||||
dateValue.value = [
|
||||
String(d.getFullYear()),
|
||||
String(d.getMonth() + 1).padStart(2, '0'),
|
||||
String(d.getDate()).padStart(2, '0')
|
||||
]
|
||||
}
|
||||
dateShow.value = true
|
||||
}
|
||||
|
||||
function onDateConfirm({ selectedValues }) {
|
||||
const v = (selectedValues || dateValue.value).join('-')
|
||||
patch(editIdx.value, { [editKey.value]: v })
|
||||
dateShow.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.oa-trip {
|
||||
padding: 4px 0 8px;
|
||||
}
|
||||
.oa-trip__leg {
|
||||
margin-bottom: 12px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px dashed var(--border, #dcebe4);
|
||||
}
|
||||
.oa-trip__head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 4px 12px 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
||||
@@ -4,16 +4,20 @@
|
||||
v-model="fileList"
|
||||
:disabled="disabled"
|
||||
:max-count="limit"
|
||||
:accept="accept"
|
||||
:capture="captureAttr"
|
||||
:after-read="onAfterRead"
|
||||
:before-delete="onBeforeDelete"
|
||||
multiple
|
||||
/>
|
||||
<div v-if="!getToken()" class="oa-upload__tip">未携带登录 token,上传可能失败</div>
|
||||
<div class="oa-upload__tip">
|
||||
{{ tipText }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { showToast } from 'vant'
|
||||
import { uploadAttachment } from '../../api/oa.js'
|
||||
import { getToken } from '../../utils/auth.js'
|
||||
@@ -24,10 +28,24 @@ const props = defineProps({
|
||||
modelValue: { type: [Array, String, Object], default: () => [] },
|
||||
disabled: { type: Boolean, default: false },
|
||||
limit: { type: Number, default: 9 },
|
||||
/** 默认同时允许图片与常见文件;图片在微信 web-view 可选「拍照 / 相册」 */
|
||||
accept: { type: String, default: 'image/*,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.zip,.rar' },
|
||||
/**
|
||||
* 不传/空:由系统选择器决定(微信内通常可选拍照或相册)
|
||||
* 传 camera:仅调起相机
|
||||
*/
|
||||
capture: { type: String, default: '' },
|
||||
formCreateInject: { type: Object, default: null }
|
||||
})
|
||||
const emit = defineEmits(['update:modelValue', 'change'])
|
||||
|
||||
const captureAttr = computed(() => (props.capture === 'camera' ? 'camera' : undefined))
|
||||
const tipText = computed(() => {
|
||||
if (!getToken()) return '未携带登录 token,上传可能失败'
|
||||
if (props.capture === 'camera') return '将直接调起相机拍照上传'
|
||||
return '图片可选择拍照或从相册选取(微信内 web-view 支持)'
|
||||
})
|
||||
|
||||
function toUrlList(raw) {
|
||||
if (raw == null || raw === '') return []
|
||||
if (Array.isArray(raw)) {
|
||||
@@ -115,7 +133,8 @@ function onBeforeDelete() {
|
||||
}
|
||||
.oa-upload__tip {
|
||||
margin-top: 4px;
|
||||
color: #cf8a19;
|
||||
color: var(--text-muted, #6b7b74);
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
</style>
|
||||
@@ -1,4 +1,31 @@
|
||||
/** 按 zkxw-sc 已发布模板实际出现的 type 构造;非设计器理论全集 */
|
||||
/** 按 zkxw-sc 已发布模板实际出现的 type 构造;套件带 children(与 Web 结构一致) */
|
||||
|
||||
const LEAVE_TYPE_OPTIONS = [
|
||||
{ label: '事假', value: '事假' },
|
||||
{ label: '调休', value: '调休' },
|
||||
{ label: '病假', value: '病假' },
|
||||
{ label: '年假', value: '年假' },
|
||||
{ label: '产假', value: '产假' },
|
||||
{ label: '陪产假', value: '陪产假' },
|
||||
{ label: '婚假', value: '婚假' },
|
||||
{ label: '丧假', value: '丧假' }
|
||||
]
|
||||
|
||||
function emptyTripLeg() {
|
||||
return {
|
||||
transport: '',
|
||||
tripType: '',
|
||||
fromCity: '',
|
||||
toCity: '',
|
||||
startDate: '',
|
||||
startHalf: '上午',
|
||||
endDate: '',
|
||||
endHalf: '下午',
|
||||
duration: null,
|
||||
durationManual: false
|
||||
}
|
||||
}
|
||||
|
||||
export const kitchenSinkRule = [
|
||||
{ type: 'input', field: 'title', title: '单行文本', value: '', $required: true },
|
||||
{ type: 'textarea', field: 'remark', title: '多行文本', value: '' },
|
||||
@@ -69,31 +96,183 @@ export const kitchenSinkRule = [
|
||||
value: [],
|
||||
props: { multiple: true }
|
||||
},
|
||||
{ type: 'leaveKit', field: 'leaveKit', title: '请假套件 leaveKit', value: {} },
|
||||
{
|
||||
type: 'leaveKit',
|
||||
field: 'leaveKitWrap',
|
||||
title: '请假套件',
|
||||
props: {
|
||||
startField: 'leaveStart',
|
||||
endField: 'leaveEnd',
|
||||
durationField: 'leaveDuration',
|
||||
typeField: 'leaveType'
|
||||
},
|
||||
children: [
|
||||
{
|
||||
type: 'select',
|
||||
field: 'leaveType',
|
||||
title: '请假类型',
|
||||
$required: true,
|
||||
options: LEAVE_TYPE_OPTIONS.map((o) => ({ ...o }))
|
||||
},
|
||||
{
|
||||
type: 'datePicker',
|
||||
field: 'leaveStart',
|
||||
title: '开始时间',
|
||||
$required: true,
|
||||
props: { type: 'datetime' }
|
||||
},
|
||||
{
|
||||
type: 'datePicker',
|
||||
field: 'leaveEnd',
|
||||
title: '结束时间',
|
||||
$required: true,
|
||||
props: { type: 'datetime' }
|
||||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'leaveDuration',
|
||||
title: '时长(h)',
|
||||
$required: true,
|
||||
props: { precision: 1, min: 0 }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'overtimeKit',
|
||||
field: 'overtimeKit',
|
||||
title: '加班套件 overtimeKit',
|
||||
value: {}
|
||||
field: 'overtimeKitWrap',
|
||||
title: '加班套件',
|
||||
props: {
|
||||
personField: 'otPerson',
|
||||
startField: 'otStart',
|
||||
endField: 'otEnd',
|
||||
durationField: 'otDuration'
|
||||
},
|
||||
children: [
|
||||
{
|
||||
type: 'person',
|
||||
field: 'otPerson',
|
||||
title: '加班人',
|
||||
$required: true,
|
||||
props: { multiple: true }
|
||||
},
|
||||
{
|
||||
type: 'datePicker',
|
||||
field: 'otStart',
|
||||
title: '开始时间',
|
||||
$required: true,
|
||||
props: { type: 'datetime' }
|
||||
},
|
||||
{
|
||||
type: 'datePicker',
|
||||
field: 'otEnd',
|
||||
title: '结束时间',
|
||||
$required: true,
|
||||
props: { type: 'datetime' }
|
||||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'otDuration',
|
||||
title: '时长(h)',
|
||||
$required: true,
|
||||
props: { precision: 1, min: 0 }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'confirmationKit',
|
||||
field: 'confirmationKit',
|
||||
title: '转正套件 confirmationKit',
|
||||
value: {}
|
||||
field: 'confirmKitWrap',
|
||||
title: '转正套件',
|
||||
children: [
|
||||
{
|
||||
type: 'datePicker',
|
||||
field: 'hireDate',
|
||||
title: '入职日期',
|
||||
props: { type: 'date' }
|
||||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'probationMonths',
|
||||
title: '试用期(月)',
|
||||
props: { min: 0 }
|
||||
},
|
||||
{
|
||||
type: 'datePicker',
|
||||
field: 'confirmationDate',
|
||||
title: '转正日期',
|
||||
props: { type: 'date' }
|
||||
},
|
||||
{
|
||||
type: 'post',
|
||||
field: 'confirmPost',
|
||||
title: '职位',
|
||||
props: { multiple: false }
|
||||
},
|
||||
{
|
||||
type: 'dept',
|
||||
field: 'confirmDept',
|
||||
title: '部门',
|
||||
props: { multiple: false }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'resignationKit',
|
||||
field: 'resignationKit',
|
||||
title: '离职套件 resignationKit',
|
||||
value: {}
|
||||
field: 'resignKitWrap',
|
||||
title: '离职套件',
|
||||
children: [
|
||||
{
|
||||
type: 'datePicker',
|
||||
field: 'resignHireDate',
|
||||
title: '入职日期',
|
||||
props: { type: 'date' }
|
||||
},
|
||||
{
|
||||
type: 'datePicker',
|
||||
field: 'lastWorkDay',
|
||||
title: '最后工作日',
|
||||
props: { type: 'date' }
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'resignReason',
|
||||
title: '离职原因',
|
||||
props: { type: 'textarea', rows: 2 }
|
||||
}
|
||||
]
|
||||
},
|
||||
{ type: 'tripKit', field: 'tripKit', title: '差旅套件 tripKit', value: {} },
|
||||
{
|
||||
type: 'tripItinerary',
|
||||
field: 'tripItinerary',
|
||||
title: '行程 tripItinerary',
|
||||
value: []
|
||||
type: 'tripKit',
|
||||
field: 'tripKitWrap',
|
||||
title: '差旅套件',
|
||||
children: [
|
||||
{
|
||||
type: 'input',
|
||||
field: 'tripReason',
|
||||
title: '出差事由',
|
||||
$required: true,
|
||||
props: { type: 'textarea', rows: 2 }
|
||||
},
|
||||
{
|
||||
type: 'tripItinerary',
|
||||
field: 'tripList',
|
||||
title: '行程',
|
||||
$required: true,
|
||||
value: [emptyTripLeg()]
|
||||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'tripDays',
|
||||
title: '出差天数',
|
||||
$required: true,
|
||||
props: { precision: 1, step: 0.5, min: 0 }
|
||||
},
|
||||
{
|
||||
type: 'person',
|
||||
field: 'tripCompanions',
|
||||
title: '同行人',
|
||||
props: { multiple: true }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import OaStubField from './components/OaStubField.vue'
|
||||
import OaMoneyField from './components/OaMoneyField.vue'
|
||||
import OaUploadField from './components/OaUploadField.vue'
|
||||
import OaReceiveAccountSelect from './components/OaReceiveAccountSelect.vue'
|
||||
@@ -8,8 +7,10 @@ import OaDeptSelect from './components/OaDeptSelect.vue'
|
||||
import OaPostSelect from './components/OaPostSelect.vue'
|
||||
import OaOwnerPersonSelect from './components/OaOwnerPersonSelect.vue'
|
||||
import OaOwnerDeptSelect from './components/OaOwnerDeptSelect.vue'
|
||||
import OaKitShell from './components/OaKitShell.vue'
|
||||
import OaTripItinerary from './components/OaTripItinerary.vue'
|
||||
|
||||
/** P0 + P1 真实组件;套件仍用 stub */
|
||||
/** 与 web-admin type 名对齐 */
|
||||
const REAL_COMPONENTS = {
|
||||
money: OaMoneyField,
|
||||
upload: OaUploadField,
|
||||
@@ -19,24 +20,19 @@ const REAL_COMPONENTS = {
|
||||
dept: OaDeptSelect,
|
||||
post: OaPostSelect,
|
||||
ownerPerson: OaOwnerPersonSelect,
|
||||
ownerDept: OaOwnerDeptSelect
|
||||
ownerDept: OaOwnerDeptSelect,
|
||||
leaveKit: OaKitShell,
|
||||
overtimeKit: OaKitShell,
|
||||
confirmationKit: OaKitShell,
|
||||
resignationKit: OaKitShell,
|
||||
tripKit: OaKitShell,
|
||||
tripItinerary: OaTripItinerary
|
||||
}
|
||||
|
||||
const STUB_TYPES = [
|
||||
'leaveKit',
|
||||
'overtimeKit',
|
||||
'confirmationKit',
|
||||
'resignationKit',
|
||||
'tripKit',
|
||||
'tripItinerary'
|
||||
]
|
||||
|
||||
export function registerOaComponents(formCreate) {
|
||||
if (!formCreate || typeof formCreate.component !== 'function') return
|
||||
for (const [name, comp] of Object.entries(REAL_COMPONENTS)) {
|
||||
formCreate.component(name, comp)
|
||||
}
|
||||
for (const name of STUB_TYPES) {
|
||||
formCreate.component(name, OaStubField)
|
||||
}
|
||||
formCreate.component('fcUpload', OaUploadField)
|
||||
}
|
||||
Reference in new issue
Block a user