ABP 開發(fā)手記,通過做一個分類管理完整實(shí)現(xiàn)前后端代碼

ABP 開發(fā)手記(Begin 2018-7-25)

7.25開始,啟用5.4版本asp net zero,做一個最簡單的分類管理和上傳圖片這兩個功能,看從學(xué)習(xí)到完成需要多久的時(shí)間

因?yàn)楣ぷ魈Γ阈浅闀r(shí)間弄了一下,最后做完這個功能,居然已經(jīng)是9.25,整整兩個月。

=============================================================================================

按照官方教程建好項(xiàng)目后,假定項(xiàng)目名稱為Relyto.CoreERP

文章內(nèi)容我按照正常的步驟完整做完一個mvc頁面。初用這個框架的時(shí)候,由于我沒有完整的閱讀官方文檔,拿著就開整 ,對整體架構(gòu)不熟悉,做每一個步驟需要在不同的項(xiàng)目文件夾切換來切換去,經(jīng)常找不到需要添加的內(nèi)容在哪里。所以這個文檔我描述了在做的過程中,每一步在哪個項(xiàng)目或者文件進(jìn)行操作,大家在做的時(shí)候注意后面的項(xiàng)目后綴,對應(yīng)原先的項(xiàng)目結(jié)構(gòu)。

#2018-7-25

#1、建實(shí)體


--Namespace

Relyto.CoreERP.Core項(xiàng)目下,新建文件夾Channel,然后建實(shí)體

需要添加以下命名空間:

using Abp.Domain.Entities;

using Abp.Domain.Entities.Auditing;

using System.ComponentModel.DataAnnotations;

using System.ComponentModel.DataAnnotations.Schema;

更改類對應(yīng)的表名,是在class類前加上以下注解:

[Table("cmn_channelinfo")]

示例:

[Table("cmn_channelinfo")]

? ? public class ChannelInfo:FullAuditedEntity ,IMustHaveTenant

{}

對于多租戶,實(shí)現(xiàn) IMustHaveTenant,并添加以下語句

public int TenantId { get; set; }

#2、添加到DbContext

Relyto.CoreERP.EntityFrameworkCore項(xiàng)目下\EntityFrameworkCore文件夾

修改:AbpZeroTemplateDbContext.cs

Add Namespace:using Relyto.CoreERP.Channel;

在下面添加一行代碼,用于下面命令行把這張表結(jié)構(gòu)生成到數(shù)據(jù)庫中去:

public virtual DbSet<ChannelInfo> ChannelInfos { get; set; }

在程序包管理器控制臺,先選擇項(xiàng)目為Relyto.CoreERP.EntityFrameworkCore,然后在下面執(zhí)行以下命令:

Add-Migration "Add Channel Info"

Update-Database

,然后檢查一下數(shù)據(jù)庫,請應(yīng)該是生成了

#3.APPlication 層

Relyto.CoreERP.Application項(xiàng)目下新建ChannelInfo文件夾

3.1 IChannelInfoAppService

using Abp.Application.Services;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using Relyto.CoreERP.Channel;

using Relyto.CoreERP.Channel.Dtos;

using Abp.Application.Services.Dto;

namespace Relyto.CoreERP.Channel

{

? ? public interface IChannelInfoAppService: IApplicationService

? ? {

? ? ? ? Task<ListResultDto<ChannelInfoListDto>> GetAll(GetAllChannelInfoInput input);

? ? ? ? System.Threading.Tasks.Task Create(CreateChannelInfoInput input);

? ? }

}

建立Dtos文件夾,生成Get,Create的方法的參數(shù)類

3.2? ChannelInfoListDto

using Abp.Application.Services.Dto;

using Abp.AutoMapper;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using Relyto.CoreERP.Channel;

using Relyto.CoreERP.SharedEnum;

namespace Relyto.CoreERP.Channel.Dtos

{

? ? [AutoMapFrom(typeof(ChannelInfo))]

? ? public class ChannelInfoListDto:FullAuditedEntityDto

? ? {


? ? ? ? public string Title { get; set; }? ? ? ?

? ? ? ? public string Description { get; set; }? ? ? ?

? ? ? ? public string SubTitle { get; set; }? ? ? ?

? ? ? ? public string ChannelCode { get; set; }

? ? ? ? public string EnglishName { get; set; }? ? ? ?

? ? ? ? public string ImageUrl { get; set; }? ? ? ?

? ? ? ? public short ChannelIndex { get; set; }? ? ? ?

? ? ? ? public int ParentID { get; set; }? ? ? ?

? ? ? ? public EnumState State { get; set; }? ? ? ?

? ? ? ? public bool IsLastNode { get; set; }

? ? }

}

