Browse Source

Merge pull request #160 from colinin/3.3

The last release of ABP Framework 3.3 was updated
pull/177/head 3.3.2
cKey 5 years ago
committed by GitHub
parent
commit
8b9c97d0a6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      aspnet-core/database/ApiGateway-Init-SqlServer.sql
  2. 7
      aspnet-core/database/ApiGateway-Init.sql
  3. 4
      aspnet-core/modules/platform/LINGYUN.Platform.Domain.Shared/LINGYUN/Platform/Datas/ValueType.cs
  4. 3
      aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Datas/DataItem.cs
  5. 12
      aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Datas/DataItemMappingOptions.cs
  6. 4
      aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/PlatformDataSeedContributor.cs
  7. 10
      aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/EntityFrameworkCore/PlatformEfCoreQueryableExtensions.cs
  8. 5
      aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/Menus/EfCoreMenuRepository.cs
  9. BIN
      aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/event-bus-cap.db
  10. 4
      aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/AppPlatformHttpApiHostModule.cs
  11. 2
      aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj
  12. 3
      vueJs/src/api/data-dictionary.ts
  13. 24
      vueJs/src/api/menu.ts
  14. 102
      vueJs/src/components/InputObject/index.vue
  15. 11
      vueJs/src/layout/components/TagsView/index.vue
  16. 6
      vueJs/src/views/admin/data-dictionary/components/CreateOrUpdateDataItemDialog.vue
  17. 12
      vueJs/src/views/admin/data-dictionary/components/DataDictionaryTree.vue
  18. 2
      vueJs/src/views/admin/data-dictionary/components/DataItemTable.vue
  19. 17
      vueJs/src/views/admin/roles/components/ManageRoleMenuDialog.vue
  20. 172
      vueJs/src/views/admin/users/components/ManageUserMenuDialog.vue
  21. 43
      vueJs/src/views/admin/users/index.vue
  22. 41
      vueJs/src/views/container/menus/components/CreateOrUpdateMenuDialog.vue
  23. 19
      vueJs/src/views/container/menus/components/MenuMetaInput.vue

8
aspnet-core/database/ApiGateway-Init-SqlServer.sql

File diff suppressed because one or more lines are too long

7
aspnet-core/database/ApiGateway-Init.sql

