| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393 |
- <template>
- <div>
- <a-form
- :model="form_values"
- :style="{ width: '100%' }"
- :rules="form_rules"
- class="dynamic-form-container-jfsdjaklfjsfjsdkalfjskaljsk"
- @submit="handleSubmit"
- >
- <template v-for="(item, index) of form_fields">
- <!-- 单行文本:数字 -->
- <a-form-item v-if="item.type === FIELD_TYPE.NUMBER" :key="index" :field="item.variable" :label="item.label">
- <a-input v-model="form_values[item.variable]" :placeholder="item.label" type="number" />
- </a-form-item>
- <!-- 单行文本:文字 -->
- <a-form-item v-if="item.type === FIELD_TYPE.TEXT_INPUT" :key="index" :field="item.variable" :label="item.label">
- <a-input v-model="form_values[item.variable]" :placeholder="item.label" />
- </a-form-item>
- <!-- 段落:多行文本 -->
- <a-form-item v-if="item.type === FIELD_TYPE.PARAGRAPH" :key="index" :field="item.variable" :label="item.label">
- <a-textarea v-model="form_values[item.variable]" :placeholder="item.label" :auto-size="item.autosize" />
- </a-form-item>
- <!-- 多选 -->
- <a-form-item v-if="item.type === FIELD_TYPE.SELECT" :key="index" :field="item.variable" :label="item.label">
- <a-select v-model="form_values[item.variable]" :placeholder="item.label" allow-clear>
- <a-option v-for="(opt, idx) of item.options" :value="opt" :key="opt + '_' + idx">{{ opt }}</a-option>
- </a-select>
- </a-form-item>
- <!-- 单文件上传 -->
- <a-form-item
- v-if="item.type === FIELD_TYPE.FILE"
- :key="index"
- :field="item.variable"
- :label="item.label"
- :required="item.required"
- :rules="[]"
- :validate-trigger="[]"
- >
- <a-upload
- v-model:file-list="form_values[item.variable]"
- :multiple="false"
- :limit="1"
- :accept="item.accept"
- :auto-upload="false"
- @change="handleFileChange(item, $event)"
- >
- <template #upload-button>
- <BtnFileUpload :popmessage="item.popmessage" />
- </template>
- <template #file-name="{ fileItem }">
- <a-tooltip :content="fileItem.name">
- <span>{{ fileItem.name }}</span>
- </a-tooltip>
- </template>
- </a-upload>
- </a-form-item>
- <!-- 多文件上传 -->
- <a-form-item
- v-if="item.type === FIELD_TYPE.FILE_LIST"
- :key="index"
- :field="item.variable"
- :label="item.label"
- :required="item.required"
- :rules="[]"
- :validate-trigger="[]"
- >
- <a-upload
- v-model:file-list="form_values[item.variable]"
- :multiple="true"
- :auto-upload="false"
- :limit="item.limit"
- :accept="item.accept"
- @change="handleFileChange(item, $event)"
- >
- <template #upload-button>
- <BtnFileUpload :popmessage="item.popmessage" />
- </template>
- <template #file-name="{ fileItem }">
- <a-tooltip :content="fileItem.name">
- <span>{{ fileItem.name }}</span>
- </a-tooltip>
- </template>
- </a-upload>
- </a-form-item>
- </template>
- <!-- 提交按钮 -->
- <a-form-item>
- <a-button class="btn_1" style="margin-right: 10px" type="primary" html-type="submit" v-if="is_init_model"
- >开始对话</a-button
- >
- <a-button class="btn_1" style="margin-right: 10px" type="primary" html-type="submit" v-else>保存</a-button>
- <a-button class="btn_1" html-type="submit" v-if="!is_init_model" @click="handleCancel">取消</a-button>
- </a-form-item>
- </a-form>
- </div>
- </template>
- <script setup>
- import { ref, reactive, computed, onMounted } from 'vue';
- import { getFieldFileUplaodAcceptString, getFileType } from './file-accept';
- import getFieldFileUplaodMessageString from './file-message';
- import BtnFileUpload from './BtnFileUpload.vue';
- import FIELD_TYPE from './def-file-type';
- import { files } from 'jszip';
- const props = defineProps({
- /**
- * 配置项
- * 数据结构,可查看同目录下的 dynamic-form-params.md 文件
- */
- form_params: Array,
- /**
- * 是否是点击智能体打开的弹框,还是点击参数配置按钮打开的弹框
- * */
- is_init_model: Boolean
- });
- const emit = defineEmits(['submitForm', 'toCancel']);
- /**
- * 表单的所有值
- */
- const form_values = reactive(initFormValues());
- /**
- * 文件数据
- */
- const file_values = ref({});
- /**
- * 表单的各字段参数
- */
- const form_fields = computed(() => {
- const forms_conf = props.form_params;
- const conf_list = [];
- const len = forms_conf.length;
- for (let i = 0; i < len; i++) {
- // const item = forms_conf[i];
- let item = {};
- for (const key in forms_conf[i]) {
- item = forms_conf[i][key];
- if (!item.type) {
- item.type = key;
- }
- }
- const itm_tp = item.type;
- // 默认值
- const conf = {
- type: itm_tp,
- label: item.label,
- variable: item.variable,
- options: item.options
- // popmessage: item.label
- };
- if (itm_tp === FIELD_TYPE.PARAGRAPH) {
- // 段落: 多行文本
- conf.autosize = {
- minRows: 2,
- maxRows: 5
- };
- }
- if (itm_tp === FIELD_TYPE.FILE) {
- // 单文件上传
- conf.required = item.required;
- // 处理 accept
- conf.accept = getFieldFileUplaodAcceptString(item.allowed_file_types, item.allowed_file_extensions);
- // 处理提示消息
- conf.popmessage = getFieldFileUplaodMessageString(item.allowed_file_types, 1);
- }
- if (itm_tp === FIELD_TYPE.FILE_LIST) {
- // 多文件上传: 最多允许上传的数量
- conf.limit = item.max_length;
- conf.required = item.required;
- // 处理 accept
- conf.accept = getFieldFileUplaodAcceptString(item.allowed_file_types, item.allowed_file_extensions);
- // 处理提示消息
- conf.popmessage = getFieldFileUplaodMessageString(item.allowed_file_types, item.max_length);
- }
- conf_list.push(conf);
- }
- return conf_list;
- });
- /**
- * 初始化表单的所有数据项
- */
- function initFormValues() {
- const form_info = props.form_params;
- const obj = {};
- const len = form_info.length;
- for (let i = 0; i < len; i++) {
- const item = form_info[i];
- for (const key in item) {
- const field_tp = item[key].type || key;
- const field_name = item[key].variable;
- const is_required = item[key].required;
- if (field_tp === FIELD_TYPE.FILE || field_tp === FIELD_TYPE.FILE_LIST) {
- obj[field_name] = [];
- } else {
- obj[field_name] = '';
- }
- }
- }
- return obj;
- }
- /**
- * 表单校验规则
- */
- const form_rules = computed(() => {
- const form_info = props.form_params;
- const obj = {};
- const len = form_info.length;
- for (let i = 0; i < len; i++) {
- const item = form_info[i];
- const field_tp = item.type;
- const field_name = item.variable;
- const is_required = item.required;
- if (field_tp === FIELD_TYPE.FILE || field_tp === FIELD_TYPE.FILE_LIST) {
- // 文件上传: 文件上传的验证不通过表单,通过自定义验证方式进行验证
- // if (is_required) {
- // item_rule.push({
- // required: is_required,
- // message: ''
- // });
- // }
- } else {
- const item_rule = [];
- // 是否是必填项
- // 非文件上传类型的 required 字段
- if (is_required) {
- item_rule.push({
- required: is_required,
- message: `${item.label}是必填项`
- });
- } else {
- // 不是必填项
- }
- if (field_tp === FIELD_TYPE.TEXT_INPUT || field_tp === FIELD_TYPE.PARAGRAPH) {
- if (item.max_length > 0) {
- // 配置最大值验证
- item_rule.push({
- maxLength: item.max_length,
- message: `最大长度为${item.max_length}`
- });
- }
- }
- obj[field_name] = item_rule;
- }
- }
- return obj;
- });
- /**
- * 处理文件响应
- * @param item
- * @param event
- */
- const handleFileChange = (item, event) => {
- const field_key = item.variable;
- const all_files = [...event];
- all_files.forEach((file) => {
- file.type = getFileType(file);
- file.transfer_method = 'local_file';
- file.limit_1 = item.type == 'file' ? true : false; //文件对应的是否支持多文件上传
- });
- // 使用file_values保存文件
- file_values.value[field_key] = [...all_files];
- // // 保存文件的数据信息
- // form_values[field_key] = event;
- };
- const handleSubmit = ({ values, errors }) => {
- if (!errors) {
- emit('submitForm', getFormFiledValues());
- }
- };
- const handleCancel = () => {
- emit('toCancel');
- };
- /**
- * 获取表单里的所有数据
- */
- const getFormFiledValues = () => {
- const res_opts = {};
- for (let key in form_values) {
- const cur_val = form_values[key];
- if (cur_val === undefined || cur_val === null || cur_val === '') {
- res_opts[key] = '';
- } else {
- res_opts[key] = form_values[key];
- }
- }
- const files = file_values.value;
- const res_files = {};
- for (let key in files) {
- res_files[key] = files[key];
- }
- return {
- // 键值对数据
- options: res_opts,
- // 文件数据
- files: res_files
- };
- };
- /**
- * 清空表单所有数据
- */
- const clearFormFiledValues = () => {
- // 初始化数据
- const init_values = initFormValues();
- for (let key in form_values) {
- form_values[key] = init_values[key];
- }
- // TODO: 清除文件数据
- };
- defineExpose({
- /**
- * 父组件通过ref,调用getValues方法,可以获取到表单里的所有数据
- */
- getValues: getFormFiledValues,
- /**
- * 父组件通过ref,调用clear方法,可以将表单里数据清空
- */
- clear: clearFormFiledValues
- });
- </script>
- <style scoped></style>
- <style>
- .dynamic-form-container-jfsdjaklfjsfjsdkalfjskaljsk .arco-upload-icon.arco-upload-icon-start {
- display: none;
- }
- .dynamic-form-container-jfsdjaklfjsfjsdkalfjskaljsk .arco-upload-progress {
- display: none;
- }
- .dynamic-form-container-jfsdjaklfjsfjsdkalfjskaljsk .arco-upload-list.arco-upload-list-type-text,
- .dynamic-form-container-jfsdjaklfjsfjsdkalfjskaljsk .arco-upload-list.arco-upload-list-type-picture {
- width: 100%;
- max-height: 400px;
- overflow-y: auto;
- padding-right: 5px;
- }
- .dynamic-form-container-jfsdjaklfjsfjsdkalfjskaljsk .arco-upload-list.arco-upload-list-type-text,
- .dynamic-form-container-jfsdjaklfjsfjsdkalfjskaljsk .arco-upload-list.arco-upload-list-type-picture {
- width: 100%;
- max-height: 300px;
- overflow-y: auto;
- padding-right: 5px;
- }
- </style>
|