mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2025-06-19 04:01:33 +08:00
parent
c613b12f11
commit
3a1a9795f6
@ -35,14 +35,13 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^2.0.9",
|
"@element-plus/icons-vue": "^2.0.9",
|
||||||
|
"@tmagic/design": "1.2.0-beta.2",
|
||||||
"@tmagic/utils": "1.2.0-beta.2",
|
"@tmagic/utils": "1.2.0-beta.2",
|
||||||
"element-plus": "^2.2.17",
|
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"sortablejs": "^1.14.0",
|
"sortablejs": "^1.14.0",
|
||||||
"vue": "^3.2.37"
|
"vue": "^3.2.37"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"element-plus": "^2.2.17",
|
|
||||||
"vue": "^3.2.37"
|
"vue": "^3.2.37"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form
|
<TMagicForm
|
||||||
class="m-form"
|
class="m-form"
|
||||||
ref="elForm"
|
ref="tMagicForm"
|
||||||
:model="values"
|
:model="values"
|
||||||
:label-width="labelWidth"
|
:label-width="labelWidth"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
@ -10,7 +10,7 @@
|
|||||||
:label-position="labelPosition"
|
:label-position="labelPosition"
|
||||||
>
|
>
|
||||||
<template v-if="initialized && Array.isArray(config)">
|
<template v-if="initialized && Array.isArray(config)">
|
||||||
<m-form-container
|
<Container
|
||||||
v-for="(item, index) in config"
|
v-for="(item, index) in config"
|
||||||
:key="item[keyProp] ?? index"
|
:key="item[keyProp] ?? index"
|
||||||
:config="item"
|
:config="item"
|
||||||
@ -19,175 +19,132 @@
|
|||||||
:step-active="stepActive"
|
:step-active="stepActive"
|
||||||
:size="size"
|
:size="size"
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
></m-form-container>
|
></Container>
|
||||||
</template>
|
</template>
|
||||||
</el-form>
|
</TMagicForm>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import { defineComponent, PropType, provide, reactive, ref, toRaw, watch } from 'vue';
|
import { provide, reactive, ref, toRaw, watch } from 'vue';
|
||||||
import { cloneDeep, isEqual } from 'lodash-es';
|
import cloneDeep from 'lodash-es/cloneDeep';
|
||||||
|
import isEqual from 'lodash-es/isEqual';
|
||||||
|
|
||||||
|
import { TMagicForm } from '@tmagic/design';
|
||||||
|
|
||||||
|
import Container from './containers/Container.vue';
|
||||||
import { getConfig } from './utils/config';
|
import { getConfig } from './utils/config';
|
||||||
import { initValue } from './utils/form';
|
import { initValue } from './utils/form';
|
||||||
import { FormConfig, FormState, FormValue } from './schema';
|
import type { FormConfig, FormState, FormValue, ValidateError } from './schema';
|
||||||
|
|
||||||
interface ValidateError {
|
const props = withDefaults(
|
||||||
message: string;
|
defineProps<{
|
||||||
field: string;
|
config: FormConfig;
|
||||||
}
|
initValues: Object;
|
||||||
|
parentValues?: Object;
|
||||||
export default defineComponent({
|
labelWidth?: string;
|
||||||
name: 'm-form',
|
disabled?: boolean;
|
||||||
|
height?: string;
|
||||||
props: {
|
stepActive?: string | number;
|
||||||
// 表单初始化值
|
size?: 'small' | 'default' | 'large';
|
||||||
initValues: {
|
inline?: boolean;
|
||||||
type: Object,
|
labelPosition?: string;
|
||||||
required: true,
|
keyProp?: string;
|
||||||
default: () => ({}),
|
popperClass?: string;
|
||||||
},
|
}>(),
|
||||||
|
{
|
||||||
parentValues: {
|
config: () => [],
|
||||||
type: Object,
|
initValues: () => ({}),
|
||||||
default: () => ({}),
|
parentValues: () => ({}),
|
||||||
},
|
labelWidth: '200px',
|
||||||
|
disabled: false,
|
||||||
// 表单配置
|
height: 'auto',
|
||||||
config: {
|
stepActive: 1,
|
||||||
type: Array as PropType<FormConfig>,
|
inline: false,
|
||||||
required: true,
|
labelPosition: 'right',
|
||||||
default: () => [],
|
keyProp: '__key',
|
||||||
},
|
|
||||||
|
|
||||||
labelWidth: {
|
|
||||||
type: String,
|
|
||||||
default: () => '200px',
|
|
||||||
},
|
|
||||||
|
|
||||||
disabled: {
|
|
||||||
type: Boolean,
|
|
||||||
default: () => false,
|
|
||||||
},
|
|
||||||
|
|
||||||
height: {
|
|
||||||
type: String,
|
|
||||||
default: () => 'auto',
|
|
||||||
},
|
|
||||||
|
|
||||||
stepActive: {
|
|
||||||
type: [String, Number],
|
|
||||||
default: () => 1,
|
|
||||||
},
|
|
||||||
|
|
||||||
size: {
|
|
||||||
type: String as PropType<'small' | 'default' | 'large'>,
|
|
||||||
},
|
|
||||||
|
|
||||||
inline: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
|
|
||||||
labelPosition: {
|
|
||||||
type: String,
|
|
||||||
default: 'right',
|
|
||||||
},
|
|
||||||
|
|
||||||
keyProp: {
|
|
||||||
type: String,
|
|
||||||
default: '__key',
|
|
||||||
},
|
|
||||||
|
|
||||||
popperClass: {
|
|
||||||
type: String,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
);
|
||||||
|
|
||||||
emits: ['change', 'field-input', 'field-change'],
|
const emit = defineEmits(['change', 'field-input', 'field-change']);
|
||||||
|
|
||||||
setup(props, { emit }) {
|
const tMagicForm = ref<InstanceType<typeof TMagicForm>>();
|
||||||
// InstanceType<typeof ElForm>,构建types的时候会出错
|
const initialized = ref(false);
|
||||||
const elForm = ref<any>();
|
const values = ref<FormValue>({});
|
||||||
const initialized = ref(false);
|
const fields = new Map<string, any>();
|
||||||
const values = ref<FormValue>({});
|
|
||||||
const fields = new Map<string, any>();
|
|
||||||
|
|
||||||
const requestFuc = getConfig('request') as Function;
|
const requestFuc = getConfig('request') as Function;
|
||||||
|
|
||||||
const formState: FormState = reactive<FormState>({
|
const formState: FormState = reactive<FormState>({
|
||||||
keyProp: props.keyProp,
|
keyProp: props.keyProp,
|
||||||
popperClass: props.popperClass,
|
popperClass: props.popperClass,
|
||||||
config: props.config,
|
config: props.config,
|
||||||
|
initValues: props.initValues,
|
||||||
|
parentValues: props.parentValues,
|
||||||
|
values,
|
||||||
|
$emit: emit as (event: string, ...args: any[]) => void,
|
||||||
|
fields,
|
||||||
|
setField: (prop: string, field: any) => fields.set(prop, field),
|
||||||
|
getField: (prop: string) => fields.get(prop),
|
||||||
|
deleteField: (prop: string) => fields.delete(prop),
|
||||||
|
post: (options: any) => {
|
||||||
|
if (requestFuc) {
|
||||||
|
return requestFuc({
|
||||||
|
...options,
|
||||||
|
method: 'POST',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
provide('mForm', formState);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
[() => props.config, () => props.initValues],
|
||||||
|
([config], [preConfig]) => {
|
||||||
|
if (!isEqual(toRaw(config), toRaw(preConfig))) {
|
||||||
|
initialized.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
initValue(formState, {
|
||||||
initValues: props.initValues,
|
initValues: props.initValues,
|
||||||
parentValues: props.parentValues,
|
config: props.config,
|
||||||
values,
|
}).then((value) => {
|
||||||
$emit: emit as (event: string, ...args: any[]) => void,
|
values.value = value;
|
||||||
fields,
|
initialized.value = true;
|
||||||
setField: (prop: string, field: any) => fields.set(prop, field),
|
|
||||||
getField: (prop: string) => fields.get(prop),
|
|
||||||
deleteField: (prop: string) => fields.delete(prop),
|
|
||||||
post: (options: any) => {
|
|
||||||
if (requestFuc) {
|
|
||||||
return requestFuc({
|
|
||||||
...options,
|
|
||||||
method: 'POST',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
);
|
||||||
|
|
||||||
provide('mForm', formState);
|
const changeHandler = () => {
|
||||||
|
emit('change', values.value);
|
||||||
|
};
|
||||||
|
|
||||||
watch(
|
defineExpose({
|
||||||
[() => props.config, () => props.initValues],
|
values,
|
||||||
([config], [preConfig]) => {
|
formState,
|
||||||
if (!isEqual(toRaw(config), toRaw(preConfig))) {
|
initialized,
|
||||||
initialized.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
initValue(formState, {
|
changeHandler,
|
||||||
initValues: props.initValues,
|
|
||||||
config: props.config,
|
resetForm: () => tMagicForm.value?.resetFields(),
|
||||||
}).then((value) => {
|
|
||||||
values.value = value;
|
submitForm: async (native?: boolean): Promise<any> => {
|
||||||
initialized.value = true;
|
try {
|
||||||
|
await tMagicForm.value?.validate();
|
||||||
|
return native ? values.value : cloneDeep(toRaw(values.value));
|
||||||
|
} catch (invalidFields: any) {
|
||||||
|
const error: string[] = [];
|
||||||
|
|
||||||
|
Object.entries(invalidFields).forEach(([, ValidateError]) => {
|
||||||
|
(ValidateError as ValidateError[]).forEach(({ field, message }) => {
|
||||||
|
if (field && message) error.push(`${field} -> ${message}`);
|
||||||
|
if (field && !message) error.push(`${field} -> 出现错误`);
|
||||||
|
if (!field && message) error.push(`${message}`);
|
||||||
});
|
});
|
||||||
},
|
});
|
||||||
{ immediate: true },
|
throw new Error(error.join('<br>'));
|
||||||
);
|
}
|
||||||
|
|
||||||
return {
|
|
||||||
initialized,
|
|
||||||
values,
|
|
||||||
elForm,
|
|
||||||
|
|
||||||
formState,
|
|
||||||
|
|
||||||
changeHandler: () => {
|
|
||||||
emit('change', values.value);
|
|
||||||
},
|
|
||||||
|
|
||||||
resetForm: () => elForm.value?.resetFields(),
|
|
||||||
|
|
||||||
submitForm: async (native?: boolean): Promise<any> => {
|
|
||||||
try {
|
|
||||||
await elForm.value?.validate();
|
|
||||||
return native ? values.value : cloneDeep(toRaw(values.value));
|
|
||||||
} catch (invalidFields: any) {
|
|
||||||
const error: string[] = [];
|
|
||||||
|
|
||||||
Object.entries(invalidFields).forEach(([, ValidateError]) => {
|
|
||||||
(ValidateError as ValidateError[]).forEach(({ field, message }) => {
|
|
||||||
if (field && message) error.push(`${field} -> ${message}`);
|
|
||||||
if (field && !message) error.push(`${field} -> 出现错误`);
|
|
||||||
if (!field && message) error.push(`${message}`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
throw new Error(error.join('<br>'));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog
|
<TMagicDialog
|
||||||
v-model="dialogVisible"
|
v-model="dialogVisible"
|
||||||
class="m-form-dialog"
|
class="m-form-dialog"
|
||||||
top="20px"
|
top="20px"
|
||||||
@ -15,7 +15,7 @@
|
|||||||
class="m-dialog-body"
|
class="m-dialog-body"
|
||||||
:style="`max-height: ${bodyHeight}; overflow-y: auto; overflow-x: hidden;`"
|
:style="`max-height: ${bodyHeight}; overflow-y: auto; overflow-x: hidden;`"
|
||||||
>
|
>
|
||||||
<m-form
|
<Form
|
||||||
v-model="stepActive"
|
v-model="stepActive"
|
||||||
ref="form"
|
ref="form"
|
||||||
:size="size"
|
:size="size"
|
||||||
@ -24,150 +24,128 @@
|
|||||||
:parent-values="parentValues"
|
:parent-values="parentValues"
|
||||||
:label-width="labelWidth"
|
:label-width="labelWidth"
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
></m-form>
|
></Form>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-row class="dialog-footer">
|
<TMagicRow class="dialog-footer">
|
||||||
<el-col :span="12" style="text-align: left">
|
<TMagicCol :span="12" style="text-align: left">
|
||||||
<div style="min-height: 1px">
|
<div style="min-height: 1px">
|
||||||
<slot name="left"></slot>
|
<slot name="left"></slot>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</TMagicCol>
|
||||||
<el-col :span="12">
|
<TMagicCol :span="12">
|
||||||
<slot name="footer">
|
<slot name="footer">
|
||||||
<el-button @click="cancel" size="small">取 消</el-button>
|
<TMagicButton @click="cancel" size="small">取 消</TMagicButton>
|
||||||
<el-button v-if="hasStep && stepActive > 1" type="info" size="small" @click="preStep">上一步</el-button>
|
<TMagicButton v-if="hasStep && stepActive > 1" type="info" size="small" @click="preStep"
|
||||||
<el-button v-if="hasStep && stepCount > stepActive" type="info" size="small" @click="nextStep"
|
>上一步</TMagicButton
|
||||||
>下一步</el-button
|
|
||||||
>
|
>
|
||||||
<el-button v-else type="primary" size="small" :loading="saveFetch" @click="save">{{
|
<TMagicButton v-if="hasStep && stepCount > stepActive" type="info" size="small" @click="nextStep"
|
||||||
|
>下一步</TMagicButton
|
||||||
|
>
|
||||||
|
<TMagicButton v-else type="primary" size="small" :loading="saveFetch" @click="save">{{
|
||||||
confirmText
|
confirmText
|
||||||
}}</el-button>
|
}}</TMagicButton>
|
||||||
</slot>
|
</slot>
|
||||||
</el-col>
|
</TMagicCol>
|
||||||
</el-row>
|
</TMagicRow>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</TMagicDialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, defineComponent, PropType, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
|
|
||||||
|
import { TMagicButton, TMagicCol, TMagicDialog, TMagicRow } from '@tmagic/design';
|
||||||
|
|
||||||
import Form from './Form.vue';
|
import Form from './Form.vue';
|
||||||
import { FormConfig, StepConfig } from './schema';
|
import { FormConfig, StepConfig } from './schema';
|
||||||
|
|
||||||
export default defineComponent({
|
const props = withDefaults(
|
||||||
name: 'm-form-dialog',
|
defineProps<{
|
||||||
|
config?: FormConfig;
|
||||||
props: {
|
values?: Object;
|
||||||
values: {
|
parentValues?: Object;
|
||||||
type: Object,
|
width?: string | number;
|
||||||
default: () => ({}),
|
labelWidth?: string;
|
||||||
},
|
fullscreen?: boolean;
|
||||||
|
title?: string;
|
||||||
parentValues: {
|
size?: 'small' | 'default' | 'large';
|
||||||
type: Object,
|
confirmText?: string;
|
||||||
},
|
}>(),
|
||||||
|
{
|
||||||
width: [Number, String],
|
config: () => [],
|
||||||
|
values: () => ({}),
|
||||||
fullscreen: Boolean,
|
confirmText: '确定',
|
||||||
|
|
||||||
title: String,
|
|
||||||
|
|
||||||
config: {
|
|
||||||
type: Array as PropType<FormConfig>,
|
|
||||||
required: true,
|
|
||||||
default: () => [],
|
|
||||||
},
|
|
||||||
|
|
||||||
labelWidth: [Number, String],
|
|
||||||
|
|
||||||
size: String as PropType<'small' | 'default' | 'large'>,
|
|
||||||
|
|
||||||
confirmText: {
|
|
||||||
type: String,
|
|
||||||
default: '确定',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
);
|
||||||
|
|
||||||
emits: ['close', 'submit', 'error', 'change'],
|
const emit = defineEmits(['close', 'submit', 'error', 'change']);
|
||||||
|
|
||||||
setup(props, { emit }) {
|
const form = ref<InstanceType<typeof Form>>();
|
||||||
const form = ref<InstanceType<typeof Form>>();
|
const dialogVisible = ref(false);
|
||||||
const dialogVisible = ref(false);
|
const saveFetch = ref(false);
|
||||||
const saveFetch = ref(false);
|
const stepActive = ref(1);
|
||||||
const stepActive = ref(1);
|
const bodyHeight = ref(`${document.body.clientHeight - 194}px`);
|
||||||
const bodyHeight = ref(`${document.body.clientHeight - 194}px`);
|
|
||||||
|
|
||||||
const stepCount = computed(() => {
|
const stepCount = computed(() => {
|
||||||
const { length } = props.config;
|
const { length } = props.config;
|
||||||
for (let index = 0; index < length; index++) {
|
for (let index = 0; index < length; index++) {
|
||||||
if (props.config[index].type === 'step') {
|
if (props.config[index].type === 'step') {
|
||||||
return (props.config[index] as StepConfig).items.length;
|
return (props.config[index] as StepConfig).items.length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
const hasStep = computed(() => {
|
const hasStep = computed(() => {
|
||||||
const { length } = props.config;
|
const { length } = props.config;
|
||||||
for (let index = 0; index < length; index++) {
|
for (let index = 0; index < length; index++) {
|
||||||
if (props.config[index].type === 'step') {
|
if (props.config[index].type === 'step') {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
const cancel = () => {
|
const cancel = () => {
|
||||||
dialogVisible.value = false;
|
dialogVisible.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const closeHandler = () => {
|
const closeHandler = () => {
|
||||||
stepActive.value = 1;
|
stepActive.value = 1;
|
||||||
emit('close');
|
emit('close');
|
||||||
};
|
};
|
||||||
|
|
||||||
const save = async () => {
|
const save = async () => {
|
||||||
try {
|
try {
|
||||||
const values = await form.value?.submitForm();
|
const values = await form.value?.submitForm();
|
||||||
emit('submit', values);
|
emit('submit', values);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit('error', e);
|
emit('error', e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const preStep = () => {
|
const preStep = () => {
|
||||||
stepActive.value -= 1;
|
stepActive.value -= 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
const nextStep = () => {
|
const nextStep = () => {
|
||||||
stepActive.value += 1;
|
stepActive.value += 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
const changeHandler = (value: any) => {
|
const changeHandler = (value: any) => {
|
||||||
emit('change', value);
|
emit('change', value);
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
defineExpose({
|
||||||
form,
|
form,
|
||||||
saveFetch,
|
saveFetch,
|
||||||
stepActive,
|
dialogVisible,
|
||||||
dialogVisible,
|
|
||||||
bodyHeight,
|
cancel,
|
||||||
stepCount,
|
save,
|
||||||
hasStep,
|
|
||||||
cancel,
|
|
||||||
closeHandler,
|
|
||||||
save,
|
|
||||||
preStep,
|
|
||||||
nextStep,
|
|
||||||
changeHandler,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-col v-show="display && config.type !== 'hidden'" :span="span">
|
<TMagicCol v-show="display && config.type !== 'hidden'" :span="span">
|
||||||
<m-form-container
|
<Container
|
||||||
:model="model"
|
:model="model"
|
||||||
:config="config"
|
:config="config"
|
||||||
:prop="prop"
|
:prop="prop"
|
||||||
@ -8,49 +8,33 @@
|
|||||||
:expand-more="expandMore"
|
:expand-more="expandMore"
|
||||||
:size="size"
|
:size="size"
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
></m-form-container>
|
></Container>
|
||||||
</el-col>
|
</TMagicCol>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, defineComponent, inject, PropType } from 'vue';
|
import { computed, inject } from 'vue';
|
||||||
|
|
||||||
|
import { TMagicCol } from '@tmagic/design';
|
||||||
|
|
||||||
import { ChildConfig, FormState } from '../schema';
|
import { ChildConfig, FormState } from '../schema';
|
||||||
import { display as displayFunction } from '../utils/form';
|
import { display as displayFunction } from '../utils/form';
|
||||||
|
|
||||||
export default defineComponent({
|
import Container from './Container.vue';
|
||||||
props: {
|
|
||||||
labelWidth: String,
|
|
||||||
expandMore: Boolean,
|
|
||||||
span: Number,
|
|
||||||
|
|
||||||
model: {
|
const props = defineProps<{
|
||||||
type: Object,
|
model: any;
|
||||||
default: () => ({}),
|
config: ChildConfig;
|
||||||
},
|
labelWidth?: string;
|
||||||
|
expandMore?: boolean;
|
||||||
|
span?: number;
|
||||||
|
size?: string;
|
||||||
|
prop?: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
config: {
|
const emit = defineEmits(['change']);
|
||||||
type: Object as PropType<ChildConfig>,
|
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
|
|
||||||
prop: String,
|
const mForm = inject<FormState | undefined>('mForm');
|
||||||
|
const display = computed(() => displayFunction(mForm, props.config.display, props));
|
||||||
size: String,
|
const changeHandler = () => emit('change', props.model);
|
||||||
},
|
|
||||||
|
|
||||||
emits: ['change'],
|
|
||||||
|
|
||||||
setup(props, { emit }) {
|
|
||||||
const mForm = inject<FormState | undefined>('mForm');
|
|
||||||
|
|
||||||
const changeHandler = () => emit('change', props.model);
|
|
||||||
|
|
||||||
return {
|
|
||||||
mForm,
|
|
||||||
display: computed(() => displayFunction(mForm, props.config.display, props)),
|
|
||||||
changeHandler,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
></component>
|
></component>
|
||||||
|
|
||||||
<template v-else-if="type && display">
|
<template v-else-if="type && display">
|
||||||
<el-form-item
|
<TMagicFormItem
|
||||||
:style="config.tip ? 'flex: 1' : ''"
|
:style="config.tip ? 'flex: 1' : ''"
|
||||||
:class="{ hidden: `${itemLabelWidth}` === '0' || !config.text }"
|
:class="{ hidden: `${itemLabelWidth}` === '0' || !config.text }"
|
||||||
:prop="itemProp"
|
:prop="itemProp"
|
||||||
@ -38,7 +38,7 @@
|
|||||||
:rules="rule"
|
:rules="rule"
|
||||||
>
|
>
|
||||||
<template #label><span v-html="type === 'checkbox' ? '' : config.text"></span></template>
|
<template #label><span v-html="type === 'checkbox' ? '' : config.text"></span></template>
|
||||||
<el-tooltip v-if="tooltip">
|
<TMagicTooltip v-if="tooltip">
|
||||||
<component
|
<component
|
||||||
:key="key(config)"
|
:key="key(config)"
|
||||||
:size="size"
|
:size="size"
|
||||||
@ -53,7 +53,7 @@
|
|||||||
<template #content>
|
<template #content>
|
||||||
<div v-html="tooltip"></div>
|
<div v-html="tooltip"></div>
|
||||||
</template>
|
</template>
|
||||||
</el-tooltip>
|
</TMagicTooltip>
|
||||||
|
|
||||||
<component
|
<component
|
||||||
v-else
|
v-else
|
||||||
@ -69,19 +69,19 @@
|
|||||||
></component>
|
></component>
|
||||||
|
|
||||||
<div v-if="extra" v-html="extra" class="m-form-tip"></div>
|
<div v-if="extra" v-html="extra" class="m-form-tip"></div>
|
||||||
</el-form-item>
|
</TMagicFormItem>
|
||||||
|
|
||||||
<el-tooltip v-if="config.tip" placement="left">
|
<TMagicTooltip v-if="config.tip" placement="left">
|
||||||
<el-icon style="line-height: 40px; margin-left: 5px"><warning-filled /></el-icon>
|
<TMagicIcon style="line-height: 40px; margin-left: 5px"><warning-filled /></TMagicIcon>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div v-html="config.tip"></div>
|
<div v-html="config.tip"></div>
|
||||||
</template>
|
</template>
|
||||||
</el-tooltip>
|
</TMagicTooltip>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else-if="items && display">
|
<template v-else-if="items && display">
|
||||||
<template v-if="name || name === 0 ? model[name] : model">
|
<template v-if="name || name === 0 ? model[name] : model">
|
||||||
<m-form-container
|
<Container
|
||||||
v-for="item in items"
|
v-for="item in items"
|
||||||
:key="key(item)"
|
:key="key(item)"
|
||||||
:model="name || name === 0 ? model[name] : model"
|
:model="name || name === 0 ? model[name] : model"
|
||||||
@ -92,202 +92,166 @@
|
|||||||
:label-width="itemLabelWidth"
|
:label-width="itemLabelWidth"
|
||||||
:prop="itemProp"
|
:prop="itemProp"
|
||||||
@change="onChangeHandler"
|
@change="onChangeHandler"
|
||||||
></m-form-container>
|
></Container>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div style="text-align: center" v-if="config.expand && type !== 'fieldset'">
|
<div style="text-align: center" v-if="config.expand && type !== 'fieldset'">
|
||||||
<el-button text @click="expandHandler">{{ expand ? '收起配置' : '展开更多配置' }}</el-button>
|
<TMagicButton text @click="expandHandler">{{ expand ? '收起配置' : '展开更多配置' }}</TMagicButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, defineComponent, inject, PropType, ref, resolveComponent, watchEffect } from 'vue';
|
import { computed, inject, ref, resolveComponent, watchEffect } from 'vue';
|
||||||
import { WarningFilled } from '@element-plus/icons-vue';
|
import { WarningFilled } from '@element-plus/icons-vue';
|
||||||
|
|
||||||
|
import { TMagicButton, TMagicFormItem, TMagicIcon, TMagicTooltip } from '@tmagic/design';
|
||||||
|
|
||||||
import { ChildConfig, ContainerCommonConfig, FormState, FormValue } from '../schema';
|
import { ChildConfig, ContainerCommonConfig, FormState, FormValue } from '../schema';
|
||||||
import { display as displayFunction, filterFunction, getRules } from '../utils/form';
|
import { display as displayFunction, filterFunction, getRules } from '../utils/form';
|
||||||
|
|
||||||
export default defineComponent({
|
const props = withDefaults(
|
||||||
name: 'm-form-container',
|
defineProps<{
|
||||||
|
model: FormValue;
|
||||||
components: { WarningFilled },
|
config: ChildConfig;
|
||||||
|
prop?: string;
|
||||||
props: {
|
labelWidth?: string;
|
||||||
labelWidth: String,
|
expandMore?: boolean;
|
||||||
expandMore: Boolean,
|
stepActive?: string | number;
|
||||||
|
size?: string;
|
||||||
model: {
|
}>(),
|
||||||
type: [Object, Array] as PropType<FormValue>,
|
{
|
||||||
required: true,
|
prop: '',
|
||||||
},
|
size: 'small',
|
||||||
|
expandMore: false,
|
||||||
config: {
|
|
||||||
type: Object as PropType<ChildConfig>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
prop: {
|
|
||||||
type: String,
|
|
||||||
default: () => '',
|
|
||||||
},
|
|
||||||
|
|
||||||
stepActive: {
|
|
||||||
type: [String, Number],
|
|
||||||
},
|
|
||||||
|
|
||||||
size: {
|
|
||||||
type: String,
|
|
||||||
default: 'small',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
);
|
||||||
|
|
||||||
emits: ['change'],
|
const emit = defineEmits(['change']);
|
||||||
|
|
||||||
setup(props, { emit }) {
|
const mForm = inject<FormState | undefined>('mForm');
|
||||||
const mForm = inject<FormState | undefined>('mForm');
|
|
||||||
|
|
||||||
const expand = ref(false);
|
const expand = ref(false);
|
||||||
|
|
||||||
const name = computed(() => props.config.name || '');
|
const name = computed(() => props.config.name || '');
|
||||||
|
|
||||||
const items = computed(() => (props.config as ContainerCommonConfig).items);
|
const items = computed(() => (props.config as ContainerCommonConfig).items);
|
||||||
|
|
||||||
const itemProp = computed(() => {
|
const itemProp = computed(() => {
|
||||||
let n: string | number = '';
|
let n: string | number = '';
|
||||||
const { names } = props.config as any;
|
const { names } = props.config as any;
|
||||||
if (names?.[0]) {
|
if (names?.[0]) {
|
||||||
[n] = names;
|
[n] = names;
|
||||||
} else if (name.value) {
|
} else if (name.value) {
|
||||||
n = name.value;
|
n = name.value;
|
||||||
} else {
|
} else {
|
||||||
return props.prop;
|
return props.prop;
|
||||||
}
|
}
|
||||||
return `${props.prop}${props.prop ? '.' : ''}${n}`;
|
return `${props.prop}${props.prop ? '.' : ''}${n}`;
|
||||||
});
|
|
||||||
|
|
||||||
const tagName = computed(() => {
|
|
||||||
const component = resolveComponent(`m-${items.value ? 'form' : 'fields'}-${type.value}`);
|
|
||||||
if (typeof component !== 'string') return component;
|
|
||||||
return 'm-fields-text';
|
|
||||||
});
|
|
||||||
|
|
||||||
const disabled = computed(() => filterFunction(mForm, props.config.disabled, props));
|
|
||||||
|
|
||||||
const tooltip = computed(() => filterFunction(mForm, props.config.tooltip, props));
|
|
||||||
|
|
||||||
const extra = computed(() => filterFunction(mForm, props.config.extra, props));
|
|
||||||
|
|
||||||
const rule = computed(() => getRules(mForm, props.config.rules, props));
|
|
||||||
|
|
||||||
const type = computed((): string => {
|
|
||||||
let { type } = props.config;
|
|
||||||
if (typeof type === 'function') {
|
|
||||||
type = type(mForm, {
|
|
||||||
model: props.model,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (type === 'form') return '';
|
|
||||||
return type?.replace(/([A-Z])/g, '-$1').toLowerCase() || (items.value ? '' : 'text');
|
|
||||||
});
|
|
||||||
|
|
||||||
const display = computed((): boolean => {
|
|
||||||
if (props.config.display === 'expand') {
|
|
||||||
return expand.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return displayFunction(mForm, props.config.display, props);
|
|
||||||
});
|
|
||||||
|
|
||||||
const itemLabelWidth = computed(() => props.config.labelWidth || props.labelWidth);
|
|
||||||
|
|
||||||
watchEffect(() => {
|
|
||||||
expand.value = props.expandMore;
|
|
||||||
});
|
|
||||||
|
|
||||||
const expandHandler = () => (expand.value = !expand.value);
|
|
||||||
|
|
||||||
const key = (config: any) => config[mForm?.keyProps];
|
|
||||||
|
|
||||||
const filterHandler = (filter: any, value: FormValue | number | string) => {
|
|
||||||
if (typeof filter === 'function') {
|
|
||||||
return filter(mForm, value, {
|
|
||||||
model: props.model,
|
|
||||||
values: mForm?.initValues,
|
|
||||||
formValue: mForm?.values,
|
|
||||||
prop: itemProp.value,
|
|
||||||
config: props.config,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter === 'number') {
|
|
||||||
return +value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
};
|
|
||||||
|
|
||||||
const changeHandler = (onChange: any, value: FormValue | number | string) => {
|
|
||||||
if (typeof onChange === 'function') {
|
|
||||||
return onChange(mForm, value, {
|
|
||||||
model: props.model,
|
|
||||||
values: mForm?.initValues,
|
|
||||||
formValue: mForm?.values,
|
|
||||||
prop: itemProp.value,
|
|
||||||
config: props.config,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const trimHandler = (trim: any, value: FormValue | number | string) => {
|
|
||||||
if (typeof value === 'string' && trim) {
|
|
||||||
return value.replace(/^\s*/, '').replace(/\s*$/, '');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onChangeHandler = async function (v: FormValue, key?: string) {
|
|
||||||
const { filter, onChange, trim, name, dynamicKey } = props.config as any;
|
|
||||||
let value: FormValue | number | string = v;
|
|
||||||
|
|
||||||
try {
|
|
||||||
value = filterHandler(filter, v);
|
|
||||||
value = (await changeHandler(onChange, value)) ?? value;
|
|
||||||
value = trimHandler(trim, value) ?? value;
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// field内容下包含field-link时,model===value, 这里避免循环引用
|
|
||||||
if ((name || name === 0) && props.model !== value && (v !== value || props.model[name] !== value)) {
|
|
||||||
// eslint-disable-next-line vue/no-mutating-props
|
|
||||||
props.model[name] = value;
|
|
||||||
}
|
|
||||||
// 动态表单类型,根据value和key参数,直接修改model
|
|
||||||
if (key !== undefined && dynamicKey) {
|
|
||||||
// eslint-disable-next-line vue/no-mutating-props
|
|
||||||
props.model[key] = value;
|
|
||||||
}
|
|
||||||
emit('change', props.model);
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
expand,
|
|
||||||
name,
|
|
||||||
type,
|
|
||||||
disabled,
|
|
||||||
itemProp,
|
|
||||||
items,
|
|
||||||
display,
|
|
||||||
itemLabelWidth,
|
|
||||||
tagName,
|
|
||||||
rule,
|
|
||||||
tooltip,
|
|
||||||
extra,
|
|
||||||
key,
|
|
||||||
onChangeHandler,
|
|
||||||
expandHandler,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const tagName = computed(() => {
|
||||||
|
const component = resolveComponent(`m-${items.value ? 'form' : 'fields'}-${type.value}`);
|
||||||
|
if (typeof component !== 'string') return component;
|
||||||
|
return 'm-fields-text';
|
||||||
|
});
|
||||||
|
|
||||||
|
const disabled = computed(() => filterFunction(mForm, props.config.disabled, props));
|
||||||
|
|
||||||
|
const tooltip = computed(() => filterFunction(mForm, props.config.tooltip, props));
|
||||||
|
|
||||||
|
const extra = computed(() => filterFunction(mForm, props.config.extra, props));
|
||||||
|
|
||||||
|
const rule = computed(() => getRules(mForm, props.config.rules, props));
|
||||||
|
|
||||||
|
const type = computed((): string => {
|
||||||
|
let { type } = props.config;
|
||||||
|
if (typeof type === 'function') {
|
||||||
|
type = type(mForm, {
|
||||||
|
model: props.model,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (type === 'form') return '';
|
||||||
|
return type?.replace(/([A-Z])/g, '-$1').toLowerCase() || (items.value ? '' : 'text');
|
||||||
|
});
|
||||||
|
|
||||||
|
const display = computed((): boolean => {
|
||||||
|
if (props.config.display === 'expand') {
|
||||||
|
return expand.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return displayFunction(mForm, props.config.display, props);
|
||||||
|
});
|
||||||
|
|
||||||
|
const itemLabelWidth = computed(() => props.config.labelWidth || props.labelWidth);
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
expand.value = props.expandMore;
|
||||||
|
});
|
||||||
|
|
||||||
|
const expandHandler = () => (expand.value = !expand.value);
|
||||||
|
|
||||||
|
const key = (config: any) => config[mForm?.keyProps];
|
||||||
|
|
||||||
|
const filterHandler = (filter: any, value: FormValue | number | string) => {
|
||||||
|
if (typeof filter === 'function') {
|
||||||
|
return filter(mForm, value, {
|
||||||
|
model: props.model,
|
||||||
|
values: mForm?.initValues,
|
||||||
|
formValue: mForm?.values,
|
||||||
|
prop: itemProp.value,
|
||||||
|
config: props.config,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter === 'number') {
|
||||||
|
return +value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const changeHandler = (onChange: any, value: FormValue | number | string) => {
|
||||||
|
if (typeof onChange === 'function') {
|
||||||
|
return onChange(mForm, value, {
|
||||||
|
model: props.model,
|
||||||
|
values: mForm?.initValues,
|
||||||
|
formValue: mForm?.values,
|
||||||
|
prop: itemProp.value,
|
||||||
|
config: props.config,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const trimHandler = (trim: any, value: FormValue | number | string) => {
|
||||||
|
if (typeof value === 'string' && trim) {
|
||||||
|
return value.replace(/^\s*/, '').replace(/\s*$/, '');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChangeHandler = async function (v: FormValue, key?: string) {
|
||||||
|
const { filter, onChange, trim, name, dynamicKey } = props.config as any;
|
||||||
|
let value: FormValue | number | string = v;
|
||||||
|
|
||||||
|
try {
|
||||||
|
value = filterHandler(filter, v);
|
||||||
|
value = (await changeHandler(onChange, value)) ?? value;
|
||||||
|
value = trimHandler(trim, value) ?? value;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// field内容下包含field-link时,model===value, 这里避免循环引用
|
||||||
|
if ((name || name === 0) && props.model !== value && (v !== value || props.model[name] !== value)) {
|
||||||
|
// eslint-disable-next-line vue/no-mutating-props
|
||||||
|
props.model[name] = value;
|
||||||
|
}
|
||||||
|
// 动态表单类型,根据value和key参数,直接修改model
|
||||||
|
if (key !== undefined && dynamicKey) {
|
||||||
|
// eslint-disable-next-line vue/no-mutating-props
|
||||||
|
props.model[key] = value;
|
||||||
|
}
|
||||||
|
emit('change', props.model);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -5,13 +5,13 @@
|
|||||||
:style="show ? 'padding: 15px 15px 0 5px;' : 'border: 0'"
|
:style="show ? 'padding: 15px 15px 0 5px;' : 'border: 0'"
|
||||||
>
|
>
|
||||||
<component v-if="name && config.checkbox" :is="!show ? 'div' : 'legend'">
|
<component v-if="name && config.checkbox" :is="!show ? 'div' : 'legend'">
|
||||||
<el-checkbox
|
<TMagicCheckbox
|
||||||
v-model="model[name].value"
|
v-model="model[name].value"
|
||||||
:prop="`${prop}${prop ? '.' : ''}${config.name}.value`"
|
:prop="`${prop}${prop ? '.' : ''}${config.name}.value`"
|
||||||
:true-label="1"
|
:true-label="1"
|
||||||
:false-label="0"
|
:false-label="0"
|
||||||
><span v-html="config.legend"></span><span v-if="config.extra" v-html="config.extra" class="m-form-tip"></span
|
><span v-html="config.legend"></span><span v-if="config.extra" v-html="config.extra" class="m-form-tip"></span
|
||||||
></el-checkbox>
|
></TMagicCheckbox>
|
||||||
</component>
|
</component>
|
||||||
<legend v-else>
|
<legend v-else>
|
||||||
<span v-html="config.legend"></span>
|
<span v-html="config.legend"></span>
|
||||||
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
<div v-if="config.schematic && show" style="display: flex">
|
<div v-if="config.schematic && show" style="display: flex">
|
||||||
<div style="flex: 1">
|
<div style="flex: 1">
|
||||||
<m-form-container
|
<Container
|
||||||
v-for="(item, index) in config.items"
|
v-for="(item, index) in config.items"
|
||||||
:key="key(item, index)"
|
:key="key(item, index)"
|
||||||
:model="name ? model[name] : model"
|
:model="name ? model[name] : model"
|
||||||
@ -30,14 +30,14 @@
|
|||||||
:labelWidth="lWidth"
|
:labelWidth="lWidth"
|
||||||
:size="size"
|
:size="size"
|
||||||
@change="change"
|
@change="change"
|
||||||
></m-form-container>
|
></Container>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<img class="m-form-schematic" :src="config.schematic" />
|
<img class="m-form-schematic" :src="config.schematic" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template v-else-if="show">
|
<template v-else-if="show">
|
||||||
<m-form-container
|
<Container
|
||||||
v-for="(item, index) in config.items"
|
v-for="(item, index) in config.items"
|
||||||
:key="key(item, index)"
|
:key="key(item, index)"
|
||||||
:model="name ? model[name] : model"
|
:model="name ? model[name] : model"
|
||||||
@ -47,7 +47,7 @@
|
|||||||
:labelWidth="lWidth"
|
:labelWidth="lWidth"
|
||||||
:size="size"
|
:size="size"
|
||||||
@change="change"
|
@change="change"
|
||||||
></m-form-container>
|
></Container>
|
||||||
</template>
|
</template>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</template>
|
</template>
|
||||||
@ -55,8 +55,12 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, inject, watch } from 'vue';
|
import { computed, inject, watch } from 'vue';
|
||||||
|
|
||||||
|
import { TMagicCheckbox } from '@tmagic/design';
|
||||||
|
|
||||||
import { FieldsetConfig, FormState } from '../schema';
|
import { FieldsetConfig, FormState } from '../schema';
|
||||||
|
|
||||||
|
import Container from './Container.vue';
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
labelWidth?: string;
|
labelWidth?: string;
|
||||||
@ -89,7 +93,7 @@ const lWidth = computed(() => {
|
|||||||
if (props.config.items) {
|
if (props.config.items) {
|
||||||
return props.config.labelWidth || props.labelWidth;
|
return props.config.labelWidth || props.labelWidth;
|
||||||
}
|
}
|
||||||
return props.config.labelWidth || props.labelWidth || (props.config.text ? null : '0');
|
return props.config.labelWidth || props.labelWidth || (props.config.text ? undefined : '0');
|
||||||
});
|
});
|
||||||
|
|
||||||
const change = () => {
|
const change = () => {
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<span class="el-table__empty-text">暂无数据</span>
|
<span class="el-table__empty-text">暂无数据</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<m-fields-group-list-item
|
<MFieldsGroupListItem
|
||||||
v-else
|
v-else
|
||||||
v-for="(item, index) in model[name]"
|
v-for="(item, index) in model[name]"
|
||||||
:key="index"
|
:key="index"
|
||||||
@ -19,138 +19,106 @@
|
|||||||
@remove-item="removeHandler"
|
@remove-item="removeHandler"
|
||||||
@swap-item="swapHandler"
|
@swap-item="swapHandler"
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
></m-fields-group-list-item>
|
></MFieldsGroupListItem>
|
||||||
|
|
||||||
<el-button @click="addHandler" size="small" v-if="addable">添加组</el-button>
|
<TMagicButton @click="addHandler" size="small" v-if="addable">添加组</TMagicButton>
|
||||||
|
|
||||||
<el-button :icon="Grid" size="small" @click="toggleMode" v-if="config.enableToggleMode">切换为表格</el-button>
|
<TMagicButton :icon="Grid" size="small" @click="toggleMode" v-if="config.enableToggleMode">切换为表格</TMagicButton>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, defineComponent, inject, PropType } from 'vue';
|
import { computed, inject } from 'vue';
|
||||||
import { Grid } from '@element-plus/icons-vue';
|
import { Grid } from '@element-plus/icons-vue';
|
||||||
|
|
||||||
|
import { TMagicButton } from '@tmagic/design';
|
||||||
|
|
||||||
import { FormState, GroupListConfig } from '../schema';
|
import { FormState, GroupListConfig } from '../schema';
|
||||||
import { initValue } from '../utils/form';
|
import { initValue } from '../utils/form';
|
||||||
|
|
||||||
import MFieldsGroupListItem from './GroupListItem.vue';
|
import MFieldsGroupListItem from './GroupListItem.vue';
|
||||||
|
|
||||||
export default defineComponent({
|
const props = defineProps<{
|
||||||
name: 'm-form-group-list',
|
model: any;
|
||||||
|
config: GroupListConfig;
|
||||||
|
name: string;
|
||||||
|
labelWidth?: string;
|
||||||
|
prop?: string;
|
||||||
|
size?: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
components: { MFieldsGroupListItem },
|
const emit = defineEmits(['change']);
|
||||||
|
|
||||||
props: {
|
const mForm = inject<FormState | undefined>('mForm');
|
||||||
labelWidth: String,
|
|
||||||
|
|
||||||
model: {
|
const addable = computed(() => {
|
||||||
type: Object,
|
if (!props.name) return false;
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
|
|
||||||
config: {
|
if (typeof props.config.addable === 'function') {
|
||||||
type: Object as PropType<GroupListConfig>,
|
return props.config.addable(mForm, {
|
||||||
default: () => ({}),
|
model: props.model[props.name],
|
||||||
},
|
formValue: mForm?.values,
|
||||||
|
prop: props.prop,
|
||||||
prop: {
|
config: props.config,
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
|
|
||||||
size: String,
|
|
||||||
|
|
||||||
name: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
emits: ['change'],
|
|
||||||
|
|
||||||
setup(props, { emit }) {
|
|
||||||
const mForm = inject<FormState | undefined>('mForm');
|
|
||||||
|
|
||||||
const addable = computed(() => {
|
|
||||||
if (!props.name) return false;
|
|
||||||
|
|
||||||
if (typeof props.config.addable === 'function') {
|
|
||||||
return props.config.addable(mForm, {
|
|
||||||
model: props.model[props.name],
|
|
||||||
formValue: mForm?.values,
|
|
||||||
prop: props.prop,
|
|
||||||
config: props.config,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return typeof props.config.addable === 'undefined' ? true : props.config.addable;
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const changeHandler = () => {
|
return typeof props.config.addable === 'undefined' ? true : props.config.addable;
|
||||||
if (!props.name) return false;
|
|
||||||
|
|
||||||
emit('change', props.model[props.name]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const addHandler = async () => {
|
|
||||||
if (!props.name) return false;
|
|
||||||
|
|
||||||
let initValues = {};
|
|
||||||
|
|
||||||
if (typeof props.config.defaultAdd === 'function') {
|
|
||||||
initValues = await props.config.defaultAdd(mForm, {
|
|
||||||
model: props.model[props.name],
|
|
||||||
formValue: mForm?.values,
|
|
||||||
prop: props.prop,
|
|
||||||
config: props.config,
|
|
||||||
});
|
|
||||||
} else if (props.config.defaultAdd) {
|
|
||||||
initValues = props.config.defaultAdd;
|
|
||||||
}
|
|
||||||
|
|
||||||
const groupValue = await initValue(mForm, {
|
|
||||||
config: props.config.items,
|
|
||||||
initValues,
|
|
||||||
});
|
|
||||||
|
|
||||||
props.model[props.name].push(groupValue);
|
|
||||||
};
|
|
||||||
|
|
||||||
const removeHandler = (index: number) => {
|
|
||||||
if (!props.name) return false;
|
|
||||||
|
|
||||||
props.model[props.name].splice(index, 1);
|
|
||||||
changeHandler();
|
|
||||||
};
|
|
||||||
|
|
||||||
const swapHandler = (idx1: number, idx2: number) => {
|
|
||||||
if (!props.name) return false;
|
|
||||||
|
|
||||||
const [currRow] = props.model[props.name].splice(idx1, 1);
|
|
||||||
props.model[props.name].splice(idx2, 0, currRow);
|
|
||||||
changeHandler();
|
|
||||||
};
|
|
||||||
|
|
||||||
const toggleMode = () => {
|
|
||||||
props.config.type = 'table';
|
|
||||||
props.config.groupItems = props.config.items;
|
|
||||||
props.config.items = (props.config.tableItems ||
|
|
||||||
props.config.items.map((item: any) => ({
|
|
||||||
...item,
|
|
||||||
label: item.label || item.text,
|
|
||||||
text: null,
|
|
||||||
}))) as any;
|
|
||||||
};
|
|
||||||
return {
|
|
||||||
Grid,
|
|
||||||
addable,
|
|
||||||
toggleMode,
|
|
||||||
removeHandler,
|
|
||||||
swapHandler,
|
|
||||||
changeHandler,
|
|
||||||
addHandler,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const changeHandler = () => {
|
||||||
|
if (!props.name) return false;
|
||||||
|
|
||||||
|
emit('change', props.model[props.name]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addHandler = async () => {
|
||||||
|
if (!props.name) return false;
|
||||||
|
|
||||||
|
let initValues = {};
|
||||||
|
|
||||||
|
if (typeof props.config.defaultAdd === 'function') {
|
||||||
|
initValues = await props.config.defaultAdd(mForm, {
|
||||||
|
model: props.model[props.name],
|
||||||
|
formValue: mForm?.values,
|
||||||
|
prop: props.prop,
|
||||||
|
config: props.config,
|
||||||
|
});
|
||||||
|
} else if (props.config.defaultAdd) {
|
||||||
|
initValues = props.config.defaultAdd;
|
||||||
|
}
|
||||||
|
|
||||||
|
const groupValue = await initValue(mForm, {
|
||||||
|
config: props.config.items,
|
||||||
|
initValues,
|
||||||
|
});
|
||||||
|
|
||||||
|
props.model[props.name].push(groupValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeHandler = (index: number) => {
|
||||||
|
if (!props.name) return false;
|
||||||
|
|
||||||
|
props.model[props.name].splice(index, 1);
|
||||||
|
changeHandler();
|
||||||
|
};
|
||||||
|
|
||||||
|
const swapHandler = (idx1: number, idx2: number) => {
|
||||||
|
if (!props.name) return false;
|
||||||
|
|
||||||
|
const [currRow] = props.model[props.name].splice(idx1, 1);
|
||||||
|
props.model[props.name].splice(idx2, 0, currRow);
|
||||||
|
changeHandler();
|
||||||
|
};
|
||||||
|
|
||||||
|
const toggleMode = () => {
|
||||||
|
props.config.type = 'table';
|
||||||
|
props.config.groupItems = props.config.items;
|
||||||
|
props.config.items = (props.config.tableItems ||
|
||||||
|
props.config.items.map((item: any) => ({
|
||||||
|
...item,
|
||||||
|
label: item.label || item.text,
|
||||||
|
text: null,
|
||||||
|
}))) as any;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,33 +1,33 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="m-fields-group-list-item">
|
<div class="m-fields-group-list-item">
|
||||||
<div>
|
<div>
|
||||||
<el-icon style="margin-right: 7px" @click="expandHandler"
|
<TMagicIcon style="margin-right: 7px" @click="expandHandler"
|
||||||
><CaretBottom v-if="expand" /><CaretRight v-else
|
><CaretBottom v-if="expand" /><CaretRight v-else
|
||||||
/></el-icon>
|
/></TMagicIcon>
|
||||||
|
|
||||||
<el-button text @click="expandHandler">{{ title }}</el-button>
|
<TMagicButton text @click="expandHandler">{{ title }}</TMagicButton>
|
||||||
|
|
||||||
<el-button
|
<TMagicButton
|
||||||
v-show="showDelete(parseInt(String(index)))"
|
v-show="showDelete(parseInt(String(index)))"
|
||||||
text
|
text
|
||||||
:icon="Delete"
|
:icon="Delete"
|
||||||
style="color: #f56c6c"
|
style="color: #f56c6c"
|
||||||
@click="removeHandler"
|
@click="removeHandler"
|
||||||
></el-button>
|
></TMagicButton>
|
||||||
|
|
||||||
<template v-if="movable()">
|
<template v-if="movable()">
|
||||||
<el-button v-show="index !== 0" text size="small" @click="changeOrder(-1)"
|
<TMagicButton v-show="index !== 0" text size="small" @click="changeOrder(-1)"
|
||||||
>上移<el-icon><CaretTop /></el-icon
|
>上移<TMagicIcon><CaretTop /></TMagicIcon
|
||||||
></el-button>
|
></TMagicButton>
|
||||||
<el-button v-show="index !== length - 1" text size="small" @click="changeOrder(1)"
|
<TMagicButton v-show="index !== length - 1" text size="small" @click="changeOrder(1)"
|
||||||
>下移<el-icon><CaretBottom /></el-icon
|
>下移<TMagicIcon><CaretBottom /></TMagicIcon
|
||||||
></el-button>
|
></TMagicButton>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<span v-if="itemExtra" v-html="itemExtra" class="m-form-tip"></span>
|
<span v-if="itemExtra" v-html="itemExtra" class="m-form-tip"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<m-form-container
|
<Container
|
||||||
v-if="expand"
|
v-if="expand"
|
||||||
:config="rowConfig"
|
:config="rowConfig"
|
||||||
:model="model"
|
:model="model"
|
||||||
@ -35,125 +35,88 @@
|
|||||||
:prop="`${prop}${prop ? '.' : ''}${String(index)}`"
|
:prop="`${prop}${prop ? '.' : ''}${String(index)}`"
|
||||||
:size="size"
|
:size="size"
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
></m-form-container>
|
></Container>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, defineComponent, inject, PropType, ref, watchEffect } from 'vue';
|
import { computed, inject, ref, watchEffect } from 'vue';
|
||||||
import { CaretBottom, CaretRight, CaretTop, Delete } from '@element-plus/icons-vue';
|
import { CaretBottom, CaretRight, CaretTop, Delete } from '@element-plus/icons-vue';
|
||||||
|
|
||||||
|
import { TMagicButton, TMagicIcon } from '@tmagic/design';
|
||||||
|
|
||||||
import { FormState, GroupListConfig } from '../schema';
|
import { FormState, GroupListConfig } from '../schema';
|
||||||
import { filterFunction } from '../utils/form';
|
import { filterFunction } from '../utils/form';
|
||||||
|
|
||||||
export default defineComponent({
|
import Container from './Container.vue';
|
||||||
name: 'm-form-group-list-item',
|
|
||||||
|
|
||||||
components: { CaretBottom, CaretRight, CaretTop },
|
const props = defineProps<{
|
||||||
|
model: any;
|
||||||
|
groupModel: any[];
|
||||||
|
config: GroupListConfig;
|
||||||
|
labelWidth?: string;
|
||||||
|
prop?: string;
|
||||||
|
size?: string;
|
||||||
|
index: number;
|
||||||
|
}>();
|
||||||
|
|
||||||
props: {
|
const emit = defineEmits(['swap-item', 'remove-item', 'change']);
|
||||||
labelWidth: String,
|
|
||||||
|
|
||||||
model: {
|
const mForm = inject<FormState | undefined>('mForm');
|
||||||
type: Object,
|
const expand = ref(false);
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
|
|
||||||
config: {
|
watchEffect(() => {
|
||||||
type: Object as PropType<GroupListConfig>,
|
expand.value = !props.index;
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
|
|
||||||
prop: String,
|
|
||||||
|
|
||||||
size: String,
|
|
||||||
|
|
||||||
index: {
|
|
||||||
type: [Number, String, Symbol],
|
|
||||||
default: 0,
|
|
||||||
},
|
|
||||||
|
|
||||||
groupModel: {
|
|
||||||
type: Array,
|
|
||||||
default: () => [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
emits: ['swap-item', 'remove-item', 'change'],
|
|
||||||
|
|
||||||
setup(props, { emit }) {
|
|
||||||
const mForm = inject<FormState | undefined>('mForm');
|
|
||||||
const expand = ref(false);
|
|
||||||
|
|
||||||
watchEffect(() => {
|
|
||||||
expand.value = !props.index;
|
|
||||||
});
|
|
||||||
|
|
||||||
const rowConfig = computed(() => ({
|
|
||||||
type: 'row',
|
|
||||||
span: props.config.span || 24,
|
|
||||||
items: props.config.items,
|
|
||||||
labelWidth: props.config.labelWidth,
|
|
||||||
[mForm?.keyProp || '__key']: `${props.config[mForm?.keyProp || '__key']}${String(props.index)}`,
|
|
||||||
}));
|
|
||||||
|
|
||||||
const title = computed(() => {
|
|
||||||
if (props.config.titleKey && props.model[props.config.titleKey]) {
|
|
||||||
return props.model[props.config.titleKey];
|
|
||||||
}
|
|
||||||
|
|
||||||
return `组 ${String(props.index)}`;
|
|
||||||
});
|
|
||||||
|
|
||||||
const length = computed(() => props.groupModel?.length || 0);
|
|
||||||
|
|
||||||
const itemExtra = computed(() => filterFunction(mForm, props.config.itemExtra, props));
|
|
||||||
|
|
||||||
const removeHandler = () => emit('remove-item', props.index);
|
|
||||||
|
|
||||||
const changeHandler = () => emit('change');
|
|
||||||
|
|
||||||
const expandHandler = () => {
|
|
||||||
expand.value = !expand.value;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 希望支持单行可控制是否显示删除按钮,不会影响现有逻辑
|
|
||||||
const showDelete = (index: number) => {
|
|
||||||
const deleteFunc = props.config.delete;
|
|
||||||
if (deleteFunc && typeof deleteFunc === 'function') {
|
|
||||||
return deleteFunc(props.model, index, mForm?.values);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 调换顺序
|
|
||||||
const changeOrder = (offset = 0) => emit('swap-item', props.index, `${String(props.index)}${offset}`);
|
|
||||||
|
|
||||||
const movable = () => {
|
|
||||||
const { movable } = props.config;
|
|
||||||
|
|
||||||
// 没有设置时,默认可移动
|
|
||||||
if (movable === undefined) return true;
|
|
||||||
if (typeof movable === 'function') {
|
|
||||||
return movable(mForm, props.index || 0, props.model, props.groupModel);
|
|
||||||
}
|
|
||||||
return movable;
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
expand,
|
|
||||||
expandHandler,
|
|
||||||
title,
|
|
||||||
showDelete,
|
|
||||||
removeHandler,
|
|
||||||
movable,
|
|
||||||
changeOrder,
|
|
||||||
itemExtra,
|
|
||||||
rowConfig,
|
|
||||||
changeHandler,
|
|
||||||
length,
|
|
||||||
Delete,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const rowConfig = computed(() => ({
|
||||||
|
type: 'row',
|
||||||
|
span: props.config.span || 24,
|
||||||
|
items: props.config.items,
|
||||||
|
labelWidth: props.config.labelWidth,
|
||||||
|
[mForm?.keyProp || '__key']: `${props.config[mForm?.keyProp || '__key']}${String(props.index)}`,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const title = computed(() => {
|
||||||
|
if (props.config.titleKey && props.model[props.config.titleKey]) {
|
||||||
|
return props.model[props.config.titleKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
return `组 ${String(props.index)}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
const length = computed(() => props.groupModel?.length || 0);
|
||||||
|
|
||||||
|
const itemExtra = computed(() => filterFunction(mForm, props.config.itemExtra, props));
|
||||||
|
|
||||||
|
const removeHandler = () => emit('remove-item', props.index);
|
||||||
|
|
||||||
|
const changeHandler = () => emit('change');
|
||||||
|
|
||||||
|
const expandHandler = () => {
|
||||||
|
expand.value = !expand.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 希望支持单行可控制是否显示删除按钮,不会影响现有逻辑
|
||||||
|
const showDelete = (index: number) => {
|
||||||
|
const deleteFunc = props.config.delete;
|
||||||
|
if (deleteFunc && typeof deleteFunc === 'function') {
|
||||||
|
return deleteFunc(props.model, index, mForm?.values);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 调换顺序
|
||||||
|
const changeOrder = (offset = 0) => emit('swap-item', props.index, `${String(props.index)}${offset}`);
|
||||||
|
|
||||||
|
const movable = () => {
|
||||||
|
const { movable } = props.config;
|
||||||
|
|
||||||
|
// 没有设置时,默认可移动
|
||||||
|
if (movable === undefined) return true;
|
||||||
|
if (typeof movable === 'function') {
|
||||||
|
return movable(mForm, props.index || 0, props.model, props.groupModel);
|
||||||
|
}
|
||||||
|
return movable;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-card
|
<TMagicCard
|
||||||
v-if="items && items.length"
|
v-if="items && items.length"
|
||||||
class="box-card m-form-panel"
|
class="box-card m-form-panel"
|
||||||
:body-style="{ display: expand ? 'block' : 'none' }"
|
:body-style="{ display: expand ? 'block' : 'none' }"
|
||||||
@ -7,7 +7,7 @@
|
|||||||
<template #header>
|
<template #header>
|
||||||
<div class="clearfix">
|
<div class="clearfix">
|
||||||
<a href="javascript:" style="width: 100%; display: block" @click="expand = !expand">
|
<a href="javascript:" style="width: 100%; display: block" @click="expand = !expand">
|
||||||
<el-icon><caret-bottom v-if="expand" /><caret-right v-else /></el-icon> {{ filter(config.title) }}
|
<TMagicIcon><CaretBottom v-if="expand" /><CaretRight v-else /></TMagicIcon> {{ filter(config.title) }}
|
||||||
<span v-if="config && config.extra" v-html="config.extra" class="m-form-tip"></span>
|
<span v-if="config && config.extra" v-html="config.extra" class="m-form-tip"></span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
<div v-if="config.schematic" style="display: flex">
|
<div v-if="config.schematic" style="display: flex">
|
||||||
<div style="flex: 1">
|
<div style="flex: 1">
|
||||||
<m-form-container
|
<Container
|
||||||
v-for="(item, index) in items"
|
v-for="(item, index) in items"
|
||||||
:key="item[mForm?.keyProp || '__key'] ?? index"
|
:key="item[mForm?.keyProp || '__key'] ?? index"
|
||||||
:config="item"
|
:config="item"
|
||||||
@ -27,14 +27,14 @@
|
|||||||
:size="size"
|
:size="size"
|
||||||
:label-width="config.labelWidth || labelWidth"
|
:label-width="config.labelWidth || labelWidth"
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
></m-form-container>
|
></Container>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<img class="m-form-schematic" :src="config.schematic" />
|
<img class="m-form-schematic" :src="config.schematic" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<m-form-container
|
<Container
|
||||||
v-for="(item, index) in items"
|
v-for="(item, index) in items"
|
||||||
:key="item[mForm?.keyProp || '__key'] ?? index"
|
:key="item[mForm?.keyProp || '__key'] ?? index"
|
||||||
:config="item"
|
:config="item"
|
||||||
@ -43,64 +43,41 @@
|
|||||||
:size="size"
|
:size="size"
|
||||||
:label-width="config.labelWidth || labelWidth"
|
:label-width="config.labelWidth || labelWidth"
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
></m-form-container>
|
></Container>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</TMagicCard>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, defineComponent, inject, PropType, ref } from 'vue';
|
import { computed, inject, ref } from 'vue';
|
||||||
import { CaretBottom, CaretRight } from '@element-plus/icons-vue';
|
import { CaretBottom, CaretRight } from '@element-plus/icons-vue';
|
||||||
|
|
||||||
|
import { TMagicCard, TMagicIcon } from '@tmagic/design';
|
||||||
|
|
||||||
import { FormState, PanelConfig } from '../schema';
|
import { FormState, PanelConfig } from '../schema';
|
||||||
import { filterFunction } from '../utils/form';
|
import { filterFunction } from '../utils/form';
|
||||||
|
|
||||||
export default defineComponent({
|
import Container from './Container.vue';
|
||||||
name: 'm-form-panel',
|
|
||||||
|
|
||||||
components: { CaretBottom, CaretRight },
|
const props = defineProps<{
|
||||||
|
model: any;
|
||||||
|
config: PanelConfig;
|
||||||
|
name: string;
|
||||||
|
labelWidth?: string;
|
||||||
|
prop?: string;
|
||||||
|
size?: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
props: {
|
const emit = defineEmits(['change']);
|
||||||
labelWidth: String,
|
|
||||||
|
|
||||||
model: {
|
const mForm = inject<FormState | undefined>('mForm');
|
||||||
type: Object,
|
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
|
|
||||||
config: {
|
const expand = ref(props.config.expand !== false);
|
||||||
type: Object as PropType<PanelConfig>,
|
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
|
|
||||||
prop: String,
|
const items = computed(() => props.config.items);
|
||||||
|
|
||||||
size: String,
|
const filter = (config: any) => filterFunction(mForm, config, props);
|
||||||
|
|
||||||
name: String,
|
const changeHandler = () => emit('change', props.model);
|
||||||
},
|
|
||||||
|
|
||||||
emits: ['change'],
|
|
||||||
|
|
||||||
setup(props, { emit }) {
|
|
||||||
const mForm = inject<FormState | undefined>('mForm');
|
|
||||||
|
|
||||||
const expand = ref(props.config.expand !== false);
|
|
||||||
|
|
||||||
const items = computed(() => props.config.items);
|
|
||||||
|
|
||||||
const filter = (config: any) => filterFunction(mForm, config, props);
|
|
||||||
|
|
||||||
const changeHandler = () => emit('change', props.model);
|
|
||||||
|
|
||||||
return {
|
|
||||||
mForm,
|
|
||||||
expand,
|
|
||||||
items,
|
|
||||||
filter,
|
|
||||||
changeHandler,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-row :gutter="10">
|
<TMagicRow :gutter="10">
|
||||||
<Col
|
<Col
|
||||||
v-for="(col, index) in config.items"
|
v-for="(col, index) in config.items"
|
||||||
:key="col[mForm?.keyProp || '__key'] ?? index"
|
:key="col[mForm?.keyProp || '__key'] ?? index"
|
||||||
@ -12,53 +12,31 @@
|
|||||||
:size="size"
|
:size="size"
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
/>
|
/>
|
||||||
</el-row>
|
</TMagicRow>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import { defineComponent, inject, PropType } from 'vue';
|
import { inject } from 'vue';
|
||||||
|
|
||||||
|
import { TMagicRow } from '@tmagic/design';
|
||||||
|
|
||||||
import { FormState, RowConfig } from '../schema';
|
import { FormState, RowConfig } from '../schema';
|
||||||
|
|
||||||
import Col from './Col.vue';
|
import Col from './Col.vue';
|
||||||
|
|
||||||
export default defineComponent({
|
const props = defineProps<{
|
||||||
name: 'm-form-row',
|
model: any;
|
||||||
|
config: RowConfig;
|
||||||
|
name: string;
|
||||||
|
labelWidth?: string;
|
||||||
|
prop?: string;
|
||||||
|
size?: string;
|
||||||
|
expandMore?: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
components: { Col },
|
const emit = defineEmits(['change']);
|
||||||
|
|
||||||
props: {
|
const mForm = inject<FormState | undefined>('mForm');
|
||||||
labelWidth: String,
|
|
||||||
expandMore: Boolean,
|
|
||||||
|
|
||||||
model: {
|
const changeHandler = () => emit('change', props.name ? props.model[props.name] : props.model);
|
||||||
type: Object,
|
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
|
|
||||||
config: {
|
|
||||||
type: Object as PropType<RowConfig>,
|
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
|
|
||||||
prop: String,
|
|
||||||
|
|
||||||
name: String,
|
|
||||||
|
|
||||||
size: String,
|
|
||||||
},
|
|
||||||
|
|
||||||
emits: ['change'],
|
|
||||||
|
|
||||||
setup(props, { emit }) {
|
|
||||||
const mForm = inject<FormState | undefined>('mForm');
|
|
||||||
|
|
||||||
const changeHandler = () => emit('change', props.name ? props.model[props.name] : props.model);
|
|
||||||
|
|
||||||
return {
|
|
||||||
mForm,
|
|
||||||
changeHandler,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,82 +1,70 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<el-steps :active="active" align-center :space="config.space">
|
<TMagicSteps :active="active" align-center :space="config.space">
|
||||||
<el-step
|
<TMagicStep
|
||||||
v-for="(item, index) in config.items"
|
v-for="(item, index) in config.items"
|
||||||
:key="item.__key"
|
:key="item.__key"
|
||||||
:title="item.title"
|
:title="item.title"
|
||||||
:active="active"
|
:active="active"
|
||||||
@click="stepClick(index)"
|
@click="stepClick(index)"
|
||||||
></el-step>
|
></TMagicStep>
|
||||||
</el-steps>
|
</TMagicSteps>
|
||||||
|
|
||||||
<template v-for="(step, index) in config.items">
|
<template v-for="(step, index) in config.items">
|
||||||
<template v-for="item in step.items">
|
<template v-for="item in step.items">
|
||||||
<m-form-container
|
<Container
|
||||||
v-if="item"
|
v-if="item"
|
||||||
v-show="active - 1 === index"
|
v-show="active - 1 === index"
|
||||||
:key="item[mForm?.keyProp || '__key']"
|
:key="item[mForm?.keyProp || '__key']"
|
||||||
:config="item"
|
:config="item"
|
||||||
:model="step.name ? model[step.name] : model"
|
:model="step.name ? model[step.name] : model"
|
||||||
:prop="step.name"
|
:prop="`${step.name}`"
|
||||||
:size="size"
|
:size="size"
|
||||||
:label-width="config.labelWidth || labelWidth"
|
:label-width="config.labelWidth || labelWidth"
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
></m-form-container>
|
></Container>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import { defineComponent, inject, PropType, ref, watchEffect } from 'vue';
|
import { inject, ref, watchEffect } from 'vue';
|
||||||
|
|
||||||
|
import { TMagicStep, TMagicSteps } from '@tmagic/design';
|
||||||
|
|
||||||
import { FormState, StepConfig } from '../schema';
|
import { FormState, StepConfig } from '../schema';
|
||||||
|
|
||||||
export default defineComponent({
|
import Container from './Container.vue';
|
||||||
name: 'm-form-step',
|
|
||||||
|
|
||||||
props: {
|
const props = withDefaults(
|
||||||
model: {
|
defineProps<{
|
||||||
type: Object,
|
model: any;
|
||||||
default: () => ({}),
|
config: StepConfig;
|
||||||
},
|
stepActive?: number;
|
||||||
|
labelWidth?: string;
|
||||||
config: {
|
size?: string;
|
||||||
type: Object as PropType<StepConfig>,
|
}>(),
|
||||||
default: () => ({}),
|
{
|
||||||
},
|
stepActive: 1,
|
||||||
|
|
||||||
stepActive: {
|
|
||||||
type: Number,
|
|
||||||
default: () => 1,
|
|
||||||
},
|
|
||||||
|
|
||||||
size: String,
|
|
||||||
|
|
||||||
labelWidth: String,
|
|
||||||
},
|
},
|
||||||
|
);
|
||||||
|
|
||||||
emits: ['change'],
|
const emit = defineEmits(['change']);
|
||||||
|
|
||||||
setup(props, { emit }) {
|
const mForm = inject<FormState | undefined>('mForm');
|
||||||
const mForm = inject<FormState | undefined>('mForm');
|
const active = ref(1);
|
||||||
const active = ref(1);
|
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
active.value = props.stepActive;
|
active.value = props.stepActive;
|
||||||
});
|
|
||||||
|
|
||||||
const stepClick = (index: number) => {
|
|
||||||
active.value = index + 1;
|
|
||||||
mForm?.$emit('update:stepActive', active.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const changeHandler = () => {
|
|
||||||
emit('change', props.model);
|
|
||||||
};
|
|
||||||
|
|
||||||
return { mForm, active, stepClick, changeHandler };
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const stepClick = (index: number) => {
|
||||||
|
active.value = index + 1;
|
||||||
|
mForm?.$emit('update:stepActive', active.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const changeHandler = () => {
|
||||||
|
emit('change', props.model);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-tabs
|
<TMagicTabs
|
||||||
v-model="activeTabName"
|
v-model="activeTabName"
|
||||||
:class="config.dynamic ? 'magic-form-dynamic-tab' : 'magic-form-tab'"
|
:class="config.dynamic ? 'magic-form-dynamic-tab' : 'magic-form-tab'"
|
||||||
:type="config.tabType"
|
:type="config.tabType"
|
||||||
@ -10,14 +10,14 @@
|
|||||||
@tab-remove="onTabRemove"
|
@tab-remove="onTabRemove"
|
||||||
>
|
>
|
||||||
<template v-for="(tab, tabIndex) in tabs">
|
<template v-for="(tab, tabIndex) in tabs">
|
||||||
<el-tab-pane
|
<TMagicTabPane
|
||||||
v-if="display(tab.display) && tabItems(tab).length"
|
v-if="display(tab.display) && tabItems(tab).length"
|
||||||
:key="tab[mForm?.keyProp || '__key'] ?? tabIndex"
|
:key="tab[mForm?.keyProp || '__key'] ?? tabIndex"
|
||||||
:name="filter(tab.status) || tabIndex.toString()"
|
:name="filter(tab.status) || tabIndex.toString()"
|
||||||
:label="filter(tab.title)"
|
:label="filter(tab.title)"
|
||||||
:lazy="tab.lazy || false"
|
:lazy="tab.lazy || false"
|
||||||
>
|
>
|
||||||
<m-form-container
|
<Container
|
||||||
v-for="item in tabItems(tab)"
|
v-for="item in tabItems(tab)"
|
||||||
:key="item[mForm?.keyProp || '__key']"
|
:key="item[mForm?.keyProp || '__key']"
|
||||||
:config="item"
|
:config="item"
|
||||||
@ -35,18 +35,22 @@
|
|||||||
:label-width="tab.labelWidth || labelWidth"
|
:label-width="tab.labelWidth || labelWidth"
|
||||||
:expand-more="expandMore"
|
:expand-more="expandMore"
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
></m-form-container>
|
></Container>
|
||||||
</el-tab-pane>
|
</TMagicTabPane>
|
||||||
</template>
|
</template>
|
||||||
</el-tabs>
|
</TMagicTabs>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, defineComponent, inject, PropType, ref, watchEffect } from 'vue';
|
import { computed, inject, ref, watchEffect } from 'vue';
|
||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
|
||||||
import { FormState, FormValue, TabConfig, TabPaneConfig } from '../schema';
|
import { TMagicTabPane, TMagicTabs } from '@tmagic/design';
|
||||||
import { display, filterFunction } from '../utils/form';
|
|
||||||
|
import { FormState, TabConfig, TabPaneConfig } from '../schema';
|
||||||
|
import { display as displayFunc, filterFunction } from '../utils/form';
|
||||||
|
|
||||||
|
import Container from './Container.vue';
|
||||||
|
|
||||||
const getActive = (mForm: FormState | undefined, props: any, activeTabName: string) => {
|
const getActive = (mForm: FormState | undefined, props: any, activeTabName: string) => {
|
||||||
const { config, model, prop } = props;
|
const { config, model, prop } = props;
|
||||||
@ -59,7 +63,7 @@ const getActive = (mForm: FormState | undefined, props: any, activeTabName: stri
|
|||||||
return '0';
|
return '0';
|
||||||
};
|
};
|
||||||
|
|
||||||
const tabClickHandler = (mForm: FormState | undefined, tab: any, props: any) => {
|
const tabClick = (mForm: FormState | undefined, tab: any, props: any) => {
|
||||||
const { config, model, prop } = props;
|
const { config, model, prop } = props;
|
||||||
|
|
||||||
// 兼容vue2的element-ui
|
// 兼容vue2的element-ui
|
||||||
@ -75,123 +79,90 @@ const tabClickHandler = (mForm: FormState | undefined, tab: any, props: any) =>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const Tab = defineComponent({
|
const props = defineProps<{
|
||||||
name: 'm-form-tab',
|
model: any;
|
||||||
|
config: TabConfig;
|
||||||
|
name: string;
|
||||||
|
size?: string;
|
||||||
|
labelWidth?: string;
|
||||||
|
prop?: string;
|
||||||
|
expandMore?: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
props: {
|
const emit = defineEmits(['change']);
|
||||||
labelWidth: String,
|
|
||||||
expandMore: Boolean,
|
|
||||||
|
|
||||||
model: {
|
const mForm = inject<FormState | undefined>('mForm');
|
||||||
type: Object,
|
const activeTabName = ref(getActive(mForm, props, ''));
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
|
|
||||||
config: {
|
const tabs = computed(() => {
|
||||||
type: Object as PropType<TabConfig>,
|
if (props.config.dynamic) {
|
||||||
default: () => ({}),
|
if (!props.config.name) throw new Error('dynamic tab 必须配置name');
|
||||||
},
|
return props.model[props.config.name] || [];
|
||||||
|
}
|
||||||
prop: String,
|
return props.config.items;
|
||||||
|
|
||||||
name: String,
|
|
||||||
|
|
||||||
size: String,
|
|
||||||
},
|
|
||||||
|
|
||||||
emits: {
|
|
||||||
change(values: FormValue) {
|
|
||||||
return values;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
setup(props, { emit }) {
|
|
||||||
const mForm = inject<FormState | undefined>('mForm');
|
|
||||||
const activeTabName = ref(getActive(mForm, props, ''));
|
|
||||||
|
|
||||||
const tabs = computed(() => {
|
|
||||||
if (props.config.dynamic) {
|
|
||||||
if (!props.config.name) throw new Error('dynamic tab 必须配置name');
|
|
||||||
return props.model[props.config.name] || [];
|
|
||||||
}
|
|
||||||
return props.config.items;
|
|
||||||
});
|
|
||||||
|
|
||||||
const filter = (config: any) => filterFunction(mForm, config, props);
|
|
||||||
|
|
||||||
watchEffect(() => {
|
|
||||||
if (typeof props.config.activeChange === 'function') {
|
|
||||||
props.config.activeChange(mForm, activeTabName.value, {
|
|
||||||
model: props.model,
|
|
||||||
prop: props.prop,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
mForm,
|
|
||||||
|
|
||||||
activeTabName,
|
|
||||||
|
|
||||||
tabs,
|
|
||||||
|
|
||||||
filter,
|
|
||||||
|
|
||||||
tabItems: (tab: TabPaneConfig) => (props.config.dynamic ? props.config.items : tab.items),
|
|
||||||
|
|
||||||
tabClickHandler: (tab: any) => tabClickHandler(mForm, tab, props),
|
|
||||||
|
|
||||||
onTabAdd: () => {
|
|
||||||
if (!props.config.name) throw new Error('dynamic tab 必须配置name');
|
|
||||||
|
|
||||||
if (typeof props.config.onTabAdd === 'function') {
|
|
||||||
props.config.onTabAdd(mForm, {
|
|
||||||
model: props.model,
|
|
||||||
prop: props.prop,
|
|
||||||
config: props.config,
|
|
||||||
});
|
|
||||||
} else if (tabs.value.length > 0) {
|
|
||||||
const newObj = cloneDeep(tabs.value[0]);
|
|
||||||
newObj.title = `标签${tabs.value.length + 1}`;
|
|
||||||
props.model[props.config.name].push(newObj);
|
|
||||||
}
|
|
||||||
emit('change', props.model);
|
|
||||||
mForm?.$emit('field-change', props.prop, props.model[props.config.name]);
|
|
||||||
},
|
|
||||||
|
|
||||||
onTabRemove: (tabName: string) => {
|
|
||||||
if (!props.config.name) throw new Error('dynamic tab 必须配置name');
|
|
||||||
|
|
||||||
if (typeof props.config.onTabRemove === 'function') {
|
|
||||||
props.config.onTabRemove(mForm, tabName, {
|
|
||||||
model: props.model,
|
|
||||||
prop: props.prop,
|
|
||||||
config: props.config,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
props.model[props.config.name].splice(+tabName, 1);
|
|
||||||
|
|
||||||
// 防止删除后没有选中的问题
|
|
||||||
if (tabName < activeTabName.value || activeTabName.value >= props.model[props.config.name].length) {
|
|
||||||
activeTabName.value = (+activeTabName.value - 1).toString();
|
|
||||||
tabClickHandler(mForm, { name: activeTabName.value }, props);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
emit('change', props.model);
|
|
||||||
mForm?.$emit('field-change', props.prop, props.model[props.config.name]);
|
|
||||||
},
|
|
||||||
|
|
||||||
display: (displayConfig: any) => display(mForm, displayConfig, props),
|
|
||||||
|
|
||||||
changeHandler: () => {
|
|
||||||
emit('change', props.model);
|
|
||||||
if (typeof props.config.onChange === 'function') {
|
|
||||||
props.config.onChange(mForm, { model: props.model, prop: props.prop, config: props.config });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default Tab;
|
const filter = (config: any) => filterFunction(mForm, config, props);
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
if (typeof props.config.activeChange === 'function') {
|
||||||
|
props.config.activeChange(mForm, activeTabName.value, {
|
||||||
|
model: props.model,
|
||||||
|
prop: props.prop,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const tabItems = (tab: TabPaneConfig) => (props.config.dynamic ? props.config.items : tab.items);
|
||||||
|
|
||||||
|
const tabClickHandler = (tab: any) => tabClick(mForm, tab, props);
|
||||||
|
|
||||||
|
const onTabAdd = () => {
|
||||||
|
if (!props.config.name) throw new Error('dynamic tab 必须配置name');
|
||||||
|
|
||||||
|
if (typeof props.config.onTabAdd === 'function') {
|
||||||
|
props.config.onTabAdd(mForm, {
|
||||||
|
model: props.model,
|
||||||
|
prop: props.prop,
|
||||||
|
config: props.config,
|
||||||
|
});
|
||||||
|
} else if (tabs.value.length > 0) {
|
||||||
|
const newObj = cloneDeep(tabs.value[0]);
|
||||||
|
newObj.title = `标签${tabs.value.length + 1}`;
|
||||||
|
props.model[props.config.name].push(newObj);
|
||||||
|
}
|
||||||
|
emit('change', props.model);
|
||||||
|
mForm?.$emit('field-change', props.prop, props.model[props.config.name]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onTabRemove = (tabName: string) => {
|
||||||
|
if (!props.config.name) throw new Error('dynamic tab 必须配置name');
|
||||||
|
|
||||||
|
if (typeof props.config.onTabRemove === 'function') {
|
||||||
|
props.config.onTabRemove(mForm, tabName, {
|
||||||
|
model: props.model,
|
||||||
|
prop: props.prop,
|
||||||
|
config: props.config,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
props.model[props.config.name].splice(+tabName, 1);
|
||||||
|
|
||||||
|
// 防止删除后没有选中的问题
|
||||||
|
if (tabName < activeTabName.value || activeTabName.value >= props.model[props.config.name].length) {
|
||||||
|
activeTabName.value = (+activeTabName.value - 1).toString();
|
||||||
|
tabClick(mForm, { name: activeTabName.value }, props);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
emit('change', props.model);
|
||||||
|
mForm?.$emit('field-change', props.prop, props.model[props.config.name]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const display = (displayConfig: any) => displayFunc(mForm, displayConfig, props);
|
||||||
|
|
||||||
|
const changeHandler = () => {
|
||||||
|
emit('change', props.model);
|
||||||
|
if (typeof props.config.onChange === 'function') {
|
||||||
|
props.config.onChange(mForm, { model: props.model, prop: props.prop, config: props.config });
|
||||||
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,146 +1,98 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="m-cascader" style="width: 100%">
|
<TMagicCascader
|
||||||
<el-cascader
|
v-model="model[name]"
|
||||||
v-model="model[name]"
|
ref="tMagicCascader"
|
||||||
ref="cascader"
|
style="width: 100%"
|
||||||
style="width: 100%"
|
clearable
|
||||||
clearable
|
filterable
|
||||||
filterable
|
:size="size"
|
||||||
:size="size"
|
:placeholder="config.placeholder"
|
||||||
:placeholder="config.placeholder"
|
:disabled="disabled"
|
||||||
:disabled="disabled"
|
:options="options"
|
||||||
:options="options"
|
:props="{ multiple: config.multiple }"
|
||||||
:props="{ multiple: config.multiple }"
|
@change="changeHandler"
|
||||||
@change="changeHandler"
|
></TMagicCascader>
|
||||||
></el-cascader>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import {
|
import { inject, ref, watchEffect } from 'vue';
|
||||||
ComponentInternalInstance,
|
|
||||||
computed,
|
import { TMagicCascader } from '@tmagic/design';
|
||||||
defineComponent,
|
|
||||||
getCurrentInstance,
|
|
||||||
inject,
|
|
||||||
PropType,
|
|
||||||
ref,
|
|
||||||
watchEffect,
|
|
||||||
} from 'vue';
|
|
||||||
|
|
||||||
import { CascaderConfig, FormState } from '../schema';
|
import { CascaderConfig, FormState } from '../schema';
|
||||||
import { getConfig } from '../utils/config';
|
import { getConfig } from '../utils/config';
|
||||||
import fieldProps from '../utils/fieldProps';
|
|
||||||
import { useAddField } from '../utils/useAddField';
|
import { useAddField } from '../utils/useAddField';
|
||||||
|
|
||||||
export default defineComponent({
|
const props = defineProps<{
|
||||||
name: 'm-fields-cascader',
|
config: CascaderConfig;
|
||||||
|
model: any;
|
||||||
|
initValues?: any;
|
||||||
|
values?: any;
|
||||||
|
name: string;
|
||||||
|
prop: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
size: 'mini' | 'small' | 'medium';
|
||||||
|
}>();
|
||||||
|
|
||||||
props: {
|
const emit = defineEmits(['change']);
|
||||||
...fieldProps,
|
|
||||||
config: {
|
|
||||||
type: Object as PropType<CascaderConfig>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
emits: ['change'],
|
const mForm = inject<FormState | null>('mForm');
|
||||||
|
|
||||||
setup(props, { emit }) {
|
useAddField(props.prop);
|
||||||
const mForm = inject<FormState | null>('mForm');
|
|
||||||
const vm = getCurrentInstance() as ComponentInternalInstance;
|
|
||||||
|
|
||||||
useAddField(props.prop);
|
const requestFunc = getConfig('request') as Function;
|
||||||
|
|
||||||
const requestFunc = getConfig('request') as Function;
|
const tMagicCascader = ref<InstanceType<typeof TMagicCascader>>();
|
||||||
|
|
||||||
const cascader = ref<any>();
|
const options = Array.isArray(props.config.options) ? ref(props.config.options) : ref([]);
|
||||||
const dialog = ref<any>();
|
const remoteData = ref<any>(null);
|
||||||
|
|
||||||
const options = Array.isArray(props.config.options) ? ref(props.config.options) : ref([]);
|
const setRemoteOptions = async function () {
|
||||||
const remoteData = ref<any>(null);
|
const { config } = props;
|
||||||
|
const { option } = config;
|
||||||
|
if (!option) return;
|
||||||
|
let { body } = option;
|
||||||
|
|
||||||
const setRemoteOptions = async function () {
|
const postOptions: Record<string, any> = {
|
||||||
const { config } = props;
|
url: option.url,
|
||||||
const { option } = config;
|
cache: option.cache,
|
||||||
if (!option) return;
|
timeout: option.timeout,
|
||||||
let { body } = option;
|
data: {},
|
||||||
|
};
|
||||||
|
|
||||||
const postOptions: Record<string, any> = {
|
if (body && mForm) {
|
||||||
url: option.url,
|
if (typeof body === 'function' && props.model && mForm) {
|
||||||
cache: option.cache,
|
body = body(mForm, {
|
||||||
timeout: option.timeout,
|
model: props.model,
|
||||||
data: {},
|
formValue: mForm.values,
|
||||||
};
|
formValues: mForm.values,
|
||||||
|
config: props.config,
|
||||||
if (body && mForm) {
|
});
|
||||||
if (typeof body === 'function' && props.model && mForm) {
|
|
||||||
body = body(mForm, {
|
|
||||||
model: props.model,
|
|
||||||
formValue: mForm.values,
|
|
||||||
formValues: mForm.values,
|
|
||||||
config: props.config,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
postOptions.data = body;
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = await requestFunc(postOptions);
|
|
||||||
|
|
||||||
remoteData.value = res[option.root];
|
|
||||||
if (remoteData.value && typeof option?.item === 'function') {
|
|
||||||
options.value = option.item(res[option.root]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 初始化
|
|
||||||
if (typeof props.config.options === 'function' && props.model && mForm) {
|
|
||||||
watchEffect(
|
|
||||||
() =>
|
|
||||||
(options.value = (props.config.options as Function)(vm, { model: props.model, formValues: mForm.values })),
|
|
||||||
);
|
|
||||||
} else if (!props.config.options || !props.config.options.length || props.config.remote) {
|
|
||||||
Promise.resolve(setRemoteOptions());
|
|
||||||
}
|
}
|
||||||
|
postOptions.data = body;
|
||||||
|
}
|
||||||
|
|
||||||
const action = computed(() => {
|
const res = await requestFunc(postOptions);
|
||||||
if (props.config.add?.action.method === 'post') {
|
|
||||||
return (options: any) =>
|
|
||||||
requestFunc({
|
|
||||||
...props.config?.add?.action.body,
|
|
||||||
...options,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
remoteData.value = res[option.root];
|
||||||
options,
|
if (remoteData.value && typeof option?.item === 'function') {
|
||||||
remoteData,
|
options.value = option.item(res[option.root]);
|
||||||
addButtonStyle: {
|
}
|
||||||
top: 0,
|
};
|
||||||
left: 0,
|
|
||||||
width: 'auto',
|
// 初始化
|
||||||
},
|
if (typeof props.config.options === 'function' && props.model && mForm) {
|
||||||
dialogVisible: false,
|
watchEffect(
|
||||||
cascader,
|
() => (options.value = (props.config.options as Function)(mForm, { model: props.model, formValues: mForm.values })),
|
||||||
dialog,
|
);
|
||||||
action,
|
} else if (!props.config.options || !props.config.options.length || props.config.remote) {
|
||||||
setRemoteOptions,
|
Promise.resolve(setRemoteOptions());
|
||||||
changeHandler: (value: any) => {
|
}
|
||||||
if (!cascader.value) return;
|
|
||||||
cascader.value.query = '';
|
const changeHandler = (value: any) => {
|
||||||
cascader.value.previousQuery = null;
|
if (!tMagicCascader.value) return;
|
||||||
emit('change', value);
|
tMagicCascader.value.setQuery('');
|
||||||
},
|
tMagicCascader.value.setPreviousQuery(null);
|
||||||
addHandler: () => {
|
emit('change', value);
|
||||||
if (!dialog.value) return;
|
};
|
||||||
dialog.value.dialogVisible = true;
|
|
||||||
},
|
|
||||||
editAfterAction: () => {
|
|
||||||
setRemoteOptions();
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,67 +1,63 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-checkbox
|
<TMagicCheckbox
|
||||||
v-model="model[name]"
|
v-model="model[name]"
|
||||||
:size="size"
|
:size="size"
|
||||||
:trueLabel="activeValue"
|
:trueLabel="activeValue"
|
||||||
:falseLabel="inactiveValue"
|
:falseLabel="inactiveValue"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:label="config.text"
|
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
></el-checkbox>
|
>{{ config.text }}</TMagicCheckbox
|
||||||
|
>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, defineComponent, PropType } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
import { TMagicCheckbox } from '@tmagic/design';
|
||||||
|
|
||||||
import { CheckboxConfig } from '../schema';
|
import { CheckboxConfig } from '../schema';
|
||||||
import fieldProps from '../utils/fieldProps';
|
|
||||||
import { useAddField } from '../utils/useAddField';
|
import { useAddField } from '../utils/useAddField';
|
||||||
|
|
||||||
export default defineComponent({
|
const props = defineProps<{
|
||||||
name: 'm-fields-checkbox',
|
config: CheckboxConfig;
|
||||||
|
model: any;
|
||||||
|
initValues?: any;
|
||||||
|
values?: any;
|
||||||
|
name: string;
|
||||||
|
prop: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
size: 'mini' | 'small' | 'medium';
|
||||||
|
}>();
|
||||||
|
|
||||||
props: {
|
const emit = defineEmits(['change']);
|
||||||
...fieldProps,
|
|
||||||
config: {
|
|
||||||
type: Object as PropType<CheckboxConfig>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
emits: ['change', 'input'],
|
useAddField(props.prop);
|
||||||
|
|
||||||
setup(props, { emit }) {
|
const activeValue = computed(() => {
|
||||||
useAddField(props.prop);
|
if (typeof props.config.activeValue === 'undefined') {
|
||||||
|
if (props.config.filter === 'number') {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return props.config.activeValue;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return undefined;
|
||||||
activeValue: computed(() => {
|
|
||||||
if (typeof props.config.activeValue === 'undefined') {
|
|
||||||
if (props.config.filter === 'number') {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return props.config.activeValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
}),
|
|
||||||
|
|
||||||
inactiveValue: computed(() => {
|
|
||||||
if (typeof props.config.inactiveValue === 'undefined') {
|
|
||||||
if (props.config.filter === 'number') {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return props.config.inactiveValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
}),
|
|
||||||
|
|
||||||
changeHandler(value: number | boolean) {
|
|
||||||
emit('change', value);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const inactiveValue = computed(() => {
|
||||||
|
if (typeof props.config.inactiveValue === 'undefined') {
|
||||||
|
if (props.config.filter === 'number') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return props.config.inactiveValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
const changeHandler = (value: number | boolean) => {
|
||||||
|
emit('change', value);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,44 +1,42 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-checkbox-group v-model="model[name]" :size="size" :disabled="disabled" @change="changeHandler">
|
<TMagicCheckboxGroup v-model="model[name]" :size="size" :disabled="disabled" @change="changeHandler">
|
||||||
<el-checkbox v-for="option in config.options" :label="option.value" :key="option.value"
|
<TMagicCheckbox
|
||||||
|
v-for="option in config.options"
|
||||||
|
:label="option.value"
|
||||||
|
:key="option.value"
|
||||||
|
:disabled="option.disabled"
|
||||||
>{{ option.text }}
|
>{{ option.text }}
|
||||||
</el-checkbox>
|
</TMagicCheckbox>
|
||||||
</el-checkbox-group>
|
</TMagicCheckboxGroup>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { defineComponent, PropType } from 'vue';
|
import { TMagicCheckbox, TMagicCheckboxGroup } from '@tmagic/design';
|
||||||
|
|
||||||
import { CheckboxGroupConfig } from '../schema';
|
import { CheckboxGroupConfig } from '../schema';
|
||||||
import fieldProps from '../utils/fieldProps';
|
|
||||||
import { useAddField } from '../utils/useAddField';
|
import { useAddField } from '../utils/useAddField';
|
||||||
|
|
||||||
export default defineComponent({
|
const props = defineProps<{
|
||||||
name: 'm-fields-checkbox-group',
|
config: CheckboxGroupConfig;
|
||||||
|
model: any;
|
||||||
|
initValues?: any;
|
||||||
|
values?: any;
|
||||||
|
name: string;
|
||||||
|
prop: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
size: 'mini' | 'small' | 'medium';
|
||||||
|
}>();
|
||||||
|
|
||||||
props: {
|
const emit = defineEmits(['change']);
|
||||||
...fieldProps,
|
|
||||||
config: {
|
|
||||||
type: Object as PropType<CheckboxGroupConfig>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
emits: ['change'],
|
useAddField(props.prop);
|
||||||
|
|
||||||
setup(props, { emit }) {
|
// 初始化选项
|
||||||
useAddField(props.prop);
|
if (props.model && !props.model[props.name]) {
|
||||||
|
props.model[props.name] = [];
|
||||||
|
}
|
||||||
|
|
||||||
// 初始化选项
|
const changeHandler = (v: Array<string | number | boolean>) => {
|
||||||
if (props.model && !props.model[props.name]) {
|
emit('change', v);
|
||||||
// eslint-disable-next-line no-param-reassign
|
};
|
||||||
props.model[props.name] = [];
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
changeHandler: (v: Array<string | number | boolean>) => {
|
|
||||||
emit('change', v);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-color-picker
|
<TMagicColorPicker
|
||||||
v-model="model[name]"
|
v-model="model[name]"
|
||||||
:size="size"
|
:size="size"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:showAlpha="true"
|
:showAlpha="true"
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
></el-color-picker>
|
></TMagicColorPicker>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { TMagicColorPicker } from '@tmagic/design';
|
||||||
|
|
||||||
import { ColorPickConfig } from '../schema';
|
import { ColorPickConfig } from '../schema';
|
||||||
import { useAddField } from '../utils/useAddField';
|
import { useAddField } from '../utils/useAddField';
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-date-picker
|
<TMagicDatePicker
|
||||||
v-model="model[name]"
|
v-model="model[name]"
|
||||||
type="date"
|
type="date"
|
||||||
:size="size"
|
:size="size"
|
||||||
@ -8,40 +8,34 @@
|
|||||||
:format="config.format"
|
:format="config.format"
|
||||||
:value-format="config.format || 'YYYY-MM-DD HH:mm:ss'"
|
:value-format="config.format || 'YYYY-MM-DD HH:mm:ss'"
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
></el-date-picker>
|
></TMagicDatePicker>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { defineComponent, PropType } from 'vue';
|
import { TMagicDatePicker } from '@tmagic/design';
|
||||||
|
|
||||||
import { datetimeFormatter } from '@tmagic/utils';
|
import { datetimeFormatter } from '@tmagic/utils';
|
||||||
|
|
||||||
import { DateConfig } from '../schema';
|
import { DateConfig } from '../schema';
|
||||||
import fieldProps from '../utils/fieldProps';
|
|
||||||
import { useAddField } from '../utils/useAddField';
|
import { useAddField } from '../utils/useAddField';
|
||||||
|
|
||||||
export default defineComponent({
|
const props = defineProps<{
|
||||||
name: 'm-fields-date',
|
config: DateConfig;
|
||||||
|
model: any;
|
||||||
|
initValues?: any;
|
||||||
|
values?: any;
|
||||||
|
name: string;
|
||||||
|
prop: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
size: 'mini' | 'small' | 'medium';
|
||||||
|
}>();
|
||||||
|
|
||||||
props: {
|
const emit = defineEmits(['change']);
|
||||||
...fieldProps,
|
|
||||||
config: {
|
|
||||||
type: Object as PropType<DateConfig>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
emits: ['change', 'input'],
|
useAddField(props.prop);
|
||||||
|
|
||||||
setup(props, { emit }) {
|
props.model[props.name] = datetimeFormatter(props.model[props.name], '');
|
||||||
useAddField(props.prop);
|
|
||||||
|
|
||||||
props.model[props.name] = datetimeFormatter(props.model[props.name], '');
|
const changeHandler = (v: string) => {
|
||||||
return {
|
emit('change', v);
|
||||||
changeHandler(v: string) {
|
};
|
||||||
emit('change', v);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-date-picker
|
<TMagicDatePicker
|
||||||
v-model="model[name]"
|
v-model="model[name]"
|
||||||
popper-class="magic-datetime-picker-popper"
|
popper-class="magic-datetime-picker-popper"
|
||||||
type="datetime"
|
type="datetime"
|
||||||
@ -10,49 +10,41 @@
|
|||||||
:value-format="config.valueFormat || 'YYYY-MM-DD HH:mm:ss'"
|
:value-format="config.valueFormat || 'YYYY-MM-DD HH:mm:ss'"
|
||||||
:default-time="config.defaultTime"
|
:default-time="config.defaultTime"
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
></el-date-picker>
|
></TMagicDatePicker>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { defineComponent, PropType } from 'vue';
|
import { TMagicDatePicker } from '@tmagic/design';
|
||||||
|
|
||||||
import { datetimeFormatter } from '@tmagic/utils';
|
import { datetimeFormatter } from '@tmagic/utils';
|
||||||
|
|
||||||
import { DateTimeConfig } from '../schema';
|
import { DateTimeConfig } from '../schema';
|
||||||
import fieldProps from '../utils/fieldProps';
|
|
||||||
import { useAddField } from '../utils/useAddField';
|
import { useAddField } from '../utils/useAddField';
|
||||||
|
|
||||||
export default defineComponent({
|
const props = defineProps<{
|
||||||
name: 'm-fields-datetime',
|
config: DateTimeConfig;
|
||||||
|
model: any;
|
||||||
|
initValues?: any;
|
||||||
|
values?: any;
|
||||||
|
name: string;
|
||||||
|
prop: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
size: 'mini' | 'small' | 'medium';
|
||||||
|
}>();
|
||||||
|
|
||||||
props: {
|
const emit = defineEmits(['change']);
|
||||||
...fieldProps,
|
|
||||||
config: {
|
|
||||||
type: Object as PropType<DateTimeConfig>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
emits: ['change'],
|
useAddField(props.prop);
|
||||||
|
|
||||||
setup(props, { emit }) {
|
const value = props.model?.[props.name].toString();
|
||||||
useAddField(props.prop);
|
if (props.model) {
|
||||||
|
if (value === 'Invalid Date') {
|
||||||
|
props.model[props.name] = '';
|
||||||
|
} else {
|
||||||
|
props.model[props.name] = datetimeFormatter(props.model[props.name], '', props.config.valueFormat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const value = props.model?.[props.name].toString();
|
const changeHandler = (v: string) => {
|
||||||
if (props.model) {
|
emit('change', v);
|
||||||
if (value === 'Invalid Date') {
|
};
|
||||||
props.model[props.name] = '';
|
|
||||||
} else {
|
|
||||||
props.model[props.name] = datetimeFormatter(props.model[props.name], '', props.config.valueFormat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
value,
|
|
||||||
changeHandler: (v: Date) => {
|
|
||||||
emit('change', v);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-date-picker
|
<TMagicDatePicker
|
||||||
v-model="value"
|
v-model="value"
|
||||||
type="datetimerange"
|
type="datetimerange"
|
||||||
range-separator="-"
|
range-separator="-"
|
||||||
@ -10,12 +10,13 @@
|
|||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:default-time="config.defaultTime"
|
:default-time="config.defaultTime"
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
></el-date-picker>
|
></TMagicDatePicker>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
|
|
||||||
|
import { TMagicDatePicker } from '@tmagic/design';
|
||||||
import { datetimeFormatter } from '@tmagic/utils';
|
import { datetimeFormatter } from '@tmagic/utils';
|
||||||
|
|
||||||
import { DaterangeConfig } from '../schema';
|
import { DaterangeConfig } from '../schema';
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="m-fields-dynamic-field">
|
<div class="m-fields-dynamic-field">
|
||||||
<el-form size="small">
|
<TMagicForm size="small">
|
||||||
<el-form-item v-for="key in Object.keys(fieldMap.value)" :key="key" :label="fieldLabelMap.value[key]">
|
<TMagicFormItem v-for="key in Object.keys(fieldMap.value)" :key="key" :label="fieldLabelMap.value[key]">
|
||||||
<el-input
|
<TMagicInput
|
||||||
v-model="fieldMap.value[key]"
|
v-model="fieldMap.value[key]"
|
||||||
:placeholder="fieldLabelMap.value[key]"
|
:placeholder="fieldLabelMap.value[key]"
|
||||||
@change="inputChangeHandler(key)"
|
@change="inputChangeHandler(key)"
|
||||||
></el-input>
|
></TMagicInput>
|
||||||
</el-form-item>
|
</TMagicFormItem>
|
||||||
</el-form>
|
</TMagicForm>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
/**
|
/**
|
||||||
* 动态表单,目前只支持input类型字段
|
* 动态表单,目前只支持input类型字段
|
||||||
* inputType: 'dynamic-field',
|
* inputType: 'dynamic-field',
|
||||||
@ -23,87 +23,73 @@
|
|||||||
* 特别注意!!!field的上一级必须extensible: true,才能保存未声明的字段
|
* 特别注意!!!field的上一级必须extensible: true,才能保存未声明的字段
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { defineComponent, onBeforeUnmount, PropType, reactive, watch } from 'vue';
|
import { onBeforeUnmount, reactive, watch } from 'vue';
|
||||||
|
|
||||||
|
import { TMagicForm, TMagicFormItem, TMagicInput } from '@tmagic/design';
|
||||||
|
|
||||||
import { DynamicFieldConfig } from '../schema';
|
import { DynamicFieldConfig } from '../schema';
|
||||||
import { getConfig } from '../utils/config';
|
import { getConfig } from '../utils/config';
|
||||||
import fieldProps from '../utils/fieldProps';
|
|
||||||
import { useAddField } from '../utils/useAddField';
|
import { useAddField } from '../utils/useAddField';
|
||||||
|
|
||||||
export default defineComponent({
|
const props = defineProps<{
|
||||||
name: 'm-fields-dynamic-field',
|
config: DynamicFieldConfig;
|
||||||
|
model: any;
|
||||||
|
initValues?: any;
|
||||||
|
values?: any;
|
||||||
|
name: string;
|
||||||
|
prop: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
size: 'mini' | 'small' | 'medium';
|
||||||
|
}>();
|
||||||
|
|
||||||
props: {
|
const emit = defineEmits(['change']);
|
||||||
...fieldProps,
|
|
||||||
config: {
|
|
||||||
type: Object as PropType<DynamicFieldConfig>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
emits: ['change'],
|
useAddField(props.prop);
|
||||||
|
|
||||||
setup(props, { emit }) {
|
const request = getConfig('request') as Function;
|
||||||
useAddField(props.prop);
|
const fieldMap = reactive<{ [key: string]: any }>({
|
||||||
|
value: {},
|
||||||
const request = getConfig('request') as Function;
|
|
||||||
const fieldMap = reactive<{ [key: string]: any }>({
|
|
||||||
value: {},
|
|
||||||
});
|
|
||||||
const fieldLabelMap = reactive<{ [key: string]: any }>({
|
|
||||||
value: {},
|
|
||||||
});
|
|
||||||
|
|
||||||
const changeFieldMap = async () => {
|
|
||||||
if (typeof props.config.returnFields !== 'function' || !props.model) return;
|
|
||||||
const fields = await props.config.returnFields(props.config, props.model, request);
|
|
||||||
fieldMap.value = {};
|
|
||||||
fieldLabelMap.value = {};
|
|
||||||
fields.forEach((v) => {
|
|
||||||
if (typeof v !== 'object' || v.name === undefined) return;
|
|
||||||
let oldVal = props.model?.[v.name] || '';
|
|
||||||
if (!oldVal && v.defaultValue !== undefined) {
|
|
||||||
oldVal = v.defaultValue;
|
|
||||||
emit('change', oldVal, v.name);
|
|
||||||
}
|
|
||||||
fieldMap.value[v.name] = oldVal;
|
|
||||||
fieldLabelMap.value[v.name] = v.label || '';
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const unwatch = watch(
|
|
||||||
() => props.model?.[props.config.dynamicKey],
|
|
||||||
(val) => {
|
|
||||||
if (val !== '') {
|
|
||||||
changeFieldMap();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
immediate: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
if (typeof unwatch === 'function') {
|
|
||||||
unwatch();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
request,
|
|
||||||
fieldMap,
|
|
||||||
fieldLabelMap,
|
|
||||||
unwatch,
|
|
||||||
|
|
||||||
changeFieldMap,
|
|
||||||
inputChangeHandler: (key: string) => {
|
|
||||||
emit('change', fieldMap.value[key], key);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
init() {},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
const fieldLabelMap = reactive<{ [key: string]: any }>({
|
||||||
|
value: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
const changeFieldMap = async () => {
|
||||||
|
if (typeof props.config.returnFields !== 'function' || !props.model) return;
|
||||||
|
const fields = await props.config.returnFields(props.config, props.model, request);
|
||||||
|
fieldMap.value = {};
|
||||||
|
fieldLabelMap.value = {};
|
||||||
|
fields.forEach((v) => {
|
||||||
|
if (typeof v !== 'object' || v.name === undefined) return;
|
||||||
|
let oldVal = props.model?.[v.name] || '';
|
||||||
|
if (!oldVal && v.defaultValue !== undefined) {
|
||||||
|
oldVal = v.defaultValue;
|
||||||
|
emit('change', oldVal, v.name);
|
||||||
|
}
|
||||||
|
fieldMap.value[v.name] = oldVal;
|
||||||
|
fieldLabelMap.value[v.name] = v.label || '';
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const unwatch = watch(
|
||||||
|
() => props.model?.[props.config.dynamicKey],
|
||||||
|
(val) => {
|
||||||
|
if (val !== '') {
|
||||||
|
changeFieldMap();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
if (typeof unwatch === 'function') {
|
||||||
|
unwatch();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const inputChangeHandler = (key: string) => {
|
||||||
|
emit('change', fieldMap.value[key], key);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
<a v-if="config.href && !disabled" target="_blank" :href="href" :style="config.css || {}">{{ displayText }}</a>
|
<a v-if="config.href && !disabled" target="_blank" :href="href" :style="config.css || {}">{{ displayText }}</a>
|
||||||
<span v-else-if="config.href && disabled" :style="config.disabledCss || {}">{{ displayText }}</span>
|
<span v-else-if="config.href && disabled" :style="config.disabledCss || {}">{{ displayText }}</span>
|
||||||
<div v-else class="m-fields-link">
|
<div v-else class="m-fields-link">
|
||||||
<el-button text type="primary" @click="editHandler">点击编辑</el-button>
|
<TMagicButton :text="true" type="primary" @click="editHandler">点击编辑</TMagicButton>
|
||||||
<m-form-dialog
|
<FormDialog
|
||||||
ref="editor"
|
ref="editor"
|
||||||
:title="config.formTitle || '编辑扩展配置'"
|
:title="config.formTitle || '编辑扩展配置'"
|
||||||
:width="config.formWidth"
|
:width="config.formWidth"
|
||||||
@ -12,101 +12,80 @@
|
|||||||
:parentValues="values"
|
:parentValues="values"
|
||||||
:fullscreen="config.fullscreen"
|
:fullscreen="config.fullscreen"
|
||||||
@submit="action"
|
@submit="action"
|
||||||
></m-form-dialog>
|
></FormDialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { computed, defineComponent, inject, PropType, ref } from 'vue';
|
import { computed, inject, ref } from 'vue';
|
||||||
|
|
||||||
|
import { TMagicButton } from '@tmagic/design';
|
||||||
|
|
||||||
import FormDialog from '../FormDialog.vue';
|
import FormDialog from '../FormDialog.vue';
|
||||||
import { FormState, LinkConfig } from '../schema';
|
import { FormState, LinkConfig } from '../schema';
|
||||||
import fieldProps from '../utils/fieldProps';
|
|
||||||
import { useAddField } from '../utils/useAddField';
|
import { useAddField } from '../utils/useAddField';
|
||||||
|
|
||||||
export default defineComponent({
|
const props = defineProps<{
|
||||||
name: 'm-fields-link',
|
config: LinkConfig;
|
||||||
|
model: any;
|
||||||
|
initValues?: any;
|
||||||
|
values?: any;
|
||||||
|
name: string;
|
||||||
|
prop: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
size: 'mini' | 'small' | 'medium';
|
||||||
|
}>();
|
||||||
|
|
||||||
props: {
|
const emit = defineEmits(['change']);
|
||||||
...fieldProps,
|
|
||||||
config: {
|
|
||||||
type: Object as PropType<LinkConfig>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
emits: ['change'],
|
useAddField(props.prop);
|
||||||
|
|
||||||
setup(props, { emit }) {
|
const formValue = ref({});
|
||||||
useAddField(props.prop);
|
const editor = ref<InstanceType<typeof FormDialog>>();
|
||||||
|
const mForm = inject<FormState | undefined>('mForm');
|
||||||
|
|
||||||
const formValue = ref({});
|
const href = computed(() => {
|
||||||
const editor = ref<InstanceType<typeof FormDialog>>();
|
if (typeof props.config.href === 'function' && props.model) {
|
||||||
const mForm = inject<FormState | undefined>('mForm');
|
return props.config.href(props.model);
|
||||||
|
}
|
||||||
const href = computed(() => {
|
return props.config.href || props.model?.[props.name];
|
||||||
if (typeof props.config.href === 'function' && props.model) {
|
|
||||||
return props.config.href(props.model);
|
|
||||||
}
|
|
||||||
return props.config.href || props.model?.[props.name];
|
|
||||||
});
|
|
||||||
|
|
||||||
const init = () => {
|
|
||||||
formValue.value = props.model?.[props.name] || {};
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
// ref
|
|
||||||
formValue,
|
|
||||||
editor,
|
|
||||||
|
|
||||||
// computed methods
|
|
||||||
href,
|
|
||||||
|
|
||||||
formConfig: computed(() => {
|
|
||||||
if (typeof props.config.form === 'function') {
|
|
||||||
return props.config.form(mForm, {
|
|
||||||
model: props.model || {},
|
|
||||||
values: props.values || {},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return props.config.form;
|
|
||||||
}),
|
|
||||||
|
|
||||||
disable: computed(() => {
|
|
||||||
if (typeof props.config.disabled !== 'undefined') {
|
|
||||||
return props.config.disabled;
|
|
||||||
}
|
|
||||||
return !href.value;
|
|
||||||
}),
|
|
||||||
|
|
||||||
displayText: computed(() => {
|
|
||||||
if (typeof props.config.displayText === 'function') {
|
|
||||||
return props.config.displayText(mForm, { model: props.model || {} });
|
|
||||||
}
|
|
||||||
if (props.config.displayText) {
|
|
||||||
return props.config.displayText;
|
|
||||||
}
|
|
||||||
return '跳转';
|
|
||||||
}),
|
|
||||||
|
|
||||||
// methods
|
|
||||||
init,
|
|
||||||
|
|
||||||
editHandler: () => {
|
|
||||||
init();
|
|
||||||
editor.value && (editor.value.dialogVisible = true);
|
|
||||||
},
|
|
||||||
|
|
||||||
action: (data: any) => {
|
|
||||||
if (props.model) {
|
|
||||||
props.model[props.name] = data;
|
|
||||||
formValue.value = data;
|
|
||||||
emit('change', props.model[props.name]);
|
|
||||||
}
|
|
||||||
editor.value && (editor.value.dialogVisible = false);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const init = () => {
|
||||||
|
formValue.value = props.model?.[props.name] || {};
|
||||||
|
};
|
||||||
|
|
||||||
|
const formConfig = computed(() => {
|
||||||
|
if (typeof props.config.form === 'function') {
|
||||||
|
return props.config.form(mForm, {
|
||||||
|
model: props.model || {},
|
||||||
|
values: props.values || {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return props.config.form;
|
||||||
|
});
|
||||||
|
|
||||||
|
const displayText = computed(() => {
|
||||||
|
if (typeof props.config.displayText === 'function') {
|
||||||
|
return props.config.displayText(mForm, { model: props.model || {} });
|
||||||
|
}
|
||||||
|
if (props.config.displayText) {
|
||||||
|
return props.config.displayText;
|
||||||
|
}
|
||||||
|
return '跳转';
|
||||||
|
});
|
||||||
|
|
||||||
|
const editHandler = () => {
|
||||||
|
init();
|
||||||
|
editor.value && (editor.value.dialogVisible = true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const action = (data: any) => {
|
||||||
|
if (props.model) {
|
||||||
|
props.model[props.name] = data;
|
||||||
|
formValue.value = data;
|
||||||
|
emit('change', props.model[props.name]);
|
||||||
|
}
|
||||||
|
editor.value && (editor.value.dialogVisible = false);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-input-number
|
<TMagicInputNumber
|
||||||
v-if="model"
|
v-if="model"
|
||||||
v-model="model[name]"
|
v-model="model[name]"
|
||||||
clearable
|
clearable
|
||||||
@ -12,42 +12,40 @@
|
|||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
@input="inputHandler"
|
@input="inputHandler"
|
||||||
></el-input-number>
|
></TMagicInputNumber>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { defineComponent, inject, PropType } from 'vue';
|
import { inject } from 'vue';
|
||||||
|
|
||||||
|
import { TMagicInputNumber } from '@tmagic/design';
|
||||||
|
|
||||||
import { FormState, NumberConfig } from '../schema';
|
import { FormState, NumberConfig } from '../schema';
|
||||||
import fieldProps from '../utils/fieldProps';
|
|
||||||
import { useAddField } from '../utils/useAddField';
|
import { useAddField } from '../utils/useAddField';
|
||||||
export default defineComponent({
|
|
||||||
name: 'm-fields-number',
|
|
||||||
|
|
||||||
props: {
|
const props = defineProps<{
|
||||||
...fieldProps,
|
config: NumberConfig;
|
||||||
config: {
|
model: any;
|
||||||
type: Object as PropType<NumberConfig>,
|
initValues?: any;
|
||||||
required: true,
|
values?: any;
|
||||||
},
|
name: string;
|
||||||
},
|
prop: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
size: 'mini' | 'small' | 'medium';
|
||||||
|
}>();
|
||||||
|
|
||||||
emits: ['change', 'input'],
|
const emit = defineEmits(['change', 'input']);
|
||||||
|
|
||||||
setup(props, { emit }) {
|
useAddField(props.prop);
|
||||||
useAddField(props.prop);
|
|
||||||
|
|
||||||
const mForm = inject<FormState | null>('mForm');
|
const mForm = inject<FormState | null>('mForm');
|
||||||
return {
|
|
||||||
mForm,
|
const changeHandler = (value: number) => {
|
||||||
changeHandler: (value: number) => {
|
emit('change', value);
|
||||||
emit('change', value);
|
};
|
||||||
},
|
|
||||||
inputHandler: (v: string) => {
|
const inputHandler = (v: string) => {
|
||||||
emit('input', v);
|
emit('input', v);
|
||||||
mForm?.$emit('field-input', props.prop, v);
|
mForm?.$emit('field-input', props.prop, v);
|
||||||
},
|
};
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,33 +1,33 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-radio-group v-if="model" v-model="model[name]" :size="size" :disabled="disabled" @change="changeHandler">
|
<TMagicRadioGroup v-if="model" v-model="model[name]" :size="size" :disabled="disabled" @change="changeHandler">
|
||||||
<el-radio v-for="option in config.options" :label="option.value" :key="option.value">{{ option.text }}</el-radio>
|
<TMagicRadio v-for="option in config.options" :label="option.value" :key="`${option.value}`">{{
|
||||||
</el-radio-group>
|
option.text
|
||||||
|
}}</TMagicRadio>
|
||||||
|
</TMagicRadioGroup>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { defineComponent } from 'vue';
|
import { TMagicRadio, TMagicRadioGroup } from '@tmagic/design';
|
||||||
|
|
||||||
import fieldProps from '../utils/fieldProps';
|
import { RadioGroupConfig } from '../schema';
|
||||||
import { useAddField } from '../utils/useAddField';
|
import { useAddField } from '../utils/useAddField';
|
||||||
|
|
||||||
export default defineComponent({
|
const props = defineProps<{
|
||||||
name: 'm-fields-radio-group',
|
config: RadioGroupConfig;
|
||||||
|
model: any;
|
||||||
|
initValues?: any;
|
||||||
|
values?: any;
|
||||||
|
name: string;
|
||||||
|
prop: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
size: 'mini' | 'small' | 'medium';
|
||||||
|
}>();
|
||||||
|
|
||||||
props: {
|
const emit = defineEmits(['change']);
|
||||||
...fieldProps,
|
|
||||||
config: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
emits: ['change'],
|
const changeHandler = (value: number) => {
|
||||||
|
emit('change', value);
|
||||||
|
};
|
||||||
|
|
||||||
setup(props, { emit }) {
|
useAddField(props.prop);
|
||||||
useAddField(props.prop);
|
|
||||||
return {
|
|
||||||
changeHandler: (v: string | number | boolean) => emit('change', v),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-select
|
<TMagicSelect
|
||||||
v-if="model"
|
v-if="model"
|
||||||
v-model="model[name]"
|
v-model="model[name]"
|
||||||
v-loading="loading"
|
v-loading="loading"
|
||||||
class="m-select"
|
class="m-select"
|
||||||
ref="select"
|
ref="tMagicSelect"
|
||||||
clearable
|
clearable
|
||||||
filterable
|
filterable
|
||||||
:popper-class="`m-select-popper ${popperClass}`"
|
:popper-class="`m-select-popper ${popperClass}`"
|
||||||
@ -19,346 +19,330 @@
|
|||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
@visible-change="visibleHandler"
|
@visible-change="visibleHandler"
|
||||||
>
|
>
|
||||||
<template v-if="config.group"><select-option-groups :options="groupOptions"></select-option-groups></template>
|
<template v-if="config.group"><SelectOptionGroups :options="groupOptions"></SelectOptionGroups></template>
|
||||||
<template v-else><select-options :options="options"></select-options></template>
|
<template v-else><SelectOptions :options="itemOptions"></SelectOptions></template>
|
||||||
<div v-loading="true" v-if="moreLoadingVisible"></div>
|
<div v-loading="true" v-if="moreLoadingVisible"></div>
|
||||||
</el-select>
|
</TMagicSelect>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { defineComponent, inject, onBeforeMount, onMounted, PropType, Ref, ref, watchEffect } from 'vue';
|
import { inject, nextTick, onBeforeMount, onMounted, Ref, ref, watchEffect } from 'vue';
|
||||||
|
|
||||||
|
import { TMagicSelect } from '@tmagic/design';
|
||||||
|
|
||||||
import { FormState, SelectConfig, SelectGroupOption, SelectOption } from '../schema';
|
import { FormState, SelectConfig, SelectGroupOption, SelectOption } from '../schema';
|
||||||
import { getConfig } from '../utils/config';
|
import { getConfig } from '../utils/config';
|
||||||
import fieldProps from '../utils/fieldProps';
|
|
||||||
import { useAddField } from '../utils/useAddField';
|
import { useAddField } from '../utils/useAddField';
|
||||||
|
|
||||||
import SelectOptionGroups from './SelectOptionGroups.vue';
|
import SelectOptionGroups from './SelectOptionGroups.vue';
|
||||||
import SelectOptions from './SelectOptions.vue';
|
import SelectOptions from './SelectOptions.vue';
|
||||||
|
|
||||||
export default defineComponent({
|
const props = defineProps<{
|
||||||
name: 'm-fields-select',
|
config: SelectConfig;
|
||||||
|
model: any;
|
||||||
|
initValues?: any;
|
||||||
|
values?: any;
|
||||||
|
name: string;
|
||||||
|
prop: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
size: 'mini' | 'small' | 'medium';
|
||||||
|
}>();
|
||||||
|
|
||||||
components: { SelectOptions, SelectOptionGroups },
|
const emit = defineEmits(['change']);
|
||||||
|
|
||||||
props: {
|
if (!props.model) throw new Error('不能没有model');
|
||||||
...fieldProps,
|
useAddField(props.prop);
|
||||||
config: {
|
|
||||||
type: Object as PropType<SelectConfig>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
emits: ['change'],
|
const tMagicSelect = ref<InstanceType<typeof TMagicSelect>>();
|
||||||
|
const mForm = inject<FormState | undefined>('mForm');
|
||||||
|
const options = ref<SelectOption[] | SelectGroupOption[]>([]);
|
||||||
|
const localOptions = ref<SelectOption[] | SelectGroupOption[]>([]);
|
||||||
|
const loading = ref(false);
|
||||||
|
const moreLoadingVisible = ref(false);
|
||||||
|
const total = ref(0);
|
||||||
|
const pgIndex = ref(0);
|
||||||
|
const pgSize = ref(20);
|
||||||
|
const query = ref('');
|
||||||
|
const remoteData = ref<any[]>([]);
|
||||||
|
const remote = ref(true);
|
||||||
|
|
||||||
setup(props, { emit }) {
|
const equalValue = (value: any, v: any): boolean => {
|
||||||
if (!props.model) throw new Error('不能没有model');
|
if (typeof v === 'object') {
|
||||||
useAddField(props.prop);
|
const key = props.config.valueKey || 'value';
|
||||||
|
return v[key] === value[key];
|
||||||
|
}
|
||||||
|
|
||||||
const select = ref<any>();
|
return value === v;
|
||||||
const mForm = inject<FormState | undefined>('mForm');
|
};
|
||||||
const options = ref<SelectOption[] | SelectGroupOption[]>([]);
|
|
||||||
const localOptions = ref<SelectOption[] | SelectGroupOption[]>([]);
|
|
||||||
const loading = ref(false);
|
|
||||||
const moreLoadingVisible = ref(false);
|
|
||||||
const total = ref(0);
|
|
||||||
const pgIndex = ref(0);
|
|
||||||
const pgSize = ref(20);
|
|
||||||
const query = ref('');
|
|
||||||
const remoteData = ref<any[]>([]);
|
|
||||||
const remote = ref(true);
|
|
||||||
|
|
||||||
const equalValue = (value: any, v: any): boolean => {
|
const mapOptions = (data: any[]) => {
|
||||||
if (typeof v === 'object') {
|
const { option } = props.config;
|
||||||
const key = props.config.valueKey || 'value';
|
const { text } = option;
|
||||||
return v[key] === value[key];
|
const { value } = option;
|
||||||
}
|
|
||||||
|
|
||||||
return value === v;
|
return data.map((item) => ({
|
||||||
};
|
text: typeof text === 'function' ? text(item) : item[text || 'text'],
|
||||||
|
value: typeof value === 'function' ? value(item) : item[value || 'value'],
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
const mapOptions = (data: any[]) => {
|
const getOptions = async () => {
|
||||||
const { option } = props.config;
|
if (!props.model) return [];
|
||||||
const { text } = option;
|
|
||||||
const { value } = option;
|
|
||||||
|
|
||||||
return data.map((item) => ({
|
if (localOptions.value.length) {
|
||||||
text: typeof text === 'function' ? text(item) : item[text || 'text'],
|
return localOptions.value;
|
||||||
value: typeof value === 'function' ? value(item) : item[value || 'value'],
|
}
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
const getOptions = async () => {
|
loading.value = true;
|
||||||
if (!props.model) return [];
|
|
||||||
|
|
||||||
if (localOptions.value.length) {
|
let items: SelectOption[] | SelectGroupOption[] = [];
|
||||||
return localOptions.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
loading.value = true;
|
const { config } = props;
|
||||||
|
const { option } = config;
|
||||||
|
let { body } = option;
|
||||||
|
|
||||||
let items: SelectOption[] | SelectGroupOption[] = [];
|
let postOptions: Record<string, any> = {
|
||||||
|
method: option.method || 'POST',
|
||||||
|
url: option.url,
|
||||||
|
cache: option.cache,
|
||||||
|
timeout: option.timeout,
|
||||||
|
mode: option.mode,
|
||||||
|
headers: option.headers || {},
|
||||||
|
json: option.json || false,
|
||||||
|
};
|
||||||
|
|
||||||
const { config } = props;
|
if (body) {
|
||||||
const { option } = config;
|
if (typeof body === 'function') {
|
||||||
let { body } = option;
|
body = body(mForm, {
|
||||||
|
model: props.model,
|
||||||
let postOptions: Record<string, any> = {
|
formValue: mForm?.values,
|
||||||
method: option.method || 'POST',
|
formValues: mForm?.values,
|
||||||
url: option.url,
|
config: props.config,
|
||||||
cache: option.cache,
|
}) as Record<string, any>;
|
||||||
timeout: option.timeout,
|
|
||||||
mode: option.mode,
|
|
||||||
headers: option.headers || {},
|
|
||||||
json: option.json || false,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (body) {
|
|
||||||
if (typeof body === 'function') {
|
|
||||||
body = body(mForm, {
|
|
||||||
model: props.model,
|
|
||||||
formValue: mForm?.values,
|
|
||||||
formValues: mForm?.values,
|
|
||||||
config: props.config,
|
|
||||||
}) as Record<string, any>;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.query = query.value;
|
|
||||||
body.pgSize = pgSize.value;
|
|
||||||
body.pgIndex = pgIndex.value;
|
|
||||||
postOptions.data = body;
|
|
||||||
}
|
|
||||||
|
|
||||||
const requestFuc = getConfig('request') as Function;
|
|
||||||
|
|
||||||
if (typeof option.beforeRequest === 'function') {
|
|
||||||
postOptions = option.beforeRequest(mForm, postOptions, {
|
|
||||||
model: props.model,
|
|
||||||
formValue: mForm?.values,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (option.method?.toLocaleLowerCase() === 'jsonp') {
|
|
||||||
postOptions.jsonpCallback = option.jsonpCallback || 'callback';
|
|
||||||
}
|
|
||||||
|
|
||||||
let res = await requestFuc(postOptions);
|
|
||||||
|
|
||||||
if (typeof option.afterRequest === 'function') {
|
|
||||||
res = option.afterRequest(mForm, res, {
|
|
||||||
model: props.model,
|
|
||||||
formValue: mForm?.values,
|
|
||||||
formValues: mForm?.values,
|
|
||||||
config: props.config,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const optionsData = res[option.root];
|
|
||||||
|
|
||||||
if (res.total > 0) {
|
|
||||||
total.value = res.total;
|
|
||||||
}
|
|
||||||
|
|
||||||
remoteData.value = remoteData.value.concat(optionsData);
|
|
||||||
if (optionsData) {
|
|
||||||
if (typeof option.item === 'function') {
|
|
||||||
items = option.item(optionsData);
|
|
||||||
} else if (optionsData.map) {
|
|
||||||
items = mapOptions(optionsData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
loading.value = false;
|
|
||||||
|
|
||||||
// 多选过滤时会导致已选的选项显示不了,所以要把已选的选项保留不要过滤没了
|
|
||||||
const selectedOptions: SelectOption[] | SelectGroupOption[] = [];
|
|
||||||
if (props.config.multiple && props.model[props.name]) {
|
|
||||||
options.value.forEach((o: any) => {
|
|
||||||
const isInclude = props.model?.[props.name].includes(o.value);
|
|
||||||
if (isInclude && !(items as any[]).find((op: any) => op.value === o.value)) {
|
|
||||||
selectedOptions.push(o);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return pgIndex.value === 0 ? (selectedOptions as any[]).concat(items) : (options.value as any).concat(items);
|
|
||||||
};
|
|
||||||
|
|
||||||
const getInitLocalOption = async () => {
|
|
||||||
if (!props.model) return [];
|
|
||||||
|
|
||||||
const value = props.model[props.name];
|
|
||||||
const { config } = props;
|
|
||||||
localOptions.value = await getOptions();
|
|
||||||
|
|
||||||
remote.value = false;
|
|
||||||
|
|
||||||
if (config.group) {
|
|
||||||
if (config.multiple && value.findIndex) {
|
|
||||||
return (localOptions.value as SelectGroupOption[]).filter(
|
|
||||||
(group) => group.options.findIndex((item) => value.find((v: any) => equalValue(item.value, v)) > -1) > -1,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (localOptions.value as SelectGroupOption[]).filter(
|
|
||||||
(group) => group.options.findIndex((item) => equalValue(item.value, value)) > -1,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.multiple && value.findIndex) {
|
|
||||||
return (localOptions.value as any[]).filter(
|
|
||||||
(item) => value.findIndex((v: any) => equalValue(item.value, v)) > -1,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (localOptions.value as any[]).filter((item) => equalValue(item.value, value));
|
|
||||||
};
|
|
||||||
|
|
||||||
const getInitOption = async () => {
|
|
||||||
if (!props.model) return [];
|
|
||||||
|
|
||||||
const { config } = props;
|
|
||||||
const { option } = config;
|
|
||||||
|
|
||||||
let options: SelectOption[] | SelectGroupOption[] = [];
|
|
||||||
|
|
||||||
let url = option.initUrl;
|
|
||||||
if (!url) {
|
|
||||||
return getInitLocalOption();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof url === 'function') {
|
|
||||||
url = await url(mForm, { model: props.model, formValue: mForm?.values });
|
|
||||||
}
|
|
||||||
|
|
||||||
const postOptions: Record<string, any> = {
|
|
||||||
method: option.method || 'POST',
|
|
||||||
url,
|
|
||||||
data: {
|
|
||||||
id: props.model[props.name],
|
|
||||||
},
|
|
||||||
mode: option.mode,
|
|
||||||
headers: option.headers || {},
|
|
||||||
json: option.json || false,
|
|
||||||
};
|
|
||||||
if (option.method?.toLocaleLowerCase() === 'jsonp') {
|
|
||||||
postOptions.jsonpCallback = option.jsonpCallback || 'callback';
|
|
||||||
}
|
|
||||||
|
|
||||||
const requestFuc = getConfig('request') as Function;
|
|
||||||
const res = await requestFuc(postOptions);
|
|
||||||
|
|
||||||
let initData = res[option.root];
|
|
||||||
if (initData) {
|
|
||||||
if (!Array.isArray(initData)) {
|
|
||||||
initData = [initData];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof option.item === 'function') {
|
|
||||||
options = option.item(initData);
|
|
||||||
} else if (initData.map) {
|
|
||||||
options = mapOptions(initData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return options;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (typeof props.config.options === 'function') {
|
|
||||||
watchEffect(() => {
|
|
||||||
typeof props.config.options === 'function' &&
|
|
||||||
Promise.resolve(
|
|
||||||
props.config.options(mForm, {
|
|
||||||
model: props.model,
|
|
||||||
prop: props.prop,
|
|
||||||
formValues: mForm?.values,
|
|
||||||
formValue: mForm?.values,
|
|
||||||
config: props.config,
|
|
||||||
}),
|
|
||||||
).then((data) => {
|
|
||||||
options.value = data;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else if (Array.isArray(props.config.options)) {
|
|
||||||
watchEffect(() => {
|
|
||||||
options.value = props.config.options as SelectOption[] | SelectGroupOption[];
|
|
||||||
});
|
|
||||||
} else if (props.config.option) {
|
|
||||||
onBeforeMount(() => {
|
|
||||||
if (!props.model) return;
|
|
||||||
const v = props.model[props.name];
|
|
||||||
if (Array.isArray(v) ? v.length : typeof v !== 'undefined') {
|
|
||||||
getInitOption().then((data) => {
|
|
||||||
options.value = data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
props.config.remote &&
|
body.query = query.value;
|
||||||
onMounted(() => {
|
body.pgSize = pgSize.value;
|
||||||
select.value?.scrollbar.wrap$.addEventListener('scroll', async (e: Event) => {
|
body.pgIndex = pgIndex.value;
|
||||||
const el = e.currentTarget as HTMLDivElement;
|
postOptions.data = body;
|
||||||
if (moreLoadingVisible.value) {
|
}
|
||||||
return;
|
|
||||||
}
|
const requestFuc = getConfig('request') as Function;
|
||||||
if (el.scrollHeight - el.clientHeight - el.scrollTop > 1) {
|
|
||||||
return;
|
if (typeof option.beforeRequest === 'function') {
|
||||||
}
|
postOptions = option.beforeRequest(mForm, postOptions, {
|
||||||
if (total.value <= options.value.length) {
|
model: props.model,
|
||||||
return;
|
formValue: mForm?.values,
|
||||||
}
|
});
|
||||||
moreLoadingVisible.value = true;
|
}
|
||||||
pgIndex.value += 1;
|
|
||||||
options.value = await getOptions();
|
if (option.method?.toLocaleLowerCase() === 'jsonp') {
|
||||||
moreLoadingVisible.value = false;
|
postOptions.jsonpCallback = option.jsonpCallback || 'callback';
|
||||||
});
|
}
|
||||||
|
|
||||||
|
let res = await requestFuc(postOptions);
|
||||||
|
|
||||||
|
if (typeof option.afterRequest === 'function') {
|
||||||
|
res = option.afterRequest(mForm, res, {
|
||||||
|
model: props.model,
|
||||||
|
formValue: mForm?.values,
|
||||||
|
formValues: mForm?.values,
|
||||||
|
config: props.config,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const optionsData = res[option.root];
|
||||||
|
|
||||||
|
if (res.total > 0) {
|
||||||
|
total.value = res.total;
|
||||||
|
}
|
||||||
|
|
||||||
|
remoteData.value = remoteData.value.concat(optionsData);
|
||||||
|
if (optionsData) {
|
||||||
|
if (typeof option.item === 'function') {
|
||||||
|
items = option.item(optionsData);
|
||||||
|
} else if (optionsData.map) {
|
||||||
|
items = mapOptions(optionsData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = false;
|
||||||
|
|
||||||
|
// 多选过滤时会导致已选的选项显示不了,所以要把已选的选项保留不要过滤没了
|
||||||
|
const selectedOptions: SelectOption[] | SelectGroupOption[] = [];
|
||||||
|
if (props.config.multiple && props.model[props.name]) {
|
||||||
|
options.value.forEach((o: any) => {
|
||||||
|
const isInclude = props.model?.[props.name].includes(o.value);
|
||||||
|
if (isInclude && !(items as any[]).find((op: any) => op.value === o.value)) {
|
||||||
|
selectedOptions.push(o);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return pgIndex.value === 0 ? (selectedOptions as any[]).concat(items) : (options.value as any).concat(items);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getInitLocalOption = async () => {
|
||||||
|
if (!props.model) return [];
|
||||||
|
|
||||||
|
const value = props.model[props.name];
|
||||||
|
const { config } = props;
|
||||||
|
localOptions.value = await getOptions();
|
||||||
|
|
||||||
|
remote.value = false;
|
||||||
|
|
||||||
|
if (config.group) {
|
||||||
|
if (config.multiple && value.findIndex) {
|
||||||
|
return (localOptions.value as SelectGroupOption[]).filter(
|
||||||
|
(group) => group.options.findIndex((item) => value.find((v: any) => equalValue(item.value, v)) > -1) > -1,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (localOptions.value as SelectGroupOption[]).filter(
|
||||||
|
(group) => group.options.findIndex((item) => equalValue(item.value, value)) > -1,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.multiple && value.findIndex) {
|
||||||
|
return (localOptions.value as any[]).filter((item) => value.findIndex((v: any) => equalValue(item.value, v)) > -1);
|
||||||
|
}
|
||||||
|
return (localOptions.value as any[]).filter((item) => equalValue(item.value, value));
|
||||||
|
};
|
||||||
|
|
||||||
|
const getInitOption = async () => {
|
||||||
|
if (!props.model) return [];
|
||||||
|
|
||||||
|
const { config } = props;
|
||||||
|
const { option } = config;
|
||||||
|
|
||||||
|
let options: SelectOption[] | SelectGroupOption[] = [];
|
||||||
|
|
||||||
|
let url = option.initUrl;
|
||||||
|
if (!url) {
|
||||||
|
return getInitLocalOption();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof url === 'function') {
|
||||||
|
url = await url(mForm, { model: props.model, formValue: mForm?.values });
|
||||||
|
}
|
||||||
|
|
||||||
|
const postOptions: Record<string, any> = {
|
||||||
|
method: option.method || 'POST',
|
||||||
|
url,
|
||||||
|
data: {
|
||||||
|
id: props.model[props.name],
|
||||||
|
},
|
||||||
|
mode: option.mode,
|
||||||
|
headers: option.headers || {},
|
||||||
|
json: option.json || false,
|
||||||
|
};
|
||||||
|
if (option.method?.toLocaleLowerCase() === 'jsonp') {
|
||||||
|
postOptions.jsonpCallback = option.jsonpCallback || 'callback';
|
||||||
|
}
|
||||||
|
|
||||||
|
const requestFuc = getConfig('request') as Function;
|
||||||
|
const res = await requestFuc(postOptions);
|
||||||
|
|
||||||
|
let initData = res[option.root];
|
||||||
|
if (initData) {
|
||||||
|
if (!Array.isArray(initData)) {
|
||||||
|
initData = [initData];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof option.item === 'function') {
|
||||||
|
options = option.item(initData);
|
||||||
|
} else if (initData.map) {
|
||||||
|
options = mapOptions(initData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return options;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof props.config.options === 'function') {
|
||||||
|
watchEffect(() => {
|
||||||
|
typeof props.config.options === 'function' &&
|
||||||
|
Promise.resolve(
|
||||||
|
props.config.options(mForm, {
|
||||||
|
model: props.model,
|
||||||
|
prop: props.prop,
|
||||||
|
formValues: mForm?.values,
|
||||||
|
formValue: mForm?.values,
|
||||||
|
config: props.config,
|
||||||
|
}),
|
||||||
|
).then((data) => {
|
||||||
|
options.value = data;
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
} else if (Array.isArray(props.config.options)) {
|
||||||
|
watchEffect(() => {
|
||||||
|
options.value = props.config.options as SelectOption[] | SelectGroupOption[];
|
||||||
|
});
|
||||||
|
} else if (props.config.option) {
|
||||||
|
onBeforeMount(() => {
|
||||||
|
if (!props.model) return;
|
||||||
|
const v = props.model[props.name];
|
||||||
|
if (Array.isArray(v) ? v.length : typeof v !== 'undefined') {
|
||||||
|
getInitOption().then((data) => {
|
||||||
|
options.value = data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
props.config.remote &&
|
||||||
select,
|
onMounted(async () => {
|
||||||
loading,
|
await nextTick();
|
||||||
remote,
|
tMagicSelect.value?.scrollbarWrap?.addEventListener('scroll', async (e: Event) => {
|
||||||
options: options as Ref<SelectOption[]>,
|
const el = e.currentTarget as HTMLDivElement;
|
||||||
groupOptions: options as Ref<SelectGroupOption[]>,
|
if (moreLoadingVisible.value) {
|
||||||
moreLoadingVisible,
|
return;
|
||||||
popperClass: mForm?.popperClass,
|
}
|
||||||
|
if (el.scrollHeight - el.clientHeight - el.scrollTop > 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (total.value <= options.value.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
moreLoadingVisible.value = true;
|
||||||
|
pgIndex.value += 1;
|
||||||
|
options.value = await getOptions();
|
||||||
|
moreLoadingVisible.value = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
getOptions,
|
const popperClass = mForm?.popperClass;
|
||||||
|
|
||||||
getRequestFuc() {
|
const changeHandler = (value: any) => {
|
||||||
return getConfig('request');
|
emit('change', value);
|
||||||
},
|
};
|
||||||
|
|
||||||
changeHandler(value: any) {
|
const visibleHandler = async (visible: boolean) => {
|
||||||
emit('change', value);
|
if (!visible) return;
|
||||||
},
|
|
||||||
|
|
||||||
async visibleHandler(visible: boolean) {
|
if (!props.config.remote) return;
|
||||||
if (!visible) return;
|
if (query.value && tMagicSelect.value) {
|
||||||
|
tMagicSelect.value.setQuery(query.value);
|
||||||
|
tMagicSelect.value.setPreviousQuery(query.value);
|
||||||
|
tMagicSelect.value.setSelectedLabel(query.value);
|
||||||
|
} else if (options.value.length <= (props.config.multiple ? props.model?.[props.name].length : 1)) {
|
||||||
|
options.value = await getOptions();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (!props.config.remote) return;
|
const remoteMethod = async (q: string) => {
|
||||||
if (query.value && select.value) {
|
if (!localOptions.value.length) {
|
||||||
select.value.query = query.value;
|
query.value = q;
|
||||||
select.value.previousQuery = query.value;
|
pgIndex.value = 0;
|
||||||
select.value.selectedLabel = query.value;
|
options.value = await getOptions();
|
||||||
} else if (options.value.length <= (props.config.multiple ? props.model?.[props.name].length : 1)) {
|
// 多选时如果过滤选项会导致已选好的标签异常,需要重新刷新一下el-select的状态
|
||||||
options.value = await getOptions();
|
if (props.config.multiple)
|
||||||
}
|
setTimeout(() => {
|
||||||
},
|
tMagicSelect.value?.setSelected();
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
async remoteMethod(q: string) {
|
const itemOptions = options as Ref<SelectOption[]>;
|
||||||
if (!localOptions.value.length) {
|
const groupOptions = options as Ref<SelectGroupOption[]>;
|
||||||
query.value = q;
|
|
||||||
pgIndex.value = 0;
|
|
||||||
options.value = await getOptions();
|
|
||||||
// 多选时如果过滤选项会导致已选好的标签异常,需要重新刷新一下el-select的状态
|
|
||||||
if (props.config.multiple)
|
|
||||||
setTimeout(() => {
|
|
||||||
select.value?.setSelected();
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-option-group v-for="(group, index) in options" :key="index" :label="group.label" :disabled="group.disabled">
|
<TMagicOptionGroup v-for="(group, index) in options" :key="index" :label="group.label" :disabled="group.disabled">
|
||||||
<el-option
|
<TMagicOption
|
||||||
v-for="(item, index) in group.options"
|
v-for="(item, index) in group.options"
|
||||||
:key="index"
|
:key="index"
|
||||||
:label="item.label"
|
:label="item.label"
|
||||||
:value="item.value"
|
:value="item.value"
|
||||||
:disabled="item.disabled"
|
:disabled="item.disabled"
|
||||||
>
|
>
|
||||||
</el-option>
|
</TMagicOption>
|
||||||
</el-option-group>
|
</TMagicOptionGroup>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { TMagicOption, TMagicOptionGroup } from '@tmagic/design';
|
||||||
|
|
||||||
import { SelectGroupOption } from '../schema';
|
import { SelectGroupOption } from '../schema';
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-option
|
<TMagicOption
|
||||||
v-for="option in options"
|
v-for="option in options"
|
||||||
:label="option.text"
|
:label="option.text"
|
||||||
:value="option.value"
|
:value="option.value"
|
||||||
:key="valueKey ? option.value[valueKey] : option.value"
|
:key="valueKey ? option.value[valueKey] : option.value"
|
||||||
:disabled="option.disabled"
|
:disabled="option.disabled"
|
||||||
></el-option>
|
></TMagicOption>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { TMagicOption } from '@tmagic/design';
|
||||||
|
|
||||||
import { SelectOption } from '../schema';
|
import { SelectOption } from '../schema';
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
|
@ -1,65 +1,62 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-switch
|
<TMagicSwitch
|
||||||
v-if="model"
|
v-model="model[name]"
|
||||||
v-model="model[n]"
|
|
||||||
:size="size"
|
:size="size"
|
||||||
:activeValue="activeValue"
|
:activeValue="activeValue"
|
||||||
:inactiveValue="inactiveValue"
|
:inactiveValue="inactiveValue"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
></el-switch>
|
></TMagicSwitch>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { computed, defineComponent, PropType } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
import { TMagicSwitch } from '@tmagic/design';
|
||||||
|
|
||||||
import { SwitchConfig } from '../schema';
|
import { SwitchConfig } from '../schema';
|
||||||
import fieldProps from '../utils/fieldProps';
|
|
||||||
import { useAddField } from '../utils/useAddField';
|
import { useAddField } from '../utils/useAddField';
|
||||||
export default defineComponent({
|
|
||||||
name: 'm-fields-switch',
|
|
||||||
|
|
||||||
props: {
|
const props = defineProps<{
|
||||||
...fieldProps,
|
config: SwitchConfig;
|
||||||
config: {
|
model: any;
|
||||||
type: Object as PropType<SwitchConfig>,
|
initValues?: any;
|
||||||
required: true,
|
values?: any;
|
||||||
},
|
name: string;
|
||||||
},
|
prop: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
size: 'mini' | 'small' | 'medium';
|
||||||
|
}>();
|
||||||
|
|
||||||
emits: ['change'],
|
const emit = defineEmits(['change']);
|
||||||
|
|
||||||
setup(props, { emit }) {
|
useAddField(props.prop);
|
||||||
useAddField(props.prop);
|
|
||||||
|
|
||||||
return {
|
const changeHandler = (value: number) => {
|
||||||
n: computed(() => props.name || props.config.name || ''),
|
emit('change', value);
|
||||||
activeValue: computed(() => {
|
};
|
||||||
if (typeof props.config.activeValue === 'undefined') {
|
|
||||||
if (props.config.filter === 'number') {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return props.config.activeValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
const activeValue = computed(() => {
|
||||||
}),
|
if (typeof props.config.activeValue === 'undefined') {
|
||||||
inactiveValue: computed(() => {
|
if (props.config.filter === 'number') {
|
||||||
if (typeof props.config.inactiveValue === 'undefined') {
|
return 1;
|
||||||
if (props.config.filter === 'number') {
|
}
|
||||||
return 0;
|
} else {
|
||||||
}
|
return props.config.activeValue;
|
||||||
} else {
|
}
|
||||||
return props.config.inactiveValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return true;
|
||||||
}),
|
});
|
||||||
changeHandler: (v: boolean | number | string) => {
|
|
||||||
emit('change', v);
|
const inactiveValue = computed(() => {
|
||||||
},
|
if (typeof props.config.inactiveValue === 'undefined') {
|
||||||
};
|
if (props.config.filter === 'number') {
|
||||||
},
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return props.config.inactiveValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-input
|
<TMagicInput
|
||||||
v-model="model[modelName]"
|
v-model="model[name]"
|
||||||
clearable
|
clearable
|
||||||
:size="size"
|
:size="size"
|
||||||
:placeholder="config.placeholder"
|
:placeholder="config.placeholder"
|
||||||
@ -20,117 +20,109 @@
|
|||||||
{{ config.append.text }}
|
{{ config.append.text }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</TMagicInput>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { computed, defineComponent, inject, PropType } from 'vue';
|
import { inject } from 'vue';
|
||||||
|
|
||||||
|
import { TMagicInput } from '@tmagic/design';
|
||||||
import { isNumber } from '@tmagic/utils';
|
import { isNumber } from '@tmagic/utils';
|
||||||
|
|
||||||
import { FormState, TextConfig } from '../schema';
|
import { FormState, TextConfig } from '../schema';
|
||||||
import fieldProps from '../utils/fieldProps';
|
|
||||||
import { useAddField } from '../utils/useAddField';
|
import { useAddField } from '../utils/useAddField';
|
||||||
|
|
||||||
export default defineComponent({
|
const props = defineProps<{
|
||||||
name: 'm-fields-text',
|
config: TextConfig;
|
||||||
|
model: any;
|
||||||
|
initValues?: any;
|
||||||
|
values?: any;
|
||||||
|
name: string;
|
||||||
|
prop: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
size: 'mini' | 'small' | 'medium';
|
||||||
|
}>();
|
||||||
|
|
||||||
props: {
|
const emit = defineEmits(['change', 'input']);
|
||||||
...fieldProps,
|
|
||||||
config: {
|
|
||||||
type: Object as PropType<TextConfig>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
emits: ['change', 'input'],
|
useAddField(props.prop);
|
||||||
|
|
||||||
setup(props, { emit }) {
|
const mForm = inject<FormState | undefined>('mForm');
|
||||||
const mForm = inject<FormState | undefined>('mForm');
|
|
||||||
|
|
||||||
useAddField(props.prop);
|
const changeHandler = (value: number) => {
|
||||||
|
emit('change', value);
|
||||||
|
};
|
||||||
|
|
||||||
const modelName = computed(() => props.name || props.config.name || '');
|
const inputHandler = (v: string) => {
|
||||||
return {
|
emit('input', v);
|
||||||
modelName,
|
mForm?.$emit('field-input', props.prop, v);
|
||||||
|
};
|
||||||
|
|
||||||
changeHandler(v: string | number) {
|
const buttonClickHandler = () => {
|
||||||
emit('change', v);
|
if (typeof props.config.append === 'string') return;
|
||||||
},
|
|
||||||
|
|
||||||
inputHandler(v: string | number) {
|
if (props.config.append?.handler) {
|
||||||
emit('input', v);
|
props.config.append.handler(mForm, {
|
||||||
mForm?.$emit('field-input', props.prop, v);
|
model: props.model,
|
||||||
},
|
values: mForm?.values,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
buttonClickHandler() {
|
const keyUpHandler = ($event: KeyboardEvent) => {
|
||||||
if (typeof props.config.append === 'string') return;
|
if (!props.model) return;
|
||||||
|
if (!props.name) return;
|
||||||
|
|
||||||
if (props.config.append?.handler) {
|
const arrowUp = $event.key === 'ArrowUp';
|
||||||
props.config.append.handler(mForm, {
|
const arrowDown = $event.key === 'ArrowDown';
|
||||||
model: props.model,
|
|
||||||
values: mForm?.values,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
keyUpHandler($event: KeyboardEvent) {
|
if (!arrowUp && !arrowDown) {
|
||||||
if (!props.model) return;
|
return;
|
||||||
if (!modelName.value) return;
|
}
|
||||||
|
|
||||||
const arrowUp = $event.key === 'ArrowUp';
|
const value = props.model[props.name];
|
||||||
const arrowDown = $event.key === 'ArrowDown';
|
let num;
|
||||||
|
let unit;
|
||||||
|
if (isNumber(value)) {
|
||||||
|
num = +value;
|
||||||
|
} else {
|
||||||
|
value.replace(/^([0-9.]+)([a-z%]+)$/, ($0: string, $1: string, $2: string) => {
|
||||||
|
num = +$1;
|
||||||
|
unit = $2;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (!arrowUp && !arrowDown) {
|
if (num === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const value = props.model[modelName.value];
|
const ctrl = navigator.platform.match('Mac') ? $event.metaKey : $event.ctrlKey;
|
||||||
let num;
|
const shift = $event.shiftKey;
|
||||||
let unit;
|
const alt = $event.altKey;
|
||||||
if (isNumber(value)) {
|
|
||||||
num = +value;
|
|
||||||
} else {
|
|
||||||
value.replace(/^([0-9.]+)([a-z%]+)$/, ($0: string, $1: string, $2: string) => {
|
|
||||||
num = +$1;
|
|
||||||
unit = $2;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (num === undefined) {
|
if (arrowUp) {
|
||||||
return;
|
if (ctrl) {
|
||||||
}
|
num += 100;
|
||||||
|
} else if (alt) {
|
||||||
|
num = (num * 10000 + 1000) / 10000;
|
||||||
|
} else if (shift) {
|
||||||
|
num = num + 10;
|
||||||
|
} else {
|
||||||
|
num += 1;
|
||||||
|
}
|
||||||
|
} else if (arrowDown) {
|
||||||
|
if (ctrl) {
|
||||||
|
num -= 100;
|
||||||
|
} else if (alt) {
|
||||||
|
num = (num * 10000 - 1000) / 10000;
|
||||||
|
} else if (shift) {
|
||||||
|
num -= 10;
|
||||||
|
} else {
|
||||||
|
num -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const ctrl = navigator.platform.match('Mac') ? $event.metaKey : $event.ctrlKey;
|
props.model[props.name] = `${num}${unit || ''}`;
|
||||||
const shift = $event.shiftKey;
|
emit('change', props.model[props.name]);
|
||||||
const alt = $event.altKey;
|
};
|
||||||
|
|
||||||
if (arrowUp) {
|
|
||||||
if (ctrl) {
|
|
||||||
num += 100;
|
|
||||||
} else if (alt) {
|
|
||||||
num = (num * 10000 + 1000) / 10000;
|
|
||||||
} else if (shift) {
|
|
||||||
num = num + 10;
|
|
||||||
} else {
|
|
||||||
num += 1;
|
|
||||||
}
|
|
||||||
} else if (arrowDown) {
|
|
||||||
if (ctrl) {
|
|
||||||
num -= 100;
|
|
||||||
} else if (alt) {
|
|
||||||
num = (num * 10000 - 1000) / 10000;
|
|
||||||
} else if (shift) {
|
|
||||||
num -= 10;
|
|
||||||
} else {
|
|
||||||
num -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
props.model[modelName.value] = `${num}${unit || ''}`;
|
|
||||||
emit('change', props.model[modelName.value]);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-input
|
<TMagicInput
|
||||||
v-model="model[name]"
|
v-model="model[name]"
|
||||||
type="textarea"
|
type="textarea"
|
||||||
:size="size"
|
:size="size"
|
||||||
@ -9,52 +9,40 @@
|
|||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
@input="inputHandler"
|
@input="inputHandler"
|
||||||
>
|
>
|
||||||
</el-input>
|
</TMagicInput>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { defineComponent, inject, PropType } from 'vue';
|
import { inject } from 'vue';
|
||||||
|
|
||||||
|
import { TMagicInput } from '@tmagic/design';
|
||||||
|
|
||||||
import { FormState, TextareaConfig } from '../schema';
|
import { FormState, TextareaConfig } from '../schema';
|
||||||
import fieldProps from '../utils/fieldProps';
|
|
||||||
import { useAddField } from '../utils/useAddField';
|
import { useAddField } from '../utils/useAddField';
|
||||||
export default defineComponent({
|
|
||||||
name: 'm-fields-textarea',
|
|
||||||
|
|
||||||
props: {
|
const props = defineProps<{
|
||||||
...fieldProps,
|
config: TextareaConfig;
|
||||||
config: {
|
model: any;
|
||||||
type: Object as PropType<TextareaConfig>,
|
initValues?: any;
|
||||||
required: true,
|
values?: any;
|
||||||
},
|
name: string;
|
||||||
},
|
prop: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
size: 'mini' | 'small' | 'medium';
|
||||||
|
}>();
|
||||||
|
|
||||||
emits: {
|
const emit = defineEmits(['change', 'input']);
|
||||||
change(values: string | number) {
|
|
||||||
return values;
|
|
||||||
},
|
|
||||||
|
|
||||||
input(values: string | number) {
|
useAddField(props.prop);
|
||||||
return values;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
setup(props, { emit }) {
|
const mForm = inject<FormState | null>('mForm');
|
||||||
useAddField(props.prop);
|
|
||||||
|
|
||||||
const mForm = inject<FormState | null>('mForm');
|
const changeHandler = (value: number) => {
|
||||||
|
emit('change', value);
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
const inputHandler = (v: string) => {
|
||||||
mForm,
|
emit('input', v);
|
||||||
changeHandler: (v: string) => {
|
mForm?.$emit('field-input', props.prop, v);
|
||||||
emit('change', v);
|
};
|
||||||
},
|
|
||||||
|
|
||||||
inputHandler: (v: string) => {
|
|
||||||
emit('input', v);
|
|
||||||
mForm?.$emit('field-input', props.prop, v);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,46 +1,35 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-time-picker
|
<TMagicTimePicker
|
||||||
v-model="model[name]"
|
v-model="model[name]"
|
||||||
:size="size"
|
:size="size"
|
||||||
value-format="HH:mm:ss"
|
|
||||||
:placeholder="config.placeholder"
|
:placeholder="config.placeholder"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
></el-time-picker>
|
></TMagicTimePicker>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { defineComponent, PropType } from 'vue';
|
import { TMagicTimePicker } from '@tmagic/design';
|
||||||
|
|
||||||
import { TimeConfig } from '../schema';
|
import { TimeConfig } from '../schema';
|
||||||
import fieldProps from '../utils/fieldProps';
|
|
||||||
import { useAddField } from '../utils/useAddField';
|
import { useAddField } from '../utils/useAddField';
|
||||||
|
|
||||||
export default defineComponent({
|
const props = defineProps<{
|
||||||
name: 'm-fields-time',
|
config: TimeConfig;
|
||||||
|
model: any;
|
||||||
|
initValues?: any;
|
||||||
|
values?: any;
|
||||||
|
name: string;
|
||||||
|
prop: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
size: 'mini' | 'small' | 'medium';
|
||||||
|
}>();
|
||||||
|
|
||||||
props: {
|
const emit = defineEmits(['change']);
|
||||||
...fieldProps,
|
|
||||||
config: {
|
|
||||||
type: Object as PropType<TimeConfig>,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
emits: {
|
useAddField(props.prop);
|
||||||
change(values: Date) {
|
|
||||||
return values;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
setup(props, { emit }) {
|
const changeHandler = (v: string) => {
|
||||||
useAddField(props.prop);
|
emit('change', v);
|
||||||
|
};
|
||||||
return {
|
|
||||||
changeHandler: (v: Date) => {
|
|
||||||
emit('change', v);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
import { App } from 'vue';
|
import { App } from 'vue';
|
||||||
|
|
||||||
|
import TMagicDesign from '@tmagic/design';
|
||||||
|
|
||||||
import Container from './containers/Container.vue';
|
import Container from './containers/Container.vue';
|
||||||
import Fieldset from './containers/Fieldset.vue';
|
import Fieldset from './containers/Fieldset.vue';
|
||||||
import GroupList from './containers/GroupList.vue';
|
import GroupList from './containers/GroupList.vue';
|
||||||
@ -53,7 +55,6 @@ import './theme/index.scss';
|
|||||||
export * from './schema';
|
export * from './schema';
|
||||||
export * from './utils/form';
|
export * from './utils/form';
|
||||||
export * from './utils/useAddField';
|
export * from './utils/useAddField';
|
||||||
export { default as fieldProps } from './utils/fieldProps';
|
|
||||||
|
|
||||||
export { default as MForm } from './Form.vue';
|
export { default as MForm } from './Form.vue';
|
||||||
export { default as MFormDialog } from './FormDialog.vue';
|
export { default as MFormDialog } from './FormDialog.vue';
|
||||||
@ -86,40 +87,42 @@ export { default as MDynamicField } from './fields/DynamicField.vue';
|
|||||||
const defaultInstallOpt = {};
|
const defaultInstallOpt = {};
|
||||||
|
|
||||||
const install = (app: App, opt: any) => {
|
const install = (app: App, opt: any) => {
|
||||||
|
app.use(TMagicDesign, opt.uiAdapter);
|
||||||
|
|
||||||
const option = Object.assign(defaultInstallOpt, opt);
|
const option = Object.assign(defaultInstallOpt, opt);
|
||||||
|
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
app.config.globalProperties.$MAGIC_FORM = option;
|
app.config.globalProperties.$MAGIC_FORM = option;
|
||||||
setConfig(option);
|
setConfig(option);
|
||||||
|
|
||||||
app.component(Form.name, Form);
|
app.component('m-form', Form);
|
||||||
app.component(FormDialog.name, FormDialog);
|
app.component('m-form-dialog', FormDialog);
|
||||||
app.component(Container.name, Container);
|
app.component('m-form-container', Container);
|
||||||
app.component('m-form-fieldset', Fieldset);
|
app.component('m-form-fieldset', Fieldset);
|
||||||
app.component(GroupList.name, GroupList);
|
app.component('m-form-group-list', GroupList);
|
||||||
app.component(Panel.name, Panel);
|
app.component('m-form-panel', Panel);
|
||||||
app.component(Row.name, Row);
|
app.component('m-form-row', Row);
|
||||||
app.component(MStep.name, MStep);
|
app.component('m-form-step', MStep);
|
||||||
app.component('m-form-table', Table);
|
app.component('m-form-table', Table);
|
||||||
app.component(Tabs.name, Tabs);
|
app.component('m-form-tab', Tabs);
|
||||||
app.component(Text.name, Text);
|
app.component('m-fields-text', Text);
|
||||||
app.component(Number.name, Number);
|
app.component('m-fields-number', Number);
|
||||||
app.component(Textarea.name, Textarea);
|
app.component('m-fields-textarea', Textarea);
|
||||||
app.component('m-fields-hidden', Hidden);
|
app.component('m-fields-hidden', Hidden);
|
||||||
app.component(Date.name, Date);
|
app.component('m-fields-date', Date);
|
||||||
app.component(DateTime.name, DateTime);
|
app.component('m-fields-datetime', DateTime);
|
||||||
app.component(Time.name, Time);
|
|
||||||
app.component(Checkbox.name, Checkbox);
|
|
||||||
app.component(Switch.name, Switch);
|
|
||||||
app.component('m-fields-daterange', Daterange);
|
app.component('m-fields-daterange', Daterange);
|
||||||
|
app.component('m-fields-time', Time);
|
||||||
|
app.component('m-fields-checkbox', Checkbox);
|
||||||
|
app.component('m-fields-switch', Switch);
|
||||||
app.component('m-fields-color-picker', ColorPicker);
|
app.component('m-fields-color-picker', ColorPicker);
|
||||||
app.component(CheckboxGroup.name, CheckboxGroup);
|
app.component('m-fields-checkbox-group', CheckboxGroup);
|
||||||
app.component(RadioGroup.name, RadioGroup);
|
app.component('m-fields-radio-group', RadioGroup);
|
||||||
app.component('m-fields-display', Display);
|
app.component('m-fields-display', Display);
|
||||||
app.component(Link.name, Link);
|
app.component('m-fields-link', Link);
|
||||||
app.component(Select.name, Select);
|
app.component('m-fields-select', Select);
|
||||||
app.component(Cascader.name, Cascader);
|
app.component('m-fields-cascader', Cascader);
|
||||||
app.component(DynamicField.name, DynamicField);
|
app.component('m-fields-dynamic-field', DynamicField);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -16,6 +16,11 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
export interface ValidateError {
|
||||||
|
message: string;
|
||||||
|
field: string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 整个表单的数据,会注入到各个组件中去
|
* 整个表单的数据,会注入到各个组件中去
|
||||||
*/
|
*/
|
||||||
@ -167,7 +172,7 @@ type DefaultValueFunction = (mForm: FormState | undefined) => any;
|
|||||||
/**
|
/**
|
||||||
* 下拉选择器选项配置
|
* 下拉选择器选项配置
|
||||||
*/
|
*/
|
||||||
export interface SelectOption {
|
export interface SelectConfigOption {
|
||||||
/** 选项的标签 */
|
/** 选项的标签 */
|
||||||
text: string | SelectOptionTextFunction;
|
text: string | SelectOptionTextFunction;
|
||||||
/** 选项的值 */
|
/** 选项的值 */
|
||||||
@ -176,10 +181,19 @@ export interface SelectOption {
|
|||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SelectOption {
|
||||||
|
/** 选项的标签 */
|
||||||
|
text: string;
|
||||||
|
/** 选项的值 */
|
||||||
|
value: any;
|
||||||
|
/** 是否禁用该选项 */
|
||||||
|
disabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下拉选择器分组选项配置
|
* 下拉选择器分组选项配置
|
||||||
*/
|
*/
|
||||||
export interface SelectGroupOption {
|
export interface SelectConfigGroupOption {
|
||||||
/** 分组的组名 */
|
/** 分组的组名 */
|
||||||
label: string;
|
label: string;
|
||||||
/** 是否禁用该选项组 */
|
/** 是否禁用该选项组 */
|
||||||
@ -194,6 +208,21 @@ export interface SelectGroupOption {
|
|||||||
}[];
|
}[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SelectGroupOption {
|
||||||
|
/** 分组的组名 */
|
||||||
|
label: string;
|
||||||
|
/** 是否禁用该选项组 */
|
||||||
|
disabled: boolean;
|
||||||
|
options: {
|
||||||
|
/** 选项的标签 */
|
||||||
|
label: string;
|
||||||
|
/** 选项的值 */
|
||||||
|
value: any;
|
||||||
|
/** 是否禁用该选项 */
|
||||||
|
disabled?: boolean;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
type SelectOptionFunction = (
|
type SelectOptionFunction = (
|
||||||
mForm: FormState | undefined,
|
mForm: FormState | undefined,
|
||||||
data: {
|
data: {
|
||||||
@ -226,11 +255,11 @@ type RemoteSelectOptionRequestFunction = (
|
|||||||
},
|
},
|
||||||
) => any;
|
) => any;
|
||||||
|
|
||||||
type RemoteSelectOptionItemFunction = (optionsData: Record<string, any>) => SelectOption[];
|
type RemoteSelectOptionItemFunction = (optionsData: Record<string, any>) => SelectOption[] | SelectGroupOption[];
|
||||||
type SelectOptionValueFunction = (item: Record<string, any>) => any;
|
type SelectOptionValueFunction = (item: Record<string, any>) => any;
|
||||||
type SelectOptionTextFunction = (item: Record<string, any>) => string;
|
type SelectOptionTextFunction = (item: Record<string, any>) => string;
|
||||||
|
|
||||||
interface CascaderOption {
|
export interface CascaderOption {
|
||||||
/** 指定选项的值为选项对象的某个属性值 */
|
/** 指定选项的值为选项对象的某个属性值 */
|
||||||
value: any;
|
value: any;
|
||||||
/** 指定选项标签为选项对象的某个属性值 */
|
/** 指定选项标签为选项对象的某个属性值 */
|
||||||
@ -302,7 +331,7 @@ export interface NumberConfig extends FormItem {
|
|||||||
min?: number;
|
min?: number;
|
||||||
max?: number;
|
max?: number;
|
||||||
step?: number;
|
step?: number;
|
||||||
placeholder?: number;
|
placeholder?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -361,7 +390,7 @@ export interface SwitchConfig extends FormItem {
|
|||||||
export interface RadioGroupConfig extends FormItem {
|
export interface RadioGroupConfig extends FormItem {
|
||||||
type: 'radio-group';
|
type: 'radio-group';
|
||||||
options: {
|
options: {
|
||||||
values: string | number | boolean;
|
value: string | number | boolean;
|
||||||
text: string;
|
text: string;
|
||||||
}[];
|
}[];
|
||||||
}
|
}
|
||||||
@ -381,6 +410,7 @@ export interface CheckboxGroupConfig extends FormItem {
|
|||||||
options: {
|
options: {
|
||||||
value: any;
|
value: any;
|
||||||
text: string;
|
text: string;
|
||||||
|
disabled?: boolean;
|
||||||
}[];
|
}[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,7 +424,7 @@ export interface SelectConfig extends FormItem, Input {
|
|||||||
valueKey?: string;
|
valueKey?: string;
|
||||||
allowCreate?: boolean;
|
allowCreate?: boolean;
|
||||||
group?: boolean;
|
group?: boolean;
|
||||||
options: SelectOption[] | SelectGroupOption[] | SelectOptionFunction;
|
options: SelectConfigOption[] | SelectConfigGroupOption[] | SelectOptionFunction;
|
||||||
remote: true;
|
remote: true;
|
||||||
option: {
|
option: {
|
||||||
url: string;
|
url: string;
|
||||||
@ -520,7 +550,7 @@ export interface TabPaneConfig {
|
|||||||
}
|
}
|
||||||
export interface TabConfig extends FormItem, ContainerCommonConfig {
|
export interface TabConfig extends FormItem, ContainerCommonConfig {
|
||||||
type: 'tab' | 'dynamic-tab';
|
type: 'tab' | 'dynamic-tab';
|
||||||
tabType?: 'tab';
|
tabType?: string;
|
||||||
editable?: boolean;
|
editable?: boolean;
|
||||||
dynamic?: boolean;
|
dynamic?: boolean;
|
||||||
tabPosition?: 'top' | 'right' | 'bottom' | 'left';
|
tabPosition?: 'top' | 'right' | 'bottom' | 'left';
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { PropType } from 'vue';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
model: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
disabled: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
size: String as PropType<'mini' | 'small' | 'medium'>,
|
|
||||||
prop: String,
|
|
||||||
initValues: Object,
|
|
||||||
values: Object,
|
|
||||||
};
|
|
@ -30,7 +30,10 @@ export default defineConfig({
|
|||||||
alias:
|
alias:
|
||||||
process.env.NODE_ENV === 'production'
|
process.env.NODE_ENV === 'production'
|
||||||
? []
|
? []
|
||||||
: [{ find: /^@tmagic\/utils/, replacement: path.join(__dirname, '../utils/src/index.ts') }],
|
: [
|
||||||
|
{ find: /^@tmagic\/utils/, replacement: path.join(__dirname, '../utils/src/index.ts') },
|
||||||
|
{ find: /^@tmagic\/design/, replacement: path.join(__dirname, '../design/src/index.ts') },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
build: {
|
build: {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user