|
|
|
@ -0,0 +1,307 @@
|
|
|
|
|
<template>
|
|
|
|
|
<layout :title="title">
|
|
|
|
|
<h1>{{title}}</h1>
|
|
|
|
|
<div class="row">
|
|
|
|
|
<div class="col-12">
|
|
|
|
|
<form ref="form" class="form-horizontal query" :action="action" @submit.prevent="onSubmit($event)" v-if="data.model">
|
|
|
|
|
<div class="card" v-if="hasPermission()&&data.schema">
|
|
|
|
|
<div class="card-body">
|
|
|
|
|
<template v-if="data.errors">
|
|
|
|
|
<div class="form-group" v-for="error in getValidationSummary(true)">
|
|
|
|
|
<div class="offset-sm-2 col-sm-10 ">
|
|
|
|
|
<div style="color:#dc3545;">{{error}}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
<input type="hidden" name="id" :value="data.model.id" />
|
|
|
|
|
<div class="form-group row">
|
|
|
|
|
<label class="col-sm-2 col-form-label" :for="key">{{data.schema.properties.name.title}}:</label>
|
|
|
|
|
<div class="col-sm-6 form-control" style="border-color:transparent;height:auto;min-height:calc(2.25rem + 2px);">
|
|
|
|
|
<template>
|
|
|
|
|
<component is="edit-string" mode="edit" name="name" :value.sync="data.model.name" @change="change" :data="data.data" />
|
|
|
|
|
</template>
|
|
|
|
|
<div style="height:1em;">
|
|
|
|
|
<span v-if="hasErrors('name')" class="field-validation-error text-danger">{{getErrors('name')}}</span>
|
|
|
|
|
<span v-else class="text-danger field-validation-valid"></span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="col-sm-4">{{data.schema.properties.name.description}}</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="form-group row">
|
|
|
|
|
<label class="col-sm-2 col-form-label" :for="key">{{data.schema.properties.type.title}}:</label>
|
|
|
|
|
<div class="col-sm-6 form-control" style="border-color:transparent;height:auto;min-height:calc(2.25rem + 2px);">
|
|
|
|
|
<template>
|
|
|
|
|
<component is="edit-selectlist" mode="edit" name="type" :value.sync="data.model.type" @change="change" :data="data.data" />
|
|
|
|
|
</template>
|
|
|
|
|
<div style="height:1em;">
|
|
|
|
|
<span v-if="hasErrors('type')" class="field-validation-error text-danger">{{getErrors('type')}}</span>
|
|
|
|
|
<span v-else class="text-danger field-validation-valid"></span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="col-sm-4">{{data.schema.properties.type.description}}</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="form-group row">
|
|
|
|
|
<label class="col-sm-2 col-form-label" :for="key">{{data.schema.properties.value.title}}:</label>
|
|
|
|
|
<div class="col-sm-6 form-control" style="border-color:transparent;height:auto;min-height:calc(2.25rem + 2px);">
|
|
|
|
|
<template>
|
|
|
|
|
<component :is="getValueComponent()" mode="edit" name="value" :value.sync="data.model.value" @change="change" :data="data.data" />
|
|
|
|
|
</template>
|
|
|
|
|
<div style="height:1em;">
|
|
|
|
|
<span v-if="hasErrors('value')" class="field-validation-error text-danger">{{getErrors('value')}}</span>
|
|
|
|
|
<span v-else class="text-danger field-validation-valid"></span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="col-sm-4">{{data.schema.properties.value.description}}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="card-footer">
|
|
|
|
|
<div class="row">
|
|
|
|
|
<div class="col-sm-2">
|
|
|
|
|
</div>
|
|
|
|
|
<div class="col-sm-10">
|
|
|
|
|
<button type="submit" class="btn btn-primary">确定</button>
|
|
|
|
|
<router-link :to="{path:'/router/shared/list.html',query:{area:area,entity:entity}}" class="btn btn-default">返回</router-link>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</form>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</layout>
|
|
|
|
|
</template>
|
|
|
|
|
<script>
|
|
|
|
|
export default {
|
|
|
|
|
props: ['parea', 'pentity', 'pid'],
|
|
|
|
|
name: 'edit',
|
|
|
|
|
data: function () {
|
|
|
|
|
return {
|
|
|
|
|
data: {
|
|
|
|
|
errors: [],
|
|
|
|
|
schema: null,
|
|
|
|
|
model: null,
|
|
|
|
|
data: null
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
computed: {
|
|
|
|
|
area: function () {
|
|
|
|
|
return this.parea || this.$route.query.area || 'default';
|
|
|
|
|
},
|
|
|
|
|
entity: function () {
|
|
|
|
|
return this.pentity || this.$route.query.entity;
|
|
|
|
|
},
|
|
|
|
|
id: function () {
|
|
|
|
|
return this.pid || this.$route.query.id;
|
|
|
|
|
},
|
|
|
|
|
mode: function () {
|
|
|
|
|
return this.pmode || this.$route.query.mode;
|
|
|
|
|
},
|
|
|
|
|
url: function () {
|
|
|
|
|
return '/IoTCenter/Admin/' + this.entity + '/' + this.mode + (this.mode === 'Add' ? '' : '?id=' + this.id);
|
|
|
|
|
},
|
|
|
|
|
name: function () {
|
|
|
|
|
return this.data.schema ? this.data.schema.title : '';
|
|
|
|
|
},
|
|
|
|
|
title: function () {
|
|
|
|
|
return this.name + '列表';
|
|
|
|
|
},
|
|
|
|
|
action: function () {
|
|
|
|
|
return '/IoTCenter/Admin/' + this.$route.query.entity + '/' + this.$route.query.mode + 'Api';
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
mounted: function () {
|
|
|
|
|
this.load();
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
load: function () {
|
|
|
|
|
var vm = this;
|
|
|
|
|
var url = this.baseUrl + this.url;
|
|
|
|
|
axios.get(url).then(function (response) {
|
|
|
|
|
vm.data = response.data;
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
getValueComponent: function () {
|
|
|
|
|
if (this.data.model.type) {
|
|
|
|
|
var value = Enumerable.from(this.data.data.typeSelectList).firstOrDefault(o => o.value === this.data.model.type.toString()).text;
|
|
|
|
|
if (value === '单行文本') {
|
|
|
|
|
return 'edit-string';
|
|
|
|
|
} else if (value === '多行文本') {
|
|
|
|
|
return 'edit-multilinetext';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 'edit-string';
|
|
|
|
|
},
|
|
|
|
|
change: function (name) {
|
|
|
|
|
var vm = this;
|
|
|
|
|
var value = this.data.model[name];
|
|
|
|
|
var property = this.data.schema.properties[name];
|
|
|
|
|
var list = [];
|
|
|
|
|
list.push(
|
|
|
|
|
this.validInternal(property.required, name, o => Promise.resolve(value !== undefined && value !== null))
|
|
|
|
|
);
|
|
|
|
|
if (value) {
|
|
|
|
|
list.push(
|
|
|
|
|
this.validInternal(property.email, name, o => Promise.resolve(/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(value)))
|
|
|
|
|
);
|
|
|
|
|
list.push(
|
|
|
|
|
this.validInternal(property.url, name, o => Promise.resolve(/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(value)))
|
|
|
|
|
);
|
|
|
|
|
list.push(
|
|
|
|
|
this.validInternal(property.date, name, o => Promise.resolve(!/Invalid|NaN/.test(new Date(value).toString())))
|
|
|
|
|
);
|
|
|
|
|
list.push(
|
|
|
|
|
this.validInternal(property.number, name, o => Promise.resolve(/^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value)))
|
|
|
|
|
);
|
|
|
|
|
list.push(
|
|
|
|
|
this.validInternal(property.digits, name, o => Promise.resolve(/^\d+$/.test(value)))
|
|
|
|
|
);
|
|
|
|
|
//dateiso
|
|
|
|
|
//creditcard
|
|
|
|
|
//accept
|
|
|
|
|
list.push(
|
|
|
|
|
this.validInternal(property.pattern, name, o => Promise.resolve(new RegExp(property.pattern.regex).test(value)))
|
|
|
|
|
);
|
|
|
|
|
list.push(
|
|
|
|
|
this.validInternal(property.minLength, name, o => Promise.resolve(value.length >= property.minLength.min))
|
|
|
|
|
);
|
|
|
|
|
list.push(
|
|
|
|
|
this.validInternal(property.maxLength, name, o => Promise.resolve(value.length <= property.maxLength.max))
|
|
|
|
|
);
|
|
|
|
|
list.push(
|
|
|
|
|
this.validInternal(property.rangeLength, name, o => Promise.resolve(value.length >= property.rangeLength.min && value.length <= property.rangeLength.max))
|
|
|
|
|
);
|
|
|
|
|
list.push(
|
|
|
|
|
this.validInternal(property.range, name, o => Promise.resolve(parseFloat(value) >= property.range.min && parseFloat(value) <= property.range.max))
|
|
|
|
|
);
|
|
|
|
|
list.push(this.validInternal(property.equalTo, name, o => Promise.resolve(o === vm.data.model[vm.camelCased(name)]))
|
|
|
|
|
);
|
|
|
|
|
list.push(
|
|
|
|
|
this.validInternal(property.remote, name, o => new Promise((resolve, reject) => {
|
|
|
|
|
var url = property.remote.url + '?' + name + '=' + value;
|
|
|
|
|
if (property.remote.additionalFields) {
|
|
|
|
|
var keys = property.remote.additionalFields.split(',');
|
|
|
|
|
for (var i = 0; i < keys.length; i++) {
|
|
|
|
|
var key = keys[i];
|
|
|
|
|
url = url + '&' + key + '=' + vm.data.model[vm.camelCased(key)];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
axios.get(url).then(function (response) {
|
|
|
|
|
resolve(response.data === true);
|
|
|
|
|
}).catch(function () {
|
|
|
|
|
resolve(false);
|
|
|
|
|
});
|
|
|
|
|
}))
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
return Promise.all(list);
|
|
|
|
|
},
|
|
|
|
|
valid: function () {
|
|
|
|
|
var vm = this;
|
|
|
|
|
var list = [];
|
|
|
|
|
_.forIn(this.data.schema.properties, function (value, key) {
|
|
|
|
|
list.push(vm.change(key));
|
|
|
|
|
});
|
|
|
|
|
return Promise.all(list);
|
|
|
|
|
},
|
|
|
|
|
validInternal: function (validator, name, valid, message) {
|
|
|
|
|
if (validator) {
|
|
|
|
|
var vm = this;
|
|
|
|
|
message = message || validator.message;
|
|
|
|
|
return valid().then(function (value) {
|
|
|
|
|
if (value) {
|
|
|
|
|
vm.removeError(name, message);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
vm.updateError(name, message);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
return Promise.resolve('');
|
|
|
|
|
},
|
|
|
|
|
camelCased: function (name) {
|
|
|
|
|
return name[0].toLowerCase() + name.substr(1);
|
|
|
|
|
},
|
|
|
|
|
removeError: function (name, message) {
|
|
|
|
|
var error = Enumerable.from(this.data.errors).firstOrDefault(o => o.key.toLowerCase() === name.toLowerCase());
|
|
|
|
|
if (error) {
|
|
|
|
|
if (Enumerable.from(error.value.errors).any(o => o.errorMessage === message)) {
|
|
|
|
|
error.value.errors = Enumerable.from(error.value.errors).where(o => o.errorMessage !== message).toArray();
|
|
|
|
|
}
|
|
|
|
|
if (error.value.errors.length === 0) {
|
|
|
|
|
var index = _.findIndex(this.data.errors, o => o.key.toLowerCase() === name.toLowerCase());
|
|
|
|
|
this.data.errors.splice(index, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
updateError: function (name, message) {
|
|
|
|
|
var error = Enumerable.from(this.data.errors).firstOrDefault(o => o.key.toLowerCase() === name.toLowerCase());
|
|
|
|
|
if (!error) {
|
|
|
|
|
error = {
|
|
|
|
|
key: name,
|
|
|
|
|
value: {
|
|
|
|
|
errors: [{ errorMessage: message }]
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
this.data.errors.push(error);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (!Enumerable.from(error.value.errors).any(o => o.errorMessage === message)) {
|
|
|
|
|
error.value.errors.push({ errorMessage: message });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
getValidationSummary: function (excludePropertyErrors) {
|
|
|
|
|
var query = Enumerable.from(this.data.errors);
|
|
|
|
|
if (excludePropertyErrors) {
|
|
|
|
|
query = query.where(o => o.key === '')
|
|
|
|
|
}
|
|
|
|
|
return query.select(o => o.value.errors[0].errorMessage).toArray();
|
|
|
|
|
},
|
|
|
|
|
hasErrors: function (key) {
|
|
|
|
|
key = key.toLowerCase();
|
|
|
|
|
return Enumerable.from(this.data.errors).any(o => o.key.toLowerCase() === key);
|
|
|
|
|
},
|
|
|
|
|
getErrors: function (key) {
|
|
|
|
|
key = key.toLowerCase();
|
|
|
|
|
return Enumerable.from(this.data.errors)
|
|
|
|
|
.where(o => o.key.toLowerCase() === key).selectMany(o => o.value.errors).select(o => o.errorMessage).toArray().join(',');
|
|
|
|
|
},
|
|
|
|
|
hasPermission: function () {
|
|
|
|
|
var permission = this.mode + '-' + this.entity;
|
|
|
|
|
return Enumerable.from(store.state.permissions).any(o => o === permission);
|
|
|
|
|
},
|
|
|
|
|
getEditComponent: function (key) {
|
|
|
|
|
var property = this.data.schema.properties[key];
|
|
|
|
|
var template = 'edit-' + (property.ui || property.format || property.type);
|
|
|
|
|
return template;
|
|
|
|
|
},
|
|
|
|
|
getDisplayComponent: function (key) {
|
|
|
|
|
var property = this.data.schema.properties[key];
|
|
|
|
|
var template = 'display-' + (property.ui || property.format || property.type);
|
|
|
|
|
return template;
|
|
|
|
|
},
|
|
|
|
|
show: function (key, value) {
|
|
|
|
|
return key !== 'id';
|
|
|
|
|
},
|
|
|
|
|
onSubmit: function (e) {
|
|
|
|
|
var vm = this;
|
|
|
|
|
vm.valid().then(function (value) {
|
|
|
|
|
if (vm.data.errors.length === 0) {
|
|
|
|
|
axios.post(e.target.action, vm.data.model).then(function (response) {
|
|
|
|
|
if (response.status === 204) {
|
|
|
|
|
var url = '/router/shared/list.html?area=' + vm.area + '&entity=' + vm.entity;
|
|
|
|
|
setTimeout(function () {
|
|
|
|
|
router.push(url);
|
|
|
|
|
}, 1000);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
vm.data = response.data;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|