pda_uniapp/components/proQuery/proQuery.vue

197 lines
6.7 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<view class="pro-query">
<form @submit="formSubmit" @reset="formReset">
<!-- -->
<view class="cu-form-group" :class="{'margin-top': index === 0}" v-for="(item, index) in visibleItems"
:key="item.key">
<view class="title">{{ item.label }}</view>
<!-- 输入框 -->
<input v-if="item.type === 'input'" :placeholder="item.placeholder || '请输入'" :name="item.key"
v-model="formData[item.key]" :disabled="item.disabled || false" />
<!-- 多行文本框 -->
<textarea v-else-if="item.type === 'textarea'" :placeholder="item.placeholder || '请输入'"
v-model="formData[item.key]" :disabled="item.disabled || false"></textarea>
<!-- 数字输入框 -->
<input v-else-if="item.type === 'number'" type="number" :placeholder="item.placeholder || '请输入'"
v-model="formData[item.key]" :disabled="item.disabled || false" />
<!-- 下拉选择picker -->
<picker v-else-if="item.type === 'select'"
@change="(e) => { formData[item.key] = item.options[e.detail.value].value }" :range="item.options"
range-key="text" :disabled="item.disabled || false">
<view class="picker">
{{ formData[item.key] ? getOptionText(item.options, formData[item.key]) : '请选择' }}
</view>
</picker>
<!-- 开关 -->
<switch v-else-if="item.type === 'switch'" :checked="formData[item.key]"
@change="(e) => { formData[item.key] = e.detail.value }"
:class="formData[item.key] ? 'checked' : ''" :disabled="item.disabled || false"></switch>
<!-- 单选组 -->
<radio-group v-else-if="item.type === 'radio'" @change="(e) => { formData[item.key] = e.detail.value }">
<radio v-for="opt in item.options" :key="opt.value" :value="opt.value"
:checked="formData[item.key] === opt.value"
:class="formData[item.key] === opt.value ? 'checked' : ''" :disabled="item.disabled || false">
{{ opt.text }}
</radio>
</radio-group>
<!-- 复选组 -->
<checkbox-group v-else-if="item.type === 'checkbox'"
@change="(e) => { formData[item.key] = e.detail.value }">
<checkbox v-for="opt in item.options" :key="opt.value" :value="opt.value"
:checked="formData[item.key] && formData[item.key].includes(opt.value)"
:class="formData[item.key] && formData[item.key].includes(opt.value) ? 'checked' : ''"
:disabled="item.disabled || false">{{ opt.text }}</checkbox>
</checkbox-group>
<!-- 日期选择 -->
<picker v-else-if="item.type === 'datePicker'" mode="date" :value="formData[item.key]"
@change="(e) => { formData[item.key] = e.detail.value }" :disabled="item.disabled || false">
<view class="picker">{{ formData[item.key] || '选择日期' }}</view>
</picker>
<!-- 时间选择 -->
<picker v-else-if="item.type === 'timePicker'" mode="time" :value="formData[item.key]"
@change="(e) => { formData[item.key] = e.detail.value }" :disabled="item.disabled || false">
<view class="picker">{{ formData[item.key] || '选择时间' }}</view>
</picker>
<!-- 自定义插槽 -->
<slot v-else-if="item.type === 'custom'" :name="item.customRender" :data="formData"></slot>
<!-- 默认 fallback -->
<input v-else :placeholder="item.placeholder || '请输入'" v-model="formData[item.key]" />
</view>
<!-- 操作按钮 -->
<view class="padding flex justify-between cu-form-group">
<view class="flex">
<button class="cu-btn block bg-blue margin-tb-sm md" form-type="submit" :disabled="isLoading">
<view class="flex align-center justify-center">
<!-- 加载旋转动画 -->
<text v-if="isLoading" class="cuIcon-loading2 cuIconfont-spin"></text>
<text>{{ isLoading ? '提交中...' : submitText }}</text>
</view>
</button>
<button class="cu-btn block line-blue margin-tb-sm md" @click="formReset"
style="margin-left: 20rpx;">重置</button>
<!-- <button class="cu-btn block line-blue margin-tb-sm lg" form-type="reset" style="margin-left: 20rpx;">重置</button> -->
</view>
<view v-if="more" class="flex">
<view class="cu-btn line-blue" @click="hiddenHandle">
{{ hidden ? '' : '' }}
</view>
</view>
</view>
</form>
</view>
</template>
<script>
export default {
name: 'ProQuery',
props: {
// 表单项配置数组
searchParam: {
type: Array,
default: () => []
},
submitText: {
type: String,
default: () => '查询'
},
},
emits: ['on-search', 'on-reset'],
data() {
return {
formData: {}, // 表单数据对象
hidden: true, // 是否隐藏有 hidden 标记的项
more: false, // 是否有隐藏项
isLoading: false, //加载状态
};
},
computed: {
// 根据 hidden 状态过滤可见项
visibleItems() {
if (this.hidden) {
return this.searchParam.filter(item => !item.hidden);
}
return this.searchParam;
},
},
watch: {
searchParam: {
immediate: true,
handler(newVal) {
if (newVal && newVal.length) {
// 初始化 formData
const data = {};
let hasHidden = false;
newVal.forEach(item => {
data[item.key] = item.defaultValue ?? '';
if (item.hidden) hasHidden = true;
});
this.formData = data;
this.more = hasHidden;
}
}
}
},
methods: {
// 获取 select 选项的显示文本
getOptionText(options, value) {
const found = options.find(opt => opt.value === value);
return found ? found.text : '';
},
// 提交事件
// formSubmit(e) {
// // 如果使用原生表单e.detail.value 包含所有 name 字段,但我们已经使用 v-model直接传 formData
// this.$emit('on-search', {
// ...this.formData
// });
// },
// ★★★ 修改提交方法:增加加载控制 ★★★
formSubmit(e) {
if (this.isLoading) return;// 防止重复提交
this.isLoading = true;
// 定义完成回调,父组件异步处理结束后必须调用
const done = () => {
this.isLoading = false;
};
// 将表单数据和 done 回调一并传递给父组件
this.$emit('on-search', {
...this.formData
}, done);
},
// 重置事件
formReset(e) {
if (e) e.preventDefault();
const data = {};
this.searchParam.forEach(item => {
data[item.key] = item.defaultValue != null ? item.defaultValue : '';
});
this.formData = data;
this.isLoading = false; // 强制重置加载状态,避免卡死
this.$emit('on-reset');
},
// 展开/收起切换
hiddenHandle() {
this.hidden = !this.hidden;
}
}
};
</script>
<style scoped>
/* 保留文件1中关于标题宽度的样式 */
.cu-form-group .title {
min-width: calc(4em + 15px);
}
/* 其它 ColorUI 样式已在全局引入,此处无需重复定义 */
</style>