123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616 |
- <template>
- <!-- <el-form ref="form" :model="insideData" :rules="insideRules" :label-width="labelWidth + 'px'"> -->
- <el-form
- v-loading="formConfig.loadingStatus"
- :element-loading-text="$t('loadingText')"
- element-loading-spinner="el-icon-loading"
- element-loading-background="rgba(0, 0, 0, 0.2)"
- ref="form"
- :model="insideData"
- :rules="insideRules"
- label-width="auto"
- >
- <el-row>
- <el-col
- v-for="(value, key, index) in insideConfig"
- :key="index"
- :span="24 / value.span"
- >
- <el-form-item v-if="value.if" :label="value.label" :prop="key">
- <!-- 解决单选多选框高度太矮导致格式错乱问题 -->
- <div style="min-height: 40px">
- <!--
- 输入框:
- type: 'input'
- itemType: 原生 input 的 type(text(默认)、number、password、textarea等,默认text)
- placeholder: 输入框占位文本,默认‘请输入’+label
- width: 文本宽度
- -->
- <el-input
- v-if="value.type === 'input'"
- v-model="insideData[key]"
- :placeholder="value.placeholder"
- :type="value.itemType"
- :disabled="value.disabled"
- :clearable="value.clearable"
- :show-password="value.itemType === 'password'"
- :autosize="{ minRows: 4, maxRows: 7 }"
- :style="{ width: value.width || '100%' }"
- size="small"
- />
- <!--
- 下拉选择框:
- type: 'select'
- placeholder: 下拉选择框占位文本,默认‘请选择’+label
- multiple: 多选,默认false
- filterable: 可搜索,默认true
- data: 绑定数据
- keyName: 绑定key,默认‘key’
- labelName: 绑定label,默认‘label’
- dict: 字典
- setData() 获取数据方法
- binding: 执行setData()返回参数的绑定路径
- -->
- <el-select
- v-else-if="value.type === 'select'"
- v-model="insideData[key]"
- :placeholder="value.placeholder"
- :multiple="value.multiple"
- :disabled="value.disabled"
- :clearable="value.clearable"
- :filterable="value.filterable"
- :style="{ width: value.width || '100%' }"
- size="small"
- @change="fn($event, value.change)"
- >
- <el-option
- v-for="item in value.data"
- :key="item[value.keyName]"
- :label="item[value.labelName]"
- :value="item[value.keyName]"
- />
- </el-select>
- <!--
- 单选:
- type: 'radio'
- data: 绑定数据
- keyName: 绑定key,默认‘key’
- labelName: 绑定label,默认‘label’
- dict: 字典
- setData() 获取数据方法
- binding: 执行setData()返回参数的绑定路径
- -->
- <el-radio-group
- v-else-if="value.type === 'radio'"
- size="small"
- v-model="insideData[key]"
- :disabled="value.disabled"
- >
- <el-radio
- v-for="item in value.data"
- :key="item[value.keyName]"
- :label="item[value.keyName]"
- >
- {{ item[value.labelName] }}
- </el-radio>
- </el-radio-group>
- <!--
- 多选:
- type: 'checkbox'
- keyName: 绑定key
- labelName: 绑定label
- dict: 字典
- setData() 获取数据方法
- binding: 执行setData()返回参数的绑定路径
- -->
- <el-checkbox-group
- v-else-if="value.type === 'checkbox'"
- size="small"
- v-model="insideData[key]"
- :disabled="value.disabled"
- >
- <el-checkbox
- v-for="item in value.data"
- :key="item[value.keyName]"
- :label="item[value.keyName]"
- >
- {{ item[value.labelName] }}
- </el-checkbox>
- </el-checkbox-group>
- <!--
- 日期选择器:
- type: 'datePicker'
- placeholder: 日期选择框占位文本
- format: 自定义显示与返回的日期格式
- itemType: element原生type,默认date(date,week,month,year)
- pickerOptions: elementUi原生picker-options
- -->
- <el-date-picker
- v-else-if="value.type === 'datePicker'"
- v-model="insideData[key]"
- :type="value.itemType"
- :placeholder="value.placeholder"
- :format="value.format"
- :value-format="value.format"
- :picker-options="value.pickerOptions"
- :disabled="value.disabled"
- :clearable="value.clearable"
- :style="{ width: value.width || '100%' }"
- size="small"
- />
- <!--
- 日期范围选择器:
- type: 'dateRange'
- beginName: 开始时间绑定名称(默认beginTime)
- endName: 结束时间绑定名称(默认endTime)
- -->
- <el-date-picker
- v-else-if="value.type === 'dateRange'"
- v-model="dateRangeData[key]"
- type="daterange"
- start-placeholder="开始日期"
- end-placeholder="结束日期"
- value-format="yyyy-MM-dd"
- :disabled="value.disabled"
- :clearable="value.clearable"
- :style="{ width: value.width || '100%' }"
- size="small"
- />
- <el-upload
- v-else-if="value.type === 'uploads'"
- class="upload-demo"
- action="/api/service-file/uploadFile"
- :on-preview="handlePreview"
- :on-remove="(file, fileList) => handleRemove(file, fileList, key)"
- :before-remove="beforeRemove"
- :limit="6"
- :on-exceed="handleExceed"
- :headers="uploadHeader"
- :on-success="
- (response, file, fileList) =>
- uploadSuccess(response, file, fileList, key)
- "
- :before-upload="(file) => beforeAvatarUpload(file, value.accept)"
- v-model="insideData[key]"
- :accept="value.accept"
- :file-list="insideData[key]"
- >
- <el-button size="small" type="primary">点击上传</el-button>
- <div slot="tip" v-if="value.tip" class="el-upload__tip">
- {{ value.tip }}
- </div>
- </el-upload>
- <el-cascader
- v-model="insideData[key]"
- v-else-if="value.type === 'cascader'"
- :options="value.data"
- :emitPath="false"
- :props="value.props || {}"
- :style="{ width: value.width || '100%' }"
- size="small"
- ></el-cascader>
- <!--
- 插槽:
- slot: 插槽命名
- span: 一行有几个el-form-item
- 例:
- <template v-slot:key>
- {{ 'demo' }}
- </template>
- -->
- <quill-editor
- ref="myQuillEditor"
- v-model="insideData[key]"
- v-else-if="value.type === 'editor'"
- />
- <slot v-else :name="key" />
- </div>
- </el-form-item>
- </el-col>
- <!--
- 搜索与重置操作按钮:
- query: 搜索方法
- -->
- <el-col
- v-if="this.formConfig['operation'] !== undefined"
- :span="
- 24 / this.formConfig['operation'].span
- ? 24 / this.formConfig['operation'].span
- : 6
- "
- >
- <div style="margin-left: 15px; line-height: 38px">
- <el-button
- type="primary"
- size="small"
- @click="formConfig['operation'].query()"
- >
- 搜索
- </el-button>
- <el-button
- size="small"
- @click="
- dateRangeData = [];
- formConfig['operation'].reset();
- "
- >
- 重置
- </el-button>
- </div>
- </el-col>
- </el-row>
- <el-row
- style="margin-bottom: 10px"
- v-if="
- formConfig.otherButton &&
- formConfig.otherButton.list &&
- formConfig.otherButton.list.length > 0
- "
- >
- <el-col
- :span="24"
- :style="'text-align: ' + formConfig.otherButton.align || 'left'"
- >
- <el-button
- v-for="(item, index) in formConfig.otherButton.list"
- :key="index"
- :type="item.type"
- size="small"
- @click="formConfig.otherButton.list[index][item.methodsText]()"
- >{{ item.name }}</el-button
- >
- </el-col>
- </el-row>
- </el-form>
- </template>
- <script>
- import { getToken } from "@/util/auth";
- import "quill/dist/quill.core.css";
- import "quill/dist/quill.snow.css";
- import "quill/dist/quill.bubble.css";
- import { quillEditor } from "vue-quill-editor";
- export default {
- components: {
- quillEditor,
- },
- name: "test",
- props: {
- // 表单值
- value: {
- type: Object,
- },
- // 表单配置
- formConfig: {
- type: Object,
- required: true,
- },
- // 必填参数校验
- insideRules: {
- type: Object,
- default: () => {
- return {};
- },
- },
- // 全局label宽度
- labelWidth: {
- type: Number,
- default: 80,
- },
- // 全局列数
- span: {
- type: Number,
- default: 1,
- },
- // 全局可清空
- clearable: {
- type: Boolean,
- default: true,
- },
- // 全局禁用
- disabled: {
- type: Boolean,
- default: false,
- },
- // 全局禁用
- change: {
- type: Function,
- default: () => {
- return {};
- },
- },
- },
- data() {
- return {
- insideConfig: {}, // 内部配置
- insideData: {}, // 内部数据
- dateRangeData: [], // 时间段
- fileData: [], // 文件路径数组
- fileList: [],
- uploadHeader: {
- Authorization: "Basic c2FiZXI6c2FiZXJfc2VjcmV0",
- "Blade-Auth": "bearer " + getToken(),
- },
- };
- },
- watch: {
- value: {
- handler() {
- this.insideData = this.value;
- },
- deep: true,
- immediate: true,
- },
- formConfig: {
- handler() {
- this.init();
- },
- deep: true,
- immediate: true,
- },
- },
- methods: {
- beforeAvatarUpload(file, accept) {
- console.log(file, accept);
- const videoType = file.type.substring(file.type.length - 3);
- if (accept.indexOf(videoType) == -1) {
- this.$message.error("上传头像图片只能是 " + accept + " 格式!");
- return false;
- }
- },
- uploadSuccess(response, file, fileList, key) {
- this.insideData[key] = [];
- for (let i = 0; i < fileList.length; i++) {
- const element = fileList[i];
- console.log(element);
- if (element.response) {
- element.response.data.name = element.response.data.fileName;
- this.insideData[key].push(element.response.data);
- } else {
- this.insideData[key].push(element);
- }
- }
- },
- handleRemove(file, fileList, key) {
- this.insideData[key] = [];
- for (let i = 0; i < fileList.length; i++) {
- const element = fileList[i];
- if (element.response) {
- element.response.data.name = element.response.data.fileName;
- this.insideData[key].push(element.response.data);
- } else {
- this.insideData[key].push(element);
- }
- }
- },
- handlePreview(file) {
- console.log(file);
- },
- handleExceed(files, fileList) {
- this.$message.warning(
- `当前限制选择 6 个文件,本次选择了 ${files.length} 个文件,共选择了 ${
- files.length + fileList.length
- } 个文件`
- );
- },
- beforeRemove(file, fileList) {
- return this.$confirm(`确定移除 ${file.name}?`);
- },
- fn(val, _fn) {
- _fn(val);
- },
- // 初始化
- init() {
- this.insideConfig = {};
- for (const key in this.formConfig) {
- // 跳过特殊方法( operation: 搜索、重置, otherButton: 新增等自定义按钮)
- if (
- key === "operation" ||
- key === "otherButton" ||
- key === "loadingStatus"
- ) {
- continue;
- }
- const value = this.formConfig[key];
- this.insideConfig[key] = {
- label: value.label,
- type: value.type ? value.type : "input",
- if: value.if === undefined ? true : value.if,
- span: value.span || this.span,
- clearable:
- value.clearable === undefined ? this.clearable : value.clearable,
- disabled:
- value.disabled === undefined ? this.disabled : value.disabled,
- change: value.change === undefined ? this.change : value.change,
- };
- switch (this.insideConfig[key].type) {
- case "input":
- this.inputHandle(key, value);
- break;
- case "select":
- this.selectHandle(key, value);
- break;
- case "radio":
- this.radioHandel(key, value);
- break;
- case "checkbox":
- this.checkboxHandel(key, value);
- break;
- case "datePicker":
- this.datePickerHandel(key, value);
- break;
- case "upload":
- this.uploadHandel(key, value);
- break;
- case "uploads":
- this.uploadsHandel(key, value);
- break;
- case "cascader":
- this.cascaderHandel(key, value);
- break;
- }
- }
- },
- //初始化
- reset() {
- this.$refs.form.resetFields();
- },
- // el-input标签处理
- inputHandle(key, value) {
- this.insideConfig[key].placeholder =
- value.placeholder || "请输入" + value.label;
- this.insideConfig[key].itemType = value.itemType || "text";
- },
- // el-select标签处理
- selectHandle(key, value) {
- this.insideConfig[key].placeholder =
- value.placeholder || "请选择" + value.label;
- this.insideConfig[key].multiple =
- value.multiple === undefined ? false : value.multiple;
- this.insideConfig[key].filterable =
- value.filterable === undefined ? true : value.filterable;
- this.insideConfig[key].keyName = value.keyName || "key";
- this.insideConfig[key].labelName = value.labelName || "label";
- this.setData(key, value);
- },
- // el-radio标签处理
- radioHandel(key, value) {
- this.insideConfig[key].keyName = value.keyName || "key";
- this.insideConfig[key].labelName = value.labelName || "label";
- this.setData(key, value);
- },
- // el-checkbox标签处理
- checkboxHandel(key, value) {
- // 默认值
- if (!this.insideData[key]) {
- this.$set(this.insideData, key, []);
- }
- this.insideConfig[key].keyName = value.keyName || "key";
- this.insideConfig[key].labelName = value.labelName || "label";
- this.setData(key, value);
- },
- // el-checkbox标签处理
- cascaderHandel(key, value) {
- // 默认值
- if (!this.insideData[key]) {
- this.$set(this.insideData, key, []);
- }
- this.insideConfig[key].props = value.props || {};
- if (
- this.insideConfig[key].props &&
- !this.insideConfig[key].props.emitPath
- )
- this.insideConfig[key].props.emitPath = false;
- this.setData(key, value);
- },
- // el-datePicker标签处理
- datePickerHandel(key, value) {
- this.insideConfig[key].placeholder = value.placeholder || "请选择日期";
- this.insideConfig[key].itemType = value.itemType || "date";
- this.insideConfig[key].format = value.format || "yyyy-MM-dd";
- },
- // 单文件上传处理
- uploadHandel(key) {
- if (this.insideData[key]) {
- this.$set(this.fileData, key, [this.insideData[key]]);
- } else if (!this.fileData[key]) {
- this.$set(this.fileData, key, []);
- }
- },
- // 多文件上传处理
- uploadsHandel(key, value) {
- this.insideConfig[key].maxSelectNum = value.maxSelectNum || 6;
- this.insideConfig[key].accept = value.accept || null;
- if (!this.insideData[key]) {
- this.$set(this.insideData, key, []);
- }
- },
- // 获取数据方法
- async setData(key, value) {
- if (value.data) {
- this.insideConfig[key].data = value.data;
- } else if (value.dict) {
- this.insideConfig[key].keyName = "dictValue";
- this.insideConfig[key].labelName = "dictLabel";
- this.insideConfig[key].data = await this.getDicts(value.dict);
- this.$forceUpdate();
- } else {
- const itemData = await value.setData();
- if (value.binding) {
- this.insideConfig[key].data = value.binding
- .split(".")
- .reduce((total, cur) => total[cur], itemData);
- } else {
- this.insideConfig[key].data = itemData;
- }
- this.$forceUpdate();
- }
- },
- // 赋值开始时间结束时间
- dateRangeChange(value, key) {
- if (this.dateRangeData[key] !== null) {
- this.$set(
- this.insideData,
- value["beginName"] || "beginTime",
- this.dateRangeData[key][0]
- );
- this.$set(
- this.insideData,
- value["endName"] || "endTime",
- this.dateRangeData[key][1]
- );
- } else {
- this.$set(
- this.insideData,
- value["beginName"] || "beginTime",
- undefined
- );
- this.$set(this.insideData, value["endName"] || "endTime", undefined);
- }
- },
- // 选择图片
- selectFile(key) {
- if (this.fileData[key].length > 0) {
- this.$set(this.insideData, key, this.fileData[key][0]);
- } else {
- this.$set(this.insideData, key, undefined);
- }
- },
- // 删除图片
- removeFile(key) {
- this.$set(this.fileData, key, []);
- this.$set(this.insideData, key, undefined);
- },
- },
- };
- </script>
- <style lang="scss" scoped>
- ::v-deep {
- .el-form-item {
- margin-bottom: 8px;
- }
- }
- </style>
|