@ -11,7 +11,7 @@
Target Server Version : 80020
File Encoding : 65001
Date: 21/12/2020 18:32:50
Date: 22/12/2020 14:45:05
*/
SET NAMES utf8mb4;
@ -521,7 +521,7 @@ INSERT INTO `appapigatewaycacheoptions` VALUES (131, 1310515735292985344, NULL,
INSERT INTO `appapigatewaycacheoptions` VALUES (132, 1316628769783480320, 0, '');
INSERT INTO `appapigatewaycacheoptions` VALUES (133, 1316628940663619584, 0, '');
INSERT INTO `appapigatewaycacheoptions` VALUES (134, 1316629112428756992, 0, '');
INSERT INTO `appapigatewaycacheoptions` VALUES (135, 1316652047017246720, 0, '');
INSERT INTO `appapigatewaycacheoptions` VALUES (135, 1316652047017246720, NULL, NULL);
INSERT INTO `appapigatewaycacheoptions` VALUES (136, 1316913899996737536, 0, '');
INSERT INTO `appapigatewaycacheoptions` VALUES (137, 1319200951383199744, 0, '');
INSERT INTO `appapigatewaycacheoptions` VALUES (138, 1319221929807024128, 0, '');
@ -1313,7 +1313,7 @@ INSERT INTO `appapigatewayreroute` VALUES (138, '{}', 'c3ebc82d55f640fb9d70a911e
INSERT INTO `appapigatewayreroute` VALUES (139, '{}', '0379fcb3a9cd4b13b562b3b5b5c3eb7d', 1316628769783480320, '【身份认证服务】- 声明类型', '/api/identity/claim-types', '', '', '/api/identity/claim-types', 'GET,POST,', '', '', '', '', '', '', '', 1, '', '', 'HTTP', '127.0.0.1:30015,', '', '', '', 0, 30000, 1, '', 'TEST-APP');
INSERT INTO `appapigatewayreroute` VALUES (140, '{}', 'de25c9a80d994f728b37eb483b2f5127', 1316628940663619584, '【身份认证服务】- 管理声明类型', '/api/identity/claim-types/{id}', '', '', '/api/identity/claim-types/{id}', 'GET,PUT,DELETE,', '', '', '', '', '', '', '', 1, '', '', 'HTTP', '127.0.0.1:30015,', '', '', '', 0, 30000, 1, '', 'TEST-APP');
INSERT INTO `appapigatewayreroute` VALUES (141, '{}', '25c19106baff4cf3a877ae8cd690a1b5', 1316629112428756992, '【身份认证服务】- 查询在用的声明类型列表', '/api/identity/claim-types/actived-list', '', '', '/api/identity/claim-types/actived-list', 'GET,', '', '', '', '', '', '', '', 1, '', '', 'HTTP', '127.0.0.1:30015,', '', '', '', 0, 30000, 1, '', 'TEST-APP');
INSERT INTO `appapigatewayreroute` VALUES (142, '{}', 'd42f8b779cf344eeaa24df0ae37fb7cf', 1316652047017246720, '【身份认证服务】- 管理用户声明', '/api/identity/users/claims/{id}', '', '', '/api/identity/users/claims/{id}', 'POST,PUT,DELETE,GET,', '', '', '', '', '', '', '', 1, '', '', 'HTTP', '127.0.0.1:30015,', '', '', '', 0, 30000, 1, '', 'TEST-APP');
INSERT INTO `appapigatewayreroute` VALUES (142, '{}', '7d3b941d8c4d4d3ebc05b6332308b992', 1316652047017246720, '【身份认证服务】- 管理用户声明', '/api/identity/users/{id}/claims', '', '', '/api/identity/users/{id}/claims', 'POST,PUT,DELETE,GET,', '', '', '', '', '', '', '', 1, '', '', 'HTTP', '127.0.0.1:30015,', '', '', '', 0, 30000, 1, '', 'TEST-APP');
INSERT INTO `appapigatewayreroute` VALUES (143, '{}', 'b86af44a34a14db4b482df8550f1bde1', 1316913899996737536, '【身份认证管理】- 管理角色声明', '/api/identity/roles/claims/{id}', '', '', '/api/identity/roles/claims/{id}', 'GET,POST,PUT,DELETE,', '', '', '', '', '', '', '', 1, '', '', 'HTTP', '127.0.0.1:30015,', '', '', '', 0, 30000, 1, '', 'TEST-APP');
INSERT INTO `appapigatewayreroute` VALUES (144, '{}', '51a14bc295044de985ae014fbcc5bddf', 1319200951383199744, '【IdentityServer4】- 发现端点', '/.well-known/openid-configuration', '', '', '/.well-known/openid-configuration', 'GET,', '', '', '', '', '', '', '', 1, '', '', 'HTTP', '127.0.0.1:44385,', '', '', '', 0, 30000, 1, '', 'TEST-APP');
INSERT INTO `appapigatewayreroute` VALUES (145, '{}', '9d859a444d774e93818237e53b6cc102', 1319221929807024128, '【身份认证服务】- 查询所有组织机构', '/api/identity/organization-units/all', '', '', '/api/identity/organization-units/all', 'GET,', '', '', '', '', '', '', '', 1, '', '', 'HTTP', '127.0.0.1:30015,', '', '', '', 0, 30000, 1, '', 'TEST-APP');
@ -1565,6 +1565,7 @@ CREATE TABLE `cap.published` (
-- Records of cap.published
-- ----------------------------
INSERT INTO `cap.published` VALUES (1340961909189136384, 'v1', 'LINGYUN.ApiGateway.EventBus.ApigatewayConfigChangeEventData', '{\"Headers\":{\"cap-callback-name\":null,\"cap-msg-id\":\"1340961909189136384\",\"cap-msg-name\":\"LINGYUN.ApiGateway.EventBus.ApigatewayConfigChangeEventData\",\"cap-msg-type\":\"Object\",\"cap-senttime\":\"2020/12/21 18:06:47 +08:00\",\"cap-corr-id\":\"1340961909189136384\",\"cap-corr-seq\":\"0\"},\"Value\":{\"DateTime\":\"2020-12-21T18:06:47.6668667+08:00\",\"AppId\":\"TEST-APP\",\"Method\":\"Create\",\"Object\":\"ReRoute\"}}', 0, '2020-12-21 18:06:48', '2020-12-22 18:06:48', 'Succeeded');
INSERT INTO `cap.published` VALUES (1341265150657449984, 'v1', 'LINGYUN.ApiGateway.EventBus.ApigatewayConfigChangeEventData', '{\"Headers\":{\"cap-callback-name\":null,\"cap-msg-id\":\"1341265150657449984\",\"cap-msg-name\":\"LINGYUN.ApiGateway.EventBus.ApigatewayConfigChangeEventData\",\"cap-msg-type\":\"Object\",\"cap-senttime\":\"2020/12/22 14:11:46 +08:00\",\"cap-corr-id\":\"1341265150657449984\",\"cap-corr-seq\":\"0\"},\"Value\":{\"DateTime\":\"2020-12-22T14:11:46.0753073+08:00\",\"AppId\":\"TEST-APP\",\"Method\":\"Modify\",\"Object\":\"ReRoute\"}}', 0, '2020-12-22 14:11:46', '2020-12-23 14:11:46', 'Succeeded');
-- ----------------------------
-- Table structure for cap.received

4
aspnet-core/modules/platform/LINGYUN.Platform.Domain.Shared/LINGYUN/Platform/Datas/ValueType.cs

@ -7,7 +7,7 @@
Boolean = 2,
Date = 3,
DateTime = 4,
Array = 5
Array = 5,
Object = 6
}
}

3
aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Datas/DataItem.cs

@ -78,6 +78,9 @@ namespace LINGYUN.Platform.Datas
case ValueType.Numeic:
DefaultValue = "0";
break;
case ValueType.Object:
DefaultValue = "{}";
break;
default:
case ValueType.String:
DefaultValue = "";

12
aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Datas/DataItemMappingOptions.cs

@ -1,4 +1,5 @@
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using Volo.Abp;
@ -90,6 +91,15 @@ namespace LINGYUN.Platform.Datas
}
return value.ToString();
});
SetMapping(ValueType.Object, value =>
{
if (value == null)
{
return "{}";
}
return JsonConvert.SerializeObject(value);
});
}
public void SetMapping(ValueType valueType, Func<object, string> func)

