Former-commit-id: d3fc6c643d67b26c1de3ab7cbacdffe399f04ba2
Former-commit-id: 1ee4d3383af9b996a4bd6f6aefc8afcc03cae7d1
TSXN
wanggang 5 years ago
parent 33c95d6836
commit fe17f46f4f

@ -297,6 +297,11 @@ namespace Infrastructure.Extensions
}
}
public static bool IsJsonRequest(this ControllerBase controller)
{
return controller.Request.Headers["accept"].ToString().Contains("json", StringComparison.OrdinalIgnoreCase);
}
public static string GetErrorMessage(this ValidationAttribute attribute, IStringLocalizer localizer, params string[] args)
{
var localizedString = localizer.GetString(attribute.GetType().Name);

@ -1,4 +1,10 @@
using Infrastructure.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Linq;
namespace Infrastructure.Web
{
@ -17,5 +23,20 @@ namespace Infrastructure.Web
ViewBag.Url = returnUrl;
return View("Redirect");
}
protected IActionResult Result<TEditModel>(object model)
{
if (this.IsJsonRequest())
{
return Json(new
{
schema = this.GetJsonSchema<TEditModel>(),
model,
errors = ModelState.Where(o => o.Value.ValidationState == ModelValidationState.Invalid),
data = ViewData
}, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver(), ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
}
return View(model);
}
}
}

@ -317,23 +317,13 @@ namespace Infrastructure.Web.Mvc
[ApiExplorerSettings(IgnoreApi = true)]
protected IActionResult Result(object model)
{
if (this.Request.Headers["accept"].ToString().Contains("json", StringComparison.OrdinalIgnoreCase))
{
return Json(new
{
schema = this.GetJsonSchema<TEditModel>(),
model,
errors = ModelState.Where(o => o.Value.ValidationState == ModelValidationState.Invalid),
data = ViewData
}, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() });
}
return View(model);
return Result<TEditModel>(model);
}
[ApiExplorerSettings(IgnoreApi = true)]
protected IActionResult Success()
{
if (this.Request.Headers["accept"].ToString().Contains("json", StringComparison.OrdinalIgnoreCase))
if (this.IsJsonRequest())
{
return this.NoContent();
}
@ -343,7 +333,7 @@ namespace Infrastructure.Web.Mvc
[ApiExplorerSettings(IgnoreApi = true)]
protected IActionResult Error(string message)
{
if (this.Request.Headers["accept"].ToString().Contains("json", StringComparison.OrdinalIgnoreCase))
if (this.IsJsonRequest())
{
return this.Problem(message);
}

@ -320,7 +320,7 @@ namespace Infrastructure.Web.Mvc
[ApiExplorerSettings(IgnoreApi = true)]
private IActionResult Result(object model)
{
return this.Request.Headers["accept"].ToString().Contains("json", StringComparison.OrdinalIgnoreCase) ? Json(model) as IActionResult : View(model);
return this.IsJsonRequest() ? Json(model) as IActionResult : View(model);
}
public IActionResult GetJsonSchema()

@ -6,8 +6,11 @@ using Infrastructure.Data;
using Infrastructure.Extensions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using NPOI.SS.Formula.Functions;
using System;
using System.Collections.Generic;
@ -53,6 +56,16 @@ namespace IoT.Shared.Areas.Admin.Controlls
public IActionResult Api(Guid apiId, Guid deviceId)
{
var model = this.GetParameters(apiId, deviceId, null);
if (this.IsJsonRequest())
{
return Json(new
{
schema = this.GetJsonSchema<EditApiParameterModel>(),
model,
errors = ModelState.Where(o => o.Value.ValidationState == ModelValidationState.Invalid),
data = ViewData
}, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver(), ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
}
return PartialView("_Api", model);
}

@ -101,7 +101,14 @@ namespace UserCenter.Controllers
public IActionResult Login(string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
return View();
return Result<LoginModel>(new LoginModel());
}
[AllowAnonymous]
[HttpPost]
public IActionResult LoginApi([FromBody] LoginModel model, string returnUrl = null)
{
return this.Login(model, returnUrl);
}
[AllowAnonymous]
@ -167,30 +174,37 @@ namespace UserCenter.Controllers
}
if (success)
{
HttpContext.JwtSignIn(model.UserName, model.RememberMe, _cfg);
if (string.IsNullOrEmpty(returnUrl))
if (this.IsJsonRequest())
{
returnUrl = Url.Action("Index", "Home");
return Json(this.CreateToken(userName));
}
ViewBag.Url = returnUrl;
var urls = new List<string>();
var list = this._siteRepo.ReadOnlyTable().ToList();
foreach (var site in list)
else
{
var username = user.UserName;
var timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();
var sign = string.Concat(userName, timestamp, site.Key).Md5();
var url = site.Login
.SetParam(nameof(username), username)
.SetParam(nameof(user.NickName), user.NickName)
.SetParam(nameof(user.Avatar), user.Avatar)
.SetParam(nameof(timestamp), timestamp)
.SetParam("rememberme", model.RememberMe)
.SetParam(nameof(sign), sign);
urls.Add(url);
HttpContext.JwtSignIn(model.UserName, model.RememberMe, _cfg);
if (string.IsNullOrEmpty(returnUrl))
{
returnUrl = Url.Action("Index", "Home");
}
ViewBag.Url = returnUrl;
var urls = new List<string>();
var list = this._siteRepo.ReadOnlyTable().ToList();
foreach (var site in list)
{
var username = user.UserName;
var timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();
var sign = string.Concat(userName, timestamp, site.Key).Md5();
var url = site.Login
.SetParam(nameof(username), username)
.SetParam(nameof(user.NickName), user.NickName)
.SetParam(nameof(user.Avatar), user.Avatar)
.SetParam(nameof(timestamp), timestamp)
.SetParam("rememberme", model.RememberMe)
.SetParam(nameof(sign), sign);
urls.Add(url);
}
Response.Headers.Remove("Location");
return View("JsonpLogin", urls);
}
Response.Headers.Remove("Location");
return View("JsonpLogin", urls);
}
else
{
@ -215,7 +229,7 @@ namespace UserCenter.Controllers
}
ModelState.AddModelError(key, message);
ViewData["ReturnUrl"] = returnUrl;
return View(model);
return Result<LoginModel>(model);
}
#endregion 登录
@ -920,6 +934,15 @@ namespace UserCenter.Controllers
return this._cfg.GetValue<int>("CaptchaSeconds");
}
private object CreateToken(String userName)
{
return new
{
AccessToken = Request.HttpContext.GetToken(userName, _cfg, DateTime.Now.AddMinutes(Convert.ToDouble(_settingService.GetSetting("AccessTokenTimeout").Value))),
RefreshToken = Request.HttpContext.GetToken(userName, _cfg, DateTime.Now.AddMinutes(Convert.ToDouble(_settingService.GetSetting("RefreshTokenTimeout").Value))),
};
}
#endregion tools
}
}

