<!-- filename: Safety Drawer.vue author: liubin date: 2024-2-19 10:38:56 description: --> <template> <el-drawer :visible="visible" :show-close="false" :wrapper-closable="false" class="drawer" custom-class="mes-drawer" size="60%" @closed="$emit('destroy')"> <SmallTitle slot="title"> {{ mode.includes('detail') ? '详情' : mode.includes('edit') ? '编辑' : '新增' }} </SmallTitle> <div class="drawer-body flex"> <div class="drawer-body__content"> <section v-for="(section, index) in sections" :key="section.key"> <SmallTitle v-if="index != 0">{{ section.name }}</SmallTitle> <div class="form-part" v-if="section.key == 'base'" style="margin-bottom: 32px"> <el-skeleton v-if="!showForm" animated /> <EquipmentInfoForm key="drawer-dialog-form" v-if="showForm" :isFireEquipment="isFireEquipment" :disabled="mode.includes('detail')" :sync-filelist="syncFileListFlag" v-model="form" /> </div> <div v-if="section.key == 'attrs'" style="margin-top: 12px; position: relative"> <div v-if="!mode.includes('detail')" style="position: absolute; top: -40px; right: 0"> <el-button @click="handleAddAttr" type="text"> <i class="el-icon-plus"></i> 添加属性 </el-button> </div> <base-table v-loading="attrListLoading" :table-props="section.props" :page="attrQuery?.params.pageNo || 1" :limit="attrQuery?.params.pageSize || 10" :table-data="list" @emitFun="handleEmitFun"> <!-- :add-button-show="mode.includes('detail') ? null : '添加属性'" @emitButtonClick="handleAddAttr" --> <method-btn v-if="section.tableBtn" slot="handleBtn" label="操作" :method-list="tableBtn" @clickBtn="handleTableBtnClick" /> </base-table> <!-- 分页组件 --> <pagination v-show="total > 0" :total="total" :page.sync="attrQuery.params.pageNo" :limit.sync="attrQuery.params.pageSize" @pagination="getAttrList" /> </div> </section> </div> <div class="drawer-body__footer"> <el-button style="" @click="handleCancel">取消</el-button> <el-button v-if="mode == 'detail'" type="primary" @click="toggleEdit"> 编辑 </el-button> <el-button v-else type="primary" @click="handleConfirm">保存</el-button> <!-- sections的第二项必须是 属性列表 --> <!-- <el-button v-if="sections[1].allowAdd" type="primary" @click="handleAddAttr"> 添加属性 </el-button> --> </div> </div> <!-- 属性对话框 --> <base-dialog v-if="sections[1].allowAdd" :dialogTitle="attrTitle" :dialogVisible="attrFormVisible" width="35%" :append-to-body="true" custom-class="baseDialog" @close="closeAttrForm" @cancel="closeAttrForm" @confirm="submitAttrForm"> <DialogForm v-if="attrFormVisible" ref="attrForm" :dataForm="attrForm" :rows="attrRows" /> </base-dialog> </el-drawer> </template> <script> import DialogForm from './DialogForm'; import EquipmentInfoForm from './EquipmentInfoForm.vue'; const SmallTitle = { name: 'SmallTitle', props: ['size'], components: {}, data() { return {}; }, methods: {}, render: function (h) { return h( 'span', { class: 'small-title', style: { fontSize: '18px', lineHeight: this.size == 'lg' ? '24px' : this.size == 'sm' ? '18px' : '20px', fontWeight: 500, fontFamily: '微软雅黑, Microsoft YaHei, Arial, Helvetica, sans-serif', }, }, this.$slots.default ); }, }; export default { components: { SmallTitle, DialogForm, EquipmentInfoForm }, props: ['sections', 'mode', 'dataId', 'isFireEquipment'], // dataId 作为一个通用的存放id的字段 data() { return { visible: false, showForm: false, btnLoading: false, total: 0, form: {}, list: [], attrTitle: '', attrForm: { id: null, equipmentId: null, name: '', value: '', }, attrFormVisible: false, attrRows: [ [ { input: true, label: '属性名称', prop: 'name', rules: [ { required: true, message: '属性名称不能为空', trigger: 'blur' }, ], }, ], [ { input: true, label: '属性值', prop: 'value', }, ], ], attrQuery: { params: { pageNo: 1, pageSize: 10, }, }, // 属性列表的请求 infoQuery: null, // 基本信息的请求 attrFormSubmitting: false, attrListLoading: false, syncFileListFlag: null, }; }, computed: { formRows() { return this.sections[0].rows.map((row) => { return row.map((col) => { if (col.key == 'eq-pics') { // 重置图片的位置 return { ...col, bind: { ...col.bind, }, style: { left: 0, right: 'unset', }, }; } return { ...col, bind: { ...col.bind, // 详情 模式下,禁用各种输入 disabled: this.mode == 'detail', }, }; }); }); }, tableBtn() { return this.mode == 'detail' ? [] : this.sections[1].tableBtn; }, }, mounted() { for (const section of this.sections) { // 请求具体信息 if ('url' in section) { const query = { url: section.url, method: section.method || 'get', params: section.queryParams || null, data: section.data || null, }; this.$axios(query).then(({ data }) => { if (section.key == 'base') { this.form = data; this.showForm = true; this.infoQuery = query; } else if (section.key == 'attrs') { this.attrQuery = query; this.list = data.list; this.total = data.total; } }); } } }, methods: { handleTableBtnClick({ type, data }) { switch (type) { case 'edit': this.handleEditAttr(data.id); break; case 'delete': this.handleDeleteAttr(data.id); break; } }, async handleConfirm() { this.btnLoading = true; this.syncFileListFlag = Math.random(); this.$nextTick(async () => { const { code, data } = await this.$axios({ url: this.sections[0].urlUpdate, method: 'put', data: this.form, }); if (code == 0) { this.$modal.msgSuccess('更新成功'); } this.btnLoading = false; this.$emit('refreshDataList'); this.handleCancel(); }); }, handleEmitFun(val) { console.log('handleEmitFun', val); }, init() { this.visible = true; }, async getAttrList() { this.attrListLoading = true; const res = await this.$axios(this.attrQuery); if (res.code == 0) { this.list = res.data.list; this.total = res.data.total; } this.attrListLoading = false; }, // 保存表单 handleSave() { this.$refs['form'][0].validate(async (valid) => { if (valid) { const isEdit = this.mode == 'edit'; await this.$axios({ url: this.sections[0][isEdit ? 'urlUpdate' : 'urlCreate'], method: isEdit ? 'put' : 'post', data: this.form, }); this.$modal.msgSuccess(`${isEdit ? '更新' : '创建'}成功`); this.visible = false; this.$emit('refreshDataList'); } }); }, handleCancel() { this.visible = false; }, // 开启编辑 toggleEdit() { this.$emit('update-mode', 'edit'); }, // 新增属性 handleAddAttr() { if (!this.dataId) return this.$message.error('请先创建设备信息'); this.attrForm = { id: null, equipmentId: this.dataId, name: '', value: '', }; this.attrTitle = '添加设备属性'; this.attrFormVisible = true; }, // 编辑属性 async handleEditAttr(attrId) { const res = await this.$axios({ url: this.sections[1].urlDetail, method: 'get', params: { id: attrId }, }); if (res.code == 0) { this.attrForm = res.data; this.attrTitle = '编辑设备属性'; this.attrFormVisible = true; } }, // 删除属性 handleDeleteAttr(attrId) { this.$confirm('确定删除该属性?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning', }) .then(async () => { const res = await this.$axios({ url: this.sections[1].urlDelete, method: 'delete', params: { id: attrId }, }); if (res.code == 0) { this.$message({ message: '删除成功', type: 'success', duration: 1500, onClose: () => { this.getAttrList(); }, }); } }) .catch(() => {}); }, // 提交属性表 submitAttrForm() { this.$refs['attrForm'].validate(async (valid) => { if (!valid) { return; } try { const isEdit = this.attrForm.id != null; this.attrFormSubmitting = true; const res = await this.$axios({ url: isEdit ? this.sections[1].urlUpdate : this.sections[1].urlCreate, method: isEdit ? 'put' : 'post', data: this.attrForm, }); if (res.code == 0) { this.closeAttrForm(); this.$message({ message: `${isEdit ? '更新' : '创建'}成功`, type: 'success', duration: 1500, onClose: () => { this.getAttrList(); }, }); } this.attrFormSubmitting = false; } catch (err) { this.$message({ message: err, type: 'error', duration: 1500, }); this.attrFormSubmitting = false; } }); }, closeAttrForm() { this.attrFormVisible = false; }, handleClick(raw) { if (raw.type === 'delete') { this.$confirm( `确定对${ raw.data.name ? '[名称=' + raw.data.name + ']' : '[序号=' + raw.data._pageIndex + ']' }进行删除操作?`, '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning', } ) .then(() => { deleteProductAttr(raw.data.id).then(({ data }) => { this.$message({ message: '操作成功', type: 'success', duration: 1500, onClose: () => { this.getList(); }, }); }); }) .catch(() => {}); } else { this.addNew(raw.data.id); } }, }, }; </script> <style scoped> .drawer >>> .el-drawer { border-radius: 8px 0 0 8px; } .drawer >>> .el-drawer__header { margin: 0; padding: 32px 32px 24px; border-bottom: 1px solid #dcdfe6; margin-bottom: 0px; } .small-title::before { content: ''; display: inline-block; vertical-align: top; width: 4px; height: 22px; border-radius: 1px; margin-right: 8px; background-color: #0b58ff; } .drawer-body { display: flex; flex-direction: column; height: 100%; } .drawer-body__content { flex: 1; /* background: #eee; */ padding: 20px 30px; overflow-y: auto; } .drawer-body__footer { display: flex; justify-content: flex-end; padding: 18px; } </style>