3.3 GetAllChannelInfoInput

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace Relyto.CoreERP.Channel.Dtos

{

? ? public class GetAllChannelInfoInput

? ? {

? ? ? ? public int ParentID { get; set; }

? ? }

}

3.4 CreateChannelInfoInput

using Abp.AutoMapper;

using Relyto.CoreERP.SharedEnum;

using System;

using System.Collections.Generic;

using System.ComponentModel.DataAnnotations;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace Relyto.CoreERP.Channel.Dtos

{

? ? [AutoMapTo(typeof(ChannelInfo))]

? ? public class CreateChannelInfoInput

? ? {

? ? ? ? public const int MaxTitleLength = 20;

? ? ? ? public const int MaxDescriptionLength = 100; //64KB

? ? ? ? /// <summary>

? ? ? ? /// 標(biāo)題

? ? ? ? /// </summary>

? ? ? ? [Required]

? ? ? ? [MaxLength(MaxTitleLength)]

? ? ? ? public string Title { get; set; }

? ? ? ? /// <summary>

? ? ? ? /// 描述

? ? ? ? /// </summary>

? ? ? ? [MaxLength(MaxDescriptionLength)]

? ? ? ? public string Description { get; set; }

? ? ? ? /// <summary>

? ? ? ? /// 子標(biāo)題

? ? ? ? /// </summary>

? ? ? ? [MaxLength(MaxTitleLength)]

? ? ? ? public string SubTitle { get; set; }

? ? ? ? /// <summary>

? ? ? ? /// channel Code附加

? ? ? ? /// </summary>

? ? ? ? [MaxLength(MaxTitleLength)]

? ? ? ? public string ChannelCode { get; set; }

? ? ? ? /// <summary>

? ? ? ? /// 英文名

? ? ? ? /// </summary>

? ? ? ? [MaxLength(MaxTitleLength)]

? ? ? ? public string EnglishName { get; set; }

? ? ? ? /// <summary>

? ? ? ? /// channel 附加的圖片地址

? ? ? ? /// </summary>

? ? ? ? public string ImageUrl { get; set; }

? ? ? ? /// <summary>

? ? ? ? /// 顯示順序

? ? ? ? /// </summary>

? ? ? ? public short ChannelIndex { get; set; }

? ? ? ? /// <summary>

? ? ? ? /// 上級ID

? ? ? ? /// </summary>

? ? ? ? [Required]

? ? ? ? public int ParentID { get; set; }

? ? ? ? /// <summary>

? ? ? ? /// 狀態(tài)

? ? ? ? /// </summary>

? ? ? ? public EnumState State { get; set; }

? ? ? ? /// <summary>

? ? ? ? /// 是否末級

? ? ? ? /// </summary>

? ? ? ? public bool IsLastNode { get; set; }

? ? }

}

#4.實(shí)現(xiàn)IChannelInfoAppService

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using Relyto.CoreERP;

using Relyto.CoreERP.Channel;

using Relyto.CoreERP.Channel.Dtos;

using Abp.Application.Services.Dto;

using Microsoft.EntityFrameworkCore;

namespace Relyto.CoreERP.Channel

{

? ? public class ChannelInfoAppService:AbpZeroTemplateAppServiceBase,IChannelInfoAppService

? ? {

? ? ? ? private readonly IRepository<ChannelInfo> _channelInfoRepository;

? ? ? ? public ChannelInfoAppService(IRepository<ChannelInfo> channelRepository)

? ? ? ? {

? ? ? ? ? ? _channelInfoRepository = channelRepository;

? ? ? ? }

? ? ? ? public async System.Threading.Tasks.Task Create(CreateChannelInfoInput input)

? ? ? ? {

? ? ? ? ? ? var channelInfo = ObjectMapper.Map<ChannelInfo>(input);

? ? ? ? ? ? await _channelInfoRepository.InsertAsync(channelInfo);

? ? ? ? }

? ? ? ? public async Task<ListResultDto<ChannelInfoListDto>> GetAll(GetAllChannelInfoInput input)

? ? ? ? {

? ? ? ? ? ? var channelInfos = await _channelInfoRepository

? ? ? ? ? ? ? ? .GetAll()? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? .Where(m=>m.ParentID==input.ParentID)

? ? ? ? ? ? ? ? .OrderByDescending(t => t.CreationTime)

? ? ? ? ? ? ? ? .ToListAsync();

? ? ? ? ? ? return new ListResultDto<ChannelInfoListDto>(

? ? ? ? ? ? ? ? ObjectMapper.Map<List<ChannelInfoListDto>>(channelInfos)

? ? ? ? ? ? );

? ? ? ? }

? ? }

}