4
aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/PlatformDataSeedContributor.cs

@ -281,9 +281,9 @@ namespace LINGYUN.Platform
"claim-type",
CodeNumberGenerator.AppendCode(adminMenu.Code, CodeNumberGenerator.CreateCode(4)),
"views/admin/claim-type/index.vue",
"Manage Organization Units",
"Manage Claim Types",
"",
"Manage Organization Units",
"Manage Claim Types",
adminMenu.Id,
layout.TenantId,
new Dictionary<string, object>()

10
aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/EntityFrameworkCore/PlatformEfCoreQueryableExtensions.cs

@ -19,6 +19,16 @@ namespace LINGYUN.Platform.EntityFrameworkCore
return queryable;
}
public static IQueryable<Menu> IncludeDetails(this IQueryable<Menu> queryable, bool include = true)
{
if (!include)
{
return queryable;
}
return queryable;
}
public static IQueryable<Data> IncludeDetails(this IQueryable<Data> queryable, bool include = true)
{
if (!include)

5
aspnet-core/modules/platform/LINGYUN.Platform.EntityFrameworkCore/LINGYUN/Platform/Menus/EfCoreMenuRepository.cs

@ -234,5 +234,10 @@ namespace LINGYUN.Platform.Menus
DbContext.Set<UserMenu>().RemoveRange(membersQuery);
}
public override IQueryable<Menu> WithDetails()
{
return GetQueryable().IncludeDetails();
}
}
}

BIN
aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/event-bus-cap.db

Binary file not shown.

4
aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/AppPlatformHttpApiHostModule.cs

