Browse Source

update

pull/1/head
wanggang 1 year ago
parent
commit
0fe9ce4914
  1. 27
      docs/demo/src/WTA.Application/Identity/Data/IdentityDbSeed.cs
  2. 1
      docs/demo/src/WTA.Application/Identity/Entities/SystemManagement/User.cs
  3. 3
      docs/demo/src/WTA.Infrastructure/Resources/zh.json
  4. 4
      docs/demo/src/WTA.Shared/Application/PaginationModel.cs
  5. 6
      docs/demo/src/WTA.Shared/Attributes/NavigationAttribute.cs
  6. 10
      docs/demo/src/WTA.Shared/Controllers/GenericController.cs
  7. 26
      docs/demo/src/WTA.Shared/Controllers/GenericControllerRouteConvention.cs
  8. 9
      docs/demo/src/WTA.Shared/Extensions/JsonSchemaExtensions.cs
  9. 16
      docs/demo/src/WTA.Shared/SignalR/PageHub.cs
  10. 2
      docs/demo/src/WTA.Shared/WebApp.cs
  11. 2
      docs/demo/src/WTA/wwwroot/api/user.js
  12. 17
      docs/demo/src/WTA/wwwroot/components/form/form-input.js
  13. 5
      docs/demo/src/WTA/wwwroot/components/form/form-item.js
  14. 4
      docs/demo/src/WTA/wwwroot/components/list/index.js
  15. 1
      docs/demo/src/WTA/wwwroot/router/index.js

27
docs/demo/src/WTA.Application/Identity/Data/IdentityDbSeed.cs

@ -104,6 +104,7 @@ public class IdentityDbSeed : IDbSeed<IdentityDbContext>
// 用户初始化
var superUser = new User
{
DepartmentId = context.Set<Department>().FirstOrDefault()?.Id,
IsReadonly = true,
UserName = "super",
NormalizedUserName = "super".Normalize(),
@ -140,18 +141,18 @@ public class IdentityDbSeed : IDbSeed<IdentityDbContext>
Order = -3,
}.UpdateId().UpdatePath());
//context.Set<Permission>().Add(new Permission
//{
// IsExternal = true,
// IsReadonly = true,
// Type = PermissionType.Resource,
// Name = "帮助",
// Number = "help",
// Path = "https://element-plus.org/",
// Method = "GET",
// Icon = "ep-link",
// Order = 1000,
//}.UpdateId().UpdatePath());
context.Set<Permission>().Add(new Permission
{
IsExternal = true,
IsReadonly = true,
Type = PermissionType.Resource,
Name = "帮助",
Number = "help",
Path = "https://element-plus.org/",
Method = "GET",
Icon = "ep-link",
Order = 1000,
}.UpdateId().UpdatePath());
WebApp.Current.Assemblies.SelectMany(o => o.GetTypes()).Where(o => o.IsClass && !o.IsAbstract && o.IsAssignableTo(typeof(IResource))).ForEach(resourceType =>
{
@ -196,7 +197,7 @@ public class IdentityDbSeed : IDbSeed<IdentityDbContext>
Path = $"{operation.TrimEnd("Async").ToSlugify()}",
IsHidden = methodInfo.GetCustomAttributes<HiddenAttribute>().Any(),
Method = method,
Icon = methodInfo.GetCustomAttribute<IconAttribute>()?.Icon ?? $"{operation.TrimEnd("Async").ToSlugify()}",
Icon = methodInfo.GetCustomAttribute<IconAttribute>()?.Icon ?? IconAttribute.File,
Order = methodInfo.GetCustomAttribute<OrderAttribute>()?.Order ?? OrderAttribute.Default,
HtmlClass = methodInfo.GetCustomAttribute<HtmlClassAttribute>()?.Class ?? HtmlClassAttribute.Default,
IsTop = methodInfo.GetCustomAttribute<MultipleAttribute>() != null

1
docs/demo/src/WTA.Application/Identity/Entities/SystemManagement/User.cs

@ -27,6 +27,7 @@ public class User : BaseEntity
[Navigation]
public Guid? DepartmentId { get; set; }
[Navigation]
public Guid? PostId { get; set; }
public Department? Department { get; set; }

3
docs/demo/src/WTA.Infrastructure/Resources/zh.json

@ -126,5 +126,6 @@
"ConnectionId": "连接Id",
"IsOnline": "在线",
"Heartbeat": "心跳",
"UserAgent": "用户代理"
"UserAgent": "用户代理",
"PostId": "岗位"
}

4
docs/demo/src/WTA.Shared/Application/PaginationModel.cs

@ -15,8 +15,10 @@ public class PaginationModel<TSearchModel, TListModel>
[DefaultValue(20)]
public int PageSize { get; set; } = 20;
public string? OrderBy { get; set; } = $"{nameof(BaseEntity.Order)},{nameof(BaseEntity.CreatedOn)}";
public int TotalCount { get; set; }
public string? OrderBy { get; set; } = $"{nameof(BaseEntity.Order)},{nameof(BaseEntity.CreatedOn)}";
public List<TListModel> Items { get; set; } = new List<TListModel>();
public bool QueryAll { get; set; }
public TSearchModel Query { get; set; } = Activator.CreateInstance<TSearchModel>();
}