#5.添加測試

跳過了

#6.Adding a New Menu Item,添加新菜單

找到

Relyto.CoreERP.Web.Mvc項(xiàng)目下AppAreaName\Startup\找到AppAreaNameNavigationProvider

類似這樣:

.AddItem(new MenuItemDefinition(

? ? ? ? ? ? ? ? ? ? ? ? AppAreaNamePageNames.Common.DemoUiComponents,

? ? ? ? ? ? ? ? ? ? ? ? L("圖片上傳"),

? ? ? ? ? ? ? ? ? ? ? ? url: "AppAreaName/ImageManager",

? ? ? ? ? ? ? ? ? ? ? ? icon: "flaticon-shapes"

? ? ? ? ? ? ? ? ? ? )

? ? ? ? ? ? ? ? );

或者需要權(quán)限:

.AddItem(new MenuItemDefinition(

? ? ? ? ? ? ? ? ? ? ? ? AppAreaNamePageNames.Common.DemoUiComponents,

? ? ? ? ? ? ? ? ? ? ? ? L("DemoUiComponents"),

? ? ? ? ? ? ? ? ? ? ? ? url: "AppAreaName/DemoUiComponents",

? ? ? ? ? ? ? ? ? ? ? ? icon: "flaticon-shapes",

? ? ? ? ? ? ? ? ? ? ? ? requiredPermissionName: AppPermissions.Pages_DemoUiComponents

? ? ? ? ? ? ? ? ? ? )

? ? ? ? ? ? ? ? )

6.1 AppAreaNamePageNames 添加幾個常量,用于菜單等需要的時(shí)候使用

? ? public static class Channel

? ? ? ? {

? ? ? ? ? ? public const string NewChannel = "Channel.New";

? ? ? ? ? ? public const string ViewAll = "Channel.ViewAll";

? ? ? ? ? ? public const string EditChannel = "Channel.Edit";

? ? ? ? }

6.2添加權(quán)限名稱,這些名稱在后面對應(yīng)的JS中也要用到

Relyto.CoreERP.Authorization.AppPermissions

? public const string Pages_Administration_ChannelManager = "Pages.Administration.Pages_Administration_ChannelManager";


6.3在Relyto.CoreERP.Core項(xiàng)目Localization\AbpZeroTemplate下添加語言詞條,這個地方要記到,以后要添加詞條資源都在這里添加

比如在代碼里使用到 L("ChannelManager"),需要在對應(yīng)的zh文件里面添加:

? <text name="ChannelManager">分類管理</text>

6.3 創(chuàng)建權(quán)限點(diǎn)

Relyto.CoreERP.Core\Authorization\AppAuthorizationProvider下

? ? ? ? administration.CreateChildPermission(AppPermissions.Pages_Administration_ChannelManager, L("ChannelManager"));

#7.創(chuàng)建MVC

Relyto.CoreERP.Web.Mvc\Areas\AppAreaName\Controllers\ChannelInfoController

創(chuàng)建control.直接添加control.Relyto.CoreERP.Web.Mvc\Areas\AppAreaName\Controllers 繼承的是 AbpZeroTemplateControllerBase

using System;

using System.Collections.Generic;

using System.Linq;

using System.Threading.Tasks;

using Abp.AspNetCore.Mvc.Authorization;

using Abp.AspNetCore.Mvc.Controllers;

using Microsoft.AspNetCore.Http;

using Microsoft.AspNetCore.Mvc;

using Relyto.CoreERP.Authorization;

using Relyto.CoreERP.Web.Controllers;

namespace Relyto.CoreERP.Web.Mvc.Areas.AppAreaName.Controllers