@ -21,7 +21,7 @@ axios.interceptors.response.use(function (response) {
loading.hide();
return response;
}, function (error) {
console.error(error.response);
console.error(error);
if (error.response.status === 401 && error.config.url.indexOf('refreshToken') === -1) {
var url = apiHost + '/UserCenter/api/v1/token/refreshToken';
var data = '"' + store.state.token.refreshToken + '"';

@ -9,6 +9,7 @@
'display-html',
'display-cron',
'edit-string',
'edit-password',
'edit-boolean',
'edit-imageurl',
'edit-integer',

@ -8,7 +8,10 @@ router.beforeEach((to, from, next) => {
isAuthenticated = jwt.exp * 1000 >= new Date().getTime();
}
if (!isAuthenticated) {
router.push('/router/login.html');
store.commit('logout');
setTimeout(function () {
router.push('/router/login.html');
}, 1000);
return;
}
}

@ -11,10 +11,17 @@ const store = new Vuex.Store({
setState(state,data) {
state[data.key] = data.value;
},
login(state, data) {
localStorage.setItem('accessToken', data.accessToken);
localStorage.setItem('refreshToken', data.refreshToken);
state.token.accessToken = data.accessToken;
state.token.refreshToken = data.refreshToken;
},
logout(state) {
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');
state.token = null;
state.token.accessToken = null;
state.token.refreshToken = null;
}
}
});

@ -0,0 +1,7 @@
<template>
<display service="IoTCenter" area="admin" entity="Command" model="Command" :id="this.$route.query.id" />
</template>
<script>
export default {
}
</script>

@ -0,0 +1,290 @@
<template>
<layout :title="title">
<h1>{{title}}</h1>
<div class="row">
<div class="col-12">
<form ref="form" :class="'form-horizontal query '+this.entity" :action="action" @submit.prevent="onSubmit($event)">
<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="name">{{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">{{getPropertyErrors('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="displayOrder">{{data.schema.properties.displayOrder.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="displayOrder" :value.sync="data.model.displayOrder" @change="change" :data="data.data" />
</template>
<div style="height:1em;">
<span v-if="hasErrors('name')" class="field-validation-error text-danger">{{getPropertyErrors('displayOrder')}}</span>
<span v-else class="text-danger field-validation-valid"></span>
</div>
</div>
<div class="col-sm-4">{{data.schema.properties.displayOrder.description}}</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="disabled">{{data.schema.properties.disabled.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-boolean" mode="edit" name="disabled" :value.sync="data.model.disabled" @change="change" :data="data.data" />
</template>
<div style="height:1em;">
<span v-if="hasErrors('name')" class="field-validation-error text-danger">{{getPropertyErrors('disabled')}}</span>
<span v-else class="text-danger field-validation-valid"></span>
</div>
</div>
<div class="col-sm-4">{{data.schema.properties.disabled.description}}</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="nodeId">{{data.schema.properties.nodeId.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="nodeId" :value.sync="data.model.nodeId" @change="change" :data="data.data" />
</template>
<div style="height:1em;">
<span v-if="hasErrors('name')" class="field-validation-error text-danger">{{getPropertyErrors('nodeId')}}</span>
<span v-else class="text-danger field-validation-valid"></span>
</div>
</div>
<div class="col-sm-4">{{data.schema.properties.nodeId.description}}</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="deviceId">{{data.schema.properties.deviceId.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="deviceId" :value.sync="data.model.deviceId" @change="change" :data="data.data" />
</template>
<div style="height:1em;">
<span v-if="hasErrors('name')" class="field-validation-error text-danger">{{getPropertyErrors('deviceId')}}</span>
<span v-else class="text-danger field-validation-valid"></span>
</div>
</div>
<div class="col-sm-4">{{data.schema.properties.deviceId.description}}</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label" for="apiId">{{data.schema.properties.apiId.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="apiId" :value.sync="data.model.apiId" @change="change" :data="data.data" />
</template>
<div style="height:1em;">
<span v-if="hasErrors('name')" class="field-validation-error text-danger">{{getPropertyErrors('apiId')}}</span>
<span v-else class="text-danger field-validation-valid"></span>
</div>
</div>
<div class="col-sm-4">{{data.schema.properties.apiId.description}}</div>
</div>
<template v-if="data.model&&data.model.apiId&&data.model.parameters.length">
<hr />
<template v-if="deviceName==='红外转发器'">
{{deviceName}}
</template>
<template v-else-if="deviceName==='串口控制器'">
{{deviceName}}
</template>
<template v-else v-for="param in data.model.parameters">
<div class="form-group row">
<label class="col-sm-2 col-form-label">{{param.description}}:</label>
<div class="col-sm-6 form-control" style="border-color:transparent;height:auto;min-height:calc(2.25rem + 2px);">
<input type="text" class="form-control" :value="param.value" />
<div style="height:1em;">
<!--<span v-if="hasErrors('name')" class="field-validation-error text-danger">{{getPropertyErrors('apiId')}}</span>
<span v-else class="text-danger field-validation-valid"></span>-->
</div>
</div>
<!--<div class="col-sm-4">{{data.schema.properties.apiId.description}}</div>-->
</div>
</template>
</template>
</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:base+'index.html',query:{area:area,entity:entity}}" class="btn btn-default">返回</router-link>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</layout>
</template>
<script>
export default {
name: 'update',
data: function () {
return {
service: 'IoTCenter',
area: "admin",
entity: 'Command',
model: 'Command',
mode: this.$route.query.mode,
id: this.$route.query.id,
data: {
errors: [],
schema: null,
model: null,
data: null
}
}
},
computed: {
path: function () {
return '/' + this.service + '/' + this.area + '/' + this.model + '/';
},
url: function () {
return this.path + this.mode + (this.mode === 'edit' ? ('?id=' + this.id) : '');
},
action: function () {
return this.path + this.mode + 'Api';
},
name: function () {
return this.data.schema ? this.data.schema.title : '';
},
title: function () {
return this.name + (this.mode === 'edit' ? '编辑' : '新建');
},
base: function () {
return this.$route.path.substr(0, this.$route.path.lastIndexOf('/') + 1);
},
deviceName: function () {
return this.data.data[this.data.model.deviceId];
}
},
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;
});
},
getSchema: function () {
return this.data.schema;
},
getModel: function () {
return this.data.model;
},
getErrors: function () {
return this.data.errors;
},
hasErrors: function (key) {
key = key.toLowerCase();
return Enumerable.from(this.getErrors()).any(o => o.key.toLowerCase() === key);
},
getValidationSummary: function (excludePropertyErrors) {
var query = Enumerable.from(this.getErrors());
if (excludePropertyErrors) {
query = query.where(o => o.key === '')
}
return query.select(o => o.value.errors[0].errorMessage).toArray();
},
getPropertyErrors: function (key) {
key = key.toLowerCase();
return Enumerable.from(this.getErrors())
.where(o => o.key.toLowerCase() === key).selectMany(o => o.value.errors).select(o => o.errorMessage).toArray().join(',');
},
change: function (name) {
return this.$validProperty(name);
},
hasPermission: function () {
var permission = this.mode + '-' + this.entity;
return Enumerable.from(store.state.permissions).any(o => o.toLowerCase() === permission.toLowerCase());
},
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 = vm.base + 'index.html?area=' + vm.area + '&entity=' + vm.entity + '&model=' + vm.model;
setTimeout(function () {
router.push(url);
}, 1000);
}
else {
vm.data = response.data;
}
});
}
});
},
getValueComponent: function () {
var vm = this;
if (vm.data.model && vm.data.model.type) {
var list = {
'布尔值': 'edit-boolean',
'Html': 'edit-html',
'图片': 'edit-imageurl',
};
var item = Enumerable.from(vm.data.data.typeSelectList).firstOrDefault(o => o.value === vm.data.model.type.toString());
var value = item ? item.text : null;
if (value) {
if (this.data.model) {
if (value === '单行文本') {
return 'edit-string';
} else if (value === '多行文本') {
return 'edit-multilinetext';
}
}
if (list[value]) {
return list[value];;
}
}
}
return 'edit-string';
}
},
watch: {
'data.model.apiId': function (val) {
var vm = this;
if (val && this.data.model.deviceId) {
var url = this.path + 'Api?apiId=' + val + '&deviceId=' + this.data.model.deviceId;
axios.get(url).then(function (response) {
console.log(response.data);
Vue.set(vm.data.data, vm.data.model.deviceId, response.data.data.device.name);
vm.data.model.parameters = response.data.model;
});
}
}
}
}
</script>

