update 附件上传功能
This commit is contained in:
parent
beca018db6
commit
c2657b190e
@ -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,30 +462,96 @@ export default {
|
||||
/** handlers */
|
||||
handleFileClick(type, file) {
|
||||
switch (type) {
|
||||
case "view":
|
||||
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 "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": {
|
||||
console.log("deleting", file);
|
||||
const { id } = file;
|
||||
this.fileList = this.fileList.filter((f) => f.id !== id);
|
||||
this.updateRemoteFiles().then((res) => {
|
||||
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,
|
||||
});
|
||||
}
|
||||
});
|
||||
break;
|
||||
})
|
||||
.catch((err) => {});
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -485,31 +568,47 @@ export default {
|
||||
typeCode: file.typeCode,
|
||||
};
|
||||
|
||||
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: "操作",
|
||||
|
Loading…
Reference in New Issue
Block a user