{

? ? [Area("AppAreaName")]

? ? [AbpMvcAuthorize(AppPermissions.Pages_Administration_ChannelManager)]

? ? public class ChannelInfoController : AbpZeroTemplateControllerBase

#8.復(fù)雜的客戶端腳本,以樹形為例,分類信息

在\Relyto.CoreERP.Web.Mvc\Areas\AppAreaName\Views\ChannelInfo

而對應(yīng)的腳本信息,css信息,確放在:

Relyto.CoreERP.Web.Mvc\wwwroot\view-resources\Areas\AppAreaName\Views\ChannelInfo

目錄,使用時(shí)注意對照

另外,在View頁面里,涉及的字符串,我們一般直接寫,但是在這里一般用L("Key")的方式,要對照

Relyto.CoreERP.Core\Localization\AbpZeroTemplate

里面的模板文件添加

前期比如我只添加中文:AbpZeroTemplate-zh-CN.xml里對照添加

舉例:

<div id="ChannelInfoEmptyInfo" ng-if="!vm.organizationTree.unitCount" class="text-muted">

? ? ? ? ? ? ? ? ? ? ? ? @L("ChannelNoInfoYet")

? ? ? ? </div>

大量的這種。是很不習(xí)慣的

研究JS,還沒明白tree是怎么生成的,噢。原來是用的JStree,以前沒有用過,難怪不懂,NND前端不懂的東西太多了,一入前端深似海。

學(xué)習(xí)地方:https://www.jstree.com/

JS Tree: Create an instance

Once the DOM is ready you can start creating jstree instances.

$(function () { $('#jstree_demo_div').jstree(); });

--------------------------------------------------------------------

讀代碼 :在 里面給了一個div? ChannelInfoEditTree

在js里面,調(diào)用了

channelinfoTree.init();

這個方法代碼:

init: function () {

? ? ? ? ? ? ? ? channelinfoTree.getTreeDataFromServer(function (treeData) {

? ? ? ? ? ? ? ? ? ? channelinfoTree.setUnitCount(treeData.length);

? ? ? ? ? ? ? ? ? ? channelinfoTree.$tree

? ? ? ? ? ? ? ? ? ? ? ? .on('changed.jstree', function (e, data) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? if (data.selected.length != 1) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? channelinfoTree.selectedOu.set(null);

? ? ? ? ? ? ? ? ? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? var selectedNode = data.instance.get_node(data.selected[0]);

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? channelinfoTree.selectedOu.set(selectedNode);

? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? })

? ? ? ? ? ? ? ? ? ? ? ? .on('move_node.jstree', function (e, data) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? var parentNodeName = (!data.parent || data.parent == '#')

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? app.localize('Root')

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? : channelinfoTree.$tree.jstree('get_node', data.parent).original.displayName;

? ? ? ? ? ? ? ? ? ? ? ? ? ? abp.message.confirm(

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? app.localize('OrganizationUnitMoveConfirmMessage', data.node.original.displayName, parentNodeName),

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? function (isConfirmed) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (isConfirmed) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? _channelinfoService.moveOrganizationUnit({

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? id: data.node.id,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? newParentId: data.parent

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }).done(function () {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? abp.notify.success(app.localize('SuccessfullyMoved'));

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? channelinfoTree.reload();

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }).fail(function (err) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? channelinfoTree.$tree.jstree('refresh'); //rollback

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? setTimeout(function () { abp.message.error(err.message); }, 500);

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? });

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? channelinfoTree.$tree.jstree('refresh'); //rollback

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? ? ? );

? ? ? ? ? ? ? ? ? ? ? ? })

? ? ? ? ? ? ? ? ? ? ? ? .jstree({

? ? ? ? ? ? ? ? ? ? ? ? ? ? 'core': {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? data: treeData,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? multiple: false,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? check_callback: function (operation, node, node_parent, node_position, more) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? return true;

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? ? ? },

? ? ? ? ? ? ? ? ? ? ? ? ? ? types: {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "default": {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "icon": "fa fa-folder m--font-warning"

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? },

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "file": {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "icon": "fa fa-file? m--font-warning"

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? ? ? },

? ? ? ? ? ? ? ? ? ? ? ? ? ? contextmenu: {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? items: channelinfoTree.contextMenu

? ? ? ? ? ? ? ? ? ? ? ? ? ? },

? ? ? ? ? ? ? ? ? ? ? ? ? ? sort: function (node1, node2) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (this.get_node(node2).original.displayName < this.get_node(node1).original.displayName) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? return 1;

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? return -1;

? ? ? ? ? ? ? ? ? ? ? ? ? ? },

? ? ? ? ? ? ? ? ? ? ? ? ? ? plugins: [

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 'types',

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 'contextmenu',

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 'wholerow',

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 'sort',

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 'dnd'

? ? ? ? ? ? ? ? ? ? ? ? ? ? ]

? ? ? ? ? ? ? ? ? ? ? ? });

#9.改好了客戶端展示頁面,要實(shí)現(xiàn)功能,先從createmodal開始吧

9.1 在Relyto.CoreERP.Web.Mvc\Areas\AppAreaName\Models\Channel

新建了CreateChannelInfoModalViewModel類,里面就實(shí)現(xiàn)了個parentid,現(xiàn)在還不知道怎么用

9.2更改View,添加了Relyto.CoreERP.Web.Mvc\Areas\AppAreaName\Views\ChannelInfo\_CreateModal.cshtml

里面好像頭部和尾部都是現(xiàn)成的。

遇的到,半天不能彈出modal框,原來是JS路徑寫錯了,下次記得檢查這個:

一開始我沒有在控制文件創(chuàng)建creeateModal這個方法,所以直接報(bào)錯。

控制文件創(chuàng)建了以后,因?yàn)閖s不對一直沒打開