6
docs/demo/src/WTA.Shared/Attributes/NavigationAttribute.cs

@ -3,10 +3,10 @@ namespace WTA.Shared.Attributes;
[AttributeUsage(AttributeTargets.Property)]
public class NavigationAttribute : Attribute
{
public NavigationAttribute(string? path = null)
public NavigationAttribute(string? property = null)
{
this.Path = path;
this.Property = property;
}
public string? Path { get; }
public string? Property { get; }
}

10
docs/demo/src/WTA.Shared/Controllers/GenericController.cs

@ -1,3 +1,4 @@
using DocumentFormat.OpenXml.Bibliography;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
@ -44,7 +45,14 @@ public class GenericController<TEntity, TModel, TListModel, TSearchModel, TImpor
{
query = query.OrderBy(model.OrderBy);
}
query = query.Skip(model.PageSize * (model.PageIndex - 1)).Take(model.PageSize);
if (model.QueryAll)
{
model.PageSize = model.TotalCount;
}
else
{
query = query.Skip(model.PageSize * (model.PageIndex - 1)).Take(model.PageSize);
}
model.Items = query
.ToList()
.Select(o => o.ToObject<TListModel>())

26
docs/demo/src/WTA.Shared/Controllers/GenericControllerRouteConvention.cs

@ -16,19 +16,19 @@ public class GenericControllerRouteConvention : IControllerModelConvention
if (baseControllerType != null)
{
var routeTemplate = $"api/{{culture=zh}}/";
var genericType = baseControllerType.GenericTypeArguments[0];
var groupAttribute = genericType.GetCustomAttributes().FirstOrDefault(o => o.GetType().IsAssignableTo(typeof(GroupAttribute)));
var moduleAttribute = groupAttribute?.GetType().GetCustomAttributes()
.Where(o => o.GetType().IsGenericType && o.GetType().GetGenericTypeDefinition() == typeof(ModuleAttribute<>))
.Select(o => o as ITypeAttribute).Select(o => o?.Type).FirstOrDefault();
if (moduleAttribute != null)
{
routeTemplate += $"{moduleAttribute.Name.TrimEnd("Module").ToSlugify()}/";
}
if (groupAttribute != null)
{
routeTemplate += $"{groupAttribute.GetType().Name.TrimEnd("Attribute").ToSlugify()}/";
}
//var genericType = baseControllerType.GenericTypeArguments[0];
//var groupAttribute = genericType.GetCustomAttributes().FirstOrDefault(o => o.GetType().IsAssignableTo(typeof(GroupAttribute)));
//var moduleAttribute = groupAttribute?.GetType().GetCustomAttributes()
// .Where(o => o.GetType().IsGenericType && o.GetType().GetGenericTypeDefinition() == typeof(ModuleAttribute<>))
// .Select(o => o as ITypeAttribute).Select(o => o?.Type).FirstOrDefault();
//if (moduleAttribute != null)
//{
// routeTemplate += $"{moduleAttribute.Name.TrimEnd("Module").ToSlugify()}/";
//}
//if (groupAttribute != null)
//{
// routeTemplate += $"{groupAttribute.GetType().Name.TrimEnd("Attribute").ToSlugify()}/";
//}
routeTemplate += "[controller]/[action]";
controller.Selectors.Add(new SelectorModel
{

9
docs/demo/src/WTA.Shared/Extensions/JsonSchemaExtensions.cs

@ -67,7 +67,6 @@ public static class JsonSchemaExtensions
{
schema.Add("type", "array");
schema.TryAdd("multiple", true);
schema.TryAdd("url", "url");
schema.Add("items", meta.ElementMetadata.GetSchema(serviceProvider, meta));
}
}
@ -132,6 +131,10 @@ public static class JsonSchemaExtensions
schema.AddNotNull("description", meta.Description);
schema.AddNotNull("format", meta.DataTypeName?.ToLowerCamelCase());
schema.AddNotNull("input", meta.TemplateHint?.ToLowerCamelCase());
if(meta.TemplateHint=="select"&&meta.IsEnumerableType&& modelType.IsGenericType)
{
schema.TryAdd("url", modelType.GetGenericArguments().First().Name.ToSlugify());
}
if (meta is DefaultModelMetadata defaultModelMetadata)
{
@ -144,9 +147,11 @@ public static class JsonSchemaExtensions
}
if (defaultModelMetadata.Attributes.Attributes.FirstOrDefault(o => o.GetType() == typeof(NavigationAttribute)) is NavigationAttribute navigationAttribute)
{
var path = navigationAttribute.Path ?? $"{propertyName[..^2]}.Name";
var path = navigationAttribute.Property ?? $"{propertyName[..^2]}.Name";
path = string.Join('.', path.Split('.').Select(o => o.ToLowerCamelCase()));
schema.Add("navigation", path);
schema.Add("input", "select");
schema.Add("url", propertyName[..^2].ToSlugify());
}
if (defaultModelMetadata.Attributes.Attributes.FirstOrDefault(o => o.GetType() == typeof(ScaffoldColumnAttribute)) is ScaffoldColumnAttribute scaffoldColumnAttribute
&& !scaffoldColumnAttribute.Scaffold)

16
docs/demo/src/WTA.Shared/SignalR/PageHub.cs

@ -43,14 +43,14 @@ public class PageHub : Hub
Login = DateTime.UtcNow,
UserAgent = httpContext?.Request.Headers["User-Agent"]
});
this.Context.Features.Get<IConnectionHeartbeatFeature>()?.OnHeartbeat(o =>
{
if (DateTime.Now.Second % 15 == 0)
{
using var scope = WebApp.Current.Services.CreateScope();
scope.ServiceProvider.GetService<IEventPublisher>()?.Publish(new SignalRHeartbeatEvent { ConnectionId = o?.ToString()! });
}
}, this.Context.ConnectionId);
//this.Context.Features.Get<IConnectionHeartbeatFeature>()?.OnHeartbeat(o =>
//{
// if (DateTime.Now.Second % 15 == 0)
// {
// using var scope = WebApp.Current.Services.CreateScope();
// scope.ServiceProvider.GetService<IEventPublisher>()?.Publish(new SignalRHeartbeatEvent { ConnectionId = o?.ToString()! });
// }
//}, this.Context.ConnectionId);
}
return base.OnConnectedAsync();
}

