一,原型展示
新增:
编辑:
详情展示:
二,实现思路
对于表单项较多,新增、编辑和详情展示表单展示内容基本一致,只是展示形式有所不同,考虑可以共用一个组件,加一个pageType字段区分是新增、编辑还是详情展示;利用数据驱动视图的思想,我们可以把页面内容抽象成数据(例如,每一个输入框可能的所有属性可以定义到一个对象中 { id: 'metricsName', name: '中文名称', type: 'text', required: true, group: 'base', value: '', valueshow: '', editDisabled: true, isValidate: true, isLength: 32, tip: '' },)id作为后端接口的返回字段,name是表单项的显示名称,type,required,value,valueshow,editDisabled,isValidate,isLength,tip都是控制input框需要的元素(抽象成可控的属性),还有一个group,这个字段是用来给输入框分类的,group的值相同的说明是在同一组,显示在同一组下。
三,代码实现
<template>
<div v-if="isLoading">
<!-- <Modal v-model="flag"> -->
<div v-for="(t,index) in titleArr" :key="index" >
<div class="item-title">{{t.name}}</div>
<Form inline label-colon ref="formInline" >
<template v-for="(item, index) in datas" >
<FormItem v-if="t.group === item.group" :key="index" :class="['item-container',pageType !==0 ? 'fixed-height':'']" :label="item.name" :label-width="100" :required="item.required">
<template v-if='pageType'>
<Input v-if="item.type ==='text'" :id="item.id" v-model="item.value" placeholder="" :disabled="pageType === 2 ? item.editDisabled : false"></Input>
<Select v-else-if="item.type ==='select'" v-model="item.value" placeholder="" :disabled="item.editDisabled">
<Option v-for="(option,i) in item.options" :key="i" :value="option.id">{{option.data}}</Option>
</Select>
<Select v-else-if="item.type ==='multiple'" multiple v-model="item.value" placeholder="">
<Option v-for="(option,i) in item.options" :key="i" :value="option.id">{{option.data}}</Option>
</Select>
<Input v-else-if="item.type==='number'" v-model.number="item.value" type="number"></Input>
<span class="tip" v-show="(item.isValidate ||item.isLength>0) && item.tip">{{item.tip}}</span>
</template>
<template v-if="!pageType">
<span>
{{item.valueshow}}
</span>
</template>
</FormItem>
</template>
</Form>
</div>
<div v-if="pageType" class="bottom-footer">
<Button type="primary" size="large" style="" @click="onSubmit">提交</Button>
<Button size="large" @click="onCancel">取消</Button>
</div>
<!-- </Modal> -->
</div>
</template>
<script>
import template from '../portrait-manager/template/template.vue';
import axios from '@/libs/api.request';
export default{
components: { template },
data () {
return {
pageType: 1, // 1新增,2编辑,0,详情
titleArr: [{ group: 'base', name: '基础属性' }, { group: 'business', name: '业务属性' }, { group: 'technology', name: '技术属性' }, { group: 'manage', name: '管理属性' }],
datas: [
// 基础属性
// { id: 'metricsCode', isHide: true, name: '指标编码', type: 'text', required: true, group: 'base', value: '', valueshow: '', editDisabled: true, isValidate: true, tip: '' },
{ id: 'metricsName', name: '中文名称', type: 'text', required: true, group: 'base', value: '', valueshow: '', editDisabled: true, isValidate: true, isLength: 32, tip: '' },
{ id: 'metricsAlias', name: '中文别名', type: 'text', required: false, group: 'base', value: '', valueshow: '', editDisabled: false },
{ id: 'metricsClass', name: '指标层级', type: 'select', group: 'base', required: true, value: '', valueshow: '', options: [{ id: '战略层', data: '战略层' }, { id: '策略层', data: '策略层' }, { id: '执行层', data: '执行层' }], isValidate: true, tip: '' },
{ id: 'englishName', name: '英文名称', type: 'text', group: 'base', required: true, value: '', valueshow: '', editDisabled: true, isValidate: true, tip: '' },
{ id: 'englishShort', name: '英文简称', type: 'text', group: 'base', required: false, value: '', valueshow: '' },
{ id: 'metricsType', name: '指标类型', type: 'select', group: 'base', required: true, value: '', valueshow: '', isValidate: true, options: [{ id: 1, data: '基础指标' }, { id: 2, data: '复合指标' }] },
{ id: 'importantClass', name: '重要等级', type: 'select', group: 'base', required: true, value: '', valueshow: '', options: [{ id: '0', data: '0' }, { id: '1', data: '1' }, { id: '2', data: '2' }, { id: '3', data: '3' }, { id: '4', data: '4' }, { id: '5', data: '5' }], isValidate: true, tip: '' },
{ id: 'versionCode', name: '版本编号', type: 'text', group: 'base', required: false, value: '', valueshow: '' },
// // 业务属性
{ id: 'business', name: '所属业务', type: 'select', group: 'business', required: true, value: '', valueshow: '', options: [], editDisabled: false, isValidate: true, tip: '' }, // 支持拓展
{ id: 'subBusiness', name: '子业务', type: 'text', group: 'business', required: false, value: '', valueshow: '', editDisabled: false },
{ id: 'topicField', name: '主题领域', type: 'select', group: 'business', required: true, value: '', valueshow: '', isValidate: true, editDisabled: false }, // 支持拓展
{ id: 'calculationObject', name: '计算对象', type: 'select', group: 'business', options: [], required: true, value: '', valueshow: '', editDisabled: false, isValidate: true, tip: '' }, // 支持拓展
{ id: 'metricDefine', name: '指标定义', type: 'text', group: 'business', required: true, value: '', valueshow: '', editDisabled: false, isValidate: true, tip: '', isLength: 255 },
{ id: 'calculationCondition', name: '计算条件', type: 'text', group: 'business', required: true, value: '', valueshow: '', editDisabled: false, isValidate: true, tip: '', isLength: 255 },
{ id: 'calculationCycle', name: '统计周期', type: 'select', group: 'business', options: [], required: true, value: '', valueshow: '', editDisabled: false, isValidate: true, tip: '' }, // 支持拓展
{ id: 'isAdd', name: '是否可加', type: 'select', group: 'business', required: true, value: '', valueshow: '0', options: [{ id: 1, data: '是' }, { id: 0, data: '否' }], editDisabled: false, isValidate: true, tip: '' },
{ id: 'metricsPurpose', name: '指标用途', type: 'text', group: 'business', required: true, value: '', valueshow: '', editDisabled: false, isValidate: true, tip: '', isLength: 255 },
// // 技术属性
{ id: 'unit', name: '计量单位', type: 'text', group: 'technology', value: '', valueshow: '', required: false },
{ id: 'dataAccuracy', name: '统计精度', type: 'number', group: 'technology', value: '', valueshow: '', required: false },
{ id: 'dataRange', name: '数据值域', type: 'text', group: 'technology', value: '', valueshow: '', required: false },
{ id: 'calculateCycle', name: '计算周期', type: 'select', group: 'technology', value: '', valueshow: '', options: [{ id: '分钟', data: '分钟' }, { id: '小时', data: '小时' }, { id: '日', data: '日' }, { id: '周', data: '周' }, { id: '月', data: '月' }, { id: '季', data: '季' }, { id: '年', data: '年' }], required: false },
{ id: 'storeType', name: '存储类型', type: 'select', group: 'technology', value: '', valueshow: '', options: [{ id: 'string', data: 'string' }, { id: 'bigint', data: 'bigint' }, { id: 'double', data: 'double' }, { id: 'decimal', data: 'decimal' }, { id: 'datetime', data: 'datetime' }, { id: 'boolean', data: 'boolean' }], required: false },
// { id: 'metricDimension', name: '常用维度', type: 'multiple', group: 'technology', value: '', valueshow: '', options: [{ id: '时间', data: '时间' }, { id: '渠道', data: '渠道' }, { id: '省份', data: '省份' }, { id: '产品', data: '产品' }] }, // 支持多选,支持扩展
{ id: 'metricDimension', name: '常用维度', type: 'multiple', group: 'technology', value: '', valueshow: '', options: [] }, // 支持多选,支持扩展
{ id: 'dataSource', name: '数据来源', type: 'text', group: 'technology', value: '', valueshow: '', required: false },
{ id: 'calculateCode', name: '计算代码', type: 'text', group: 'technology', value: '', valueshow: '', required: false }, // 支持较多的字符,动态字符支持
{ id: 'processLevel', name: '加工层级', type: 'select', group: 'technology', value: '', valueshow: '', options: [{ id: 'ODS', data: 'ODS' }, { id: 'DWD', data: 'DWD' }, { id: 'DWS', data: 'DWS' }, { id: 'ADS', data: 'ADS' }], required: false },
// // 管理属性
{ id: 'defineDept', name: '指标定义部门', type: 'text', required: false, group: 'manage', value: '', valueshow: '', editDisabled: false },
{ id: 'defineUser', name: '指标定义人', type: 'text', required: false, group: 'manage', value: '', valueshow: '', editDisabled: false },
{ id: 'defineTime', name: '定义时间', type: 'text', required: false, group: 'manage', value: '', valueshow: '', editDisabled: false },
{ id: 'developmentDept', name: '指标开发部门', type: 'text', group: 'manage', value: '', valueshow: '', required: false },
// { id: 'developmentUser', name: '指标开发人', type: 'text', group: 'manage', value: '', valueshow: '', required: false, editDisabled: true },
{ id: 'developmentTime', name: '开发时间', type: 'text', group: 'manage', value: '', valueshow: '', required: false },
{ id: 'auditDept', name: '指标审核部门', type: 'text', group: 'manage', value: '', valueshow: '', required: false },
{ id: 'auditUser', name: '指标审核人', type: 'text', group: 'manage', value: '', valueshow: '' },
{ id: 'auditTime', name: '审核时间', type: 'text', group: 'manage', value: '', valueshow: '', required: false },
{ id: 'metricsExplain', name: '指标说明', type: 'text', group: 'manage', value: '', valueshow: '', required: false },
{ id: 'calculateEquation', name: '计算公式', type: 'text', group: 'manage', value: '', valueshow: '' }
// { id: 'status', name: '指标状态', type: 'select', group: 'manage', value: '', valueshow: '', required: false, editDisabled: true, options: [{ id: 1, data: '审核通过' }, { id: 0, data: '未审核' }, { id: -1, data: '已删除' }] }
],
quotaSearch: '',
detailDatas: {},
metricDimensionVal: [],
isLoading: false
};
},
created () {
let query = this.$route.query;
if (query.type === 'add') {
this.getDictionary();
this.isLoading = true;
}
if (query.type === 'edit') {
this.pageType = 2;
} else if (query.type === 'detail') {
this.pageType = 0;
} else if (query.type === 'add') {
this.pageType = 1;
this.clearForm();
}
if (query.type === 'edit' || query.type === 'detail') {
this.datas.unshift({ id: 'metricsCode', name: '指标编码', type: 'text', required: true, group: 'base', value: '', valueshow: '', editDisabled: true, isValidate: true, tip: '' });
let row = JSON.parse(sessionStorage.getItem('Quota'));
this.detailDatas = row;
this.getDictionary().then(() => {
this.isLoading = true;
for (let key in this.detailDatas) {
if (key === 'developmentUser') {
this.datas.splice(31, 0, { id: 'developmentUser', name: '指标开发人', type: 'text', group: 'manage', value: '', valueshow: '', required: false, editDisabled: true }
);
}
if (key === 'status') {
this.datas.push({ id: 'status', name: '指标状态', type: 'select', group: 'manage', value: '', valueshow: '', required: false, editDisabled: true, options: [{ id: 1, data: '审核通过' }, { id: 0, data: '未审核' }, { id: -1, data: '已删除' }] }
);
}
for (let i = 0; i < this.datas.length; ++i) {
if (key === this.datas[i].id) {
this.datas[i].value = this.detailDatas[key];
// console.log('this.data[i].value', this.datas[i].value);
// 需要数据转换的
let validateKey = ['business', 'calculationObject', 'topicField', 'calculationCycle', 'isAdd', 'metricsType', 'status'];
// var flag = key === 'business' || key === 'calculationObject' || key === 'topicField' || key === 'calculationCycle' || key === 'metricDimension' || key === 'isAdd' || key === 'metricsType' ||
if (validateKey.indexOf(key) >= 0) {
this.datas[i].valueshow = this.transForm(key, this.detailDatas[key]);
} else {
this.datas[i].valueshow = this.detailDatas[key];// 展示
if (key === 'metricDimension') {
if (this.detailDatas[key].indexOf(',')) {
var arr = [];
this.datas[i].value = this.detailDatas[key].split(',');
this.datas[i].value.map((item) => {
this.datas[i].options.map((eachOpt) => {
if (eachOpt.data === item) {
arr.push(eachOpt.id);
}
});
});
this.datas[i].value = arr;
}
}
}
}
}
}
});
}
},
methods: {
getDictionary () {
let a = axios.request({
url: 'enum/attribute',
method: 'GET'
}).then(res => {
// console.log('business', res);
this.datas.map((item) => {
if (item.id === 'business') {
item.options = res;
}
});
});
let b = axios.request({
url: 'enum/compute_object',
method: 'GET'
}).then(res => {
// console.log('calculationObject', res);
this.datas.map((item) => {
if (item.id === 'calculationObject') {
item.options = res;
}
});
});
let c = axios.request({
url: 'enum/thene_domain',
method: 'GET'
}).then(res => {
// console.log('topicField', res);
this.datas.map((item) => {
if (item.id === 'topicField') {
item.options = res;
}
});
});
let d = axios.request({
url: 'enum/compute_cycle',
method: 'GET'
}).then(res => {
// console.log('calculationCycle', res);
this.datas.map((item) => {
if (item.id === 'calculationCycle') {
item.options = res;
}
});
});
let e = axios.request({
url: 'enum/metric_dimension',
method: 'GET'
}).then(res => {
// console.log('metricDimension', res);
this.datas.map((item) => {
if (item.id === 'metricDimension') {
item.options = res;
}
});
});
;
return Promise.all([a, b, c, d, e]);
},
validate () {
for (let i = 0; i < this.datas.length; i++) {
// console.log('this.datas[i].value', this.datas[i].id, this.datas[i].value);
if (this.datas[i].isValidate) { // 空校验
if (this.datas[i].value === '' || this.datas[i].value === null) {
this.datas[i].tip = this.datas[i].name + '不能为空';
} else {
let item = this.datas[i];
// 长度校验
item.tip = '';
if (item.id === 'metricsName' || item.id === 'englishName' || item.id === 'metricsPurpose' || item.id === 'metricDefine' || item.id === 'calculationCondition') {
if (item.value && (item.value.length > item.isLength)) {
item.tip = '最多支持' + item.isLength + '个字符';
} else {
item.tip = '';
}
}
}
}
}
var flag = this.datas.every((item) => {
return !item.tip;
});
// console.log('flag', flag);
return flag;
},
clearForm () {
this.datas.map((item) => {
item.value = '';
});
},
onSubmit () {
var isValidate = this.validate();
console.log('isValidate', isValidate, this.datas);
if (isValidate) {
let str = '';
for (let i = 0; i < this.datas.length; ++i) {
if (this.datas[i].id === 'metricDimension' && this.datas[i].value) {
let a = this.datas[i].value;
for (let j = 0; j < a.length; j++) {
str += this.transForm('metricDimension', a[j]) + ',';
}
str = str.substr(0, str.length - 1);
this.detailDatas[this.datas[i].id] = str;
// this.detailDatas[this.datas[i].id] = this.datas[i].value.join(',');
} else {
this.detailDatas[this.datas[i].id] = this.datas[i].value;
}
}
if (this.pageType === 2) { // 编辑
console.log('this.detailDatas编辑', this.detailDatas);
axios.request({
url: 'metrics',
method: 'PUT',
data: this.detailDatas
}).then(res => {
console.log('编辑成功==', res);
this.$router.push({
path: `/quota_manage/quota_list`
});
});
} else if (this.pageType === 1) { // 新增
console.log('this.detailDatas新增', this.detailDatas);
axios.request({
url: 'metrics',
method: 'POST',
data: this.detailDatas
}).then(res => {
console.log('新增成功==', res);
if (res.msg !== 'success') {
this.$Message.error(res.msg);
} else {
this.$router.push({
path: `/quota_manage/quota_list`
});
}
});
}
}
},
onCancel () {
this.$router.push({
path: `/quota_manage/quota_list`
});
},
transForm (key, value) {
// console.log('转换', key, value);
if (key === 'business') { // 所属业务
switch (value) {
case 1 :
value = '微爱业务中心';
break;
case 2 :
value = '保险业务中心';
break;
case 3 :
value = '健康业务中心';
break;
case 4 :
value = '会员业务中心';
break;
case 5 :
value = '内容运营中心';
break;
case 6 :
value = '客服运营中心';
break;
case 7 :
value = '智能营销中心';
break;
case 8 :
value = '增长合作中心';
break;
default :
value = '';
}
}
if (key === 'calculationObject') { // 计算对象
switch (value) {
case 1 :
value = '用户';
break;
case 2 :
value = '订单';
break;
case 3 :
value = '项目';
break;
case 4 :
value = '粉丝';
break;
case 5 :
value = '保单';
break;
default :
value = '';
}
}
if (key === 'topicField') { // 主题领域
switch (value) {
case 1 :
value = '用户';
break;
case 2 :
value = '流量';
break;
case 3 :
value = '交易订单';
break;
case 4 :
value = '项目';
break;
case 5 :
value = '保单';
break;
default :
value = '';
}
}
if (key === 'calculationCycle') { // 统计周期
switch (value) {
case 1 :
value = '五分钟';
break;
case 2 :
value = '一小时';
break;
case 3 :
value = '7日';
break;
case 4 :
value = '两个周';
break;
case 5 :
value = '一个月';
break;
case 6:
value = '一季';
break;
case 7:
value = '一年';
break;
default :
value = '';
}
}
if (key === 'metricDimension') { // 常用维度
switch (value) {
case 1 :
value = '时间';
break;
case 2 :
value = '渠道';
break;
case 3 :
value = '省份';
break;
case 4 :
value = '产品';
break;
default :
value = '';
}
}
if (key === 'isAdd') {
switch (value) {
case 1 :
value = '是';
break;
case 0 :
value = '否';
break;
default :
value = '';
}
}
if (key === 'metricsType') {
switch (value) {
case 1 :
value = '基础指标';
break;
case 2 :
value = '复合指标';
break;
default :
value = '';
}
}
if (key === 'status') {
switch (value) {
case 1 :
value = '审核通过';
break;
case 0 :
value = '未审核';
break;
case -1 :
value = '已删除';
break;
default :
value = '';
}
}
// status;
return value;
}
}
};
</script>
<style lang="less" scoped>
.item-title{
background-color:rgba(215, 215, 215, 1);
width:100%;
height:27px;
line-height: 27px;
padding-left: 5px;
margin-bottom: 20px;
font-weight: 700px;
font-size: 13px;
color:#333333;
}
.fixed-height{
height:32px;
}
.item-container{
width:30%;
.tip{
position: relative;
top: -10px;
color:red;
}
}
.bottom-footer{
margin:0 auto;
text-align: center;
padding:20px 0px;
/deep/button{
width:120px;
margin-left:20px;
}
}
</style>
四,实现意义
将数据和页面结构及样式分离,可剥离成组件,代码简洁,易于阅读,容易维护,有较强的可扩展性。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。