? ? ? ? var _createModal = new app.ModalManager({

? ? ? ? ? ? viewUrl: abp.appPath + 'AppAreaName/ChannelInfo/CreateModal',

? ? ? ? ? ? scriptUrl: abp.appPath + 'view-resources/Areas/AppAreaName/Views/ChannelInfo/_CreateModal.js',? =》剛才就是這個路徑寫錯了,所以就不彈出圣誕框 。

? ? ? ? ? ? modalClass:'CreateChannelInfoModal'? =》這個類名,就是 _CreateModal里面開始那個類。如果對不上,則后來點(diǎn)保存沒有反應(yīng)。我找了半天才發(fā)現(xiàn)這個問題。

function() {

? ? app.modals.CreateChannelInfoModalViewModel = function () {

? ? 就是上面這個代碼

這個類里面就是通過var channelInfo = _$form.serializeFormToObject();

直接就把界面上的數(shù)據(jù),form里面的,序列化,然后就傳給后端,后端使用的是DtoInput,也不知道 怎么弄的,居然可以直接解析出來。

然后就去寫數(shù)據(jù)庫了。感覺客戶端主要是太不熟悉了。慢慢看代碼 還是看的懂。

套路就是

服務(wù)端App定義的服務(wù),客戶端可以直接變成js來用,這個真牛逼。當(dāng)然要注意把方法的第一個字母小寫了。

cshtml頁面里,直接用DtoInput的字段名來做數(shù)據(jù),自然就可以映射到服務(wù)端dto去,應(yīng)該還要整理一下文本框架,單選,多選,日期,圖片等各種類型的客戶端處理方法。

從user那個來看,還可以有更復(fù)雜的頁面方法來實(shí)現(xiàn) 。

這樣客戶端的邏輯代碼就相對多一些。

? ? ? ? });

9.3 在APPService 那個項(xiàng)目可以通過AbpSession.TenantId 來獲取當(dāng)前的TenantID.

9.4.已搞定添加到數(shù)據(jù)庫,但是現(xiàn)在顯示 還是undefind


#10.解決顯示問題

1.解決了分類顯示那里不能正確顯示的問題,搞明白了()里面是對子節(jié)點(diǎn)的統(tǒng)計(jì)

原來是這個在搞定節(jié)點(diǎn)顯示:

generateTextOnTree: function (ou) {

? ? ? ? ? ? ? ? var itemClass = ou.memberCount > 0 ? ' ou-text-has-members' : ' ou-text-no-members';

? ? ? ? ? ? ? ? return '<span title="' + ou.id + '" class="ou-text' + itemClass

? ? ? ? ? ? ? ? ? ? + '" data-ou-id="' + ou.id + '">'

? ? ? ? ? ? ? ? ? ? + app.htmlUtils.htmlEncodeText(ou.title)

? ? ? ? ? ? ? ? ? ? + ' (<span class="ou-text-member-count">'

? ? ? ? ? ? ? ? ? ? + ou.memberCount

? ? ? ? ? ? ? ? ? ? + '</span>) <i class="fa fa-caret-down text-muted"></i></span>';

? ? ? ? ? ? },

其中有幾個注意事項(xiàng):

a.title這種字段,在服務(wù)端是全大定,到了這里是首字母小寫才正常。

b.memberCount是服務(wù)端app層統(tǒng)計(jì)出來的,而organ那里有個方法,我還沒有寫過那種方法,待確定。他用了一個join+new就搞定了分類統(tǒng)計(jì)的問題。

#11 遇到本地在樹狀選擇里沒有復(fù)選框的問題

1.編輯頻道信息,結(jié)果發(fā)現(xiàn)做角色與權(quán)限管理那里,樹狀沒有復(fù)選框,不知道為什么在我的界面上沒有回來

最后我在

Relyto.CoreERP.Web.Mvc\wwwroot\view-resources\Areas\AppAreaName\Views\Common\PermissionTree.js

修改了一個變量:

'checkbox': {

? ? ? ? ? ? ? ? ? ? keep_selected_style: true,? --false =>true

? ? ? ? ? ? ? ? ? ? three_state: false,

? ? ? ? ? ? ? ? ? ? cascade: '',

? ? ? ? ? ? ? ? ? ? visible:true

? ? ? ? ? ? ? ? },

可以看到藍(lán)色背景的選擇結(jié)果,勉強(qiáng)可以,不曉得為哈我這個上面不出來復(fù)選框。

折騰了一晚上,只解決了這個問題。效率很低啊

還有就是把權(quán)限又搞懂了一點(diǎn)。 現(xiàn)在還建了子權(quán)限菜單。在數(shù)據(jù)庫里有個表,對應(yīng)createpermison那塊

https://blog.csdn.net/new0801/article/details/54766984這篇文章講的比較清楚,一步一步做就可以了

#還是前端工作

發(fā)現(xiàn)前端工作量真大啊。寫個修改,也要寫那么久

沒有解決到復(fù)選框的問題,現(xiàn)在發(fā)現(xiàn)abp前端這個好麻煩啊,每個controller對應(yīng)的方法都要有個Model類。

現(xiàn)在還全部是用的實(shí)體復(fù)制,沒有做變更,空了還要來整理。權(quán)限、實(shí)體內(nèi)容 這一塊,然后寫個文檔。

又是checkbox???,在編輯的時(shí)候,一選中chekcobx就valid error.搞了半天,要用這種style才能繼續(xù)的下去,原因嘛,我也不懂,看起來怪怪的

<label for="IsLastNode" class="m-checkbox">


? ? ? ? ? ? <input id="IsLastNode"? type="checkbox" name="IsLastNode" value="true" @(Model.IsLastNode ? "checked=\"checked\"" : "")>

? ? ? ? ? ? @L("IsLastNode")

? ? ? ? ? ? <span></span>

? ? ? ? </label>

我看很多地方都是這樣寫的,抄過來就可以用,但原因嘛,沒明白 。

現(xiàn)在基本完成添加和修改了。接下來,那就把展示那里,把點(diǎn)擊后,其附加信息顯示出來這塊做了嘛。

坑:juqery設(shè)置<input textbox 不是用text(),而是用val();

我最后又遇到checkbox,沒搞定用javascript更改期check值。最后換文本了。我這個版本跟checkbox有仇?怎么都不出來chekcbox

在Service Update那里,從DBRepority取出來的實(shí)體不能用object.Automapper去修改數(shù)據(jù)。必須用傳統(tǒng)的賦值方法修改過去。


#2018-8-6

1.查看信息做完后,考慮做添加下級,結(jié)果發(fā)現(xiàn)添加下級的時(shí)候,我沒有把parentid在controller那里添加進(jìn)去,修改后,數(shù)據(jù)到是對了

接下來就是不能分組顯示。查看organunit,使用了一種不太懂的語法完成。我修改了getall()以后,還是不分組,看代碼,似懂非懂

細(xì)致的觀察了一下js代碼,發(fā)現(xiàn)是把一個parentId寫成了parnetID。原來寫在了大寫。在js里面首字母小寫后,后面就不對了。

這種約定我沒有找到文檔,但在abp里面確實(shí)存在這種約定,可能大家都不用這種方式開發(fā),我也沒有看到相關(guān)的文檔。

更奇怪的是,我做了 按channelindex排序后發(fā)現(xiàn)是倒序的,后來查看了app service層確實(shí)是orderbydesending。所以不怪別個。

目前看來樹級的狀態(tài)基本正常了,接下來就刪除 了。

這玩意兒還缺一個刷新的按鈕,從服務(wù)器重新取數(shù)據(jù)來刷一下。

#2018-8-9

1.終于在今晚完成了刪除功能,現(xiàn)在除()里面顯示的總數(shù)據(jù)不對,缺權(quán)限完,其他功能基本完成,跌跌撞撞用了10多天,都還沒有完全搞完,前端真是坑啊。

還有圖片上傳的功能還沒有做呢。

2.JS端的權(quán)限搞懂了

var _permissions = {

? ? ? ? ? ? create: abp.auth.isGranted('Pages.Administration.ChannelManager.Create'),

? ? ? ? ? ? edit: abp.auth.isGranted('Pages.Administration.ChannelManager.Edit'),

? ? ? ? ? ? delete: abp.auth.isGranted('Pages.Administration.ChannelManager.Delete')

? ? ? ? };

這個就是創(chuàng)建權(quán)限點(diǎn)的,對應(yīng)D:\Project\2018\Relyto.CoreERP\aspnet-core\src\Relyto.CoreERP.Core\Authorization\AppAuthorizationProvider.cs

下的權(quán)限點(diǎn),注意里面的isGranted 我用了 這個,沒有用原來的haspermit那個方法。另外,后面的.是字條串常量。要去常量類里copy

接下來就是controll層和Application的Service要同樣加權(quán)限。

service層是:? ? ? ? [AbpAuthorize(AppPermissions.Pages_Administration_ChannelManager_Delete)]

controll層是:[AbpMvcAuthorize(AppPermissions.Pages_Administration_ChannelManager_Edit)]

有點(diǎn)區(qū)別的。

到此權(quán)限暫時(shí)可以用了哈。

現(xiàn)在主要就是圖片上傳的功能 了。

順便還添加了一個refresh方法。

#2018-8-22

1.搞清楚了圖像上傳后,是存了一個GUID,放在[AppBinaryObjects]中,目前只寫了數(shù)據(jù)庫保存,還沒有寫本地保存。

所以我把代碼全部改了一下,關(guān)聯(lián)表只存GUID,不存URL

因?yàn)槭菙?shù)據(jù)庫,我看JS中當(dāng)前圖像最大存放:9990000,實(shí)測小于1.2M,沒看懂這個單位。