@ -0,0 +1,7 @@
<template>
<list service="IoTCenter" area="admin" entity="Command" model="Command" />
</template>
<script>
export default {
}
</script>

@ -1,43 +1,160 @@
<template>
<form class="weui-form" id="form" method="post">
<div class="weui-cells weui-cells_form">
<div class="weui-cell">
<div class="weui-cell__hd"><label class="weui-label">用户名</label></div>
<div class="weui-cell__bd">
<input class="weui-input" type="text" name="userName" placeholder="用户名" maxlength="100" required pattern="REG_userName" emptytips="请输入用户名" notmatchtips="用户名输入不合法">
</div>
</div>
<div class="weui-cell">
<div class="weui-cell__hd"><label class="weui-label">密码</label></div>
<div class="weui-cell__bd">
<input class="weui-input" type="password" name="password" placeholder="密码" maxlength="100" required pattern="REG_password" tips="请输入密码" notmatchtips="密码输入不合法">
</div>
<layout :title="title">
<h1>{{title}}</h1>
<div class="row">
<div class="col-12">
<form ref="form" :class="'form-horizontal query '+this.entity" :action="action" @submit.prevent="onSubmit($event)">
<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" v-for="(value,key,index) in data.schema.properties" v-if="show(key,value)">
<label class="col-sm-2 col-form-label" :for="key">{{value.title}}:</label>
<div v-if="data.model" class="col-sm-6 form-control" style="border-color:transparent;height:auto;min-height:calc(2.25rem + 2px);">
<template v-if="value.readOnly&&mode!=='add'">
<input type="hidden" :name="key" :value="data.model[key]" />
<component :is="getDisplayComponent(key)" :title="value.title" :name="key" :value="data.model[key]" :data="data.data" v-if="data.model" />
</template>
<template v-else>
<component :is="getEditComponent(key)" mode="edit" :title="value.title" :name="key" :value.sync="data.model[key]" :data="data.data" :nullable="value.nullable" @change="change" />
</template>
<div style="height:1em;">
<span v-if="hasErrors(key)" class="field-validation-error text-danger">{{getPropertyErrors(key)}}</span>
<span v-else class="text-danger field-validation-valid"></span>
</div>
</div>
<div class="col-sm-4">{{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:base+'index.html',query:{area:area,entity:entity}}" class="btn btn-default">返回</router-link>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
<a class="weui-btn weui-btn_primary my-3" href="javascript:" id="showTooltips" v-on:click="submit()">确定</a>
</form>
</layout>
</template>
<script>
export default {
props: ['service', 'area', 'entity', 'model', 'id', 'mode'],
name: 'update',
data: function () {
return {
title: '登录',
url: '/UserCenter/api/v1/token/getToken'
data: {
errors: [],
schema: null,
model: null,
data: null
}
}
},
computed: {
path: function () {
return '/UserCenter/Account/Login';
},
action: function () {
return this.baseUrl + this.path + 'Api'
},
name: function () {
return this.data.schema ? this.data.schema.title : '';
},
title: function () {
return '登录';
},
base: function () {
return this.$route.path.substr(0, this.$route.path.lastIndexOf('/') + 1);
}
},
mounted: function () {
document.querySelector('title').innerHTML = this.title;
this.load();
},
methods: {
submit: function () {
var form = $("#form");
var data = form.serializeJSON();
var url = config.baseUrl + this.url;
axios.post(url, data).then(function (response) {
localStorage.setItem('accessToken', response.data.accessToken);
localStorage.setItem('refreshToken', response.data.refreshToken);
store.commit('setState', { key: 'token', value: response.data });
router.push('/');
load: function () {
var vm = this;
var url = this.baseUrl + this.path;
axios.get(url).then(function (response) {
vm.data = response.data;
});
},
getSchema: function () {
return this.data.schema;
},
getModel: function () {
return this.data.model;
},
getErrors: function () {
return this.data.errors;
},
hasErrors: function (key) {
key = key.toLowerCase();
return Enumerable.from(this.getErrors()).any(o => o.key.toLowerCase() === key);
},
getValidationSummary: function (excludePropertyErrors) {
var query = Enumerable.from(this.getErrors());
if (excludePropertyErrors) {
query = query.where(o => o.key === '')
}
return query.select(o => o.value.errors[0].errorMessage).toArray();
},
getPropertyErrors: function (key) {
key = key.toLowerCase();
return Enumerable.from(this.getErrors())
.where(o => o.key.toLowerCase() === key).selectMany(o => o.value.errors).select(o => o.errorMessage).toArray().join(',');
},
change: function (name) {
return this.$validProperty(name);
},
hasPermission: function () {
return true;
},
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 === 200) {
if (response.data.errors) {
this.data = response.data;
}
else {
store.commit('login', response.data);
setTimeout(function () {
router.push('/');
}, 1000);
}
}
else {
vm.data = response.data;
}
});
}
});
}
}