2
docs/demo/src/WTA.Shared/WebApp.cs

@ -182,7 +182,7 @@ public class WebApp
{
if (scope.ServiceProvider.GetService(serviceType) is IJobService jobService)
{
scheduler.Schedule(() => jobService.Invoke()).Cron(cron);
//scheduler.Schedule(() => jobService.Invoke()).Cron(cron);
}
}
}

2
docs/demo/src/WTA/wwwroot/api/user.js

@ -64,7 +64,7 @@ const logout = () => {
};
const getUser = async () => {
const result = await post("system-management/user/info");
const result = await post("user/info");
const user = result.data;
user.roles = Enumerable.from(user.userRoles)
.select((o) => o.role)

17
docs/demo/src/WTA/wwwroot/components/form/form-input.js

@ -1,6 +1,7 @@
import html from "html";
import { ref, reactive, watch } from "vue";
import { dayjs } from "element-plus";
import { post } from "../../request/index.js";
export default {
template: html`
@ -20,8 +21,9 @@ export default {
:multiple="!!schema.multiple"
clearable
style="width:100%"
:title="JSON.stringify(options)"
>
<el-option v-for="item in schema.options" :key="item.value" :label="item.label" :value="item.value" />
<el-option v-for="item in options" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</template>
<el-input
@ -83,11 +85,24 @@ export default {
return schema.input ?? schema.type;
};
/*end*/
const options = ref([]);
if (props.schema.options) {
options.value = props.schema.options;
} else if (props.schema.url) {
try {
const url = `${props.schema.url}/index`;
const result = await post(url, { queryAll: true });
options.value = result.data?.items;
} catch (error) {
console.log(error);
}
}
return {
model,
getDisabled,
getInput,
dayjs,
options,
};
},
};

5
docs/demo/src/WTA/wwwroot/components/form/form-item.js

@ -8,9 +8,9 @@ export default {
template: html`
<template v-if="showItem()">
<template v-if="schema.type==='object'"></template>
<template v-if="schema.type!=='array'||(schema.items.type!=='object'&&schema.items.type!=='array')"> </template>
<template v-else-if="schema.type!=='array'||schema.items.type!=='array'">
<el-form-item
:title="getProp(prop)"
:title="schema.type"
:label="schema.title"
:prop="getProp(prop)"
:rules="getRules(parentSchema,schema,model)"
@ -19,6 +19,7 @@ export default {
<app-form-input :schema="schema" :prop="prop" v-model="model" :isReadOnly="mode==='details'" />
</el-form-item>
</template>
</template>
</template>
`,
props: ["modelValue", "mode", "parentSchema", "schema", "prop", "errors"],

4
docs/demo/src/WTA/wwwroot/components/list/index.js

@ -2,7 +2,7 @@ import html, { getProp } from "html";
import AppForm from "../form/index.js";
import { get, post } from "../../request/index.js";
import { ref, reactive } from "vue";
import { useRoute } from "vue-router";
import { useRoute, useRouter } from "vue-router";
import { useI18n } from "vue-i18n";
import SvgIcon from "../../components/icon/index.js";
import { schemaToModel } from "../../utils/index.js";
@ -196,7 +196,7 @@ export default {
const dialogVisible = ref(false);
const route = useRoute();
const { t } = useI18n();
const baseUrl = `${route.meta.path}`.substring(1);
const baseUrl = `${route.meta.controller}`;
const indexUrl = `${baseUrl}/index`;
const vm = (await get(indexUrl)).data;
const schema = vm.schema;

1
docs/demo/src/WTA/wwwroot/router/index.js

@ -95,6 +95,7 @@ const reset = (list, parent = null) => {
if (o.type === "Resource") {
item.component = import(`../views/${o.component ? o.component : "list"}.js`);
}
item.meta.controller = item.path;
item.meta.path = `${parent === null ? "/" : parent.meta.path + "/"}${item.path}`;
item.meta.fullName = `${parent === null ? "" : parent.meta.title + " > "}${item.meta.title}`;
if (o.type === "Resource") {

Loading…
Cancel
Save