update 附件上传功能
This commit is contained in:
		@@ -1,649 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
	<el-dialog
 | 
			
		||||
		class="super-flexible-dialog"
 | 
			
		||||
		:title="isDetail ? title.detail : !dataForm.id ? title.add : title.edit"
 | 
			
		||||
		:visible.sync="visible"
 | 
			
		||||
		@close="handleClose"
 | 
			
		||||
		:distory-on-close="true"
 | 
			
		||||
		:close-on-click-modal="false">
 | 
			
		||||
		<div style="max-height: 60vh; overflow-y: scroll; overflow-x: hidden">
 | 
			
		||||
			<el-form ref="dataForm" :model="dataForm" :rules="dataFormRules">
 | 
			
		||||
				<!-- 如果需要更精细一点的布局,可以根据配置项实现地再复杂一点,但此处暂时全部采用一行两列布局  -->
 | 
			
		||||
				<el-row v-for="n in rows" :key="n" :gutter="20">
 | 
			
		||||
					<el-col v-for="c in COLUMN_PER_ROW" :key="`${n}+'col'+${c}`" :span="getSpan(n, c)">
 | 
			
		||||
						<!-- <el-col v-for="c in COLUMN_PER_ROW" :key="`${n}+'col'+${c}`" :span="24 / COLUMN_PER_ROW"> -->
 | 
			
		||||
						<!-- :class="{ 'hidden-input': configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].hidden }" -->
 | 
			
		||||
						<el-form-item
 | 
			
		||||
							v-if="configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)]"
 | 
			
		||||
							:prop="configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name"
 | 
			
		||||
							:key="`${n}-col-${c}-item`"
 | 
			
		||||
							:label="getLabel(n, c)">
 | 
			
		||||
							<!-- 暂时先不实现部分输入方式 -->
 | 
			
		||||
							<el-input
 | 
			
		||||
								v-if="getType(n, c) === 'input'"
 | 
			
		||||
								:placeholder="getPlaceholder(n, c)"
 | 
			
		||||
								v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"
 | 
			
		||||
								clearable
 | 
			
		||||
								:disabled="isDetail" />
 | 
			
		||||
							<el-radio
 | 
			
		||||
								v-if="getType(n, c) === 'radio'"
 | 
			
		||||
								v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"
 | 
			
		||||
								:disabled="isDetail" />
 | 
			
		||||
							<el-checkbox
 | 
			
		||||
								v-if="getType(n, c) === 'check'"
 | 
			
		||||
								v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"
 | 
			
		||||
								:disabled="isDetail" />
 | 
			
		||||
							<el-select
 | 
			
		||||
								v-if="getType(n, c) === 'select'"
 | 
			
		||||
								:placeholder="getPlaceholder(n, c)"
 | 
			
		||||
								v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"
 | 
			
		||||
								clearable
 | 
			
		||||
								:disabled="isDetail"
 | 
			
		||||
								@change="emitSelectChange(configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name, $event)">
 | 
			
		||||
								<el-option
 | 
			
		||||
									v-for="opt in configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].options"
 | 
			
		||||
									:key="opt.label + Math.random()"
 | 
			
		||||
									:label="opt.label"
 | 
			
		||||
									:value="opt.value" />
 | 
			
		||||
							</el-select>
 | 
			
		||||
							<el-switch
 | 
			
		||||
								v-if="getType(n, c) === 'switch'"
 | 
			
		||||
								v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"
 | 
			
		||||
								:disabled="isDetail" />
 | 
			
		||||
							<el-cascader
 | 
			
		||||
								v-if="getType(n, c) === 'cascader'"
 | 
			
		||||
								v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"
 | 
			
		||||
								:options="configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].options"
 | 
			
		||||
								:props="configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].props"
 | 
			
		||||
								:disabled="isDetail"
 | 
			
		||||
								clearable />
 | 
			
		||||
							<el-time-select
 | 
			
		||||
								v-if="getType(n, c) === 'time'"
 | 
			
		||||
								v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"
 | 
			
		||||
								:disabled="isDetail" />
 | 
			
		||||
							<el-date-picker
 | 
			
		||||
								v-if="getType(n, c) === 'date'"
 | 
			
		||||
								v-bind="configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].props"
 | 
			
		||||
								:placeholder="getPlaceholder(n, c)"
 | 
			
		||||
								v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"
 | 
			
		||||
								:disabled="isDetail" />
 | 
			
		||||
						</el-form-item>
 | 
			
		||||
					</el-col>
 | 
			
		||||
				</el-row>
 | 
			
		||||
 | 
			
		||||
				<!-- extra components , like Markdown or RichEdit -->
 | 
			
		||||
				<template v-if="configs.extraComponents && configs.extraComponents.length > 0">
 | 
			
		||||
					<el-form-item
 | 
			
		||||
						v-for="(ec, index) in configs.extraComponents"
 | 
			
		||||
						:key="ec.name + index"
 | 
			
		||||
						:label="ec.label"
 | 
			
		||||
						class="extra-components">
 | 
			
		||||
						<component
 | 
			
		||||
							style="margin-top: 40px"
 | 
			
		||||
							v-if="ec.hasModel"
 | 
			
		||||
							:is="ec.component"
 | 
			
		||||
							v-bind="ec.props"
 | 
			
		||||
							v-model="dataForm[ec.name]"
 | 
			
		||||
							@ready="handleEditorReady"
 | 
			
		||||
							:read-only="isDetail" />
 | 
			
		||||
						<!-- <component v-if="ec.hasModel" :is="ec.component" v-bind="ec.props" v-model="dataForm[ec.name]" /> -->
 | 
			
		||||
						<component
 | 
			
		||||
							v-else
 | 
			
		||||
							:is="ec.component"
 | 
			
		||||
							v-bind="ec.props"
 | 
			
		||||
							@uploader-update-filelist="handleUploadListUpdate($event, ec.props.extraParams.typeCode)"
 | 
			
		||||
							:uploader-inject-file-list="/*用于设备分流的*/ fileList[ec.props.extraParams.typeCode]"
 | 
			
		||||
							:read-only="isDetail" />
 | 
			
		||||
					</el-form-item>
 | 
			
		||||
				</template>
 | 
			
		||||
			</el-form>
 | 
			
		||||
 | 
			
		||||
			<!-- <template v-if="dataForm.id && configs.subtable">
 | 
			
		||||
				<attr-form :related-id="dataForm.id" v-bind="configs.subtable" :is-detail="isDetail" />
 | 
			
		||||
			</template> -->
 | 
			
		||||
		</div>
 | 
			
		||||
		<span slot="footer" class="dialog-footer">
 | 
			
		||||
			<template v-for="(operate, index) in configs.operations">
 | 
			
		||||
				<!-- {{ operate.name | btnNameFilter }} -->
 | 
			
		||||
				<el-button
 | 
			
		||||
					v-if="
 | 
			
		||||
						!isDetail &&
 | 
			
		||||
						(operate.showAlways ||
 | 
			
		||||
							(((dataForm.id && operate.showOnEdit) || (!dataForm.id && !operate.showOnEdit)) &&
 | 
			
		||||
								(operate.permission ? $hasPermission(operate.permission) : true)))
 | 
			
		||||
					"
 | 
			
		||||
					:key="`operate-${index}`"
 | 
			
		||||
					:type="btnType[operate.name]"
 | 
			
		||||
					@click="handleClick(operate)"
 | 
			
		||||
					>{{ btnName[operate.name] }}</el-button
 | 
			
		||||
				>
 | 
			
		||||
			</template>
 | 
			
		||||
			<el-button v-if="isDetail" @click="handleClick({ name: 'cancel' })">{{ $t('cancel') }}</el-button>
 | 
			
		||||
		</span>
 | 
			
		||||
	</el-dialog>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
// import CKEditor from 'ckeditor4-vue'
 | 
			
		||||
// import AttrForm from './AttrForm'
 | 
			
		||||
// import { pick } from 'lodash/object'
 | 
			
		||||
import { pick as __pick } from '@/utils/filters';
 | 
			
		||||
// import i18n from '@/i18n'
 | 
			
		||||
import $http from '@/utils/request';
 | 
			
		||||
 | 
			
		||||