@ -0,0 +1,22 @@
<template>
<div>
<input type="password" :name="currentName" class="form-control" v-model="currentValue" />
</div>
</template>
<script>
export default {
props: ['prefix', 'name', 'value', 'data'],
data: function () {
return {
currentName: this.prefix ? (this.prefix + '.' + this.name) : this.name,
currentValue: this.value
};
},
watch: {
currentValue(val) {
this.$emit('update:value', val);
this.$emit('change', this.name);
}
}
};
</script>

@ -34,7 +34,7 @@
<img class="brand-image img-circle elevation-3" :src="data.logo" />
<span class="brand-text font-weight-light">{{data.name}}</span>
</a>
<div class="sidebar">
<div class="sidebar" v-if="data.username">
<nav class="mt-2">
<ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false" v-if="area==='default'">
<li class="nav-item">
@ -64,7 +64,7 @@
</router-link>
</li>
<li class="nav-item" v-if="hasPermission('Read-Setting')">
<router-link :key="$route.fullPath" to="/router/shared/index.html?area=admin&entity=Setting" :class="getLinkClass('Setting')">
<router-link :key="$route.fullPath" to="/router/admin/setting/index.html?area=admin&entity=Setting" :class="getLinkClass('Setting')">
<i class="far fa-circle nav-icon"></i>
<p>
配置管理
@ -169,10 +169,10 @@
</router-link>
</li>
<li class="nav-item" v-if="hasPermission('Read-Command')">
<router-link :key="$route.fullPath" to="/router/shared/index.html?area=admin&entity=Command" :class="getLinkClass('Command')">
<router-link :key="$route.fullPath" to="/router/admin/command/index.html?area=admin&entity=Command" :class="getLinkClass('Command')">
<i class="far fa-circle nav-icon"></i>
<p>
命令管理
命令管理
</p>
</router-link>
</li>
@ -367,7 +367,9 @@
methods: {
logout() {
store.commit('logout');
router.push('/router/login.html');
setTimeout(function () {
router.push('/router/login.html');
}, 1000);
},
toggle: function (e) {
$(e.currentTarget).parent('li').toggleClass('menu-open');

Loading…
Cancel
Save