|
@@ -19,100 +19,43 @@
|
|
|
<a-step>结果</a-step>
|
|
|
</a-steps>
|
|
|
|
|
|
- <!-- 动态渲染表单数据 -->
|
|
|
- <template v-if="isShowArray">
|
|
|
- <keep-alive>
|
|
|
- <div class="steps-conter">
|
|
|
- <div>
|
|
|
- <div v-for="(item, index) in StepsData[current - 1]" :key="item.id || item.field">
|
|
|
- <div :style="{ width: width }" v-show="visibleShowMap[item.field]">
|
|
|
- <a-form-item :label="item.label" :rules="item.rules" :field="item.field"
|
|
|
- :validate-trigger="rulesTagse(item?.rules)">
|
|
|
- <!-- 使用 key 触发重新渲染 -->
|
|
|
- <component :is="'a-' + item.type" v-model="formState[item.field]"
|
|
|
- :placeholder="item.type === 'input' ? '请输入' : '请选择' + item.label" allow-clear
|
|
|
- :style="{ width: item.width ? item.width + 'px' : '' }"
|
|
|
- :key="formState[item.field]">
|
|
|
- <template v-if="item.type === 'select'">
|
|
|
- <a-option v-for="option in item.options" :key="option.value"
|
|
|
- :value="option.value">
|
|
|
- {{ option.label }}
|
|
|
- </a-option>
|
|
|
- </template>
|
|
|
- </component>
|
|
|
- </a-form-item>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </keep-alive>
|
|
|
- </template>
|
|
|
-
|
|
|
- <!-- 如果 StepsData 不是数组的格式,渲染单个表单项 -->
|
|
|
- <template v-if="!isShowArray">
|
|
|
- <component :is="'a-' + StepsData.type" v-model="StepsData.value"
|
|
|
- :placeholder="StepsData.type === 'input' ? '请输入' : '请选择' + StepsData.label" allow-clear
|
|
|
- :style="{ width: StepsData.width ? StepsData.width + 'px' : '' }">
|
|
|
- <template v-if="StepsData.type === 'select'">
|
|
|
- <a-option v-for="option in StepsData.options" :key="option.value" :value="option.value">
|
|
|
- {{ option.label }}
|
|
|
- </a-option>
|
|
|
- </template>
|
|
|
- </component>
|
|
|
- </template>
|
|
|
-
|
|
|
- <!-- 底部按钮 -->
|
|
|
- <div class="step-footer">
|
|
|
- <a-space size="large">
|
|
|
- <template v-if="isShowArray">
|
|
|
- <a-button type="secondary" :disabled="current <= 1" @click="onPrev">
|
|
|
- <IconLeft /> 上一步
|
|
|
- </a-button>
|
|
|
- <a-button type="primary" :disabled="current >= maxStep" @click="onNext" v-if="maxStep !== current">
|
|
|
- 下一步
|
|
|
- <IconRight />
|
|
|
- </a-button>
|
|
|
-
|
|
|
- <a-button type="primary" @click="onFinish" v-else>
|
|
|
- 确认
|
|
|
- </a-button>
|
|
|
- </template>
|
|
|
-
|
|
|
- <template v-if="!isShowArray">
|
|
|
- <a-button type="primary" @click="onCancel">
|
|
|
- 取消
|
|
|
- </a-button>
|
|
|
- <a-button type="primary" @click="onFinish">
|
|
|
- 确认
|
|
|
- </a-button>
|
|
|
- </template>
|
|
|
- </a-space>
|
|
|
+ <div class="form-container">
|
|
|
+ <div :style="{ width: width }">
|
|
|
+ <StepForm :StepsData="StepsData" :current="current" :isShowArray="isShowArray" />
|
|
|
+ </div>
|
|
|
</div>
|
|
|
+
|
|
|
+
|
|
|
+ <StepButton :current="current" :maxStep="maxStep" :isShowArray="isShowArray" :onPrev="onPrev" :onNext="onNext"
|
|
|
+ :onFinish="onFinish" />
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
import { ref, defineProps, toRefs, computed, defineEmits } from 'vue';
|
|
|
-
|
|
|
-// const StepsData = [
|
|
|
-// [
|
|
|
-// { type: 'select', label: '姓名', field: 'name', value: '',options:[], isVisible: (item, e) => {
|
|
|
-// if(e.gender=='male'){
|
|
|
-// item.options = [{ value: 'male', label: '男' }, { value: 'female', label: '女' }]
|
|
|
-// }
|
|
|
-// return e.gender=='male'
|
|
|
-// } },
|
|
|
-// { type: 'select', label: '性别', field: 'gender',value:"", options: [{ value: 'male', label: '男' }, { value: 'female', label: '女' }] },
|
|
|
-// ],
|
|
|
-// [
|
|
|
-// { type: 'input', label: '年龄', field: 'age', value: '' },
|
|
|
-// { type: 'input', label: '电话', field: 'phone', value: '' },
|
|
|
-// ],
|
|
|
-]
|
|
|
+import StepButton from './StepButton.vue'
|
|
|
+import StepForm from './StepForm.vue'
|
|
|
+// const StepsData =
|
|
|
const props = defineProps({
|
|
|
StepsData: {
|
|
|
type: Array,
|
|
|
- default: () => [] // 默认值设置为数组套数组
|
|
|
+ default: () => [
|
|
|
+ [
|
|
|
+ {
|
|
|
+ type: 'select', label: '姓名', field: 'name', value: '', options: [], isVisible: (item, e) => {
|
|
|
+ if (e.gender == 'male') {
|
|
|
+ item.options = [{ value: 'male', label: '男' }, { value: 'female', label: '女' }]
|
|
|
+ }
|
|
|
+ return e.gender == 'male'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { type: 'select', label: '性别', field: 'gender', value: "", options: [{ value: 'male', label: '男' }, { value: 'female', label: '女' }] },
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ { type: 'input', label: '年龄', field: 'age', value: '' },
|
|
|
+ { type: 'input', label: '电话', field: 'phone', value: '' },
|
|
|
+ ],
|
|
|
+ ] // 默认值设置为数组套数组
|
|
|
}, // 步骤条数据层
|
|
|
width: {
|
|
|
type: [String, Number],
|
|
@@ -128,56 +71,12 @@ const { StepsData, width } = toRefs(props);
|
|
|
const isShowArray = computed(() => Array.isArray(StepsData.value));
|
|
|
|
|
|
// 初始化表单状态
|
|
|
-const formState = ref({});
|
|
|
+
|
|
|
const current = ref(1);
|
|
|
const submitShow = ref(false)
|
|
|
// 计算最大步骤数
|
|
|
const maxStep = computed(() => (isShowArray.value ? StepsData.value.length : 1));
|
|
|
|
|
|
-// 初始化 formState
|
|
|
-if (isShowArray.value) {
|
|
|
- StepsData.value.forEach(step => {
|
|
|
- step.forEach(item => {
|
|
|
- if (item.field) {
|
|
|
- formState.value[item.field] = item.value;
|
|
|
- }
|
|
|
- });
|
|
|
- });
|
|
|
-} else if (StepsData.value && StepsData.value.value) {
|
|
|
- formState.value = StepsData.value.value;
|
|
|
-}
|
|
|
-
|
|
|
-// 使用 computed 来动态计算每个表单项的可见性
|
|
|
-const visibleShowMap = computed(() => {
|
|
|
- const visibilityMap = {};
|
|
|
- // 遍历每个步骤,计算每个表单项的可见性
|
|
|
- StepsData.value.forEach((step) => {
|
|
|
- step.forEach((item) => {
|
|
|
- if (item.field) {
|
|
|
- if (item.isVisible) {
|
|
|
- if (typeof item.isVisible === 'function') {
|
|
|
- // 如果 isVisible 是函数,执行并设置结果
|
|
|
- visibilityMap[item.field] = item.isVisible(item, formState.value);
|
|
|
- } else {
|
|
|
- // 否则直接使用 isVisible 的值
|
|
|
- visibilityMap[item.field] = item.isVisible;
|
|
|
- }
|
|
|
- } else {
|
|
|
- visibilityMap[item.field] = true; // 默认可见
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- return visibilityMap;
|
|
|
-});
|
|
|
-
|
|
|
-// 表单验证方式
|
|
|
-const rulesTagse = (item) => {
|
|
|
- if (!item) return ''
|
|
|
- return item[0]?.trigger
|
|
|
-}
|
|
|
-
|
|
|
// 上一步
|
|
|
const onPrev = () => {
|
|
|
current.value = Math.max(1, current.value - 1);
|
|
@@ -202,30 +101,21 @@ const onCancel = () => {
|
|
|
// 确认
|
|
|
const onFinish = () => {
|
|
|
emit('onSubmit', formState.value)
|
|
|
- current.value = Math.min(maxStep.value+1, current.value + 1);
|
|
|
+ current.value = Math.min(maxStep.value + 1, current.value + 1);
|
|
|
submitShow.value = true
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
|
-.step-footer {
|
|
|
- width: 100%;
|
|
|
- height: 200px;
|
|
|
- text-align: center;
|
|
|
- background: var(--color-bg-2);
|
|
|
- color: #C2C7CC;
|
|
|
- padding-top: 20px;
|
|
|
-}
|
|
|
-
|
|
|
-.steps-conter {
|
|
|
- display: flex;
|
|
|
- justify-content: center;
|
|
|
- margin-top: 20px;
|
|
|
-}
|
|
|
-
|
|
|
.header {
|
|
|
margin-bottom: 50px;
|
|
|
display: flex;
|
|
|
justify-content: end;
|
|
|
}
|
|
|
+
|
|
|
+.form-container{
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
</style>
|