const i18n = {
 | 
			
		||||
	t: (a) => a,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 标题 for i18n
 | 
			
		||||
const title = {
 | 
			
		||||
	// detail: i18n.t('detail'),
 | 
			
		||||
	// add: i18n.t('add'),
 | 
			
		||||
	// edit: i18n.t('edit'),
 | 
			
		||||
	detail: '详情',
 | 
			
		||||
	add: '添加',
 | 
			
		||||
	edit: '编辑',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 或者也可以改造成自定义颜色:
 | 
			
		||||
const btnType = {
 | 
			
		||||
	save: 'success',
 | 
			
		||||
	update: 'primary',
 | 
			
		||||
	reset: 'text',
 | 
			
		||||
	// cancel: 'text'
 | 
			
		||||
	// add more...
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const btnName = {
 | 
			
		||||
	save: '保存',
 | 
			
		||||
	update: '更新',
 | 
			
		||||
	reset: '重置',
 | 
			
		||||
	cancel: '取消',
 | 
			
		||||
	// for i18n
 | 
			
		||||
	// save: i18n.t('save'),
 | 
			
		||||
	// update: i18n.t('update'),
 | 
			
		||||
	// reset: i18n.t('reset'),
 | 
			
		||||
	// cancel: i18n.t('cancel'),
 | 
			
		||||
	// add more...
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 每行的列数
 | 
			
		||||
const COLUMN_PER_ROW = 2;
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
	name: 'AddOrUpdateDialog',
 | 
			
		||||
	// components: { AttrForm },
 | 
			
		||||
	props: {
 | 
			
		||||
		configs: {
 | 
			
		||||
			type: Object,
 | 
			
		||||
			default: () => ({}), // 此处省去类型检查,使用者自行注意就好
 | 
			
		||||
		},
 | 
			
		||||
		url: {
 | 
			
		||||
			type: Object,
 | 
			
		||||
			default: () => ({}), // 此处省去类型检查,使用者自行注意就好
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	filters: {
 | 
			
		||||
		nameFilter: function (name) {
 | 
			
		||||
			if (!name) return null;
 | 
			
		||||
			// for i18n
 | 
			
		||||
			const defaultNames = {
 | 
			
		||||
				name: '名称',
 | 
			
		||||
				code: '编码',
 | 
			
		||||
				remark: '备注',
 | 
			
		||||
				description: '描述',
 | 
			
		||||
				specifications: '规格',
 | 
			
		||||
				// name: i18n.t('name'),
 | 
			
		||||
				// code: i18n.t('code'),
 | 
			
		||||
				// remark: i18n.t('remark'),
 | 
			
		||||
				// description: i18n.t('desc'),
 | 
			
		||||
				// specifications: i18n.t('prod.spec'),
 | 
			
		||||
				// add more...
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			return defaultNames[name];
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	// provide() {
 | 
			
		||||
	// 	return {
 | 
			
		||||
	// 		_df: this.dataForm
 | 
			
		||||
	// 	}
 | 
			
		||||
	// },
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			COLUMN_PER_ROW,
 | 
			
		||||
			title,
 | 
			
		||||
			/** 按钮相关属性 */
 | 
			
		||||
			btnName,
 | 
			
		||||
			btnType,
 | 
			
		||||
			defaultNames: {
 | 
			
		||||
				name: '名称',
 | 
			
		||||
				code: '编码',
 | 
			
		||||
				remark: '备注',
 | 
			
		||||
				description: '描述',
 | 
			
		||||
				specifications: '规格',
 | 
			
		||||
				// add more...
 | 
			
		||||
				// name: i18n.t('name'),
 | 
			
		||||
				// code: i18n.t('code'),
 | 
			
		||||
				// remark: i18n.t('remark'),
 | 
			
		||||
				// description: i18n.t('desc'),
 | 
			
		||||
				// specifications: i18n.t('prod.spec'),
 | 
			
		||||
				// add more...
 | 
			
		||||
			},
 | 
			
		||||
			defaultPlaceholders: {}, // 自动根据 defaultNames 计算得来
 | 
			
		||||
			/** 表单相关属性 */
 | 
			
		||||
			visible: false,
 | 
			
		||||
			isEdit: false,
 | 
			
		||||
			isDetail: false,
 | 
			
		||||
			dataForm: {},
 | 
			
		||||
			dataFormRules: {},
 | 
			
		||||
			tempForm: [], // 临时保存自动生成的code,或其他数据
 | 
			
		||||
			shouldWait: null,
 | 
			
		||||
			fileForm: {}, // 文件上传分流用、合并用的表单,根据 typeCode 进行分流,在请求时合并
 | 
			
		||||
			fileList: {}, // 文件加载时分流,依据 typeCode
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	computed: {
 | 
			
		||||
		rows() {
 | 
			
		||||
			// 本组件只实现了'一行两列'的表单布局
 | 
			
		||||
			return Math.ceil(this.configs.fields.length / COLUMN_PER_ROW);
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	created() {
 | 
			
		||||
		/** load lang */
 | 
			
		||||
		// CKEditor.load()
 | 
			
		||||
		// console.log('lang', CKEditor.component.props.config.defaultLanguage = 'en' )
 | 
			
		||||
	},
 | 
			
		||||
	mounted() {
 | 
			
		||||
		/** 计算 defaultPlaceholders */
 | 
			
		||||
		// const prefix = i18n.t('hints.input');
 | 
			
		||||
		const prefix = '请输入';
 | 
			
		||||
		Object.entries(this.defaultNames).map(([key, value]) => {
 | 
			
		||||
			this.defaultPlaceholders[key] = prefix + value;
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		/** 转换 configs.fields 的结构,把纯字符串转为对象 */
 | 
			
		||||
		this.$nextTick(() => {
 | 
			
		||||
			this.configs.fields = this.configs.fields.map((item) => {
 | 
			
		||||
				if (typeof item === 'string') {
 | 
			
		||||
					return { name: item };
 | 
			
		||||
				}
 | 
			
		||||
				return item;
 | 
			
		||||
			});
 | 
			
		||||
 | 
			
		||||
			/** 动态设置dataForm字段 */
 | 
			
		||||
			this.configs.fields.forEach((item) => {
 | 
			
		||||
				this.$set(this.dataForm, [item.name], '');
 | 
			
		||||
 | 
			
		||||
				/** select 的默认值设置 */
 | 
			
		||||
				if (item.type === 'select') {
 | 
			
		||||
					const opts = item.options || [];
 | 
			
		||||
					const dft = opts.find((item) => item.default || false);
 | 
			
		||||
					if (dft) {
 | 
			
		||||
						this.$set(this.dataForm, [item.name], dft.value);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (item.api) {
 | 
			
		||||
					/** 自动请求并填充 */
 | 
			
		||||
					// or this.shouldWaitPool = []
 | 
			
		||||
					this.shouldWait =
 | 
			
		||||
						// this.$http({
 | 
			
		||||
						// 	url: this.$http.adornUrl(item.api),
 | 
			
		||||
						// 	method: 'POST', // 也可以改成动态决定
 | 
			
		||||
						// })
 | 
			
		||||
						$http
 | 
			
		||||
							.get(item.api)
 | 
			
		||||
							// .then(({ data: res }) => {
 | 
			
		||||
							.then((res) => {
 | 
			
		||||
								if (res && res.code === 0) {
 | 
			
		||||
									// this.dataForm[item.name] = res.data // <=== 此处需要对接口
 | 
			
		||||
									this.tempForm.push({ name: item.name, data: res.data });
 | 
			
		||||
								}
 | 
			
		||||
							});
 | 
			
		||||
				} // end if (item.api)
 | 
			
		||||
 | 
			
		||||
				// 如果有 relatedField,就需要在当前item的数据加载后,刷新 relatedField 的列表
 | 
			
		||||
				if (item.relatedField) {
 | 
			
		||||
					this.$watch(
 | 
			
		||||
						function () {
 | 
			
		||||
							return this.dataForm[item.name];
 | 
			
		||||
						},
 | 
			
		||||
						function (val, old) {
 | 
			
		||||
							if (val && val !== old) {
 | 
			
		||||
								this.$emit('select-change', { name: item.name, id: val });
 | 
			
		||||
							}
 | 
			
		||||
						},
 | 
			
		||||
						{ deep: true, immediate: true }
 | 
			
		||||
					);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (item.required) {
 | 
			
		||||
					const requiredRule = {
 | 
			
		||||
						required: true,
 | 
			
		||||
						message: '必填项',
 | 
			
		||||
						// message: i18n.t('validate.required'),
 | 
			
		||||
						// trigger: 'change'
 | 
			
		||||
						trigger: 'blur',
 | 
			
		||||
					};
 | 
			
		||||
					/** 检查是否已经存在该字段的规则 */
 | 
			
		||||
					const exists = this.dataFormRules[item.name] || null;
 | 
			
		||||
					/** 设置验证规则  */
 | 
			
		||||
					if (exists) {
 | 
			
		||||
						const unset = true;
 | 
			
		||||
						for (const rule of exists) {
 | 
			
		||||
							if (rule.required) unset = false;
 | 
			
		||||
						}
 | 
			
		||||
						if (unset) {
 | 
			
		||||
							exists.push(requiredRule);
 | 
			
		||||
						}
 | 
			
		||||
					} else {
 | 
			
		||||
						/** 不存在已有规则 */
 | 
			
		||||
						this.$set(this.dataFormRules, [item.name], [requiredRule]);
 | 
			
		||||
					}
 | 
			
		||||
				} // end if (item.required)
 | 
			
		||||
 | 
			
		||||
				if (item.rules) {
 | 
			
		||||
					const exists = this.dataFormRules[item.name] || null;
 | 
			
		||||
					if (exists) {
 | 
			
		||||
						// 浅拷贝过去
 | 
			
		||||
						exists.push(...item.rules);
 | 
			
		||||
					} else {
 | 
			
		||||
						this.$set(this.dataFormRules, [item.name], [...item.rules]);
 | 
			
		||||
					}
 | 
			
		||||
				} // end if (item.rules)
 | 
			
		||||
			});
 | 
			
		||||
 | 
			
		||||
			/** 计算默认值 */
 | 
			
		||||
			function calDefault(type) {
 | 
			
		||||
				switch (type) {
 | 
			
		||||
					case 'array':
 | 
			
		||||
						return [];
 | 
			
		||||
					// more case...
 | 
			
		||||
					default:
 | 
			
		||||
						return '';
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			/** 检查是否需要额外的组件 */
 | 
			
		||||
			this.configs.extraComponents &&
 | 
			
		||||
				this.configs.extraComponents.forEach((item) => {
 | 
			
		||||
					// if (Object.hasOwn(this.dataForm, [item.name])) {
 | 
			
		||||
					if (this.dataForm.hasOwnProperty(item.name)) {
 | 
			
		||||
						return;
 | 
			
		||||
					} else {
 | 
			
		||||
						this.$set(this.dataForm, [item.name], calDefault(item.fieldType));
 | 
			
		||||
					}
 | 
			
		||||
				});
 | 
			
		||||
 | 
			
		||||
			/** 单独设置 id */
 | 
			
		||||
			this.$set(this.dataForm, 'id', null);
 | 
			
		||||
		});
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	methods: {
 | 
			
		||||
		getSpan(n, c) {
 | 
			
		||||
			const opt = this.configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)];
 | 
			
		||||
			return opt && opt.span ? opt.span : 24 / COLUMN_PER_ROW;
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		getLabel(n, c) {
 | 
			
		||||
			const opt = this.configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)];
 | 
			
		||||
			if (opt) {
 | 
			
		||||
				// if opt is valid
 | 
			
		||||
				return opt.label ? opt.label : this.defaultNames[opt.name];
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		getPlaceholder(n, c) {
 | 
			
		||||
			if (this.isDetail) {
 | 
			
		||||
				/** 如果是详情,就不展示 提示文本 */
 | 
			
		||||
				return '';
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			const opt = this.configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)];
 | 
			
		||||
			if (opt) {
 | 
			
		||||
				// if opt is valid
 | 
			
		||||
				return opt.placeholder
 | 
			
		||||
					? opt.placeholder
 | 
			
		||||
					: this.defaultPlaceholders[opt.name]
 | 
			
		||||
					? this.defaultPlaceholders[opt.name]
 | 
			
		||||
					: opt.label
 | 
			
		||||
					? (opt.type === 'select' ? '请选择' : '请输入') + opt.label
 | 
			
		||||
					: // ? (opt.type === 'select' ? i18n.t('choose') : i18n.t('hints.input')) + opt.label
 | 
			
		||||
					  null;
 | 
			
		||||
 | 
			
		||||
				// : opt.type === 'select'
 | 
			
		||||
				// ? i18n.t('choose')
 | 
			
		||||
				// : '请输入'
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		getType(n, c) {
 | 
			
		||||
			const opt = this.configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)];
 | 
			
		||||
			if (opt) {
 | 
			
		||||
				if (!opt.type || ['input', 'number' /** add more.. */].includes(opt.type)) {
 | 
			
		||||
					return 'input';
 | 
			
		||||
				} else if (['select' /** add more.. */].includes(opt.type)) {
 | 
			
		||||
					return 'select';
 | 
			
		||||
				} else if (['cascader'].includes(opt.type)) {
 | 
			
		||||
					return 'cascader';
 | 
			
		||||
				} else if (['date'].includes(opt.type)) {
 | 
			
		||||
					return 'date';
 | 
			
		||||
				}
 | 
			
		||||
				// add more...
 | 
			
		||||
			} else {
 | 
			
		||||
				return 'input';
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		init(id, isdetail = false) {
 | 
			
		||||
			this.isDetail = isdetail;
 | 
			
		||||
			this.visible = true;
 | 
			
		||||
			this.$nextTick(() => {
 | 
			
		||||
				this.$refs['dataForm'].resetFields();
 | 
			
		||||
				this.dataForm.id = id || null;
 | 
			
		||||
				if (this.dataForm.id) {
 | 
			
		||||
					// this.$http({
 | 
			
		||||
					// 	url: this.$http.adornUrl(`${this.configs.infoUrl}/${this.dataForm.id}`),
 | 
			
		||||
					// 	method: 'get'
 | 
			
		||||
					// })
 | 
			
		||||
					$http.get(this.url.base + `/${this.dataForm.id}`).then((res) => {
 | 
			
		||||
						console.log('[base dialog init] ', res);
 | 
			
		||||
						if (res && res.code === 0) {
 | 
			
		||||
							const dataFormKeys = Object.keys(this.dataForm);
 | 
			
		||||
							console.log('keys ===> ', dataFormKeys);
 | 
			
		||||
							// console.log('data form keys: ', dataFormKeys, pick(res.data, dataFormKeys))
 | 
			
		||||
							this.dataForm = __pick(res.data, dataFormKeys);
 | 
			
		||||
							console.log('pick(res.data, dataFormKeys) ===> ', __pick(res.data, dataFormKeys));
 | 
			
		||||
							// LABEL: FILE_RELATED
 | 
			
		||||
							/** 对文件下载进行分流 */
 | 
			
		||||
							this.fileList = {};
 | 
			
		||||
							if (this.dataForm.files) {
 | 
			
		||||
								// console.log('files: ', this.dataForm.files)
 | 
			
		||||
								this.dataForm.files.forEach((file) => {
 | 
			
		||||
									// const fileName = file.fileUrl.split('/').pop()
 | 
			
		||||
									/** [1] 处理 fileList */
 | 
			
		||||
									// if (Object.hasOwn(this.fileList, file.typeCode)) {
 | 
			
		||||
									if (this.fileList.hasOwnProperty(file.typeCode)) {
 | 
			
		||||
										/** 已存在 */
 | 
			
		||||
										// this.fileList[file.typeCode].push({ id: file.id, name: fileName, typeCode: file.typeCode })
 | 
			
		||||
										this.fileList[file.typeCode].push(file);
 | 
			
		||||
									} else {
 | 
			
		||||
										// this.fileList[file.typeCode] = [{ id: file.id, name: fileName, typeCode: file.typeCode }]
 | 
			
		||||
										this.fileList[file.typeCode] = [file];
 | 
			
		||||
									}
 | 
			
		||||
 | 
			
		||||
									/** [2] 处理 fileForm */
 | 
			
		||||
									// if (Object.hasOwn(this.fileForm, file.typeCode)) {
 | 
			
		||||
									if (this.fileForm.hasOwnProperty(file.typeCode)) {
 | 
			
		||||
										this.fileForm[file.typeCode].push(file.id);
 | 
			
		||||
									} else {
 | 
			
		||||
										this.fileForm[file.typeCode] = [file.id];
 | 
			
		||||
									}
 | 
			
		||||
								});
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					});
 | 
			
		||||
				} else {
 | 
			
		||||
					/** 如果不是编辑,就填充自动生成的数据 */
 | 
			
		||||
					if (this.shouldWait)
 | 
			
		||||
						this.shouldWait.then(() => {
 | 
			
		||||
							if (this.tempForm.length) {
 | 
			
		||||
								// console.log('create new, tempform', JSON.stringify(this.tempForm.length))
 | 
			
		||||
								this.tempForm.forEach((item) => {
 | 
			
		||||
									// console.log('item data', item.data)
 | 
			
		||||
									this.dataForm[item.name] = item.data;
 | 
			
		||||
								});
 | 
			
		||||
								// console.log('create new, dataform', JSON.stringify(this.dataForm))
 | 
			
		||||
							}
 | 
			
		||||
							this.shouldWait = null;
 | 
			
		||||
						});
 | 
			
		||||
				}
 | 
			
		||||
			});
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		emitSelectChange(name, id) {
 | 
			
		||||
			const currentField = this.configs.fields.find((item) => item.name === name);
 | 
			
		||||
			if (currentField.relatedField) {
 | 
			
		||||
				this.dataForm[currentField.relatedField] = null;
 | 
			
		||||
			}
 | 
			
		||||
			this.$emit('select-change', { name, id });
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		handleEditorReady(val) {},
 | 
			
		||||
 | 
			
		||||
		handleClick(btn) {
 | 
			
		||||
			/** 提取url */
 | 
			
		||||
			// const urls = {};
 | 
			
		||||
			// this.configs.operations.map((item) => {
 | 
			
		||||
			// 	urls[item.name] = {};
 | 
			
		||||
			// 	urls[item.name].url = item.url;
 | 
			
		||||
			// 	urls[item.name].extraFields = item.extraFields || {};
 | 
			
		||||
			// });
 | 
			
		||||
			/** 操作 */
 | 
			
		||||
			switch (btn.name) {
 | 
			
		||||
				case 'save':
 | 
			
		||||
				case 'update':
 | 
			
		||||
					/** 需要验证表单的操作 */
 | 
			
		||||
					this.$refs['dataForm'].validate((valid) => {
 | 
			
		||||
						if (valid) {
 | 
			
		||||
							/** 对于文件上传的单独处理(合并处理) */
 | 
			
		||||
							if (Object.keys(this.fileForm).length) {
 | 
			
		||||
								// LABEL: FILE_RELATED
 | 
			
		||||
								let fileIds = [];
 | 
			
		||||
								for (const [key, item] of Object.entries(this.fileForm)) {
 | 
			
		||||
									if (Array.isArray(item)) {
 | 
			
		||||
										fileIds = fileIds.concat(item);
 | 
			
		||||
									} else {
 | 
			
		||||
										console.error('handleClick(): 上传文件数组类型不正确');
 | 
			
		||||
									}
 | 
			
		||||
								}
 | 
			
		||||
								this.$set(this.dataForm, 'fileIds', fileIds);
 | 
			
		||||
							}
 | 
			
		||||
 | 
			
		||||
							// console.log('before send: ', this.dataForm)
 | 
			
		||||
 | 
			
		||||
							// this.$http({
 | 
			
		||||
							// 	url: this.$http.adornUrl(urls[btn.name].url),
 | 
			
		||||
							// 	method: btn.name === 'save' ? 'POST' : 'PUT',
 | 
			
		||||
							// 	data: { ...this.dataForm, ...urls[btn.name].extraFields },
 | 
			
		||||
							// })
 | 
			
		||||
							$http[btn.name === 'save' ? 'post' : 'put'](btn.url, { ...this.dataForm, ...btn.extraFields })
 | 
			
		||||
								.then((res) => {
 | 
			
		||||
									// .then(({ data: res }) => {
 | 
			
		||||
									console.log('save res: ', res, btn.name, this.dataForm);
 | 
			
		||||
									if (res && res.code === 0) {
 | 
			
		||||
										this.$message({
 | 
			
		||||
											message: '操作成功!',
 | 
			
		||||
											// message: i18n.t('prompt.success'),
 | 
			
		||||
											// message: btn.name === 'save' ? i18n.t('prompt.success') : '更新成功!',
 | 
			
		||||
											type: 'success',
 | 
			
		||||
											duration: 1500,
 | 
			
		||||
											onClose: () => {
 | 
			
		||||
												this.$emit('refreshDataList');
 | 
			
		||||
												this.visible = false;
 | 
			
		||||
											},
 | 
			
		||||
										});
 | 
			
		||||
									} else {
 | 
			
		||||
										this.$message.error(res.msg);
 | 
			
		||||
									}
 | 
			
		||||
								})
 | 
			
		||||
								.catch((err) => {
 | 
			
		||||
									this.$message({
 | 
			
		||||
										message: err,
 | 
			
		||||
										type: 'error',
 | 
			
		||||
										duration: 2000,
 | 
			
		||||
									});
 | 
			
		||||
								});
 | 
			
		||||
						}
 | 
			
		||||
					});
 | 
			
		||||
					return;
 | 
			
		||||
				case 'reset':
 | 
			
		||||
					for (const key of Object.keys(this.dataForm)) {
 | 
			
		||||
						if (typeof this.dataForm[key] === 'string') {
 | 
			
		||||
							this.dataForm[key] = '';
 | 
			
		||||
						} else if (this.dataForm[key] instanceof Array) {
 | 
			
		||||
							this.dataForm[key].splice(0);
 | 
			
		||||
						} else {
 | 
			
		||||
							this.dataForm[key] = null;
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					break;
 | 
			
		||||
				case 'cancel':
 | 
			
		||||
					this.handleClose();
 | 
			
		||||
				// add more..
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// LABEL: FILE_RELATED
 | 
			
		||||
		handleUploadListUpdate(filelist, typeCode = 'DefaultTypeCode') {
 | 
			
		||||
			// console.log('before handleUploadListUpdate(): ', JSON.parse(JSON.stringify(this.fileForm)))
 | 
			
		||||
			// 设备类型 typeCode: EquipmentTypeFile
 | 
			
		||||
			// 设备信息 typeCode: EquipmentInfoFile | EquipmentInfoImage
 | 
			
		||||
 | 
			
		||||
			// 原先写法:直接更新 dataForm 对象,不适用于有多个上传组件的需求
 | 
			
		||||
			// this.$set(
 | 
			
		||||
			// 	this.dataForm,
 | 
			
		||||
			// 	'fileIds',
 | 
			
		||||
			// 	filelist.map(item => item.id)
 | 
			
		||||
			// )
 | 
			
		||||
			// console.log('handleUploadListUpdate(): ', this.dataForm)
 | 
			
		||||
			// 现更改为分流写法
 | 
			
		||||
			this.$set(
 | 
			
		||||
				this.fileForm,
 | 
			
		||||
				typeCode,
 | 
			
		||||
				filelist.map((item) => item.id)
 | 
			
		||||
			);
 | 
			
		||||
			// console.log('after handleUploadListUpdate(): ', this.fileForm)
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		handleClose() {
 | 
			
		||||
			this.$emit('destory-dialog');
 | 
			
		||||
			this.visible = false;
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
.super-flexible-dialog >>> .el-select,
 | 
			
		||||
.super-flexible-dialog >>> .el-cascader {
 | 
			
		||||
	width: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.super-flexible-dialog >>> ::-webkit-scrollbar {
 | 
			
		||||
	width: 4px;
 | 
			
		||||
	border-radius: 4px;
 | 
			
		||||
	background: #fff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.super-flexible-dialog >>> ::-webkit-scrollbar-thumb {
 | 
			
		||||
	width: 4px;
 | 
			
		||||
	border-radius: 4px;
 | 
			
		||||
	background: #ccc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.super-flexible-dialog >>> .hidden-input {
 | 
			
		||||
	display: none;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,181 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
	<el-row class="base-search-form">
 | 
			
		||||
		<div class="brand-color-line"></div>
 | 
			
		||||
		<el-form :inline="true" :model="searchForm" :rules="headConfig.rules">
 | 
			
		||||
			<!-- <el-col :span="opt.span ? +opt.span : 4" v-for="opt in options" :key="opt.id"> -->
 | 
			
		||||
			<el-form-item
 | 
			
		||||
				v-for="(opt, index) in headConfig.fields"
 | 
			
		||||
				:key="opt.prop"
 | 
			
		||||
				:label="opt.label ? opt.label : null"
 | 
			
		||||
				:prop="'' + index"
 | 
			
		||||
				:rules="opt.bind?.rules ? opt.bind.rules : undefined"
 | 
			
		||||
			>
 | 
			
		||||
				<el-input
 | 
			
		||||
					v-if="opt.input"
 | 
			
		||||
					v-model="searchForm[index]"
 | 
			
		||||
					v-bind="opt.bind"
 | 
			
		||||
				/>
 | 
			
		||||
				<el-select
 | 
			
		||||
					v-if="opt.select"
 | 
			
		||||
					v-model="searchForm[index]"
 | 
			
		||||
					v-bind="opt.bind"
 | 
			
		||||
				>
 | 
			
		||||
					<el-option
 | 
			
		||||
						v-for="item in opt.select"
 | 
			
		||||
						:key="item.value"
 | 
			
		||||
						:label="item.label"
 | 
			
		||||
						:value="item.value"
 | 
			
		||||
					/>
 | 
			
		||||
				</el-select>
 | 
			
		||||
				<el-date-picker
 | 
			
		||||
					v-if="opt.timerange"
 | 
			
		||||
					v-model="searchForm[index]"
 | 
			
		||||
					v-bind="opt.bind"
 | 
			
		||||
				/>
 | 
			
		||||
				<el-upload
 | 
			
		||||
					v-if="opt.upload"
 | 
			
		||||
					:key="'upload_' + Math.random().toString()"
 | 
			
		||||
					class="inline-block pl-3"
 | 
			
		||||
					action="https://jsonplaceholder.typicode.com/posts/"
 | 
			
		||||
				>
 | 
			
		||||
					<el-button type="primary">上传文件</el-button>
 | 
			
		||||
				</el-upload>
 | 
			
		||||
				<el-button
 | 
			
		||||
					v-if="
 | 
			
		||||
						opt.button &&
 | 
			
		||||
							(!opt.button.permission || $hasPermission(opt.button.permission))
 | 
			
		||||
					"
 | 
			
		||||
					:key="'button' + Math.random().toString()"
 | 
			
		||||
					:type="opt.button.type"
 | 
			
		||||
					@click="handleBtnClick(opt.button.name)"
 | 
			
		||||
					>{{ opt.button.name }}</el-button
 | 
			
		||||
				>
 | 
			
		||||
			</el-form-item>
 | 
			
		||||
		</el-form>
 | 
			
		||||
	</el-row>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
export default {
 | 
			
		||||
	name: "",
 | 
			
		||||
	props: {
 | 
			
		||||
		headConfig: {
 | 
			
		||||
			type: Object,
 | 
			
		||||
			default: () => ({}),
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			searchForm: {
 | 
			
		||||
				// 最大参数个数:10个,不够则在这里加
 | 
			
		||||
				0: null, // 参数一
 | 
			
		||||
				1: null,
 | 
			
		||||
				2: null,
 | 
			
		||||
				3: null,
 | 
			
		||||
				4: null,
 | 
			
		||||
				5: null,
 | 
			
		||||
				6: null,
 | 
			
		||||
				7: null,
 | 
			
		||||
				8: null,
 | 
			
		||||
				9: null,
 | 
			
		||||
			},
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	watch: {
 | 
			
		||||
		searchForm: {
 | 
			
		||||
			handler: (val) => {
 | 
			
		||||
				console.log("new val", val);
 | 
			
		||||
			},
 | 
			
		||||
			deep: true,
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	created() {},
 | 
			
		||||
	mounted() {
 | 
			
		||||
		console.log(
 | 
			
		||||
			"head form config",
 | 
			
		||||
			JSON.parse(JSON.stringify(this.headConfig))
 | 
			
		||||
		);
 | 
			
		||||
		this.headConfig.fields.forEach((field, index) => {
 | 
			
		||||
			if (field.default) {
 | 
			
		||||
				// default 必须有个 value 属性!哪怕是 input 输入框
 | 
			
		||||
				this.searchForm[index] = field.default.value;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// 更新选项列表
 | 
			
		||||
			if (!field.watch && field.fn && typeof field.fn === "function") {
 | 
			
		||||
				// 设置自身的选项列表
 | 
			
		||||
				field.fn().then((res) => {
 | 
			
		||||
					field.select = res.map((_) => {
 | 
			
		||||
						// 找到默认项
 | 
			
		||||
						if (_.default) {
 | 
			
		||||
							this.searchForm[index] = _.value;
 | 
			
		||||
						}
 | 
			
		||||
						return _;
 | 
			
		||||
					});
 | 
			
		||||
					console.log("[update] 更新选项列表", res, field.select);
 | 
			
		||||
				});
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// 如果需要监听关联字段
 | 
			
		||||
			if (field.watch) {
 | 
			
		||||
				const { index: innerIdx, condition } = field.watch;
 | 
			
		||||
				console.log(
 | 
			
		||||
					"=====field.watch=====",
 | 
			
		||||
					innerIdx,
 | 
			
		||||
					this.searchForm[innerIdx],
 | 
			
		||||
					this.headConfig.fields[innerIdx].default
 | 
			
		||||
				);
 | 
			
		||||
				// 设置监听器
 | 
			
		||||
				this.$watch(
 | 
			
		||||
					() => this.searchForm[innerIdx],
 | 
			
		||||
					(val) => {
 | 
			
		||||
						const queryParams = { [condition]: val };
 | 
			
		||||
						// field.watch.condition.forEach(c => {
 | 
			
		||||
						// 	queryParams
 | 
			
		||||
						// })
 | 
			
		||||
						this.$http(field.url, queryParams).then((res) => {
 | 
			
		||||
							console.log("[==>] 更新有前置条件的字段!!!", queryParams, res);
 | 
			
		||||
							// 此处是外部的 index
 | 
			
		||||
							this.searchForm[index] = Math.floor(Math.random() * 10);
 | 
			
		||||
						});
 | 
			
		||||
					}
 | 
			
		||||
				);
 | 
			
		||||
 | 
			
		||||
				console.log("[BaseSearchForm] mounted(): ", this.searchForm);
 | 
			
		||||
				// 如果此时已经有默认值了,就立马根据这个默认值来发起请求
 | 
			
		||||
				if (this.searchForm[innerIdx]) {
 | 
			
		||||
					// TODO: 这个判断好像不太需要...
 | 
			
		||||
					console.log("TODO: 这个判断好像不太需要...");
 | 
			
		||||
				} else {
 | 
			
		||||
					console.log("TODO: 监听的字段还没来得及设置值呢...");
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		handleBtnClick(name) {
 | 
			
		||||
			this.$emit("btn-click", { btnName: name, payload: this.searchForm });
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
.base-search-form {
 | 
			
		||||
	display: flex;
 | 
			
		||||
	/* align-items: center; */
 | 
			
		||||
	/* position: relative; */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.brand-color-line {
 | 
			
		||||
	display: inline-block;
 | 
			
		||||
	height: 20px;
 | 
			
		||||
	width: 6px;
 | 
			
		||||
	margin-right: 8px;
 | 
			
		||||
	margin-top: 10px;
 | 
			
		||||
	border-radius: 2px;
 | 
			
		||||
	background: #0b58ff;
 | 
			
		||||
	/* position: absolute; */
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,206 +0,0 @@
 | 
			
		||||
<!--
 | 
			
		||||
 * @Date: 2020-12-14 09:07:03
 | 
			
		||||
 * @LastEditors: gtz
 | 
			
		||||
 * @LastEditTime: 2022-06-13 08:59:21
 | 
			
		||||
 * @FilePath: \mt-bus-fe\src\components\BaseTable\index.vue
 | 
			
		||||
 * @Description:
 | 
			
		||||
-->
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="">
 | 
			
		||||
    <el-table
 | 
			
		||||
      :header-cell-style="{
 | 
			
		||||
        background: '#FAFAFA',
 | 
			
		||||
        color: '#606266',
 | 
			
		||||
        height: '40px',
 | 
			
		||||
      }"
 | 
			
		||||
      :data="renderData"
 | 
			
		||||
      :show-header="showHeader"
 | 
			
		||||
      :border="border"
 | 
			
		||||
      fit
 | 
			
		||||
      highlight-current-rows
 | 
			
		||||
      style="width: 100%"
 | 
			
		||||
      @row-click="handleRowClick"
 | 
			
		||||
      @selection-change="handleSelectionChange"
 | 
			
		||||
      >
 | 
			
		||||
      <!-- :max-height="height ? height : tableHeight(325)" -->
 | 
			
		||||
      <el-table-column v-if="sbox" type="selection" width="55" fixed />
 | 
			
		||||
      <el-table-column
 | 
			
		||||
        v-if="page && limit && !toggleCustomIndex"
 | 
			
		||||
        prop="_pageIndex"
 | 
			
		||||
        :label="'tableHeader.index' | i18nFilter"
 | 
			
		||||
        width="70"
 | 
			
		||||
        align="center"
 | 
			
		||||
        fixed
 | 
			
		||||
      />
 | 
			
		||||
      <el-table-column
 | 
			
		||||
        v-for="item in renderTableHeadList"
 | 
			
		||||
        :key="item.prop"
 | 
			
		||||
        v-bind="item"
 | 
			
		||||
        :align="item.align ? item.align : 'left'"
 | 
			
		||||
        :min-width="item.minWidth ? item.minWidth : 150"
 | 
			
		||||
        :fixed="item.isFixed ? true : false"
 | 
			
		||||
        :show-overflow-tooltip="true"
 | 
			
		||||
      >
 | 
			
		||||
        <template slot-scope="scope">
 | 
			
		||||
          <component
 | 
			
		||||
            :is="item.subcomponent"
 | 
			
		||||
            v-if="item.subcomponent"
 | 
			
		||||
            :key="scope.row.id"
 | 
			
		||||
            :inject-data="{ ...scope.row, ...item }"
 | 
			
		||||
            @emitData="emitData"
 | 
			
		||||
          />
 | 
			
		||||
          <span v-else>{{
 | 
			
		||||
            scope.row[item.prop] | commonFilter(item.filter)
 | 
			
		||||
          }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <slot name="content" />
 | 
			
		||||
      <slot name="handleBtn" />
 | 
			
		||||
    </el-table>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<script>
 | 
			
		||||
export default {
 | 
			
		||||
  name: "BaseTable",
 | 
			
		||||
  filters: {
 | 
			
		||||
    commonFilter: (source, filterType = (a) => a) => {
 | 
			
		||||
      return filterType(source);
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  props: {
 | 
			
		||||
    toggleCustomIndex: {
 | 
			
		||||
      type: Boolean,
 | 
			
		||||
      default: false,
 | 
			
		||||
    },
 | 
			
		||||
    topBtnConfig: {
 | 
			
		||||
      type: Array,
 | 
			
		||||
      default: () => {
 | 
			
		||||
        return [];
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    showHeader: {
 | 
			
		||||
      type: Boolean,
 | 
			
		||||
      default: true,
 | 
			
		||||
    },
 | 
			
		||||
    border: {
 | 
			
		||||
      type: Boolean,
 | 
			
		||||
      default: false,
 | 
			
		||||
    },
 | 
			
		||||
    height: {
 | 
			
		||||
      type: Number,
 | 
			
		||||
      required: false,
 | 
			
		||||
      default: 0,
 | 
			
		||||
    },
 | 
			
		||||
    tableData: {
 | 
			
		||||
      type: Array,
 | 
			
		||||
      required: true,
 | 
			
		||||
      // validator: (val) => val.filter((item) => !isObject(item)).length === 0,
 | 
			
		||||
    },
 | 
			
		||||
    tableConfig: {
 | 
			
		||||
      type: Array,
 | 
			
		||||
      required: true,
 | 
			
		||||
      // validator: (val) =>
 | 
			
		||||
      //   val.filter((item) => !isString(item.prop) || !isString(item.label))
 | 
			
		||||
      //     .length === 0,
 | 
			
		||||
    },
 | 
			
		||||
    isLoading: {
 | 
			
		||||
      type: Boolean,
 | 
			
		||||
      required: false,
 | 
			
		||||
    },
 | 
			
		||||
    page: {
 | 
			
		||||
      type: Number,
 | 
			
		||||
      required: false,
 | 
			
		||||
      default: 0,
 | 
			
		||||
    },
 | 
			
		||||
    limit: {
 | 
			
		||||
      type: Number,
 | 
			
		||||
      required: false,
 | 
			
		||||
      default: 0,
 | 
			
		||||
    },
 | 
			
		||||
    sbox: {
 | 
			
		||||
      type: Boolean,
 | 
			
		||||
      required: false,
 | 
			
		||||
    },
 | 
			
		||||
    highIndex: {
 | 
			
		||||
      // 首行是否默认高亮
 | 
			
		||||
      type: Boolean,
 | 
			
		||||
      required: false,
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      tableConfigBak: [],
 | 
			
		||||
      selectedBox: new Array(100).fill(true),
 | 
			
		||||
      // tableHeight,
 | 
			
		||||
      tableRowIndex: null,
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  computed: {
 | 
			
		||||
    renderData() {
 | 
			
		||||
      return this.tableData.map((item, index) => {
 | 
			
		||||
        return {
 | 
			
		||||
          ...item,
 | 
			
		||||
          _pageIndex: (this.page - 1) * this.limit + index + 1,
 | 
			
		||||
        };
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    renderTableHeadList() {
 | 
			
		||||
      return this.tableConfig.filter((item, index) => {
 | 
			
		||||
        return this.selectedBox[index];
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  watch: {
 | 
			
		||||
    tableData: function (val) {
 | 
			
		||||
      if (this.highIndex) {
 | 
			
		||||
        // 默认高亮行的,重置默认高亮行为第一行
 | 
			
		||||
        this.tableRowIndex = 0;
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  beforeMount() {
 | 
			
		||||
    this.selectedBox = new Array(100).fill(true);
 | 
			
		||||
    if (this.highIndex) {
 | 
			
		||||
      this.tableRowIndex = 0;
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  // mounted() {
 | 
			
		||||
  //   this.tableConfigBak = cloneDeep(this.tableConfig).map(item => {
 | 
			
		||||
  //     return {
 | 
			
		||||
  //       ...item,
 | 
			
		||||
  //       selected: true
 | 
			
		||||
  //     }
 | 
			
		||||
  //   })
 | 
			
		||||
  // },
 | 
			
		||||
  methods: {
 | 
			
		||||
    emitData(val) {
 | 
			
		||||
      this.$emit("emitFun", val);
 | 
			
		||||
    },
 | 
			
		||||
    clickTopButton(val) {
 | 
			
		||||
      this.$emit("clickTopBtn", val);
 | 
			
		||||
    },
 | 
			
		||||
    handleSelectionChange(val) {
 | 
			
		||||
      this.$emit("selectChangeFun", val);
 | 
			
		||||
    },
 | 
			
		||||
    handleRowClick(row) {
 | 
			
		||||
      this.tableRowIndex = this.getArrayIndex(this.tableData, row); // 获取当前点击行下标
 | 
			
		||||
      this.$emit("selectRow", row);
 | 
			
		||||
    },
 | 
			
		||||
    tableRowClassName({ row, rowIndex }) {
 | 
			
		||||
      if (rowIndex === this.tableRowIndex) {
 | 
			
		||||
        return "success-row";
 | 
			
		||||
      }
 | 
			
		||||
      return "";
 | 
			
		||||
    },
 | 
			
		||||
    getArrayIndex(arr, obj) {
 | 
			
		||||
      var i = arr.length;
 | 
			
		||||
      while (i--) {
 | 
			
		||||
        if (arr[i].id === obj.id) {
 | 
			
		||||
          return i;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      return -1;
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,19 +0,0 @@
 | 
			
		||||
<!-- 基本上传 -->
 | 
			
		||||
<template>
 | 
			
		||||
	<div></div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
export default {
 | 
			
		||||
	name: '',
 | 
			
		||||
	props: {},
 | 
			
		||||
	data() {
 | 
			
		||||
		return {};
 | 
			
		||||
	},
 | 
			
		||||
	created() {},
 | 
			
		||||
	mounted() {},
 | 
			
		||||
	methods: {},
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped></style>
 | 
			
		||||
@@ -210,6 +210,8 @@ export default {
 | 
			
		||||
        url: file.url,
 | 
			
		||||
        typeCode: file.typeCode,
 | 
			
		||||
      }));
 | 
			
		||||
      // 更新请求
 | 
			
		||||
      this.addOrUpdate("PUT");
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /** utitilities */
 | 
			
		||||
@@ -265,7 +267,7 @@ export default {
 | 
			
		||||
                  url: file.fileUrl,
 | 
			
		||||
                }));
 | 
			
		||||
              }
 | 
			
		||||
              console.log("[DialogJustForm] init():", __pick(res.data, Object.keys(this.dataForm)));
 | 
			
		||||
              console.log("[DialogJustForm] init():", this.dataForm);
 | 
			
		||||
            }
 | 
			
		||||
            this.loadingStatus = false;
 | 
			
		||||
          });
 | 
			
		||||
@@ -290,6 +292,53 @@ export default {
 | 
			
		||||
      console.log("[DialogJustForm] handleComponentModelUpdate", this.dataForm[propName]);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    addOrUpdate(method = "POST") {
 | 
			
		||||
      if ("parentId" in this.dataForm) {
 | 
			
		||||
        console.log("[DialogJustForm parentId]", this.dataForm.parentId);
 | 
			
		||||
        // 对特殊的键做特殊处理,如 parentId 是一个 cascader,获取的值是 ["xxx"],后端只需要xxx
 | 
			
		||||
        const lastItem = this.dataForm.parentId.length - 1;
 | 
			
		||||
        this.dataForm.parentId = this.dataForm.parentId[lastItem];
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this.$refs.dataForm.validate((passed, result) => {
 | 
			
		||||
        if (passed) {
 | 
			
		||||
          this.loadingStatus = true;
 | 
			
		||||
 | 
			
		||||
          let httpPayload = null;
 | 
			
		||||
          /** 针对有文件上传选项的弹窗提供特殊的 payload */
 | 
			
		||||
          if (this.dataForm.files) {
 | 
			
		||||
            httpPayload = {
 | 
			
		||||
              ...this.dataForm,
 | 
			
		||||
              fileIds: this.dataForm.files.map((file) => file.id),
 | 
			
		||||
            };
 | 
			
		||||
          } else {
 | 
			
		||||
            httpPayload = this.dataForm;
 | 
			
		||||
          }
 | 
			
		||||
          /** 发送 */
 | 
			
		||||
          return this.$http({
 | 
			
		||||
            url: this.urls.base,
 | 
			
		||||
            method,
 | 
			
		||||
            data: httpPayload,
 | 
			
		||||
          })
 | 
			
		||||
            .then(({ data: res }) => {
 | 
			
		||||
              console.log("[add&update] res is: ", res);
 | 
			
		||||
              if (res.code === 0) {
 | 
			
		||||
                this.$message.success(method === "POST" ? "添加成功" : "更新成功");
 | 
			
		||||
                this.$emit("refreshDataList");
 | 
			
		||||
                this.loadingStatus = false;
 | 
			
		||||
                if (method === "POST") this.handleClose();
 | 
			
		||||
              }
 | 
			
		||||
            })
 | 
			
		||||
            .catch((errMsg) => {
 | 
			
		||||
              this.$message.error("参数错误:" + errMsg);
 | 
			
		||||
              if (this.loadingStatus) this.loadingStatus = false;
 | 
			
		||||
            });
 | 
			
		||||
        } else {
 | 
			
		||||
          this.$message.error("请核查字段信息");
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    handleBtnClick(payload) {
 | 
			
		||||
      console.log("btn click payload: ", payload);
 | 
			
		||||
 | 
			
		||||
@@ -302,52 +351,9 @@ export default {
 | 
			
		||||
            this.resetForm(true, true); // true means exclude id, immediate execution
 | 
			
		||||
            break;
 | 
			
		||||
          case "add":
 | 
			
		||||
          case "update": {
 | 
			
		||||
            if ("parentId" in this.dataForm) {
 | 
			
		||||
              console.log("[DialogJustForm parentId]", this.dataForm.parentId);
 | 
			
		||||
              // 对特殊的键做特殊处理,如 parentId 是一个 cascader,获取的值是 ["xxx"],后端只需要xxx
 | 
			
		||||
              const lastItem = this.dataForm.parentId.length - 1;
 | 
			
		||||
              this.dataForm.parentId = this.dataForm.parentId[lastItem];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.$refs.dataForm.validate((passed, result) => {
 | 
			
		||||
              if (passed) {
 | 
			
		||||
                this.loadingStatus = true;
 | 
			
		||||
                const method = payload.name === "add" ? "POST" : "PUT";
 | 
			
		||||
                let httpPayload = null;
 | 
			
		||||
                /** 针对有文件上传选项的弹窗提供特殊的 payload */
 | 
			
		||||
                if (this.dataForm.files) {
 | 
			
		||||
                  httpPayload = {
 | 
			
		||||
                    ...this.dataForm,
 | 
			
		||||
                    fileIds: this.dataForm.files.map((file) => file.id),
 | 
			
		||||
                  };
 | 
			
		||||
                } else {
 | 
			
		||||
                  httpPayload = this.dataForm;
 | 
			
		||||
                }
 | 
			
		||||
                /** 发送 */
 | 
			
		||||
                this.$http({
 | 
			
		||||
                  url: this.urls.base,
 | 
			
		||||
                  method,
 | 
			
		||||
                  data: httpPayload,
 | 
			
		||||
                })
 | 
			
		||||
                  .then(({ data: res }) => {
 | 
			
		||||
                    console.log("[add&update] res is: ", res);
 | 
			
		||||
                    if (res.code === 0) {
 | 
			
		||||
                      this.$message.success(payload.name === "add" ? "添加成功" : "更新成功");
 | 
			
		||||
                      this.$emit("refreshDataList");
 | 
			
		||||
                      this.loadingStatus = false;
 | 
			
		||||
                      this.handleClose();
 | 
			
		||||
                    }
 | 
			
		||||
                  })
 | 
			
		||||
                  .catch((errMsg) => {
 | 
			
		||||
                    this.$message.error("参数错误:" + errMsg);
 | 
			
		||||
                    if (this.loadingStatus) this.loadingStatus = false;
 | 
			
		||||
                  });
 | 
			
		||||
              } else {
 | 
			
		||||
                this.$message.error("请核查字段信息");
 | 
			
		||||
              }
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
          case "update":
 | 
			
		||||
            this.addOrUpdate((payload.name === "add" ? "POST" : "PUT"));
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        console.log("[x] 不是这么用的! 缺少name属性");
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,7 @@
 | 
			
		||||
          :show-file-list="false"
 | 
			
		||||
          :headers="uploadHeaders"
 | 
			
		||||
          :on-success="handleUploadSuccess"
 | 
			
		||||
          :before-upload="handleUploadCheck"
 | 
			
		||||
        >
 | 
			
		||||
          <el-button plain type="primary" size="small" class="at-right-top" style=""> <i class="el-icon-upload"></i> 上传 </el-button>
 | 
			
		||||
        </el-upload>
 | 
			
		||||
@@ -128,6 +129,7 @@
 | 
			
		||||
              :current-page="attrPage"
 | 
			
		||||
              :current-size="attrSize"
 | 
			
		||||
              :refresh-layout-key="Math.random()"
 | 
			
		||||
              v-loading="loadingStatus"
 | 
			
		||||
            />
 | 
			
		||||
            <!-- paginator  -->
 | 
			
		||||
            <el-pagination
 | 
			
		||||
@@ -147,8 +149,9 @@
 | 
			
		||||
 | 
			
		||||
          <!-- 附件标签页 -->
 | 
			
		||||
          <div v-if="dataForm.id && tab.key === 'attachment'" key="attachment">
 | 
			
		||||
            <div class="upload-tips" style="font-size: 0.8em; margin-bottom: 12px">文件大小不要超过 2MB</div>
 | 
			
		||||
            <!-- 附件列表 -->
 | 
			
		||||
            <div class="">
 | 
			
		||||
            <div class="" v-loading="loadingStatus">
 | 
			
		||||
              <ul class="file-list">
 | 
			
		||||
                <li v-for="(file, index) in fileList" :key="index">
 | 
			
		||||
                  <span class="file-name">{{ file.name }}</span>
 | 
			
		||||
@@ -166,11 +169,17 @@
 | 
			
		||||
                </li>
 | 
			
		||||
              </ul>
 | 
			
		||||
            </div>
 | 
			
		||||
            <!-- 提示信息 -->
 | 
			
		||||
            <!-- img preview dialog  -->
 | 
			
		||||
            <el-dialog key="image-preview-dialog" class="image-preview-dialog" :visible.sync="imgPreviewDialogVisible" :append-to-body="true">
 | 
			
		||||
              <div class="img-container">
 | 
			
		||||
                <img width="100%" :src="currentImgUrl" alt="" />
 | 
			
		||||
              </div>
 | 
			
		||||
            </el-dialog>
 | 
			
		||||
          </div>
 | 
			
		||||
        </el-tab-pane>
 | 
			
		||||
      </el-tabs>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <!-- sub dialog  -->
 | 
			
		||||
    <small-dialog
 | 
			
		||||
      :append-to-body="true"
 | 
			
		||||
@@ -341,7 +350,9 @@ export default {
 | 
			
		||||
      attrPage: 1,
 | 
			
		||||
      attrSize: 5,
 | 
			
		||||
      attrTotal: 0,
 | 
			
		||||
      fileList: [{ name: "1.png" }, { name: "2.png" }],
 | 
			
		||||
      fileList: [],
 | 
			
		||||
      imgPreviewDialogVisible: false,
 | 
			
		||||
      currentImgUrl: "",
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  computed: {
 | 
			
		||||
@@ -377,8 +388,10 @@ export default {
 | 
			
		||||
      const editMode = operate.showOnEdit && this.dataForm.id;
 | 
			
		||||
      const addMode = !operate.showOnEdit && !this.dataForm.id;
 | 
			
		||||
      const permission = operate.permission ? this.$hasPermission(operate.permission) : true;
 | 
			
		||||
      return notDetailMode && (showAlways || ((editMode || addMode) && permission));
 | 
			
		||||
      const currentMenuKey = this.configs.menu.find((item) => item.name === this.activeMenu)?.key;
 | 
			
		||||
      return notDetailMode && (showAlways || ((editMode || addMode) && permission)) && currentMenuKey === "info";
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    resetForm(excludeId = false, immediate = false) {
 | 
			
		||||
      setTimeout(
 | 
			
		||||
        () => {
 | 
			
		||||
@@ -399,7 +412,7 @@ export default {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /** init **/
 | 
			
		||||
    init(id, detailMode) {
 | 
			
		||||
    init(id, detailMode, menu) {
 | 
			
		||||
      // this.dialogVisible = true;
 | 
			
		||||
      if (this.$refs.dataForm && this.$refs.dataForm.length) {
 | 
			
		||||
        // 当不是首次渲染dialog的时候,一开始就清空验证信息,本组件的循环里只有一个 dataForm 所以只用取 [0] 即可
 | 
			
		||||
@@ -434,6 +447,10 @@ export default {
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            this.loadingStatus = false;
 | 
			
		||||
            // 是否要跳转到附件页
 | 
			
		||||
            if (menu && menu.key === "attachment") {
 | 
			
		||||
              this.activeMenu = this.configs.menu.find((item) => item.key === menu.key)?.name;
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
        } else {
 | 
			
		||||
          // 如果不是编辑
 | 
			
		||||
@@ -445,31 +462,97 @@ export default {
 | 
			
		||||
    /** handlers */
 | 
			
		||||
    handleFileClick(type, file) {
 | 
			
		||||
      switch (type) {
 | 
			
		||||
        case "view":
 | 
			
		||||
          break;
 | 
			
		||||
        case "download": {
 | 
			
		||||
          /** 通知 */
 | 
			
		||||
          this.$notify({
 | 
			
		||||
            title: "成功",
 | 
			
		||||
            message: "开始下载",
 | 
			
		||||
            type: "success",
 | 
			
		||||
          });
 | 
			
		||||
        case "view": {
 | 
			
		||||
          // 加载图片
 | 
			
		||||
          this.$http
 | 
			
		||||
            .get("/pms/attachment/downloadFile", {
 | 
			
		||||
              params: {
 | 
			
		||||
                attachmentId: file.id,
 | 
			
		||||
                type: 0, // 0 预览,1 下载
 | 
			
		||||
              },
 | 
			
		||||
              responseType: "blob",
 | 
			
		||||
            })
 | 
			
		||||
            .then(({ data: res }) => {
 | 
			
		||||
              console.log("preivew", res);
 | 
			
		||||
              if (/image/i.test(res.type)) {
 | 
			
		||||
                // 显示图片
 | 
			
		||||
                this.currentImgUrl = URL.createObjectURL(res);
 | 
			
		||||
                this.imgPreviewDialogVisible = true;
 | 
			
		||||
              } else {
 | 
			
		||||
                this.$message({
 | 
			
		||||
                  message: "非图片文件请下载后预览",
 | 
			
		||||
                  type: "error",
 | 
			
		||||
                  duration: 1500,
 | 
			
		||||
                });
 | 
			
		||||
              }
 | 
			
		||||
            });
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
        case "delete": {
 | 
			
		||||
          console.log("deleting", file);
 | 
			
		||||
          const { id } = file;
 | 
			
		||||
          this.fileList = this.fileList.filter((f) => f.id !== id);
 | 
			
		||||
          this.updateRemoteFiles().then((res) => {
 | 
			
		||||
            /** 通知 */
 | 
			
		||||
            this.$notify({
 | 
			
		||||
              title: "成功",
 | 
			
		||||
              message: "已删除",
 | 
			
		||||
              type: "success",
 | 
			
		||||
 | 
			
		||||
        case "download": {
 | 
			
		||||
          // 下载图片
 | 
			
		||||
          this.$http
 | 
			
		||||
            .get("/pms/attachment/downloadFile", {
 | 
			
		||||
              params: {
 | 
			
		||||
                attachmentId: file.id,
 | 
			
		||||
                type: 1, // 0 预览,1 下载
 | 
			
		||||
              },
 | 
			
		||||
              responseType: "blob",
 | 
			
		||||
            })
 | 
			
		||||
            .then(({ data: res }) => {
 | 
			
		||||
              const blob = new Blob([res]);
 | 
			
		||||
 | 
			
		||||
              /** 通知 */
 | 
			
		||||
              this.$notify({
 | 
			
		||||
                title: "成功",
 | 
			
		||||
                message: "开始下载",
 | 
			
		||||
                type: "success",
 | 
			
		||||
                duration: 1200,
 | 
			
		||||
              });
 | 
			
		||||
 | 
			
		||||
              if ("download" in document.createElement("a")) {
 | 
			
		||||
                const alink = document.createElement("a");
 | 
			
		||||
                alink.download = file.name;
 | 
			
		||||
                alink.style.display = "none";
 | 
			
		||||
                alink.target = "_blank";
 | 
			
		||||
                alink.href = URL.createObjectURL(blob);
 | 
			
		||||
                document.body.appendChild(alink);
 | 
			
		||||
                alink.click();
 | 
			
		||||
                URL.revokeObjectURL(alink.href);
 | 
			
		||||
                document.body.removeChild(alink);
 | 
			
		||||
              } else {
 | 
			
		||||
                navigator.msSaveBlob(blob, fileName);
 | 
			
		||||
              }
 | 
			
		||||
            });
 | 
			
		||||
          });
 | 
			
		||||
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        case "delete": {
 | 
			
		||||
          return this.$confirm(`确定删除图片: ${file.name}`, "提示", {
 | 
			
		||||
            confirmButtonText: "确认",
 | 
			
		||||
            cancelButtonText: "我再想想",
 | 
			
		||||
            type: "warning",
 | 
			
		||||
          })
 | 
			
		||||
            .then(() => {
 | 
			
		||||
              this.loadingStatus = true;
 | 
			
		||||
              const newFilelist = this.fileList.filter((f) => f.id !== file.id);
 | 
			
		||||
              this.updateRemoteFiles(newFilelist).then((msg) => {
 | 
			
		||||
                if (msg && msg === "success") {
 | 
			
		||||
                  this.fileList = newFilelist;
 | 
			
		||||
                  this.loadingStatus = false;
 | 
			
		||||
                  /** 通知 */
 | 
			
		||||
                  this.$notify({
 | 
			
		||||
                    title: "成功",
 | 
			
		||||
                    message: "已删除",
 | 
			
		||||
                    type: "success",
 | 
			
		||||
                    duration: 1200,
 | 
			
		||||
                  });
 | 
			
		||||
                }
 | 
			
		||||
              });
 | 
			
		||||
            })
 | 
			
		||||
            .catch((err) => {});
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -485,31 +568,47 @@ export default {
 | 
			
		||||
          typeCode: file.typeCode,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        this.fileList.push(fileItem);
 | 
			
		||||
        /** 通知 */
 | 
			
		||||
        this.$notify({
 | 
			
		||||
          title: "成功",
 | 
			
		||||
          message: "上传成功",
 | 
			
		||||
          type: "success",
 | 
			
		||||
        this.loadingStatus = true;
 | 
			
		||||
        this.updateRemoteFiles([...this.fileList, fileItem]).then((msg) => {
 | 
			
		||||
          if (msg && msg === "success") {
 | 
			
		||||
            this.fileList.push(fileItem);
 | 
			
		||||
            this.loadingStatus = false;
 | 
			
		||||
            /** 通知 */
 | 
			
		||||
            this.$notify({
 | 
			
		||||
              title: "成功",
 | 
			
		||||
              message: "上传成功",
 | 
			
		||||
              type: "success",
 | 
			
		||||
              duration: 1200,
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.updateRemoteFiles();
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    updateRemoteFiles() {
 | 
			
		||||
    updateRemoteFiles(filelist) {
 | 
			
		||||
      return this.$http
 | 
			
		||||
        .put("/pms/product", {
 | 
			
		||||
          id: "id" in this.dataForm ? this.dataForm.id : "DEFAULT_ID",
 | 
			
		||||
          // code: "code" in this.dataForm ? this.dataForm.code : "DEFAULT_CODE",
 | 
			
		||||
          // ...this.dataForm,
 | 
			
		||||
          fileIds: this.fileList.map((f) => f.id),
 | 
			
		||||
          fileIds: filelist.map((f) => f.id),
 | 
			
		||||
        })
 | 
			
		||||
        .then(({ data: res }) => {
 | 
			
		||||
          console.log("updateFileList", this.fileList, res);
 | 
			
		||||
          if (res.code === 0) return "success";
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    handleUploadCheck(file) {
 | 
			
		||||
      console.log("[before upload]", file);
 | 
			
		||||
      const LIMIT = 2 * 1024 * 1024; // bytes
 | 
			
		||||
      if (file.size > LIMIT) {
 | 
			
		||||
        this.$message({
 | 
			
		||||
          message: "文件大小不能超过 2MB",
 | 
			
		||||
          type: "error",
 | 
			
		||||
          duration: 1500,
 | 
			
		||||
        });
 | 
			
		||||
        return false;
 | 
			
		||||
      } else return true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    handleComponentModelUpdate(propName, { subject, payload: { data } }) {
 | 
			
		||||
      this.dataForm[propName] = JSON.stringify(data);
 | 
			
		||||
      console.log("[DialogJustForm] handleComponentModelUpdate", this.dataForm[propName]);
 | 
			
		||||
@@ -538,6 +637,15 @@ export default {
 | 
			
		||||
                // 如果通过验证
 | 
			
		||||
                this.loadingStatus = true;
 | 
			
		||||
                const method = payload.name === "add" ? "POST" : "PUT";
 | 
			
		||||
 | 
			
		||||
                // 判断是否有附件选项
 | 
			
		||||
                const hasAttachment = !!this.configs.menu.find((item) => item.key === "attachment");
 | 
			
		||||
                if (hasAttachment) {
 | 
			
		||||
                  const fileIds = this.fileList.map((item) => item.id);
 | 
			
		||||
                  this.$set(this.dataForm, "fileIds", fileIds);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // 实际发送请求
 | 
			
		||||
                this.$http({
 | 
			
		||||
                  url: this.urls.base,
 | 
			
		||||
                  method,
 | 
			
		||||
@@ -555,15 +663,11 @@ export default {
 | 
			
		||||
                    if (this.loadingStatus) this.loadingStatus = false;
 | 
			
		||||
                  });
 | 
			
		||||
              } else {
 | 
			
		||||
                // 没有通过验证
 | 
			
		||||
                // this.$message.error(JSON.stringify(result));
 | 
			
		||||
                this.$message.error("请核查字段信息");
 | 
			
		||||
              }
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        console.log("[x] 不是这么用的! 缺少name属性");
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    handleTabClick(payload) {
 | 
			
		||||
@@ -764,4 +868,7 @@ ul.file-list > li:hover {
 | 
			
		||||
  width: 16px;
 | 
			
		||||
  height: 16px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* .image-preview-dialog {
 | 
			
		||||
} */
 | 
			
		||||
</style>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,2 +0,0 @@
 | 
			
		||||
配置文件选项总结
 | 
			
		||||
 | 
			
		||||
@@ -1,2 +0,0 @@
 | 
			
		||||
// 表格中的可点击文本
 | 
			
		||||
export default {}
 | 
			
		||||
@@ -53,8 +53,8 @@ export default {
 | 
			
		||||
    },
 | 
			
		||||
    detailMode: {
 | 
			
		||||
      type: Boolean,
 | 
			
		||||
      default: false
 | 
			
		||||
    }
 | 
			
		||||
      default: false,
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
@@ -83,9 +83,19 @@ export default {
 | 
			
		||||
            attachmentId: file.id,
 | 
			
		||||
            type: 1,
 | 
			
		||||
          },
 | 
			
		||||
          responseType: "blob",
 | 
			
		||||
        })
 | 
			
		||||
        .then(({ data: res }) => {
 | 
			
		||||
          const blob = new Blob([res]);
 | 
			
		||||
 | 
			
		||||
          /** 通知 */
 | 
			
		||||
          this.$notify({
 | 
			
		||||
            title: "成功",
 | 
			
		||||
            message: "开始下载",
 | 
			
		||||
            type: "success",
 | 
			
		||||
            duration: 1200,
 | 
			
		||||
          });
 | 
			
		||||
 | 
			
		||||
          if ("download" in document.createElement("a")) {
 | 
			
		||||
            const alink = document.createElement("a");
 | 
			
		||||
            alink.download = file.name;
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@
 | 
			
		||||
      :show-file-list="false"
 | 
			
		||||
      :headers="uploadHeaders"
 | 
			
		||||
      :on-success="handleUploadSuccess"
 | 
			
		||||
      :before-upload="handleUploadCheck"
 | 
			
		||||
    >
 | 
			
		||||
      <el-button :disabled="disabled" size="small" type="primary">{{ buttonText }}</el-button>
 | 
			
		||||
      <div slot="tip" class="el-upload__tip">
 | 
			
		||||
@@ -42,7 +43,7 @@ export default {
 | 
			
		||||
    tips: {
 | 
			
		||||
      type: Object,
 | 
			
		||||
      default: () => ({
 | 
			
		||||
        hint: "只能上传jpg/png文件, 且不超过500kb",
 | 
			
		||||
        hint: "文件大小不超过 2MB",
 | 
			
		||||
        success: "上传成功!",
 | 
			
		||||
      }),
 | 
			
		||||
    },
 | 
			
		||||
@@ -64,14 +65,9 @@ export default {
 | 
			
		||||
    return { showMsg: false, uploadedFileList: [] };
 | 
			
		||||
  },
 | 
			
		||||
  watch: {
 | 
			
		||||
    // fileList: {
 | 
			
		||||
    //   handler: (arr) => {
 | 
			
		||||
    //     if (arr && arr.length > 0) {
 | 
			
		||||
    //       this.uploadedFileList = arr;
 | 
			
		||||
    //     }
 | 
			
		||||
    //   },
 | 
			
		||||
    //   immediate: true,
 | 
			
		||||
    // },
 | 
			
		||||
    fileList(val) {
 | 
			
		||||
      this.uploadedFileList = val ?? [];
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  computed: {
 | 
			
		||||
    uploadHeaders() {
 | 
			
		||||
@@ -103,6 +99,18 @@ export default {
 | 
			
		||||
        .catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    handleUploadCheck(file) { 
 | 
			
		||||
      const LIMIT = 2 * 1024 * 1024; // bytes
 | 
			
		||||
      if (file.size > LIMIT) {
 | 
			
		||||
        this.$message({
 | 
			
		||||
          message: "文件大小不能超过 2MB",
 | 
			
		||||
          type: "error",
 | 
			
		||||
          duration: 1500,
 | 
			
		||||
        });
 | 
			
		||||
        return false;
 | 
			
		||||
      } else return true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    handleUploadSuccess(response, file, fileList) {
 | 
			
		||||
      console.log("[UploadBtn] uploadedFileList", response, file, fileList, this.uploadedFileList);
 | 
			
		||||
 | 
			
		||||
@@ -115,13 +123,6 @@ export default {
 | 
			
		||||
          typeCode: file.typeCode,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        /** 通知 */
 | 
			
		||||
        this.$notify({
 | 
			
		||||
          title: "成功",
 | 
			
		||||
          message: "上传成功",
 | 
			
		||||
          type: "success",
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.uploadedFileList.push(fileItem);
 | 
			
		||||
        this.$emit("update-file-list", this.uploadedFileList);
 | 
			
		||||
        // this.showMsg = true;
 | 
			
		||||
 
 | 
			
		||||
@@ -224,12 +224,12 @@ export default {
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
        case "status": {
 | 
			
		||||
          console.log('status', data)
 | 
			
		||||
          console.log("status", data);
 | 
			
		||||
          // TODO: 类似于这种字符串,可以统一集中到一个文件里
 | 
			
		||||
          const { id, code } = data;
 | 
			
		||||
          const queryCondition = { id, code };
 | 
			
		||||
          if ("enabled" in data) queryCondition.enabled = data['enabled'];
 | 
			
		||||
          if ("status" in data) queryCondition.status = data['status'];
 | 
			
		||||
          if ("enabled" in data) queryCondition.enabled = data["enabled"];
 | 
			
		||||
          if ("status" in data) queryCondition.status = data["status"];
 | 
			
		||||
          // 更改状态,更改状态需要 id 和 code 然后是 状态 enabled
 | 
			
		||||
          this.$http.put(this.urls.base, queryCondition).then(({ data: res }) => {
 | 
			
		||||
            if (res.code === 0) {
 | 
			
		||||
@@ -238,6 +238,9 @@ export default {
 | 
			
		||||
          });
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
        case "view-attachment": {
 | 
			
		||||
          this.openDialog(data, false, { key: "attachment" });
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -268,11 +271,11 @@ export default {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /** 打开对话框 */
 | 
			
		||||
    openDialog(row_id, detail_mode) {
 | 
			
		||||
    openDialog(row_id, detail_mode, tag_info) {
 | 
			
		||||
      this.dialogVisible = true;
 | 
			
		||||
 | 
			
		||||
      this.$nextTick(() => {
 | 
			
		||||
        this.$refs["edit-dialog"].init(/** some args... */ row_id, detail_mode);
 | 
			
		||||
        this.$refs["edit-dialog"].init(/** some args... */ row_id, detail_mode, tag_info);
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ export default function () {
 | 
			
		||||
    { prop: "weight", label: "重量", filter: (val) => (val ? val + " kg" : "-") },
 | 
			
		||||
    { prop: "processTime", label: "产线完成单位产品用时", width: 200, filter: (val) => val + " s" },
 | 
			
		||||
    { prop: "remark", label: "备注" },
 | 
			
		||||
    { prop: "description", label: "附件信息", subcomponent: TableTextComponent, buttonContent: "查看附件" },
 | 
			
		||||
    { prop: "description", label: "附件信息", subcomponent: TableTextComponent, buttonContent: "查看附件", actionName: 'view-attachment' },
 | 
			
		||||
    {
 | 
			
		||||
      prop: "operations",
 | 
			
		||||
      name: "操作",
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user