add 设备表、产品表 & 同步DialogJustForm到DialogWithMenu

This commit is contained in:
lb 2023-02-02 17:03:28 +08:00
parent cb3e47a45e
commit 9ccc8b44b3
6 changed files with 747 additions and 399 deletions

View File

@ -162,8 +162,6 @@ export default {
} else {
col.options.splice(0);
}
return col;
});
}
});

View File

@ -2,8 +2,9 @@
<el-dialog
class="dialog-with-menu"
:visible="selfVisible"
@close="handleClose"
@closed="resetForm"
:distory-on-close="true"
:close-on-click-modal="configs.clickModalToClose ?? true"
>
<!-- title -->
<div slot="title" class="dialog-title">
@ -14,37 +15,14 @@
<!-- menu -->
<el-tabs v-model="activeMenu" type="card" @tab-click="handleTabClick">
<!-- <el-tab-pane v-for="(tab, index) in configs.menu" :key="index" :label="tab.name" :name="tab.name"> -->
<el-tab-pane
v-for="(tab, index) in actualMenus"
:key="index"
:label="tab.name"
:name="tab.name"
>
<el-tab-pane v-for="(tab, index) in actualMenus" :key="index" :label="tab.name" :name="tab.name">
<div v-if="index === 0">
<!-- form -->
<el-form ref="dataForm" :model="dataForm">
<el-row
v-for="(row, rowIndex) in configs.form.rows"
:key="'row_' + rowIndex"
:gutter="20"
>
<el-col
v-for="(col, colIndex) in row"
:key="colIndex"
:span="24 / row.length"
>
<el-form-item
:label="col.label"
:prop="col.prop"
:rules="col.rules || null"
>
<el-input
v-if="col.input"
v-model="dataForm[col.prop]"
clearable
:disabled="detailMode"
v-bind="col.elparams"
/>
<el-form ref="dataForm" :model="dataForm" v-loading="loadingStatus">
<el-row v-for="(row, rowIndex) in configs.form.rows" :key="'row_' + rowIndex" :gutter="20">
<el-col v-for="(col, colIndex) in row" :key="colIndex" :span="24 / row.length">
<el-form-item :label="col.label" :prop="col.prop" :rules="col.rules || null">
<el-input v-if="col.input" v-model="dataForm[col.prop]" clearable :disabled="detailMode" v-bind="col.elparams" />
<el-select
v-if="col.select"
v-model="dataForm[col.prop]"
@ -53,12 +31,7 @@
v-bind="col.elparams"
@change="handleSelectChange(col, $event)"
>
<el-option
v-for="(opt, optIdx) in col.options"
:key="'option_' + optIdx"
:label="opt.label"
:value="opt.value"
/>
<el-option v-for="(opt, optIdx) in col.options" :key="'option_' + optIdx" :label="opt.label" :value="opt.value" />
</el-select>
<el-switch
v-if="col.switch"
@ -68,13 +41,7 @@
@change="handleSwitchChange"
:disabled="detailMode"
/>
<el-input
v-if="col.textarea"
type="textarea"
v-model="dataForm[col.prop]"
:disabled="detailMode"
v-bind="col.elparams"
/>
<el-input v-if="col.textarea" type="textarea" v-model="dataForm[col.prop]" :disabled="detailMode" v-bind="col.elparams" />
<!-- add more... -->
</el-form-item>
</el-col>
@ -82,19 +49,8 @@
</el-form>
</div>
<div v-if="dataForm.id && index === 1">
<el-button
v-if="!detailMode"
type="primary"
style="margin-bottom: 16px"
@click="handleAddParam()"
>添加</el-button
>
<BaseListTable
:table-config="null"
:column-config="filteredTableProps"
:table-data="subList"
@operate-event="handleTableRowOperate"
/>
<el-button v-if="!detailMode" type="primary" style="margin-bottom: 16px" @click="handleAddParam()">添加</el-button>
<BaseListTable :table-config="null" :column-config="filteredTableProps" :table-data="subList" @operate-event="handleTableRowOperate" />
<!-- paginator -->
</div>
</el-tab-pane>
@ -114,13 +70,9 @@
<!-- footer -->
<div slot="footer">
<template v-for="(operate, index) in configs.form.operations">
<el-button
v-if="showButton(operate)"
:key="'operation_' + index"
:type="operate.type"
@click="handleBtnClick(operate)"
>{{ operate.label }}</el-button
>
<el-button v-if="showButton(operate)" :key="'operation_' + index" :type="operate.type" @click="handleBtnClick(operate)">{{
operate.label
}}</el-button>
</template>
<el-button @click="handleBtnClick({ name: 'cancel' })">取消</el-button>
</div>
@ -144,14 +96,53 @@ export default {
inject: ["urls"],
data() {
const dataForm = {};
this.configs.form.rows.forEach((row) => {
row.forEach((col) => {
dataForm[col.prop] = col.default ?? "";
console.log("==========>", col.prop, dataForm[col.prop]);
if (col.upload) dataForm[col.prop] = col.default ?? [];
else dataForm[col.prop] = col.default ?? null;
if (col.fetchData)
col.fetchData().then(({ data: res }) => {
console.log("[Fetch Data]", res.data.list);
if (res.code === 0 && res.data.list) {
this.$set(
col,
"options",
res.data.list.map((i) => ({ label: i.name, value: i.id }))
);
// col.options = res.data.list;
} else {
col.options.splice(0);
}
// dataForm[col.prop] = col.default ?? null; // not perfect!
});
else if (col.fetchTreeData) {
// parentId 0
col.fetchTreeData().then(({ data: res }) => {
console.log("[Fetch Tree Data]", res.data.list);
if (res.code === 0 && res.data.list) {
//
const obj = {};
res.data.list.map((item) => {
obj[item.id] = item;
});
//
let filteredList = reConstructTreeData(obj);
console.log("** filteredList **", filteredList);
// options
this.$set(col, "options", filteredList);
} else {
col.options.splice(0);
}
});
}
});
});
return {
// configs,
loadingStatus: false,
activeMenu: this.configs.menu[0].name,
dataForm,
detailMode: false,
@ -172,9 +163,7 @@ export default {
});
},
filteredTableProps() {
return this.detailMode
? this.configs.table.props.filter((v) => v.prop !== "operations")
: this.configs.table.props;
return this.detailMode ? this.configs.table.props.filter((v) => v.prop !== "operations") : this.configs.table.props;
},
},
methods: {
@ -184,28 +173,30 @@ export default {
const showAlways = operate.showAlways ?? false;
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 permission = operate.permission ? this.$hasPermission(operate.permission) : true;
return notDetailMode && (showAlways || ((editMode || addMode) && permission));
},
resetForm(excludeId = false) {
setTimeout(() => {
resetForm(excludeId = false, immediate = false) {
setTimeout(
() => {
Object.keys(this.dataForm).forEach((key) => {
if (excludeId && key === "id") return;
this.dataForm[key] = null;
});
this.activeMenu = this.configs.menu[0].name;
}, 500);
this.$refs.dataForm[0].clearValidate();
this.$emit("dialog-closed"); //
},
immediate ? 0 : 100
);
},
/** init **/
init(id, detailMode) {
this.selfVisible = true;
if (this.$refs.dataForm && this.$refs.dataForm.length) {
// dialog dataForm [0]
this.$refs.dataForm[0].clearValidate()
this.$refs.dataForm[0].clearValidate();
}
console.log("[dialog] DialogWithHead init():", id, detailMode);
@ -216,22 +207,14 @@ export default {
this.dataForm.id = id || null;
if (this.dataForm.id) {
//
this.$http
.get(this.urls.base + `/${this.dataForm.id}`)
.then(({ data: res }) => {
// dev env:
// if (LOCAL) res.data.id = res.data._id;
// end dev env
console.log("[base dialog init] ", res);
this.loadingStatus = true;
this.$http.get(this.urls.base + `/${this.dataForm.id}`).then(({ data: 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)
);
console.log("pick(res.data, dataFormKeys) ===> ", __pick(res.data, dataFormKeys));
// LABEL: FILE_RELATED
/** 对文件下载进行分流 */
// this.fileList = {};
@ -260,7 +243,7 @@ export default {
// });
// }
}
this.selfVisible = true;
this.loadingStatus = false;
});
} else {
//
@ -285,22 +268,36 @@ export default {
this.handleClose();
break;
case "reset":
this.resetForm(true); // true means exclude id
this.resetForm(true, true); // true means exclude id
break;
case "add":
case "update": {
this.$refs.dataForm[0].validate((passed, result) => {
if (passed) {
//
this.loadingStatus = true;
const method = payload.name === "add" ? "POST" : "PUT";
this.$http({
url: this.urls.base,
method,
data: this.dataForm,
}).then(({ data: res }) => {
})
.then(({ data: res }) => {
console.log("[add&update] res is: ", res);
this.$message.success(
payload.name === "add" ? "添加成功" : "更新成功"
);
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(JSON.stringify(result));
this.$message.error("请核查字段信息");
}
});
}
}
@ -356,7 +353,7 @@ export default {
},
handleClose() {
this.resetForm();
// this.resetForm();
this.selfVisible = false;
},
@ -439,6 +436,6 @@ export default {
.dialog-with-menu >>> .el-dialog__header {
padding: 10px 20px 10px;
background: linear-gradient(to bottom, rgba(0, 0, 0, 0.25), white);
/* background: linear-gradient(to bottom, rgba(0, 0, 0, 0.25), white); */
}
</style>

View File

@ -0,0 +1,140 @@
import TableOperaionComponent from '@/components/noTemplateComponents/operationComponent'
import TableTextComponent from '@/components/noTemplateComponents/detailComponent'
import switchBtn from '@/components/noTemplateComponents/switchBtn'
export default function () {
const tableProps = [
{ prop: 'name', label: '设备名称' },
{ prop: 'code', label: '设备编码' },
{ prop: 'equipmentType', label: '设备类型' },
{ prop: 'enabled', label: '状态', subcomponent: switchBtn }, // subcomponent
{ prop: 'remark', label: '备注' },
{ prop: 'description', label: '查看详情', subcomponent: TableTextComponent },
{
prop: 'operations',
name: '操作',
fixed: 'right',
width: 120,
subcomponent: TableOperaionComponent,
options: ['edit', { name: 'delete', permission: 'pms:equipment:delete' }]
}
]
const headFormFields = [
{
label: '设备名称',
prop: 'name',
input: true,
default: { value: '' },
bind: { placeholder: '请输入设备名称' }
},
{
button: {
type: 'primary',
name: '查询'
}
},
{
button: {
type: 'plain',
name: '新增',
permission: 'pms:equipment:save'
}
}
]
const dialogConfigs = {
menu: [{ name: '设备信息' }, { name: '设备属性信息', onlyEditMode: false }],
form: {
rows: [
[
{ input: true, label: '设备名称', prop: 'name', rules: { required: true, message: 'not empty', trigger: 'blur' }, elparams: { placeholder: '请输入设备名称' } },
{ input: true, label: '设备名称编码', prop: 'code', rules: { required: true, message: 'not empty', trigger: 'blur' }, elparams: { placeholder: '请输入设备名称编码' } },
// { input: true, label: '版本号', prop: 'version', elparams: { placeholder: '请输入版本号' } },
{
select: true,
label: '设备类型',
prop: 'equipmentTypeId',
options: [
// { label: '1', value: 1 },
// { label: '2', value: 2 },
// { label: '3', value: 3 },
],
fetchData: () => {
return this.$http.get('/pms/equipmentType/page', { params: { page: 1, limit: 999, key: '' } })
},
elparams: { placeholder: '选择一个设备类型' }
},
],
[{ textarea: true, label: '备注', prop: 'remark', elparams: { placeholder: '备注' } }],
],
operations: [
{ name: 'add', label: '保存', type: 'primary', permission: 'pms:equipment:save', showOnEdit: false },
{ name: 'update', label: '更新', type: 'primary', permission: 'pms:equipment:update', showOnEdit: true },
{ name: 'reset', label: '重置', type: 'warning', showAlways: true },
// { name: 'cancel', label: '取消', showAlways: true },
],
},
table: {
// extraParams: ['stepId'],
extraParams: 'stepId',
props: [
{ prop: 'createTime', label: '创建时间' },
{ prop: 'equipmentId', label: '所属设备id' },
{ prop: 'attrName', label: '属性名称', isEditField: true },
{ prop: 'attrValue', label: '属性值', isEditField: true },
{
prop: 'operations',
name: '操作',
fixed: 'right',
width: 120,
subcomponent: TableOperaionComponent,
options: [
{ name: 'edit', permission: 'pms:equipment:update' },
{ name: 'delete', permission: 'pms:equipment:delete' },
]
}
],
data: [
// TOOD 暂时用不到,但获取可以考虑把拉取接口数据的函数迁移到此文件(没有太大必要)
],
},
subDialog: {
extraParam: 'equipmentId',
rows: [
[
{ input: true, label: '属性名称', prop: 'attrName', elparams: { placeholder: '请输入属性名称' } },
{ input: true, label: '属性值', prop: 'attrValue', rules: { required: true, message: 'not empty', trigger: 'blur' }, elparams: { placeholder: '请输入属性值' } },
],
[
{ textarea: true, label: '备注', prop: 'remark', elparams: { placeholder: '添加备注' } },
]
],
operations: [
{ name: 'add', label: '保存', type: 'primary', permission: 'pms:equipment:save', showOnEdit: false },
{ name: 'update', label: '更新', type: 'primary', permission: 'pms:equipment:update', showOnEdit: true },
],
},
};
return {
dialogConfigs,
tableConfig: {
table: null, // 此处可省略el-table 上的配置项
column: tableProps, // el-column-item 上的配置项
},
headFormConfigs: {
rules: null, // 名称是由 BaseSearchForm.vue 组件固定的
fields: headFormFields // 名称是由 BaseSearchForm.vue 组件固定的
},
urls: {
base: '/pms/equipment',
page: '/pms/equipment/page'
}
}
}

View File

@ -0,0 +1,32 @@
<template>
<ListViewWithHead :table-config="tableConfig" :head-config="headFormConfigs" :dialog-configs="dialogConfigs" :listQueryExtra="['name']" />
</template>
<script>
import initConfig from './config';
import ListViewWithHead from '@/views/atomViews/ListViewWithHead.vue';
export default {
name: 'BlenderView',
components: { ListViewWithHead },
provide() {
return {
urls: this.allUrls
}
},
data() {
const { tableConfig, headFormConfigs, urls, dialogConfigs } = initConfig.call(this);
return {
tableConfig,
headFormConfigs,
allUrls: urls,
dialogConfigs,
};
},
created() {},
mounted() {},
methods: {},
};
</script>
<style scoped></style>

View File

@ -0,0 +1,149 @@
import TableOperaionComponent from '@/components/noTemplateComponents/operationComponent'
import TableTextComponent from '@/components/noTemplateComponents/detailComponent'
import StatusComponent from '@/components/noTemplateComponents/statusComponent'
import { timeFilter, dictFilter } from '@/utils/filters'
export default function () {
const tableProps = [
{ prop: 'createTime', label: '添加时间', filter: timeFilter },
{ prop: 'name', label: '产品名称' },
{ prop: 'code', label: '产品编码' },
{ prop: 'typeDictValue', label: '产品类型', filter: dictFilter('product_type') },
{ prop: 'specifications', label: '规格' },
{ prop: 'unitDictValue', label: '单位', filter: dictFilter('unit') },
{ prop: 'weight', label: '重量(kg)' },
{ prop: 'remark', label: '备注' },
{ prop: 'description', label: '附件信息', subcomponent: TableTextComponent, buttonContent: '查看附件' },
{
prop: 'operations',
name: '操作',
fixed: 'right',
width: 120,
subcomponent: TableOperaionComponent,
options: ['edit', { name: 'delete', permission: 'pms:product:delete' }]
}
]
const headFormFields = [
{
label: '关键字',
prop: 'key',
input: true,
default: { value: '' },
bind: { placeholder: '请输入产品名称或编码' }
},
{
button: {
type: 'primary',
name: '查询'
}
},
{
button: {
type: 'plain',
name: '新增',
permission: 'pms:product:save'
}
}
]
const dictList = JSON.parse(localStorage.getItem('dictList') || {})
const dialogConfigs = {
menu: [{ name: '产品信息' }, { name: '产品属性信息', onlyEditMode: false }],
form: {
rows: [
[
{ input: true, label: '产品名称/砖型名称', prop: 'name', rules: { required: true, message: 'not empty', trigger: 'blur' }, elparams: { placeholder: '请输入设备名称' } },
{ input: true, label: '产品编码/砖型编码', prop: 'code', rules: { required: true, message: 'not empty', trigger: 'blur' }, elparams: { placeholder: '请输入设备名称编码' } },
// { input: true, label: '版本号', prop: 'version', elparams: { placeholder: '请输入版本号' } },
{
select: true,
label: '产品类型',
prop: 'typeDictValue',
options: 'product_type' in dictList ? dictList['product_type'].map(item => ({ value: item.dictValue, label: item.dictLabel })) : [],
elparams: { placeholder: '选择一个产品类型' }
},
],
[
{ input: true, label: '规格', prop: 'specifications', rules: { required: true, message: 'not empty', trigger: 'blur' }, elparams: { placeholder: '请输入设备名称编码' } },
{ input: true, label: '单位平方数', prop: 'code', rules: { required: true, message: 'not empty', trigger: 'blur' }, elparams: { placeholder: '请输入设备名称编码' } },
{
select: true,
label: '单位',
prop: 'unitDictValue',
options: 'unit' in dictList ? dictList['unit'].map(item => ({ value: item.dictValue, label: item.dictLabel })) : [],
elparams: { placeholder: '选择一个产品类型' }
},
],
[{ textarea: true, label: '备注', prop: 'remark', elparams: { placeholder: '备注' } }],
],
operations: [
{ name: 'add', label: '保存', type: 'primary', permission: 'pms:product:save', showOnEdit: false },
{ name: 'update', label: '更新', type: 'primary', permission: 'pms:product:update', showOnEdit: true },
{ name: 'reset', label: '重置', type: 'warning', showAlways: true },
// { name: 'cancel', label: '取消', showAlways: true },
],
},
table: {
// extraParams: ['stepId'],
extraParams: 'productId',
props: [
{ prop: 'createTime', label: '创建时间' },
{ prop: 'productId', label: '产品ID' },
{ prop: 'attrName', label: '属性名称', isEditField: true },
{ prop: 'attrValue', label: '属性值', isEditField: true },
{
prop: 'operations',
name: '操作',
fixed: 'right',
width: 120,
subcomponent: TableOperaionComponent,
options: [
{ name: 'edit', permission: 'pms:product:update' },
{ name: 'delete', permission: 'pms:product:delete' },
]
}
],
data: [
// TOOD 暂时用不到,但获取可以考虑把拉取接口数据的函数迁移到此文件(没有太大必要)
],
},
subDialog: {
extraParam: 'productId',
rows: [
[
{ input: true, label: '属性名称', prop: 'attrName', elparams: { placeholder: '请输入属性名称' } },
{ input: true, label: '属性值', prop: 'attrValue', rules: { required: true, message: 'not empty', trigger: 'blur' }, elparams: { placeholder: '请输入属性值' } },
],
[
{ textarea: true, label: '备注', prop: 'remark', elparams: { placeholder: '添加备注' } },
]
],
operations: [
{ name: 'add', label: '保存', type: 'primary', permission: 'pms:product:save', showOnEdit: false },
{ name: 'update', label: '更新', type: 'primary', permission: 'pms:product:update', showOnEdit: true },
],
},
};
return {
dialogConfigs,
tableConfig: {
table: null, // 此处可省略el-table 上的配置项
column: tableProps, // el-column-item 上的配置项
},
headFormConfigs: {
rules: null, // 名称是由 BaseSearchForm.vue 组件固定的
fields: headFormFields // 名称是由 BaseSearchForm.vue 组件固定的
},
urls: {
base: '/pms/product',
page: '/pms/product/page'
}
}
}

View File

@ -0,0 +1,32 @@
<template>
<ListViewWithHead :table-config="tableConfig" :head-config="headFormConfigs" :dialog-configs="dialogConfigs" :listQueryExtra="['key']" />
</template>
<script>
import initConfig from './config';
import ListViewWithHead from '@/views/atomViews/ListViewWithHead.vue';
export default {
name: 'BlenderView',
components: { ListViewWithHead },
provide() {
return {
urls: this.allUrls
}
},
data() {
const { tableConfig, headFormConfigs, urls, dialogConfigs } = initConfig.call(this);
return {
tableConfig,
headFormConfigs,
allUrls: urls,
dialogConfigs,
};
},
created() {},
mounted() {},
methods: {},
};
</script>
<style scoped></style>