@ -46,7 +46,7 @@ using Volo.Abp.SettingManagement.EntityFrameworkCore;
using Volo.Abp.TenantManagement.EntityFrameworkCore;
using Volo.Abp.Threading;
using Volo.Abp.VirtualFileSystem;
using Volo.Abp.Http.Client.IdentityModel;
using Volo.Abp.Http.Client.IdentityModel.Web;
namespace LINGYUN.Platform
{
@ -57,7 +57,7 @@ namespace LINGYUN.Platform
typeof(PlatformHttpApiModule),
typeof(PlatformEntityFrameworkCoreModule),
typeof(AbpIdentityHttpApiClientModule),
typeof(AbpHttpClientIdentityModelModule),
typeof(AbpHttpClientIdentityModelWebModule),
typeof(AbpAspNetCoreMultiTenancyModule),
typeof(AbpFeatureManagementEntityFrameworkCoreModule),
typeof(AbpAuditLoggingEntityFrameworkCoreModule),

2
aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj

@ -41,7 +41,7 @@
<PackageReference Include="Volo.Abp.Autofac" Version="3.3.0" />
<PackageReference Include="Volo.Abp.BlobStoring.FileSystem" Version="3.3.0" />
<PackageReference Include="Volo.Abp.Identity.HttpApi.Client" Version="3.3.0" />
<PackageReference Include="Volo.Abp.Http.Client.IdentityModel" Version="3.3.0" />
<PackageReference Include="Volo.Abp.Http.Client.IdentityModel.Web" Version="3.3.0" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore.MySQL" Version="3.3.0" />
<PackageReference Include="Volo.Abp.AuditLogging.EntityFrameworkCore" Version="3.3.0" />
<PackageReference Include="Volo.Abp.FeatureManagement.EntityFrameworkCore" Version="3.3.0" />

3
vueJs/src/api/data-dictionary.ts

@ -59,7 +59,8 @@ export enum ValueType {
Boolean = 2,
Date = 3,
DateTime = 4,
Array = 5
Array = 5,
Object = 6
}
export class DataItem {

24
vueJs/src/api/menu.ts

@ -29,8 +29,13 @@ export default class MenuService {
return ApiService.Get<ListResultDto<Menu>>(_url, serviceUrl)
}
public static getRoleMenuList(payload: GetRoleMenu) {
const _url = sourceUrl + '/by-role?' + urlStringify(payload)
public static getRoleMenuList(role: string, platformType: PlatformType) {
const _url = sourceUrl + `/by-role/${role}/${platformType}`
return ApiService.Get<ListResultDto<Menu>>(_url, serviceUrl)
}
public static getUserMenuList(userId: string, platformType: PlatformType) {
const _url = sourceUrl + `/by-user/${userId}/${platformType}`
return ApiService.Get<ListResultDto<Menu>>(_url, serviceUrl)
}
@ -52,6 +57,11 @@ export default class MenuService {
const _url = sourceUrl + '/by-role'
return ApiService.Put<void>(_url, payload,serviceUrl)
}
public static setUserMenu(payload: UserMenu) {
const _url = sourceUrl + '/by-user'
return ApiService.Put<void>(_url, payload,serviceUrl)
}
}
export class MenuCreateOrUpdate {
@ -84,11 +94,6 @@ export class GetAllMenu implements ISortedResultRequest {
platformType?: PlatformType
}
export class GetRoleMenu {
role!: string
platformType!: PlatformType
}
export class GetMenuByPaged extends PagedAndSortedResultRequestDto {
filter = ''
reverse = false
@ -111,3 +116,8 @@ export class RoleMenu {
roleName!: string
menuIds = new Array<string>()
}
export class UserMenu {
userId!: string
menuIds = new Array<string>()
}

102
vueJs/src/components/InputObject/index.vue

@ -0,0 +1,102 @@
<template>
<div>
<el-row
v-for="(key, index) in Object.keys(objectValue)"
:key="index"
style="margin-bottom: 10px;"
>
<el-col :span="10">
<span style="width: 30%;">名称</span>
<el-input
:value="key"
style="width: 80%;margin-left: 10px;"
/>
</el-col>
<el-col :span="10">
<span style="width: 30%;"></span>
<el-input
:value="value[key]"
style="width: 87%;margin-left: 10px;"
/>
</el-col>
<el-col :span="4">
<el-button
type="danger"
icon="el-icon-delete"
style="width: 100%;"
@click="onItemDeleted(key)"
>
删除项目
</el-button>
</el-col>
</el-row>
<el-row style="margin-top: 10px;">
<el-col :span="10">
<span style="width: 30%;">名称</span>
<el-input
v-model="newItemName"
style="width: 80%;margin-left: 10px;"
/>
</el-col>
<el-col :span="10">
<span style="width: 30%;"></span>
<el-input
v-model="newItemValue"
style="width: 87%;margin-left: 10px;"
/>
</el-col>
<el-col :span="4">
<el-button
type="success"
style="width: 100%;"
@click="onItemAdded(newItemName, newItemValue)"
>
<i class="ivu-icon ivu-icon-md-add" />
添加项目
</el-button>
</el-col>
</el-row>
</div>
</template>
<script lang="ts">
import { Component, Vue, Prop } from 'vue-property-decorator'
@Component({
name: 'InputObject'
})
export default class extends Vue {
@Prop({ default: () => { return {} } })
private value!: object
private newItemName = ''
private newItemValue = ''
get objectValue() {
if (this.value) {
return this.value
}
return {}
}
onItemAdded(key: string, value: any) {
if (key && value) {
let added: {[key: string]: any} = {}
added = Object.assign(this.objectValue, added)
added[key] = value
console.log(added)
this.$emit('input', added)
this.newItemName = ''
this.newItemValue = ''
}
}
onItemDeleted(key: string) {
let changed: {[key: string]: any} = {}
changed = Object.assign(this.objectValue, changed)
delete changed[key]
this.$emit('input', changed)
this.$forceUpdate()
}
}
</script>

11
vueJs/src/layout/components/TagsView/index.vue

@ -18,7 +18,7 @@
@click.middle.native="!isAffix(tag)?closeSelectedTag(tag):''"
@contextmenu.prevent.native="openMenu(tag, $event)"
>
{{ $t('route.' + tag.meta.title) }}
{{ routeTitle(tag) }}
<span
v-if="!isAffix(tag)"
class="el-icon-close"
@ -80,6 +80,15 @@ export default class extends Vue {
return PermissionModule.routes
}
get routeTitle() {
return (route: any) => {
if (route.meta.displayName) {
return route.meta.displayName
}
return this.$t('route.' + route.meta.title)
}
}
@Watch('$route')
private onRouteChange() {
this.addTags()

6
vueJs/src/views/admin/data-dictionary/components/CreateOrUpdateDataItemDialog.vue

@ -26,6 +26,7 @@
>
<el-input
v-model="dataItem.name"
:disabled="isEdit"
/>
</el-form-item>
<el-form-item
@ -85,6 +86,11 @@
label="Array"
:value="5"
/>
<el-option
key="Object"
label="Object"
:value="6"
/>
</el-select>
</el-form-item>
<el-form-item

12
vueJs/src/views/admin/data-dictionary/components/DataDictionaryTree.vue

@ -10,7 +10,7 @@
style="float: right;"
type="primary"
icon="ivu-icon ivu-icon-md-add"
@click="handleEditData"
@click="handleEditData('')"
>
{{ $t('AppPlatform.Data:AddNew') }}
</el-button>
@ -99,7 +99,7 @@ export default class DataDictionaryTree extends Vue {
icon: 'el-icon-edit',
disabled: !checkPermission(['Platform.DataDictionary.Update']),
onClick: () => {
this.handleEditData(data)
this.handleEditData(data.id)
}
},
{
@ -107,7 +107,7 @@ export default class DataDictionaryTree extends Vue {
icon: 'ivu-icon ivu-icon-md-add',
disabled: !checkPermission(['Platform.DataDictionary.Create']),
onClick: () => {
this.handleEditData()
this.handleEditData('')
}
},
{
@ -152,11 +152,11 @@ export default class DataDictionaryTree extends Vue {
}
}
private handleEditData(data?: Data) {
private handleEditData(dataId: string) {
this.editDataTitle = this.l('AppPlatform.Data:AddNew')
this.isEditData = false
if (data) {
this.editDataId = data.id
if (dataId) {
this.editDataId = dataId
this.isEditData = true
this.editDataTitle = this.l('AppPlatform.Data:Edit')
} else {

2
vueJs/src/views/admin/data-dictionary/components/DataItemTable.vue

@ -141,6 +141,8 @@ import CreateOrUpdateDataItemDialog from './CreateOrUpdateDataItemDialog.vue'
return 'DateTime'
case ValueType.Array:
return 'Array'
case ValueType.Object:
return 'Object'
default:
case ValueType.String:
return 'String'

17
vueJs/src/views/admin/roles/components/ManageRoleMenuDialog.vue

@ -2,6 +2,7 @@
<el-dialog
v-el-draggable-dialog
width="800px"
:title="$t('AppPlatform.Menu:Manage')"
:visible="showDialog"
custom-class="modal-form"
:close-on-click-modal="false"
@ -72,9 +73,9 @@
<script lang="ts">
import { Component, Vue, Prop, Watch } from 'vue-property-decorator'
import MenuService, { Menu, GetAllMenu, GetRoleMenu, RoleMenu } from '@/api/menu'
import MenuService, { Menu, GetAllMenu, RoleMenu } from '@/api/menu'
import { generateTree } from '@/utils'
import { PlatformTypes } from '@/api/layout'
import { PlatformType, PlatformTypes } from '@/api/layout'
import { Tree } from 'element-ui'
@Component({
@ -90,7 +91,6 @@ export default class ManageRoleMenuDialog extends Vue {
private menus = new Array<Menu>()
private roleMenuIds = new Array<string>()
private getMenuQuery = new GetAllMenu()
private getRoleMenuQuery = new GetRoleMenu()
private platformTypes = PlatformTypes
private confirmButtonBusy = false
private menuProps = {
@ -110,9 +110,9 @@ export default class ManageRoleMenuDialog extends Vue {
this.handleGetRoleMenus()
}
private onPlatformTypeChanged(value: any) {
this.getRoleMenuQuery.platformType = value
private onPlatformTypeChanged() {
this.handleGetMenus()
this.handleGetRoleMenus()
}
private handleGetMenus() {
@ -125,9 +125,8 @@ export default class ManageRoleMenuDialog extends Vue {
private handleGetRoleMenus() {
if (this.showDialog && this.roleName) {
this.getRoleMenuQuery.role = this.roleName
MenuService
.getRoleMenuList(this.getRoleMenuQuery)
.getRoleMenuList(this.roleName, this.getMenuQuery.platformType || PlatformType.None)
.then(res => {
this.roleMenuIds = res.items.map(item => item.id)
})
@ -150,6 +149,10 @@ export default class ManageRoleMenuDialog extends Vue {
}
private onFormClosed() {
this.$nextTick(() => {
const tree = this.$refs.roleMenuTree as Tree
tree.setCheckedKeys([])
})
this.$emit('closed')
}
}

172
vueJs/src/views/admin/users/components/ManageUserMenuDialog.vue

@ -0,0 +1,172 @@
<template>
<el-dialog
v-el-draggable-dialog
width="800px"
:title="$t('AppPlatform.Menu:Manage')"
:visible="showDialog"
custom-class="modal-form"
:close-on-click-modal="false"
:close-on-press-escape="false"
:show-close="false"
@close="onFormClosed"
>
<el-form>
<el-card>
<el-form-item
label-width="120px"
:label="$t('AppPlatform.DisplayName:PlatformType')"
>
<el-select
v-model="getMenuQuery.platformType"
style="width: 100%;"
class="filter-item"
clearable
:placeholder="$t('pleaseSelectBy', {name: $t('AppPlatform.DisplayName:PlatformType')})"
@change="onPlatformTypeChanged"
>
<el-option
v-for="item in platformTypes"
:key="item.key"
:label="item.key"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item
label-width="120px"
:label="$t('AppPlatform.DisplayName:Menus')"
>
<el-tree
ref="userMenuTree"
show-checkbox
:check-strictly="true"
node-key="id"
:data="menus"
:props="menuProps"
:default-checked-keys="userMenuIds"
/>
</el-form-item>
</el-card>
<el-form-item>
<el-button
class="cancel"
type="info"
style="width:100px"
@click="onFormClosed"
>
{{ $t('AbpUi.Cancel') }}
</el-button>
<el-button
class="confirm"
type="primary"
style="width:100px"
icon="el-icon-check"
:loading="confirmButtonBusy"
@click="onSave"
>
{{ confirmButtonTitle }}
</el-button>
</el-form-item>
</el-form>
</el-dialog>
</template>
<script lang="ts">
import { Component, Vue, Prop, Watch } from 'vue-property-decorator'
import MenuService, { Menu, GetAllMenu, UserMenu } from '@/api/menu'
import { generateTree } from '@/utils'
import { PlatformType, PlatformTypes } from '@/api/layout'
import { Tree } from 'element-ui'
@Component({
name: 'ManageUserMenuDialog'
})
export default class ManageUserMenuDialog extends Vue {
@Prop({ default: false })
private showDialog!: boolean
@Prop({ default: '' })
private userId!: string
private menus = new Array<Menu>()
private userMenuIds = new Array<string>()
private getMenuQuery = new GetAllMenu()
private platformTypes = PlatformTypes
private confirmButtonBusy = false
private menuProps = {
children: 'children',
label: 'displayName'
}
get confirmButtonTitle() {
if (this.confirmButtonBusy) {
return this.$t('AbpUi.SavingWithThreeDot')
}
return this.$t('AbpUi.Save')
}
@Watch('showDialog', { immediate: true })
private onShowDialogChanged() {
this.handleGetUserMenus()
}
private onPlatformTypeChanged() {
this.handleGetMenus()
this.handleGetUserMenus()
}
private handleGetMenus() {
MenuService
.getAll(this.getMenuQuery)
.then(res => {
this.menus = generateTree(res.items)
})
}
private handleGetUserMenus() {
if (this.showDialog && this.userId) {
MenuService
.getUserMenuList(this.userId, this.getMenuQuery.platformType || PlatformType.None)
.then(res => {
this.userMenuIds = res.items.map(item => item.id)
})
} else {
this.userMenuIds.length = 0
}
}
private onSave() {
const userMenuTree = this.$refs.userMenuTree as Tree
const userMenu = new UserMenu()
userMenu.userId = this.userId
userMenu.menuIds = userMenuTree.getCheckedKeys()
MenuService
.setUserMenu(userMenu)
.then(() => {
this.$message.success(this.$t('successful').toString())
this.onFormClosed()
})
}
private onFormClosed() {
this.$nextTick(() => {
const tree = this.$refs.userMenuTree as Tree
tree.setCheckedKeys([])
})
this.$emit('closed')
}
}
</script>
<style lang="scss" scoped>
.confirm {
position: absolute;
margin-top: 10px;
right: 0px;
}
.cancel {
position: absolute;
margin-top: 10px;
right: 120px;
}
</style>

43
vueJs/src/views/admin/users/index.vue

@ -116,10 +116,19 @@
<el-table-column
:label="$t('AbpIdentity.Actions')"
align="center"
width="120px"
fixed="right"
width="250px"
min-width="250px"
>
<template slot-scope="{row}">
<el-button
:disabled="!checkPermission(['AbpIdentity.Users.Update'])"
size="mini"
type="primary"
icon="el-icon-edit"
@click="handleShowUserDialog(row.id)"
>
{{ $t('AbpIdentity.Edit') }}
</el-button>
<el-dropdown
class="options"
@command="handleCommand"
@ -127,17 +136,11 @@
<el-button
v-permission="['AbpIdentity.Users']"
size="mini"
type="primary"
type="info"
>
{{ $t('AbpIdentity.Actions') }}<i class="el-icon-arrow-down el-icon--right" />
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
:command="{key: 'edit', row}"
:disabled="!checkPermission(['AbpIdentity.Users.Update'])"
>
{{ $t('AbpIdentity.Edit') }}
</el-dropdown-item>
<el-dropdown-item
:command="{key: 'permission', row}"
:disabled="!checkPermission(['AbpIdentity.Users.ManagePermissions'])"
@ -156,6 +159,12 @@
>
{{ $t('AbpIdentity.ManageClaim') }}
</el-dropdown-item>
<el-dropdown-item
:command="{key: 'menu', row}"
:disabled="!checkPermission(['Platform.Menu.ManageUsers'])"
>
{{ $t('AppPlatform.Menu:Manage') }}
</el-dropdown-item>
<el-dropdown-item
divided
:command="{key: 'delete', row}"
@ -189,6 +198,12 @@
@closed="onClaimDialogClosed"
/>
<manage-user-menu-dialog
:show-dialog="showManageUserMenuDialog"
:user-id="editUserId"
@closed="showManageUserMenuDialog=false"
/>
<permission-form
provider-name="U"
:provider-key="editUserId"
@ -207,6 +222,7 @@ import Component, { mixins } from 'vue-class-component'
import UserApiService, { User, UsersGetPagedDto } from '@/api/users'
import Pagination from '@/components/Pagination/index.vue'
import PermissionForm from '@/components/PermissionForm/index.vue'
import ManageUserMenuDialog from './components/ManageUserMenuDialog.vue'
import UserCreateOrUpdateForm from './components/UserCreateOrUpdateForm.vue'
import UserClaimCreateOrUpdateForm from './components/UserClaimCreateOrUpdateForm.vue'
import { dateFormat, abpPagerFormat } from '@/utils'
@ -217,6 +233,7 @@ import { checkPermission } from '@/utils/permission'
components: {
Pagination,
PermissionForm,
ManageUserMenuDialog,
UserCreateOrUpdateForm,
UserClaimCreateOrUpdateForm
},
@ -238,6 +255,7 @@ export default class extends mixins(DataListMiXin, EventBusMiXin) {
private showUserDialog = false
private showClaimDialog = false
private showPermissionDialog = false
private showManageUserMenuDialog = false
get allowedEditPermission() {
return this.editUserId !== UserModule.id && checkPermission(['AbpIdentity.Users.ManagePermissions'])
@ -302,12 +320,13 @@ export default class extends mixins(DataListMiXin, EventBusMiXin) {
/** 响应更多操作命令 */
private handleCommand(command: any) {
switch (command.key) {
case 'edit' :
this.handleShowUserDialog(command.row.id)
break
case 'claim' :
this.handleShowCliamDialog(command.row)
break
case 'menu' :
this.editUserId = command.row.id
this.showManageUserMenuDialog = true
break
case 'permission' :
this.handleShowPermissionDialog(command.row.id)
break

41
vueJs/src/views/container/menus/components/CreateOrUpdateMenuDialog.vue

@ -126,7 +126,7 @@
:label="$t(('AppPlatform.DisplayName:Meta'))"
>
<el-form-item
v-for="(dataItem) in bindData.items"
v-for="(dataItem) in dataItems"
:key="dataItem.id"
:label="dataItem.displayName"
:prop="'meta.' + dataItem.name"
@ -136,16 +136,16 @@
trigger: 'blur'
}"
>
<el-popover
<!-- <el-popover
:ref="dataItem.name"
trigger="hover"
:title="dataItem.displayName"
:content="dataItem.description"
:content="dataItem.description || dataItem.displayName"
/>
<span
slot="label"
v-popover="dataItem.name"
>{{ dataItem.displayName }}</span>
>{{ dataItem.displayName }}</span> -->
<menu-meta-input
v-model="menu.meta[dataItem.name]"
:prop-name="'meta.' + dataItem.name"
@ -186,9 +186,8 @@ import MenuService, {
MenuUpdate,
MenuCreateOrUpdate
} from '@/api/menu'
import DataService, { Data } from '@/api/data-dictionary'
import LayoutService, { Layout, GetLayoutByPaged } from '@/api/layout'
import { abpPagerFormat } from '@/utils/index'
import DataService, { Data, DataItem } from '@/api/data-dictionary'
import LayoutService, { Layout } from '@/api/layout'
import MenuMetaInput from './MenuMetaInput.vue'
@ -222,15 +221,18 @@ export default class CreateOrUpdateMenuDialog extends Vue {
return this.$t('AppPlatform.Menu:AddNew')
}
get dataItems() {
const items = this.bindData.items.sort((pre: DataItem, next: DataItem) => {
return pre.valueType < next.valueType ? -1 : 0
})
return items
}
private activedTab = 'basic'
private menu = new Menu()
private bindData = new Data()
private layouts = new Array<Layout>()
private layoutId = ''
private layoutPage = 1
private layoutTotal = 0
private layoutEnd = false
private layoutQuery = new GetLayoutByPaged()
@Watch('showDialog')
private onShowDialogChanged() {
@ -242,19 +244,11 @@ export default class CreateOrUpdateMenuDialog extends Vue {
}
private handleGetLayouts() {
if (!this.isEdit && !this.layoutEnd) {
this.layoutQuery.skipCount = abpPagerFormat(this.layoutPage, this.layoutQuery.maxResultCount)
if (!this.isEdit) {
LayoutService
.getList(this.layoutQuery)
.getAllList()
.then(res => {
this.layouts.push(...res.items)
this.layoutTotal = res.totalCount
if (res.items.length === 0 ||
res.items.length < this.layoutQuery.maxResultCount) {
this.layoutEnd = true
} else {
this.layoutPage += 1
}
this.layouts = res.items
})
}
}
@ -282,6 +276,9 @@ export default class CreateOrUpdateMenuDialog extends Vue {
private onLayoutChanged() {
const layout = this.layouts.find(x => x.id === this.layoutId)
if (layout) {
if (!this.isEdit) {
this.menu.meta = {}
}
if (!this.parentId) {
// ,
this.menu.component = layout.path

19
vueJs/src/views/container/menus/components/MenuMetaInput.vue

@ -32,6 +32,11 @@
:value="inputArrayValue(value)"
@input="onInputMetaChanged"
/>
<input-object
v-else-if="dataItem.valueType===6"
:value="inputObjectValue"
@input="onInputMetaChanged"
/>
</div>
</template>
@ -40,12 +45,14 @@ import { Component, Vue, Prop } from 'vue-property-decorator'
import { DataItem } from '@/api/data-dictionary'
import { isBoolean } from 'lodash'
import ElInputTag from '@/components/InputTag/index.vue'
import InputObject from '@/components/InputObject/index.vue'
import { isArray } from '@/utils/validate'
@Component({
name: 'MenuMetaInput',
components: {
ElInputTag
ElInputTag,
InputObject
}
})
export default class MenuMetaInput extends Vue {
@ -87,6 +94,16 @@ export default class MenuMetaInput extends Vue {
this.value = String(value).split(',')
}
get inputObjectValue() {
if (typeof this.value === 'object') {
return this.value
}
if (typeof this.value === 'string') {
return JSON.parse(this.value)
}
return JSON.parse(String(this.value))
}
onInputMetaChanged(value: any) {
this.$emit('input', value)
}

Loading…
Cancel
Save