不過折騰了一遍。完善了添加、修改刪除后刷新的問題,解決了添加、刪除、修改過程中圖片顯示、上傳的問題,以及服務(wù)端在編輯、刪除同步刪除相關(guān)圖片的問題。

#2018-9-14

1.找了個前端的上傳圖片的框架bootstrap-fileinput,好不容易搞定了前端,但是還沒有搞定后臺存儲的問題。

#2018-9-17

1.發(fā)現(xiàn)在cshtml端,必須通過

@section Styles

? ? {

? ? <link rel="stylesheet" abp-href="/view-resources/Areas/AppAreaName/Views/ImageManager/bootstrap-fileinput/css/fileinput.min.css" asp-append-version="true" />

}

@section Scripts

? ? {

? ? <script abp-src="/view-resources/Areas/AppAreaName/Views/ImageManager/bootstrap-fileinput/js/fileinput.min.js" asp-append-version="true"></script>

? ? <script abp-src="/view-resources/Areas/AppAreaName/Views/ImageManager/bootstrap-fileinput/js/locales/zh.js" asp-append-version="true"></script>

? ? <script abp-src="/view-resources/Areas/AppAreaName/Views/ImageManager/upload_fileinput.js" asp-append-version="true"></script>

}

這樣的方式引入樣式和js文件,才能正確解決跨域的問題。也解決了文件上傳不發(fā)送到controller端的問題

2.在文件保存時(shí),如果發(fā)現(xiàn)文件路徑所在的文件夾沒有創(chuàng)建,會報(bào)錯,比如uploadfile文件夾沒有創(chuàng)建,會報(bào)內(nèi)部錯誤。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容