diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 81cf37fc8a..e33a07a197 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -14,15 +14,17 @@ jobs: build-test: runs-on: windows-latest steps: - - uses: actions/checkout@v1 - - uses: actions/setup-dotnet@master - with: - dotnet-version: "3.1.100" + - uses: actions/checkout@v2 + - uses: actions/setup-dotnet@master + with: + dotnet-version: 3.1.100 - - name: Build All - run: .\build\build-all.ps1 - shell: pwsh + - name: Build All + run: .\build-all.ps1 + working-directory: .\build + shell: powershell - - name: Test All - run: .\build\test-all.ps1 - shell: pwsh + - name: Test All + run: .\test-all.ps1 + working-directory: .\build + shell: powershell diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json index 9e90c427d1..a5089e06f7 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json @@ -14,6 +14,7 @@ "Permission:Delete": "Delete", "Permission:Create": "Create", "Menu:Organizations": "Organizations", + "Menu:Accounting": "Accounting", "Menu:Packages": "Packages", "NpmPackageDeletionWarningMessage": "This NPM Package will be deleted. Do you confirm that?", "NugetPackageDeletionWarningMessage": "This Nuget Package will be deleted. Do you confirm that?", @@ -92,6 +93,14 @@ "OrganizationNamePlaceholder": "Organization name...", "UsernameOrEmail": "Username or email", "UsernameOrEmailPlaceholder": "Username or email...", - "Member": "Member" + "Member": "Member", + "QuotationPurchasedOrderNo": "Quotation Purchased Order No", + "QuotationTime": "Quotation Time", + "CompanyName": "Company Name", + "CompanyAddress": "Company Address", + "Price": "Price", + "ExtraText": "Extra Text", + "ExtraAmount": "Extra Amount", + "DownloadQuotation": "Download Quotation" } } \ No newline at end of file diff --git a/common.props b/common.props index a6d559c52c..19b6f81fe6 100644 --- a/common.props +++ b/common.props @@ -1,7 +1,7 @@ latest - 2.6.0 + 2.7.0 $(NoWarn);CS1591 https://abp.io/assets/abp_nupkg.png https://abp.io diff --git a/docs/en/Exception-Handling.md b/docs/en/Exception-Handling.md index 38a380dc64..3ccade9767 100644 --- a/docs/en/Exception-Handling.md +++ b/docs/en/Exception-Handling.md @@ -316,7 +316,7 @@ The `context` object contains necessary information about the exception occurred Some exception types are automatically thrown by the framework: - `AbpAuthorizationException` is thrown if the current user has no permission to perform the requested operation. See [authorization](Authorization.md) for more. -- `AbpValidationException` is thrown if the input of the current request is not valid. See [validation] (Validation.md) for more. +- `AbpValidationException` is thrown if the input of the current request is not valid. See [validation](Validation.md) for more. - `EntityNotFoundException` is thrown if the requested entity is not available. This is mostly thrown by [repositories](Repositories.md). You can also throw these type of exceptions in your code (although it's rarely needed). diff --git a/docs/en/Multi-Tenancy.md b/docs/en/Multi-Tenancy.md index 27fe70086c..6adef9b214 100644 --- a/docs/en/Multi-Tenancy.md +++ b/docs/en/Multi-Tenancy.md @@ -172,11 +172,11 @@ namespace MyCompany.MyProject { options.Tenants = new[] { - new TenantInformation( + new TenantConfiguration( Guid.Parse("446a5211-3d72-4339-9adc-845151f8ada0"), //Id "tenant1" //Name ), - new TenantInformation( + new TenantConfiguration( Guid.Parse("25388015-ef1c-4355-9c18-f6b6ddbaf89d"), //Id "tenant2" //Name ) @@ -252,7 +252,7 @@ TODO: This package implements ITenantStore using a real database... #### Tenant Information -ITenantStore works with **TenantInformation** class that has several properties for a tenant: +ITenantStore works with **TenantConfiguration** class that has several properties for a tenant: * **Id**: Unique Id of the tenant. * **Name**: Unique name of the tenant. diff --git a/docs/en/Tutorials/Part-1.md b/docs/en/Tutorials/Part-1.md index 9f8671d92a..a0aa6612e9 100644 --- a/docs/en/Tutorials/Part-1.md +++ b/docs/en/Tutorials/Part-1.md @@ -982,11 +982,13 @@ import { GetBooks } from '../actions/books.actions'; import { Books } from '../models/books'; import { BooksService } from '../../books/shared/books.service'; import { tap } from 'rxjs/operators'; +import { Injectable } from '@angular/core'; @State({ name: 'BooksState', defaults: { books: {} } as Books.State, }) +@Injectable() export class BooksState { @Selector() static getBooks(state: Books.State) { diff --git a/docs/en/Tutorials/Part-2.md b/docs/en/Tutorials/Part-2.md index a754893114..9565724cb8 100644 --- a/docs/en/Tutorials/Part-2.md +++ b/docs/en/Tutorials/Part-2.md @@ -574,11 +574,13 @@ import { GetBooks, CreateUpdateBook } from '../actions/books.actions'; //<== add import { Books } from '../models/books'; import { BooksService } from '../../books/shared/books.service'; import { tap } from 'rxjs/operators'; +import { Injectable } from '@angular/core'; @State({ name: 'BooksState', defaults: { books: {} } as Books.State, }) +@Injectable() export class BooksState { @Selector() static getBooks(state: Books.State) { @@ -1330,11 +1332,13 @@ import { GetBooks, CreateUpdateBook, DeleteBook } from '../actions/books.actions import { Books } from '../models/books'; import { BooksService } from '../../books/shared/books.service'; import { tap } from 'rxjs/operators'; +import { Injectable } from '@angular/core'; @State({ name: 'BooksState', defaults: { books: {} } as Books.State, }) +@Injectable() export class BooksState { @Selector() static getBooks(state: Books.State) { diff --git a/docs/en/UI/Angular/Confirmation-Service.md b/docs/en/UI/Angular/Confirmation-Service.md new file mode 100644 index 0000000000..a8d2c4c2a7 --- /dev/null +++ b/docs/en/UI/Angular/Confirmation-Service.md @@ -0,0 +1,163 @@ +# Confirmation Popup + +You can use the `ConfirmationService` in @abp/ng.theme.shared package to display a confirmation popup by placing at the root level in your project. + + +## Getting Started + +You do not have to provide the `ConfirmationService` at module or component level, because it is already **provided in root**. You can inject and start using it immediately in your components, directives, or services. + + +```js +import { ConfirmationService } from '@abp/ng.theme.shared'; + +@Component({ + /* class metadata here */ +}) +class DemoComponent { + constructor(private confirmation: ConfirmationService) {} +} +``` + +## Usage + +You can use the `success`, `warn`, `error`, and `info` methods of `ConfirmationService` to display a confirmation popup. + +### How to Display a Confirmation Popup + +```js +const confirmationStatus$ = this.confirmation.success('Message', 'Title'); +``` + +- The `ConfirmationService` methods accept three parameters that are `message`, `title`, and `options`. +- `success`, `warn`, `error`, and `info` methods return an [RxJS Subject](https://rxjs-dev.firebaseapp.com/guide/subject) to listen to confirmation popup closing event. The type of event value is [`Confirmation.Status`](https://github.com/abpframework/abp/blob/master/npm/ng-packs/packages/theme-shared/src/lib/models/confirmation.ts#L24) that is an enum. + +### How to Listen Closing Event + +You can subscribe to the confirmation closing event like below: + +```js +import { Confirmation, ConfirmationService } from '@abp/ng.theme.shared'; + +constructor(private confirmation: ConfirmationService) {} + +this.confirmation + .warn('::WillBeDeleted', { key: '::AreYouSure', defaultValue: 'Are you sure?' }) + .subscribe((status: Confirmation.Status) => { + // your code here + }); +``` + + +- The `message` and `title` parameters accept a string, localization key or localization object. See the [localization document](./Localization.md) +- `Confirmation.Status` is an enum and has three properties; + - `Confirmation.Status.confirm` is a closing event value that will be emitted when the popup is closed by the confirm button. + - `Confirmation.Status.reject` is a closing event value that will be emitted when the popup is closed by the cancel button. + - `Confirmation.Status.dismiss` is a closing event value that will be emitted when the popup is closed by pressing the escape. + + +If you are not interested in the confirmation status, you do not have to subscribe to the returned observable: + +```js +this.confirmation.error('You are not authorized.', 'Error'); +``` + +### How to Display a Confirmation Popup With Given Options + +Options can be passed as the third parameter to `success`, `warn`, `error`, and `info` methods: + +```js +const options: Partial = { + hideCancelBtn: false, + hideYesBtn: false, + cancelText: 'Close', + yesText: 'Confirm', + messageLocalizationParams: ['Demo'], + titleLocalizationParams: [], +}; + +this.confirmation.warn( + 'AbpIdentity::RoleDeletionConfirmationMessage', + 'Are you sure?', + options, +); +``` + +- `hideCancelBtn` option hides the cancellation button when `true`. Default value is `false` +- `hideYesBtn` option hides the confirmation button when `true`. Default value is `false` +- `cancelText` is the text of the cancellation button. A localization key or localization object can be passed. Default value is `AbpUi::Cancel` +- `yesText` is the text of the confirmation button. A localization key or localization object can be passed. Default value is `AbpUi::Yes` +- `messageLocalizationParams` is the interpolation parameters for the localization of the message. +- `titleLocalizationParams` is the interpolation parameters for the localization of the title. + +With the options above, the confirmation popup looks like this: + +![confirmation](./images/confirmation.png) + +### How to Remove a Confirmation Popup + +The open confirmation popup can be removed manually via the `clear` method: + +```js +this.confirmation.clear(); +``` + +## API + +### success + +```js +success( + message: Config.LocalizationParam, + title: Config.LocalizationParam, + options?: Partial, +): Observable +``` + +> See the [`Config.LocalizationParam` type](https://github.com/abpframework/abp/blob/master/npm/ng-packs/packages/core/src/lib/models/config.ts#L46) and [`Confirmation` namespace](https://github.com/abpframework/abp/blob/master/npm/ng-packs/packages/theme-shared/src/lib/models/confirmation.ts) + + +### warn + +```js +warn( + message: Config.LocalizationParam, + title: Config.LocalizationParam, + options?: Partial, +): Observable +``` + +### error + +```js +error( + message: Config.LocalizationParam, + title: Config.LocalizationParam, + options?: Partial, +): Observable +``` + +### info + +```js +info( + message: Config.LocalizationParam, + title: Config.LocalizationParam, + options?: Partial, +): Observable +``` + +### clear + +```js +clear( + status: Confirmation.Status = Confirmation.Status.dismiss +): void +``` + +- `status` parameter is the value of the confirmation closing event. + + +## What's Next? + +- [Toast Overlay](./Toaster-Service.md) diff --git a/docs/en/UI/Angular/Dom-Insertion-Service.md b/docs/en/UI/Angular/Dom-Insertion-Service.md index 489a7a4e1f..88f30136b3 100644 --- a/docs/en/UI/Angular/Dom-Insertion-Service.md +++ b/docs/en/UI/Angular/Dom-Insertion-Service.md @@ -125,6 +125,16 @@ removeContent(element: HTMLScriptElement | HTMLStyleElement): void - `element` parameter is the inserted `HTMLScriptElement` or `HTMLStyleElement` element, which was returned by `insertContent` method. +### has + +```js +has(content: string): boolean +``` + +The `has` method returns a boolean value that indicates the given content has already been added to the DOM or not. + +- `content` parameter is the content of the inserted `HTMLScriptElement` or `HTMLStyleElement` element. + ## What's Next? - [ContentProjectionService](./Content-Projection-Service.md) diff --git a/docs/en/UI/Angular/Http-Requests.md b/docs/en/UI/Angular/HTTP-Requests.md similarity index 99% rename from docs/en/UI/Angular/Http-Requests.md rename to docs/en/UI/Angular/HTTP-Requests.md index 71878c8045..2ac5aa1b49 100644 --- a/docs/en/UI/Angular/Http-Requests.md +++ b/docs/en/UI/Angular/HTTP-Requests.md @@ -206,4 +206,4 @@ You may find `Rest.Observe` enum [here](https://github.com/abpframework/abp/blob ## What's Next? -* [Localization](./Localization.md) \ No newline at end of file +* [Localization](./Localization.md) diff --git a/docs/en/UI/Angular/Lazy-Load-Service.md b/docs/en/UI/Angular/Lazy-Load-Service.md index a03381869e..b4eddf7b25 100644 --- a/docs/en/UI/Angular/Lazy-Load-Service.md +++ b/docs/en/UI/Angular/Lazy-Load-Service.md @@ -52,7 +52,7 @@ class DemoComponent { The `load` method returns an observable to which you can subscibe in your component or with an `async` pipe. In the example above, the `NgIf` directive will render `` only **if the script gets successfully loaded or is already loaded before**. -> You can subscribe multiple times in your template with `async` pipe. The styles will only be loaded once. +> You can subscribe multiple times in your template with `async` pipe. The Scripts will only be loaded once. Please refer to [LoadingStrategy](./Loading-Strategy.md) to see all available loading strategies and how you can build your own loading strategy. diff --git a/docs/en/UI/Angular/Permission-Management.md b/docs/en/UI/Angular/Permission-Management.md index ababd25e7f..d86e8c96b2 100644 --- a/docs/en/UI/Angular/Permission-Management.md +++ b/docs/en/UI/Angular/Permission-Management.md @@ -76,4 +76,4 @@ Granted Policies are stored in the `auth` property of `ConfigState`. ## What's Next? -* [Config State](./Config-State.md) \ No newline at end of file +- [Confirmation Popup](./Confirmation-Service.md) \ No newline at end of file diff --git a/docs/en/UI/Angular/Toaster-Service.md b/docs/en/UI/Angular/Toaster-Service.md new file mode 100644 index 0000000000..191f0b34fd --- /dev/null +++ b/docs/en/UI/Angular/Toaster-Service.md @@ -0,0 +1,157 @@ +# Toast Overlay + +You can use the `ToasterService` in @abp/ng.theme.shared package to display messages in an overlay by placing at the root level in your project. + + +## Getting Started + +You do not have to provide the `ToasterService` at module or component level, because it is already **provided in root**. You can inject and start using it immediately in your components, directives, or services. + + +```js +import { ToasterService } from '@abp/ng.theme.shared'; + +@Component({ + /* class metadata here */ +}) +class DemoComponent { + constructor(private toaster: ToasterService) {} +} +``` + +## Usage + +You can use the `success`, `warn`, `error`, and `info` methods of `ToasterService` to display an overlay. + +### How to Display a Toast Overlay + +```js +this.toast.success('Message', 'Title'); +``` + +- The `ToasterService` methods accept three parameters that are `message`, `title`, and `options`. +- `success`, `warn`, `error`, and `info` methods return the id of opened toast overlay. The toast can be removed with this id. + +### How to Display a Toast Overlay With Given Options + +Options can be passed as the third parameter to `success`, `warn`, `error`, and `info` methods: + +```js +import { Toaster, ToasterService } from '@abp/ng.theme.shared'; +//... + +constructor(private toaster: ToasterService) {} + +//... +const options: Partial = { + life: 10000, + sticky: false, + closable: true, + tapToDismiss: true, + messageLocalizationParams: ['Demo', '1'], + titleLocalizationParams: [] + }; + + this.toaster.error('AbpUi::EntityNotFoundErrorMessage', 'AbpUi::Error', options); +``` + +- `life` option is the closing time in milliseconds. Default value is `5000`. +- `sticky` option keeps toast overlay on the screen by ignoring the `life` option when `true`. Default value is `false`. +- `closable` option displays the close icon on the toast overlay when it is `true`. Default value is `true`. +- `tapToDismiss` option, when `true`, allows closing the toast overlay by clicking over it. Default value is `false`. +- `yesText` is the text of the confirmation button. A localization key or localization object can be passed. Default value is `AbpUi::Yes`. +- `messageLocalizationParams` is the interpolation parameters for the localization of the message. +- `titleLocalizationParams` is the interpolation parameters for the localization of the title. + +With the options above, the toast overlay looks like this: + +![toast](./images/toast.png) + +### How to Remove a Toast Overlay + +The open toast overlay can be removed manually via the `remove` method by passing the `id` of toast: + +```js +const toastId = this.toast.success('Message', 'Title') + +this.toast.remove(toastId); +``` + +### How to Remove All Toasts + +The all open toasts can be removed manually via the `clear` method: + +```js +this.toast.clear(); +``` + +## API + +### success + +```js +success( + message: Config.LocalizationParam, + title: Config.LocalizationParam, + options?: Partial, +): number +``` + +- `Config` namespace can be imported from `@abp/ng.core`. +- `Toaster` namespace can be imported from `@abp/ng.theme.shared`. + +> See the [`Config.LocalizationParam` type](https://github.com/abpframework/abp/blob/master/npm/ng-packs/packages/core/src/lib/models/config.ts#L46) and [`Toaster` namespace](https://github.com/abpframework/abp/blob/master/npm/ng-packs/packages/theme-shared/src/lib/models/toaster.ts) + + +### warn + +```js +warn( + message: Config.LocalizationParam, + title: Config.LocalizationParam, + options?: Partial, +): number +``` + +### error + +```js +error( + message: Config.LocalizationParam, + title: Config.LocalizationParam, + options?: Partial, +): number +``` + +### info + +```js +info( + message: Config.LocalizationParam, + title: Config.LocalizationParam, + options?: Partial, +): number +``` + +### remove + +```js +remove(id: number): void +``` + +Removes an open toast by the given id. + +### clear + +```js +clear(): void +``` + +Removes all open toasts. + +## See Also +- [Confirmation Popup](./Confirmation-Service.md) + +## What's Next? + +- [Config State](./Config-State.md) diff --git a/docs/en/UI/Angular/images/confirmation.png b/docs/en/UI/Angular/images/confirmation.png new file mode 100644 index 0000000000..efe4c98ea7 Binary files /dev/null and b/docs/en/UI/Angular/images/confirmation.png differ diff --git a/docs/en/UI/Angular/images/toast.png b/docs/en/UI/Angular/images/toast.png new file mode 100644 index 0000000000..24cdd0fe0c Binary files /dev/null and b/docs/en/UI/Angular/images/toast.png differ diff --git a/docs/en/UI/AspNetCore/Tag-Helpers/Index.md b/docs/en/UI/AspNetCore/Tag-Helpers/Index.md index aefbb88e01..229460de92 100644 --- a/docs/en/UI/AspNetCore/Tag-Helpers/Index.md +++ b/docs/en/UI/AspNetCore/Tag-Helpers/Index.md @@ -12,18 +12,18 @@ ABP Framework also adds some **useful features** to the standard bootstrap compo Here, the list of components those are wrapped by the ABP Framework: +* [Alerts](Alerts.md) * [Buttons](Buttons.md) * [Cards](Cards.md) -* [Alerts](Alerts.md) -* [Tabs](Tabs.md) -* [Grids](Grids.md) -* [Modals](Modals.md) * [Collapse](Collapse.md) * [Dropdowns](Dropdowns.md) +* [Grids](Grids.md) * [List Groups](List-Groups.md) +* [Modals](Modals.md) * [Paginator](Paginator.md) * [Popovers](Popovers.md) * [Progress Bars](Progress-Bars.md) +* [Tabs](Tabs.md) * [Tooltips](Tooltips.md) * ... diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index 8b5d41aa59..472f153321 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -337,6 +337,14 @@ "text": "Permission Management", "path": "UI/Angular/Permission-Management.md" }, + { + "text": "Confirmation Popup", + "path": "UI/Angular/Confirmation-Service.md" + }, + { + "text": "Toast Overlay", + "path": "UI/Angular/Toaster-Service.md" + }, { "text": "Config State", "path": "UI/Angular/Config-State.md" diff --git a/docs/pt-BR/Tutorials/Angular/Part-I.md b/docs/pt-BR/Tutorials/Angular/Part-I.md index 3b79483cd3..3b0b1daf1b 100644 --- a/docs/pt-BR/Tutorials/Angular/Part-I.md +++ b/docs/pt-BR/Tutorials/Angular/Part-I.md @@ -537,11 +537,13 @@ import { GetBooks } from '../actions/books.actions'; import { Books } from '../models/books'; import { BooksService } from '../../books/shared/books.service'; import { tap } from 'rxjs/operators'; +import { Injectable } from '@angular/core'; @State({ name: 'BooksState', defaults: { books: {} } as Books.State, }) +@Injectable() export class BooksState { @Selector() static getBooks(state: Books.State) { diff --git a/docs/zh-Hans/API/Auto-API-Controllers.md b/docs/zh-Hans/API/Auto-API-Controllers.md index 93ac124913..c3f5d44d71 100644 --- a/docs/zh-Hans/API/Auto-API-Controllers.md +++ b/docs/zh-Hans/API/Auto-API-Controllers.md @@ -6,7 +6,7 @@ ABP可以按照惯例 **自动** 将你的应用程序服务配置为API控制 ## 配置 -基本配置很简单. 只需配置`AbpAspNetCoreMvcOptions`并使用`ConventionalControllers.Create`方法,如下所示: +基本配置很简单. 只需配置`AbpAspNetCoreMvcOptions`并使用`ConventionalControllers.Create`方法,如下所示: ````csharp [DependsOn(BookStoreApplicationModule)] @@ -82,7 +82,7 @@ Configure(options => * 删除'**Async**'后缀. 如果方法名称为'GetPhonesAsync',则变为`GetPhones`. * 删除**HTTP method前缀**. 基于的HTTP method删除`GetList`,`GetAll`,`Get`,`Put`,`Update`,`Delete`,`Remove`,`Create`,`Add`,`Insert`,`Post`和`Patch`前缀, 因此`GetPhones`变为`Phones`, 因为`Get`前缀和GET请求重复. * 将结果转换为**camelCase**. - * 如果生成的操作名称为**空**,则它不会添加到路径中.否则它会被添加到路由中(例如'/phones').对于`GetAllAsync`方法名称,它将为空,因为`GetPhonesAsync`方法名称将为`phone`. + * 如果生成的操作名称为**空**,则它不会添加到路径中.否则它会被添加到路由中(例如'/phones').对于`GetAllAsync`方法名称,它将为空,因为`GetPhonesAsync`方法名称将为`phone`. * 可以通过设置`UrlActionNameNormalizer`选项来自定义.It's an action delegate that is called for every method. * 如果有另一个带有'Id'后缀的参数,那么它也会作为最终路线段添加到路线中(例如'/phoneId'). diff --git a/docs/zh-Hans/Application-Services.md b/docs/zh-Hans/Application-Services.md index 72e0319cde..d0e29c2881 100644 --- a/docs/zh-Hans/Application-Services.md +++ b/docs/zh-Hans/Application-Services.md @@ -380,4 +380,4 @@ public class DistrictKey ### 生命周期 -应用服务的生命周期是[transient](Dependency-Injection)的,它们会自动注册到依赖注入系统. \ No newline at end of file +应用服务的生命周期是[transient](Dependency-Injection)的,它们会自动注册到依赖注入系统. \ No newline at end of file diff --git a/docs/zh-Hans/AspNetCore/Tag-Helpers/Buttons.md b/docs/zh-Hans/AspNetCore/Tag-Helpers/Buttons.md index 848d043312..ebfeb6f2aa 100644 --- a/docs/zh-Hans/AspNetCore/Tag-Helpers/Buttons.md +++ b/docs/zh-Hans/AspNetCore/Tag-Helpers/Buttons.md @@ -86,7 +86,7 @@ ABP框架定义了Tag Helper用于简单的创建bootstrap按钮. ### `icon-type` -`icon-type` 是一个可选参数。它的默认值是 `FontAwesome`. 你可以创建自己的图标类型提供程序并更改它. +`icon-type` 是一个可选参数.它的默认值是 `FontAwesome`. 你可以创建自己的图标类型提供程序并更改它. 你可以为按钮选择以下图标类型: diff --git a/docs/zh-Hans/Audit-Logging.md b/docs/zh-Hans/Audit-Logging.md index a028e640b2..a8b6e66449 100644 --- a/docs/zh-Hans/Audit-Logging.md +++ b/docs/zh-Hans/Audit-Logging.md @@ -43,12 +43,12 @@ Configure(options => * `IsEnabledForGetRequests` (默认值: `false`): HTTP GET请求通常不应该在数据库进行任何更改,审计日志系统不会为GET请求保存审计日志对象. 将此值设置为 `true` 可为GET请求启用审计日志系统. * `ApplicationName`: 如果有多个应用程序保存审计日志到单一的数据库,使用此属性设置为你的应用程序名称区分不同的应用程序日志. * `IgnoredTypes`: 审计日志系统忽略的 `Type` 列表. 如果它是实体类型,则不会保存此类型实体的更改. 在序列化操作参数时也使用此列表. -* `EntityHistorySelectors`:选择器列表,用于确定是否选择了用于保存实体更改的实体类型. 有关详细信息请参阅下面的部分. +* `EntityHistorySelectors`:选择器列表,用于确定是否选择了用于保存实体更改的实体类型. 有关详细信息请参阅下面的部分. * `Contributors`: `AuditLogContributor` 实现的列表. 贡献者是扩展审计日志系统的一种方式. 有关详细信息请参阅下面的"审计日志贡献者"部分. ### 实体历史选择器 -保存您的所有实体的所有变化将需要大量的数据库空间. 出于这个原因**审计日志系统不保存为实体的任何改变,除非你明确地对其进行配置**. +保存你的所有实体的所有变化将需要大量的数据库空间. 出于这个原因**审计日志系统不保存为实体的任何改变,除非你明确地对其进行配置**. 要保存的所有实体的所有更改,只需使用 `AddAllEntities()` 扩展方法. @@ -131,7 +131,7 @@ public class HomeController : AbpController 可以为任何类型的类(注册到[依赖注入](Dependency-Injection.md)并从依赖注入解析)启用审计日志,默认情况下仅对控制器和应用程序服务启用. -对于任何需要被审计记录的类或方法都可以使用 `[Audited]` 和`IAuditingEnabled`.此外,您的类可以(直接或固有的)实现 `IAuditingEnabled` 接口以认启用该类的审计日志记录. +对于任何需要被审计记录的类或方法都可以使用 `[Audited]` 和`IAuditingEnabled`.此外,你的类可以(直接或固有的)实现 `IAuditingEnabled` 接口以认启用该类的审计日志记录. ### 启用/禁用 实体 & 属性 @@ -211,8 +211,8 @@ public class MyUser : Entity * **AuditLogInfo**: 具有以下属性: * `ApplicationName`: 当你保存不同的应用审计日志到同一个数据库,这个属性用来区分应用程序. - * `UserId`:当前用户的Id,用户未登录为 `null`. - * `UserName`:当前用户的用户名,如果用户已经登录(这里的值不依赖于标识模块/系统进行查找). + * `UserId`:当前用户的Id,用户未登录为 `null`. + * `UserName`:当前用户的用户名,如果用户已经登录(这里的值不依赖于标识模块/系统进行查找). * `TenantId`: 当前租户的Id,对于多租户应用. * `TenantName`: 当前租户的名称,对于多租户应用. * `ExecutionTime`: 审计日志对象创建的时间. @@ -222,28 +222,28 @@ public class MyUser : Entity * `ClientIpAddress`: 客户端/用户设备的IP地址. * `CorrelationId`: 当前[相关Id](CorrelationId.md). 相关Id用于在单个逻辑操作中关联由不同应用程序(或微服务)写入的审计日志. * `BrowserInfo`: 当前用户的浏览器名称/版本信息,如果有的话. - * `HttpMethod`: 当前HTTP请求的方法(GET,POST,PUT,DELETE ...等). + * `HttpMethod`: 当前HTTP请求的方法(GET,POST,PUT,DELETE ...等). * `HttpStatusCode`: HTTP响应状态码. * `Url`: 请求的URL. * **AuditLogActionInfo**: 一个 审计日志动作通常是web请求期间控制器动作或[应用服务](Application-Services.md)方法调用. 一个审计日志可以包含多个动作. 动作对象具有以下属性: - * `ServiceName`:执行的控制器/服务的名称. - * `MethodName`:控制器/服务执行的方法的名称. - * `Parameters`:传递给方法的参数的JSON格文本. + * `ServiceName`:执行的控制器/服务的名称. + * `MethodName`:控制器/服务执行的方法的名称. + * `Parameters`:传递给方法的参数的JSON格文本. * `ExecutionTime`: 执行的时间. * `ExecutionDuration`: 方法执行时长,以毫秒为单位. 可以用来观察方法的性能. * **EntityChangeInfo**: 表示一个实体在Web请求中的变更. 审计日志可以包含0个或多个实体的变更. 实体变更具有以下属性: * `ChangeTime`: 当实体被改变的时间. - * `ChangeType`:具有以下字段的枚举: `Created`(0), `Updated`(1)和 `Deleted`(2). + * `ChangeType`:具有以下字段的枚举: `Created`(0), `Updated`(1)和 `Deleted`(2). * `EntityId`: 更改实体的Id. - * `EntityTenantId`:实体所属的租户Id. + * `EntityTenantId`:实体所属的租户Id. * `EntityTypeFullName`: 实体的类型(类)的完整命名空间名称(例如Book实体的*Acme.BookStore.Book*. * **EntityPropertyChangeInfo**: 表示一个实体的属性的更改.一个实体的更改信息(上面已说明)可含有具有以下属性的一个或多个属性的更改: * `NewValue`: 属性的新值. 如果实体已被删除为 `null`. - * `OriginalValue`:变更前旧/初始值. 如果实体是新创建为 `null`. + * `OriginalValue`:变更前旧/初始值. 如果实体是新创建为 `null`. * `PropertyName`: 实体类的属性名称. - * `PropertyTypeFullName`:属性类型的完整命名空间名称. + * `PropertyTypeFullName`:属性类型的完整命名空间名称. * **Exception**: 审计日志对象可能包含零个或多个异常. 可以得到失败请求的异常信息. -* **Comment**:用于将自定义消息添加到审计日志条目的任意字符串值. 审计日志对象可能包含零个或多个注释. +* **Comment**:用于将自定义消息添加到审计日志条目的任意字符串值. 审计日志对象可能包含零个或多个注释. 除了上面说明的标准属性之外,`AuditLogInfo`, `AuditLogActionInfo` 和 `EntityChangeInfo` 对象还实现了`IHasExtraProperties` 接口,你可以向这些对象添加自定义属性. @@ -331,7 +331,7 @@ public class MyService : ITransientDependency ### 手动创建审计日志范围 你很少需要手动创建审计日志的范围,但如果你需要,可以使用 `IAuditingManager` 创建审计日志的范围. -例: +例: ````csharp public class MyService : ITransientDependency @@ -366,7 +366,7 @@ public class MyService : ITransientDependency } ```` -您可以调用其他服务,它们可能调用其他服务,它们可能更改实体,等等. 所有这些交互都保存为finally块中的一个审计日志对象. +你可以调用其他服务,它们可能调用其他服务,它们可能更改实体,等等. 所有这些交互都保存为finally块中的一个审计日志对象. ## 审计日志模块 diff --git a/docs/zh-Hans/Authorization.md b/docs/zh-Hans/Authorization.md index a43565279e..99139be3ac 100644 --- a/docs/zh-Hans/Authorization.md +++ b/docs/zh-Hans/Authorization.md @@ -153,7 +153,7 @@ myGroup.AddPermission( myGroup.AddPermission("Author_Management", isEnabled: false); ```` -通常你不需要定义禁用权限(除非您暂时想要禁用应用程序的功能). 无论怎样,你可能想要禁用依赖模块中定义的权限,这样你可以禁用相关的功能. 参阅下面的 "*更改依赖模块的权限定义*" 节,查看示例用法. +通常你不需要定义禁用权限(除非你暂时想要禁用应用程序的功能). 无论怎样,你可能想要禁用依赖模块中定义的权限,这样你可以禁用相关的功能. 参阅下面的 "*更改依赖模块的权限定义*" 节,查看示例用法. > 注意:检查一个未定义的权限会抛出异常,而被禁用的权限的返回禁止(false). diff --git a/docs/zh-Hans/Background-Workers.md b/docs/zh-Hans/Background-Workers.md index dfd26c7b82..1daedde384 100644 --- a/docs/zh-Hans/Background-Workers.md +++ b/docs/zh-Hans/Background-Workers.md @@ -2,7 +2,7 @@ ## 介绍 -背景工人在应用简单独立的线程在后台运行。一般来说,他们定期运行,以执行一些任务。例子; +背景工人在应用简单独立的线程在后台运行.一般来说,他们定期运行,以执行一些任务.例子; 后台工作者在应用程序后台运行的简单的独立线程,一般来说它们定期运行执行一些任务.例如; * 后台工作者可以定期**删除过时的日志**. @@ -72,7 +72,7 @@ public class PassiveUserCheckerWorker : AsyncPeriodicBackgroundWorkerBase } ```` -* `AsyncPeriodicBackgroundWorkerBase` 使用 `AbpTimer`(线程安全定时器)对象来确定**时间段**. 我们可以在构造函数中设置了`Period` 属性。 +* `AsyncPeriodicBackgroundWorkerBase` 使用 `AbpTimer`(线程安全定时器)对象来确定**时间段**. 我们可以在构造函数中设置了`Period` 属性. * 它需要实现 `DoWorkAsync` 方法**执行**定期任务. * 最好使用 `PeriodicBackgroundWorkerContext` **解析依赖** 而不是构造函数. 因为 `AsyncPeriodicBackgroundWorkerBase` 使用 `IServiceScope` 在你的任务执行结束时会对其 **disposed**. * `AsyncPeriodicBackgroundWorkerBase` **捕获并记录** 由 `DoWorkAsync` 方法抛出的 **异常**. diff --git a/docs/zh-Hans/Blog-Posts/2019-02-22/Post.md b/docs/zh-Hans/Blog-Posts/2019-02-22/Post.md index 30a5d691e9..998a454abc 100644 --- a/docs/zh-Hans/Blog-Posts/2019-02-22/Post.md +++ b/docs/zh-Hans/Blog-Posts/2019-02-22/Post.md @@ -13,7 +13,7 @@ ABP框架的主要目标之一是提供[创建微服务解决方案的便利基 - 使用[Ocelot](https://github.com/ThreeMammals/Ocelot)库开发了多个**网关** / BFF(后端为前端(Backend for Frontends)). - 使用[IdentityServer](https://identityserver.io/)框架开发**身份验证服务**.它也是一个带有必要UI的SSO(单点登录)应用程序. - 有**多个数据库**.一些微服务有自己的数据库,而一些服务/应用程序共享一个数据库(以演示不同的用例). -- 具有不同类型的数据库:**SQL Server**(使用**Entity Framework Core** ORM)和**MongoDB**. +- 具有不同类型的数据库:**SQL Server**(使用**Entity Framework Core** ORM)和**MongoDB**. - 有一个**控制台应用程序**来显示通过身份验证使用服务的最简单方法. - 使用[Redis](https://redis.io/)进行**分布式缓存**. - 使用[RabbitMQ](https://www.rabbitmq.com/)进行服务到服务(service-to-service)的**消息传递**. @@ -28,27 +28,27 @@ ABP框架的主要目标之一是提供[创建微服务解决方案的便利基 ## 路线图 -在第一个稳定版本(v1.0)之前还有很多工作要做.您可以在GitHub仓库上看到[优先的积压项目](https://github.com/abpframework/abp/issues?q=is%3Aopen+is%3Aissue+milestone%3ABacklog). +在第一个稳定版本(v1.0)之前还有很多工作要做.你可以在GitHub仓库上看到[优先的积压项目](https://github.com/abpframework/abp/issues?q=is%3Aopen+is%3Aissue+milestone%3ABacklog). 根据我们的估计,我们计划在2019年第二季度(可能在五月或六月)发布v1.0.所以,不用等待太长时间了.我们也对第一个稳定版本感到非常兴奋. 我们还将完善[文档](https://abp.io/documents/abp/latest),因为它现在还远未完成. -第一个版本可能不包含SPA模板.但是,如果可能的话,我们想要准备一个简单些的.SPA框架还没有确定下来.备选有:**Angular,React和Blazor**.请将您的想法写为对此帖的评论. +第一个版本可能不包含SPA模板.但是,如果可能的话,我们想要准备一个简单些的.SPA框架还没有确定下来.备选有:**Angular,React和Blazor**.请将你的想法写为对此帖的评论. ## 中文网 -中国有一个大型的ABP社区.他们创建了一个中文版的abp.io网站:https://abp.io/. 他们一直在保持更新.感谢中国的开发人员,特别是[Liming Ma](https://github.com/maliming). +中国有一个大型的ABP社区.他们创建了一个中文版的abp.io网站:https://abp.io/. 他们一直在保持更新.感谢中国的开发人员,特别是[Liming Ma](https://github.com/maliming). ## NDC {London} 2019 很高兴作为合作伙伴参加[NDC {London}](https://ndc-london.com/)2019 .我们已经与许多开发人员讨论过当前的ASP.NET Boilerplate和ABP vNext,我们得到了很好的反馈. -我们还有机会与[Scott Hanselman](https://twitter.com/shanselman)和[Jon Galloway](https://twitter.com/jongalloway)交谈.他们参观了我们的展位,我们谈到了ABP vNext的想法.他们喜欢新的ABP框架的功能,方法和目标.在twitter上查看一些照片和评论: +我们还有机会与[Scott Hanselman](https://twitter.com/shanselman)和[Jon Galloway](https://twitter.com/jongalloway)交谈.他们参观了我们的展位,我们谈到了ABP vNext的想法.他们喜欢新的ABP框架的功能,方法和目标.在twitter上查看一些照片和评论: ![scott-and-jon](scott-and-jon.png) ## 跟上步伐 -* 您可以标星并关注**GitHub**存储库:https://github.com/abpframework/abp -* 您可以关注官方**Twitter**帐户获取新闻:https://twitter.com/abpframework +* 你可以标星并关注**GitHub**存储库:https://github.com/abpframework/abp +* 你可以关注官方**Twitter**帐户获取新闻:https://twitter.com/abpframework diff --git a/docs/zh-Hans/Blog-Posts/2019-06-19 v0_18_Release/Post.md b/docs/zh-Hans/Blog-Posts/2019-06-19 v0_18_Release/Post.md index a25e1c0a97..6b3c76d2e2 100644 --- a/docs/zh-Hans/Blog-Posts/2019-06-19 v0_18_Release/Post.md +++ b/docs/zh-Hans/Blog-Posts/2019-06-19 v0_18_Release/Post.md @@ -4,7 +4,7 @@ ABP v0.18已发布, 包含解决的[80+个issue](https://github.com/abpframework ## 网站更改 -[abp.io](https://abp.io)网站**完全更新**以突出ABP框架的目标和重要功能.文档和博客网址也会更改: +[abp.io](https://abp.io)网站**完全更新**以突出ABP框架的目标和重要功能.文档和博客网址也会更改: - `abp.io/documents`移至[docs.abp.io](https://docs.abp.io). - `abp.io/blog`转移到[blog.abp.io](https://blog.abp.io). @@ -21,25 +21,25 @@ ABP CLI现在是创建新项目的首选方式,你仍然可以从[开始](https: ### 用法 -使用命令行窗口安装ABP CLI: +使用命令行窗口安装ABP CLI: ```` bash dotnet tool install -g Volo.Abp.Cli ```` -创建一个新应用程序: +创建一个新应用程序: ```` bash abp new Acme.BookStore ```` -将模块添加到应用程序: +将模块添加到应用程序: ```` bash abp add-module Volo.Blogging ```` -更新解决方案中所有与ABP相关的包: +更新解决方案中所有与ABP相关的包: ```` bash abp update @@ -59,7 +59,7 @@ abp update ## 更改日志 -以下是此版本附带的一些其他功能和增强功能: +以下是此版本附带的一些其他功能和增强功能: * 新[Volo.Abp.Dapper](https://www.nuget.org/packages/Volo.Abp.Dapper)包. * 新[Volo.Abp.Specifications](https://www.nuget.org/packages/Volo.Abp.Specifications)包. diff --git a/docs/zh-Hans/Blog-Posts/2019-08-16 v0_19_Release/Post.md b/docs/zh-Hans/Blog-Posts/2019-08-16 v0_19_Release/Post.md index 831cc791e9..9f82f6dce3 100644 --- a/docs/zh-Hans/Blog-Posts/2019-08-16 v0_19_Release/Post.md +++ b/docs/zh-Hans/Blog-Posts/2019-08-16 v0_19_Release/Post.md @@ -14,12 +14,12 @@ ABP v0.19已发布,包含解决的[~90个问题](https://github.com/abpframework * 更新了[ABP CLI](https://docs.abp.io/en/abp/latest/CLI)和[下载页面](https://abp.io/get-started),以便能够使用新的UI选项生成项目. * 创建了[教程](https://docs.abp.io/en/abp/latest/Tutorials/Angular/Part-I)以使用新的UI选项快速入门. -我们基于最新的Angular工具和趋势创建了模板,文档和基础架构: +我们基于最新的Angular工具和趋势创建了模板,文档和基础架构: * 使用[NgBootstrap](https://ng-bootstrap.github.io/)和[PrimeNG](https://www.primefaces.org/primeng/)作为UI组件库.你可以使用自己喜欢的库,没问题,但预构建的模块可以使用这些库. * 使用[NGXS](https://ngxs.gitbook.io/ngxs/)作为状态管理库. -Angular是第一个SPA UI选项,但它不是最后一个.在v1.0发布之后,我们将开始第二个UI选项的工作.虽然尚未决定,但候选的有Blazor,React和Vue.js. 等待你的反馈.你可以使用以下issue进行投票(thumb): +Angular是第一个SPA UI选项,但它不是最后一个.在v1.0发布之后,我们将开始第二个UI选项的工作.虽然尚未决定,但候选的有Blazor,React和Vue.js. 等待你的反馈.你可以使用以下issue进行投票(thumb): * [Blazor](https://github.com/abpframework/abp/issues/394) * [Vue.js](https://github.com/abpframework/abp/issues/1168) diff --git a/docs/zh-Hans/Blog-Posts/2019-09-25 v0_21_Release/Post.md b/docs/zh-Hans/Blog-Posts/2019-09-25 v0_21_Release/Post.md index 7633f3ea33..c4d98244fb 100644 --- a/docs/zh-Hans/Blog-Posts/2019-09-25 v0_21_Release/Post.md +++ b/docs/zh-Hans/Blog-Posts/2019-09-25 v0_21_Release/Post.md @@ -14,8 +14,8 @@ ABP框架越来越接近v1.0.我们打算在今年10月中旬发布1.0. 现在, ## Techorama荷兰2019 -[Techorama NL](https://techorama.nl/)是欧洲最大的会议之一.今年,Volosoft是会议的赞助商,并将有一个展位与软件开发人员讨论ABP框架和软件开发.我们的展位墙如下图所示: +[Techorama NL](https://techorama.nl/)是欧洲最大的会议之一.今年,Volosoft是会议的赞助商,并将有一个展位与软件开发人员讨论ABP框架和软件开发.我们的展位墙如下图所示: ![volosoft-booth](volosoft-booth.png) -如果您也参加会议,请到展位讨论ABP框架.我们还为您准备了一些私货:) +如果你也参加会议,请到展位讨论ABP框架.我们还为你准备了一些私货:) diff --git a/docs/zh-Hans/Blog-Posts/2020-03-19 v2_3_Release/Post.md b/docs/zh-Hans/Blog-Posts/2020-03-19 v2_3_Release/Post.md index a17bef2e1b..73585582f5 100644 --- a/docs/zh-Hans/Blog-Posts/2020-03-19 v2_3_Release/Post.md +++ b/docs/zh-Hans/Blog-Posts/2020-03-19 v2_3_Release/Post.md @@ -24,7 +24,7 @@ 我们终于完成了**react native移动应用程序**.目前,它可以让你**登录**,管理**用户**和**租户**.它利用ABP框架相同的设置,授权和本地化系统. -应用程序的一些截图: +应用程序的一些截图: ![mobile-ui](react-native-ui.png) @@ -34,7 +34,7 @@ 从我们的Angular应用程序中调用服务器中的REST端点是很常见的.这种情况下,我们一般创建**服务**(在服务器上包含各个服务的方法)和**模型对象**(对应服务器上的[DTO](https://docs.abp.io/en/abp/latest/Data-Transfer-Objects)). -除了手动创建这样的与服务器交互的服务外,我们可以使用像[NSWAG](https://github.com/RicoSuter/NSwag)工具来为我们生成服务代理.但是NSWAG有以下几个我们遇到的问题: +除了手动创建这样的与服务器交互的服务外,我们可以使用像[NSWAG](https://github.com/RicoSuter/NSwag)工具来为我们生成服务代理.但是NSWAG有以下几个我们遇到的问题: * 它产生一个**大,单一**的.ts文件; * 当你的应用程序增长时,它变得**太大**了. @@ -58,12 +58,12 @@ abp generate-proxy ### 添加模块的源代码 -应用程序启动模板带有一些[应用模块](https://docs.abp.io/en/abp/latest/Modules/Index), 以**Nuget和NPM包**的方式**预先安装了** .这样做有几个重要的优点: +应用程序启动模板带有一些[应用模块](https://docs.abp.io/en/abp/latest/Modules/Index), 以**Nuget和NPM包**的方式**预先安装了** .这样做有几个重要的优点: * 当新版本可用时, 你可以 **轻松地[升级](https://docs.abp.io/en/abp/latest/CLI#update)** 这些模块. * 你的解决方案**更干净**,这样你就可以专注于自己的代码. -但是,当你需要对一个依赖的模块**大量定制**时,就不如它的代码在你的应用程序中那么容易.为了解决这个问题,我们引入了一个[ABP CLI](https://docs.abp.io/en/abp/latest/CLI)的新命令, 在你的解决方案中用代码**替换**Nuget包.用法很简单: +但是,当你需要对一个依赖的模块**大量定制**时,就不如它的代码在你的应用程序中那么容易.为了解决这个问题,我们引入了一个[ABP CLI](https://docs.abp.io/en/abp/latest/CLI)的新命令, 在你的解决方案中用代码**替换**Nuget包.用法很简单: ````bash abp add-module --with-source-code @@ -75,19 +75,19 @@ abp add-module --with-source-code 此外,我们也创建了文档来说明如何定制依赖的模块而不改变它们的源代码(见下面的部分).仍然建议以包的方式使用模块,以便在以后可以轻松升级. -> 免费模块的源代码是**MIT**许可,所以你可以自由更改它们并添加到您的解决方案中. +> 免费模块的源代码是**MIT**许可,所以你可以自由更改它们并添加到你的解决方案中. ### 切换到预览版 ABP框架正在迅速发展,我们经常发布新版本.不过,如果你想更紧密地追随它,你可以使用**每日预览包**. -我们创建了一个ABP CLI命令来轻松地为你的解决方案**更新到最新的预览包**.在你的解决方案的根文件夹中运行以下命令: +我们创建了一个ABP CLI命令来轻松地为你的解决方案**更新到最新的预览包**.在你的解决方案的根文件夹中运行以下命令: ````bash abp switch-to-preview ```` -它会修改所有ABP相关的NuGet和NPM包的版本.当你需要时你也可以**切换回最新稳定版**: +它会修改所有ABP相关的NuGet和NPM包的版本.当你需要时你也可以**切换回最新稳定版**: ````bash abp switch-to-stable @@ -131,7 +131,7 @@ abp switch-to-stable ## 下一步? -我们未来几个月的目标如下: +我们未来几个月的目标如下: * 完成**文档和示例**,写更多的教程. * 使框架和现有模块的更加**可定制和可扩展**. diff --git a/docs/zh-Hans/CLI.md b/docs/zh-Hans/CLI.md index 0a802ffdc1..4d037ef2fd 100644 --- a/docs/zh-Hans/CLI.md +++ b/docs/zh-Hans/CLI.md @@ -41,12 +41,12 @@ abp new Acme.BookStore * `--template` 或者 `-t`: 指定模板. 默认的模板是 `app`,会生成web项目.可用的模板有: * `app` (default): [应用程序模板](Startup-Templates/Application.md). 其他选项: - * `--ui` 或者 `-u`: 指定ui框架.默认`mvc`框架.其他选项: - * `mvc`: ASP.NET Core MVC.此模板的其他选项: + * `--ui` 或者 `-u`: 指定ui框架.默认`mvc`框架.其他选项: + * `mvc`: ASP.NET Core MVC.此模板的其他选项: * `--tiered`: 创建分层解决方案,Web和Http Api层在物理上是分开的.如果未指定会创建一个分层的解决方案,此解决方案没有那么复杂,适合大多数场景. - * `angular`: Angular. 这个模板还有一些额外的选项: + * `angular`: Angular. 这个模板还有一些额外的选项: * `--separate-identity-server`: 将Identity Server应用程序与API host应用程序分开. 如果未指定,则服务器端将只有一个端点. - * `none`: 无UI. 这个模板还有一些额外的选项: + * `none`: 无UI. 这个模板还有一些额外的选项: * `--separate-identity-server`: 将Identity Server应用程序与API host应用程序分开. 如果未指定,则服务器端将只有一个端点. * `--mobile` 或者 `-m`: 指定移动应用程序框架. 默认框架是 `react-native`. 其他选项: * `none`: 不包含移动应用程序. @@ -57,7 +57,7 @@ abp new Acme.BookStore * `module`: [Module template](Startup-Templates/Module.md). 其他选项: * `--no-ui`: 不包含UI.仅创建服务模块(也称为微服务 - 没有UI). * `--output-folder` 或者 `-o`: 指定输出文件夹,默认是当前目录. -* `--version` 或者 `-v`: 指定ABP和模板的版本.它可以是 [release tag](https://github.com/abpframework/abp/releases) 或者 [branch name](https://github.com/abpframework/abp/branches). 如果没有指定,则使用最新版本.大多数情况下,您会希望使用最新的版本. +* `--version` 或者 `-v`: 指定ABP和模板的版本.它可以是 [release tag](https://github.com/abpframework/abp/releases) 或者 [branch name](https://github.com/abpframework/abp/branches). 如果没有指定,则使用最新版本.大多数情况下,你会希望使用最新的版本. * `--template-source` 或者 `-ts`: 指定自定义模板源用于生成项目,可以使用本地源和网络源(例如 `D\localTemplate` 或 `https://.zip`). * `--create-solution-folder` 或者 `-csf`: 指定项目是在输出文件夹中的新文件夹中还是直接在输出文件夹中. * `--connection-string` 或者 `-cs`: 重写所有 `appsettings.json` 文件的默认连接字符串. 默认连接字符串是 `Server=localhost;Database=MyProjectName;Trusted_Connection=True;MultipleActiveResultSets=true`. 如果你不想使用默认,你可以设置自己的连接字符串. 默认的数据库提供程序是 `SQL Server`, 所以你只能输入SQL Server连接字符串! @@ -186,9 +186,9 @@ abp generate-proxy [options] #### Options -* `--apiUrl` 或者 `-a`:指定HTTP API的根URL. 如果未指定这个选项,默认使用你Angular应用程序的`environment.ts`文件API URL. 在运行 `generate-proxy` 命令之前,你的host必须启动正在运行. +* `--apiUrl` 或者 `-a`:指定HTTP API的根URL. 如果未指定这个选项,默认使用你Angular应用程序的`environment.ts`文件API URL. 在运行 `generate-proxy` 命令之前,你的host必须启动正在运行. * `--ui` 或者 `-u`: 指定UI框架,默认框架是angular.当前只有angular一个选项, 但我们会通过更改CLI增加新的选项. 尽请关注! -* `--module` 或者 `-m`:指定模块名. 默认模块名称为app. 如果你想所有模块,你可以指定 `--module all` 命令. +* `--module` 或者 `-m`:指定模块名. 默认模块名称为app. 如果你想所有模块,你可以指定 `--module all` 命令. 示例: diff --git a/docs/zh-Hans/Customizing-Application-Modules-Extending-Entities.md b/docs/zh-Hans/Customizing-Application-Modules-Extending-Entities.md index 76a43ea80a..3e5ff3f6cd 100644 --- a/docs/zh-Hans/Customizing-Application-Modules-Extending-Entities.md +++ b/docs/zh-Hans/Customizing-Application-Modules-Extending-Entities.md @@ -50,7 +50,7 @@ ObjectExtensionManager.Instance * 你提供了 `IdentityUser` 作为实体名(泛型参数), `string` 做为新属性的类型, `SocialSecurityNumber` 做为属性名(也是数据库表的字段名). * 你还需要提供一个使用[EF Core Fluent API](https://docs.microsoft.com/en-us/ef/core/modeling/entity-properties)定义数据库映射属性的操作. -> 必须在使用相关的 `DbContext` 之前执行此代码. 应用程序启动模板定义了一个名为 `YourProjectNameEntityExtensions` 的静态类. 你可以在此类中定义扩展确保在正确的时间执行它. 否则你需要自己处理. +> 必须在使用相关的 `DbContext` 之前执行此代码. 应用程序启动模板定义了一个名为 `YourProjectNameEfCoreEntityExtensionMappings` 的静态类. 你可以在此类中定义扩展确保在正确的时间执行它. 否则你需要自己处理. 定义实体扩展后你需要使用EF Core的[Add-Migration](https://docs.microsoft.com/en-us/ef/core/miscellaneous/cli/powershell#add-migration)和[Update-Database](https://docs.microsoft.com/en-us/ef/core/miscellaneous/cli/powershell#update-database)命令来创建code first迁移类并更新数据库. diff --git a/docs/zh-Hans/Customizing-Application-Modules-Overriding-Services.md b/docs/zh-Hans/Customizing-Application-Modules-Overriding-Services.md index 1ba35adf80..caa448a14a 100644 --- a/docs/zh-Hans/Customizing-Application-Modules-Overriding-Services.md +++ b/docs/zh-Hans/Customizing-Application-Modules-Overriding-Services.md @@ -54,7 +54,7 @@ context.Services.Replace( ## 重写一个服务类 -大多数情况下,你会仅想改变服务当前实现的一个或几个方法. 重新实现完整的接口变的繁琐,更好的方法是继承原始类并重写方法。 +大多数情况下,你会仅想改变服务当前实现的一个或几个方法. 重新实现完整的接口变的繁琐,更好的方法是继承原始类并重写方法. ### 示例: 重写服务方法 diff --git a/docs/zh-Hans/Entities.md b/docs/zh-Hans/Entities.md index 1a059e477f..fd8528dc30 100644 --- a/docs/zh-Hans/Entities.md +++ b/docs/zh-Hans/Entities.md @@ -72,7 +72,7 @@ public class BookAppService : ApplicationService, IBookAppService * `BookAppService` 注入图书实体的默认[仓库](Repositories.md),使用`InsertAsync`方法插入 `Book` 到数据库中. * `GuidGenerator`类型是 `IGuidGenerator`,它是在`ApplicationService`基类中定义的属性. ABP将这样常用属性预注入,所以不需要手动[注入](Dependency-Injection.md). -* 如果您想遵循DDD最佳实践,请参阅下面的*聚合示例*部分. +* 如果你想遵循DDD最佳实践,请参阅下面的*聚合示例*部分. ### 具有复合键的实体 @@ -228,7 +228,7 @@ ABP框架不强制你应用任何DDD规则或模式.但是,当你准备应用的 ## 基类和接口的审计属性 -有一些属性,像`CreationTime`,`CreatorId`,`LastModificationTime`...在所有应用中都很常见. ABP框架提供了一些接口和基类来**标准化**这些属性,并**自动设置它们的值**. +有一些属性,像`CreationTime`,`CreatorId`,`LastModificationTime`...在所有应用中都很常见. ABP框架提供了一些接口和基类来**标准化**这些属性,并**自动设置它们的值**. ### 审计接口 @@ -285,7 +285,7 @@ ABP框架不强制你应用任何DDD规则或模式.但是,当你准备应用的 所有这些基类都有非泛型版本,可以使用 `AuditedEntity` 和 `FullAuditedAggregateRoot` 来支持复合主键; -所有这些基类也有 `... WithUser`,像 `FullAuditedAggregateRootWithUser` 和 `FullAuditedAggregateRootWithUser`. 这样就可以将导航属性添加到你的用户实体. 但在聚合根之间添加导航属性不是一个好做法,所以这种用法是不建议的(除非你使用EF Core之类的ORM可以很好地支持这种情况,并且你真的需要它. 请记住这种方法不适用于NoSQL数据库(如MongoDB),你必须真正实现聚合模式). +所有这些基类也有 `... WithUser`,像 `FullAuditedAggregateRootWithUser` 和 `FullAuditedAggregateRootWithUser`. 这样就可以将导航属性添加到你的用户实体. 但在聚合根之间添加导航属性不是一个好做法,所以这种用法是不建议的(除非你使用EF Core之类的ORM可以很好地支持这种情况,并且你真的需要它. 请记住这种方法不适用于NoSQL数据库(如MongoDB),你必须真正实现聚合模式). ## 额外的属性 diff --git a/docs/zh-Hans/Entity-Framework-Core-Migrations.md b/docs/zh-Hans/Entity-Framework-Core-Migrations.md index caef6e76f2..caf5778753 100644 --- a/docs/zh-Hans/Entity-Framework-Core-Migrations.md +++ b/docs/zh-Hans/Entity-Framework-Core-Migrations.md @@ -1,7 +1,7 @@  # EF Core数据库迁移 -本文首先介绍[应用程序启动模板](Startup-Templates/Application.md)提供的**默认结构**,并讨论您可能希望为自己的应用程序实现的**各种场景**. +本文首先介绍[应用程序启动模板](Startup-Templates/Application.md)提供的**默认结构**,并讨论你可能希望为自己的应用程序实现的**各种场景**. > 本文档适用于希望完全理解和自定义[应用程序启动模板](Startup-Templates/Application.md)附带的数据库结构的人员. 如果你只是想创建实体和管理代码优先(code first)迁移,只需要遵循[启动教程](Tutorials/Index.md). @@ -95,7 +95,7 @@ Volo.Abp.IdentityServer.AbpIdentityServerDbProperties.DbTablePrefix = "Ids"; 这个项目有应用程序的 `DbContext`类(本例中的 `BookStoreDbContex` ). -**每个模块都使用自己的 `DbContext` 类**来访问数据库。同样你的应用程序有它自己的 `DbContext`. 通常在应用程序中使用这个 `DbContet`(如果你遵循最佳实践,应该在[仓储](Repositories.md)中使用). 它几乎是一个空的 `DbContext`,因为你的应用程序在一开始没有任何实体,除了预定义的 `AppUser` 实体: +**每个模块都使用自己的 `DbContext` 类**来访问数据库.同样你的应用程序有它自己的 `DbContext`. 通常在应用程序中使用这个 `DbContet`(如果你遵循最佳实践,应该在[仓储](Repositories.md)中使用). 它几乎是一个空的 `DbContext`,因为你的应用程序在一开始没有任何实体,除了预定义的 `AppUser` 实体: ````csharp [ConnectionStringName("Default")] @@ -268,10 +268,10 @@ public class BackgroundJobsDbContext ##### 重用模块的表 -您可能想在应用程序中**重用依赖模块的表**. 在这种情况下你有两个选择: +你可能想在应用程序中**重用依赖模块的表**. 在这种情况下你有两个选择: 1. 你可以**直接使用模块定义的实体**(你仍然可以在某种程度上[扩展实体](Customizing-Application-Modules-Extending-Entities.md)). -2. 你可以**创建一个新的实体**映射到同一个数据库表。 +2. 你可以**创建一个新的实体**映射到同一个数据库表. ###### 使用由模块定义的实体 @@ -307,7 +307,7 @@ namespace Acme.BookStore 示例注入了 `IRepository`(默认仓储). 它定义了标准的存储库方法并实现了 `IQueryable` 接口. -另外,身份模块定义了 `IIdentityUserRepository`(自定义仓储),你的应用程序也可以注入和使用它. `IIdentityUserRepository` 为 `IdentityUser` 实体提供了额外的定制方法,但它没有实现 `IQueryable`. +另外,身份模块定义了 `IIdentityUserRepository`(自定义仓储),你的应用程序也可以注入和使用它. `IIdentityUserRepository` 为 `IdentityUser` 实体提供了额外的定制方法,但它没有实现 `IQueryable`. ###### 创建一个新的实体 @@ -352,7 +352,7 @@ namespace Acme.BookStore.Roles * 它继承了[`AggregateRoot`类](Entities.md)和实现了[`IMultiTenant`]接口(Multi-Tenancy.md),因为 `IdentityRole` 也做了同样的继承. * 你可以添加 `IdentityRole` 实体定义的任何属性. 本例只加了 `TenantId` 和 `Name` 属性,因为我们这里只需要它们. 你可以把setters设置为私有(如同本例)以防意外更改身份模块的属性. * 你可以添加自定义(附加)属性. 本例添加了 `Title` 属性. -* **构造函数是私有的**,所以它不允许直接创建一个新的 `AppRole` 实体。创建角色身份模块的责任. 你可以查询角色,设置/更新自定义属性,但做为最佳实践你不应该在代码中创建和删除角色(尽管没有强制的限制). +* **构造函数是私有的**,所以它不允许直接创建一个新的 `AppRole` 实体.创建角色身份模块的责任. 你可以查询角色,设置/更新自定义属性,但做为最佳实践你不应该在代码中创建和删除角色(尽管没有强制的限制). 现在是时候定义EF Core映射. 打开应用程序的 `DbContext` (此示例中是 `BookStoreDbContext` )添加以下属性: @@ -360,7 +360,7 @@ namespace Acme.BookStore.Roles public DbSet Roles { get; set; } ```` -然后在 `OnModelCreating` 方法中配置映射(调用 `base.OnModelCreating(builder)` 之后): +然后在 `OnModelCreating` 方法中配置映射(调用 `base.OnModelCreating(builder)` 之后): ````csharp protected override void OnModelCreating(ModelBuilder builder) diff --git a/docs/zh-Hans/Entity-Framework-Core-MySQL.md b/docs/zh-Hans/Entity-Framework-Core-MySQL.md index 5f9d8023ab..15e2205c38 100644 --- a/docs/zh-Hans/Entity-Framework-Core-MySQL.md +++ b/docs/zh-Hans/Entity-Framework-Core-MySQL.md @@ -12,12 +12,12 @@ ## UseMySQL() -查找你的解决方案中 `UseSqlServer()`调用,替换为 `UseMySQL()`. 检查下列文件: +查找你的解决方案中 `UseSqlServer()`调用,替换为 `UseMySQL()`. 检查下列文件: * `.EntityFrameworkCore` 项目中的*YourProjectName*EntityFrameworkCoreModule.cs. * `.EntityFrameworkCore` 项目中的*YourProjectName*MigrationsDbContextFactory.cs. -> 根据你的解决方案的结构,你可能发现更多需要改变代码的文件. +> 根据你的解决方案的结构,你可能发现更多需要改变代码的文件. ## 更改连接字符串 @@ -27,7 +27,7 @@ MySQL连接字符串与SQL Server连接字符串不同. 所以检查你的解决 ## 更改迁移DbContext -MySQL DBMS与SQL Server有一些细微的差异. 某些模块数据库映射配置(尤其是字段长度)会导致MySQL出现问题. 例如某些[IdentityServer模块](Modules/IdentityServer.md)表就存在这样的问题,它提供了一个选项可以根据您的DBMS配置字段. +MySQL DBMS与SQL Server有一些细微的差异. 某些模块数据库映射配置(尤其是字段长度)会导致MySQL出现问题. 例如某些[IdentityServer模块](Modules/IdentityServer.md)表就存在这样的问题,它提供了一个选项可以根据你的DBMS配置字段. 启动模板包含*YourProjectName*MigrationsDbContext,它负责维护和迁移数据库架构. 此DbContext基本上调用依赖模块的扩展方法来配置其数据库表. diff --git a/docs/zh-Hans/Entity-Framework-Core-Other-DBMS.md b/docs/zh-Hans/Entity-Framework-Core-Other-DBMS.md index ca12d7524f..ca70d8b5c6 100644 --- a/docs/zh-Hans/Entity-Framework-Core-Other-DBMS.md +++ b/docs/zh-Hans/Entity-Framework-Core-Other-DBMS.md @@ -63,7 +63,7 @@ MySQL连接字符串与SQL Server连接字符串不同. 所以检查你的解决 ## 更改迁移DbContext -MySQL DBMS与SQL Server有一些细微的差异. 某些模块数据库映射配置(尤其是字段长度)会导致MySQL出现问题. 例如某些[IdentityServer模块](Modules/IdentityServer.md)表就存在这样的问题,它提供了一个选项可以根据您的DBMS配置字段. +MySQL DBMS与SQL Server有一些细微的差异. 某些模块数据库映射配置(尤其是字段长度)会导致MySQL出现问题. 例如某些[IdentityServer模块](Modules/IdentityServer.md)表就存在这样的问题,它提供了一个选项可以根据你的DBMS配置字段. 启动模板包含*YourProjectName*MigrationsDbContext,它负责维护和迁移数据库架构. 此DbContext基本上调用依赖模块的扩展方法来配置其数据库表. diff --git a/docs/zh-Hans/Entity-Framework-Core-PostgreSQL.md b/docs/zh-Hans/Entity-Framework-Core-PostgreSQL.md index bb1de20207..08f8f405d1 100644 --- a/docs/zh-Hans/Entity-Framework-Core-PostgreSQL.md +++ b/docs/zh-Hans/Entity-Framework-Core-PostgreSQL.md @@ -12,12 +12,12 @@ ## UsePostgreSql() -查找你的解决方案中 `UseSqlServer()`调用,替换为 `UsePostgreSql()`. 检查下列文件: +查找你的解决方案中 `UseSqlServer()`调用,替换为 `UsePostgreSql()`. 检查下列文件: * `.EntityFrameworkCore` 项目中的*YourProjectName*EntityFrameworkCoreModule.cs. * `.EntityFrameworkCore` 项目中的*YourProjectName*MigrationsDbContextFactory.cs. -> 根据你的解决方案的结构,你可能发现更多需要改变代码的文件. +> 根据你的解决方案的结构,你可能发现更多需要改变代码的文件. ## 更改连接字符串 diff --git a/docs/zh-Hans/Entity-Framework-Core-SQLite.md b/docs/zh-Hans/Entity-Framework-Core-SQLite.md index 4b8e009fe4..d75f8ba5b7 100644 --- a/docs/zh-Hans/Entity-Framework-Core-SQLite.md +++ b/docs/zh-Hans/Entity-Framework-Core-SQLite.md @@ -12,12 +12,12 @@ ## UseSqlite() -查找你的解决方案中 `UseSqlServer()`调用,替换为 `UseSqlite()`. 检查下列文件: +查找你的解决方案中 `UseSqlServer()`调用,替换为 `UseSqlite()`. 检查下列文件: * `.EntityFrameworkCore` 项目中的*YourProjectName*EntityFrameworkCoreModule.cs. * `.EntityFrameworkCore` 项目中的*YourProjectName*MigrationsDbContextFactory.cs. -> 根据你的解决方案的结构,你可能发现更多需要改变代码的文件. +> 根据你的解决方案的结构,你可能发现更多需要改变代码的文件. ## 更改连接字符串 diff --git a/docs/zh-Hans/Entity-Framework-Core.md b/docs/zh-Hans/Entity-Framework-Core.md index d2af31f4d2..5ae6ce1070 100644 --- a/docs/zh-Hans/Entity-Framework-Core.md +++ b/docs/zh-Hans/Entity-Framework-Core.md @@ -108,7 +108,7 @@ protected override void OnModelCreating(ModelBuilder builder) ### 配置连接字符串选择 如果你的应用程序有多个数据库,你可以使用 `connectionStringName]` Attribute为你的DbContext配置连接字符串名称. -例: +例: ```csharp [ConnectionStringName("MySecondConnString")] @@ -274,7 +274,7 @@ public override async Task DeleteAsync( ## 访问 EF Core API -大多数情况下应该隐藏仓储后面的EF Core API(这也是仓储的设计目地). 但是如果想要通过仓储访问DbContext实现,则可以使用`GetDbContext()`或`GetDbSet()`扩展方法. 例: +大多数情况下应该隐藏仓储后面的EF Core API(这也是仓储的设计目地). 但是如果想要通过仓储访问DbContext实现,则可以使用`GetDbContext()`或`GetDbSet()`扩展方法. 例: ````csharp public class BookService @@ -304,7 +304,7 @@ public class BookService 默认,实体的所有额外属性存储在数据库的一个 `JSON` 对象中. -实体扩展系统允许你存储额外属性在数据库的单独字段中. 有关额外属性和实体扩展系统的更多信息,请参阅下列文档: +实体扩展系统允许你存储额外属性在数据库的单独字段中. 有关额外属性和实体扩展系统的更多信息,请参阅下列文档: * [自定义应用模块: 扩展实体](Customizing-Application-Modules-Extending-Entities.md) * [实体](Entities.md) @@ -313,7 +313,7 @@ public class BookService ### ObjectExtensionManager.Instance -`ObjectExtensionManager` 实现单例模式,因此你需要使用静态的 `ObjectExtensionManager.Instance` 来执行所有操作。 +`ObjectExtensionManager` 实现单例模式,因此你需要使用静态的 `ObjectExtensionManager.Instance` 来执行所有操作. ### MapEfCoreProperty @@ -417,7 +417,7 @@ context.Services.AddAbpDbContext(options => }); ```` -现在,您的自定义仓储也可以使用`IBookStoreDbContext`接口: +现在,你的自定义仓储也可以使用`IBookStoreDbContext`接口: ````csharp public class BookRepository : EfCoreRepository, IBookRepository diff --git a/docs/zh-Hans/Exception-Handling.md b/docs/zh-Hans/Exception-Handling.md index 6bbbed56d4..3d8408b26d 100644 --- a/docs/zh-Hans/Exception-Handling.md +++ b/docs/zh-Hans/Exception-Handling.md @@ -295,8 +295,8 @@ services.Configure(options => 框架会自动抛出以下异常类型: -- 当用户没有权限执行操作时,会抛出 `AbpAuthorizationException` 异常. 有关更多信息,请参阅授权文档(TODO:link). -- 如果当前请求的输入无效,则抛出`AbpValidationException 异常`. 有关更多信息,请参阅授权文档(TODO:link). +- 当用户没有权限执行操作时,会抛出 `AbpAuthorizationException` 异常. 有关更多信息,请参阅授权文档[authorization](Authorization.md). +- 如果当前请求的输入无效,则抛出`AbpValidationException 异常`. 有关更多信息,请参阅[验证文档](Validation.md). - 如果请求的实体不存在,则抛出`EntityNotFoundException` 异常. 此异常大多数由 [repositories](Repositories.md) 抛出. 你同样可以在代码中抛出这些类型的异常(虽然很少需要这样做) diff --git a/docs/zh-Hans/Getting-Started-AspNetCore-Application.md b/docs/zh-Hans/Getting-Started-AspNetCore-Application.md index 370e99c091..46348ecbdf 100644 --- a/docs/zh-Hans/Getting-Started-AspNetCore-Application.md +++ b/docs/zh-Hans/Getting-Started-AspNetCore-Application.md @@ -156,7 +156,7 @@ services.AddApplication(options => }); ```` -4. 更新 `Program.cs`代码, 不再使用`WebHost.CreateDefaultBuilder()`方法(因为它使用默认的DI容器): +4. 更新 `Program.cs`代码, 不再使用`WebHost.CreateDefaultBuilder()`方法(因为它使用默认的DI容器): ````csharp public class Program diff --git a/docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md b/docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md index 90291e968f..2778f3db42 100644 --- a/docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md +++ b/docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md @@ -4,7 +4,7 @@ 本教程使用 **ABP CLI** 创建一个新项目. 更多选项, 请参阅[入门](https://abp.io/get-started)页面. -如果你之前未安装,请使用命令行安装ABP CLI: +如果你之前未安装,请使用命令行安装ABP CLI: ````bash dotnet tool install -g Volo.Abp.Cli diff --git a/docs/zh-Hans/How-To/Customize-SignIn-Manager.md b/docs/zh-Hans/How-To/Customize-SignIn-Manager.md index a98c57e495..2b6f7a612f 100644 --- a/docs/zh-Hans/How-To/Customize-SignIn-Manager.md +++ b/docs/zh-Hans/How-To/Customize-SignIn-Manager.md @@ -42,14 +42,14 @@ public override async Task GetE { var auth = await Context.AuthenticateAsync(Microsoft.AspNetCore.Identity.IdentityConstants.ExternalScheme); var items = auth?.Properties?.Items; - if (auth?.Principal == null || items == null || !items.ContainsKey("LoginProviderKey")) + if (auth?.Principal == null || items == null || !items.ContainsKey(LoginProviderKey)) { return null; } if (expectedXsrf != null) { - if (!items.ContainsKey("XsrfKey")) + if (!items.ContainsKey(XsrfKey)) { return null; } diff --git a/docs/zh-Hans/Index.md b/docs/zh-Hans/Index.md index d946d8f0bb..71e5a520da 100644 --- a/docs/zh-Hans/Index.md +++ b/docs/zh-Hans/Index.md @@ -12,7 +12,7 @@ ABP是一个**开源应用程序框架**,专注于基于ASP.NET Core的Web应用 * [ASP.NET Core MVC 模板](Getting-Started-AspNetCore-MVC-Template.md) -如果您想从头开始(使用空项目),请手动安装ABP框架并使用以下教程: +如果你想从头开始(使用空项目),请手动安装ABP框架并使用以下教程: * [控制台应用程序](Getting-Started-Console-Application.md) * [ASP.NET Core Web 应用程序](Getting-Started-AspNetCore-Application.md) diff --git a/docs/zh-Hans/Modules/Docs.md b/docs/zh-Hans/Modules/Docs.md index 20382d24f2..96452f2bd5 100644 --- a/docs/zh-Hans/Modules/Docs.md +++ b/docs/zh-Hans/Modules/Docs.md @@ -326,7 +326,7 @@ There are no projects yet! {"GitHubRootUrl":"https://github.com/abpframework/abp/tree/{version}/docs/zh-Hans/","GitHubAccessToken":"***","GitHubUserAgent":""} ``` - 注意 `GitHubAccessToken` 用 `***` 掩盖. 这是一个私人令牌,你必须从GitHub获取它. 请参阅 https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/ + 注意 `GitHubAccessToken` 用 `***` 掩盖. 这是一个私人令牌,你必须从GitHub获取它. 请参阅 https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/ - MainWebsiteUrl: `/` @@ -338,7 +338,7 @@ There are no projects yet! INSERT [dbo].[DocsProjects] ([Id], [Name], [ShortName], [Format], [DefaultDocumentName], [NavigationDocumentName], [MinimumVersion], [DocumentStoreType], [ExtraProperties], [MainWebsiteUrl], [LatestVersionBranchName], [ParametersDocumentName]) VALUES (N'12f21123-e08e-4f15-bedb-ae0b2d939658', N'ABP framework (GitHub)', N'abp', N'md', N'Index', N'docs-nav.json', NULL, N'GitHub', N'{"GitHubRootUrl":"https://github.com/abpframework/abp/tree/{version}/docs","GitHubAccessToken":"***","GitHubUserAgent":""}', N'/', N'master', N'') ``` -请注意,`GitHubAccessToken` 被屏蔽了.它是一个私人令牌,你必须获得自己的令牌并替换 `***` 字符串. +请注意,`GitHubAccessToken` 被屏蔽了.它是一个私人令牌,你必须获得自己的令牌并替换 `***` 字符串. 现在你可以运行应用程序并导航到 `/Documents`. @@ -378,9 +378,9 @@ INSERT [dbo].[DocsProjects] ([Id], [Name], [ShortName], [Format], [DefaultDocume INSERT [dbo].[DocsProjects] ([Id], [Name], [ShortName], [Format], [DefaultDocumentName], [NavigationDocumentName], [MinimumVersion], [DocumentStoreType], [ExtraProperties], [MainWebsiteUrl], [LatestVersionBranchName], [ParametersDocumentName]) VALUES (N'12f21123-e08e-4f15-bedb-ae0b2d939659', N'ABP framework (FileSystem)', N'abp', N'md', N'Index', N'docs-nav.json', NULL, N'FileSystem', N'{"Path":"C:\\Github\\abp\\docs"}', N'/', NULL, N'') ``` -添加上面的一个示例项目后运行该应用程序. 在菜单中你会看到`文档` 链接,点击菜单链接打开文档页面. +添加上面的一个示例项目后运行该应用程序. 在菜单中你会看到`文档` 链接,点击菜单链接打开文档页面. -到目前为止, 我们已经从abp.io网站创建了一个新的应用程序,并为Docs模块做好准备. +到目前为止, 我们已经从abp.io网站创建了一个新的应用程序,并为Docs模块做好准备. ### 7- 添加一个新文档 @@ -454,7 +454,7 @@ public class Person } ``` -因为并不是项目中的每个文档都有章节或者不需要所有的参数,你必须声明哪些参数将用于对文档进行分段,在文档的任何地方都可以使用JSON块. +因为并不是项目中的每个文档都有章节或者不需要所有的参数,你必须声明哪些参数将用于对文档进行分段,在文档的任何地方都可以使用JSON块. 例如 [Getting-Started.md](https://github.com/abpio/abp-commercial-docs/blob/master/en/getting-started.md): @@ -570,7 +570,7 @@ This document assumes that you prefer to use **{{ UI_Value }}** as the UI framew ![Navigation menu](../images/docs-module_download-sample-navigation-menu.png) -最后,为您的项目添加了一个新的Docs模块, 该模块由GitHub提供. +最后,为你的项目添加了一个新的Docs模块, 该模块由GitHub提供. ## 全文搜索(Elastic Search) diff --git a/docs/zh-Hans/Multi-Tenancy.md b/docs/zh-Hans/Multi-Tenancy.md index 8913c27ede..49cf358205 100644 --- a/docs/zh-Hans/Multi-Tenancy.md +++ b/docs/zh-Hans/Multi-Tenancy.md @@ -172,11 +172,11 @@ namespace MyCompany.MyProject { options.Tenants = new[] { - new TenantInformation( + new TenantConfiguration( Guid.Parse("446a5211-3d72-4339-9adc-845151f8ada0"), //Id "tenant1" //Name ), - new TenantInformation( + new TenantConfiguration( Guid.Parse("25388015-ef1c-4355-9c18-f6b6ddbaf89d"), //Id "tenant2" //Name ) @@ -252,7 +252,7 @@ TODO: This package implements ITenantStore using a real database... #### 租户信息 -ITenantStore跟 **TenantInformation**类一起工作,并且包含了几个租户属性: +ITenantStore跟 **TenantConfiguration**类一起工作,并且包含了几个租户属性: * **Id**:租户的唯一Id. * **Name**: 租户的唯一名称. diff --git a/docs/zh-Hans/Object-Extensions.md b/docs/zh-Hans/Object-Extensions.md index 27957708f4..a0f1e5534b 100644 --- a/docs/zh-Hans/Object-Extensions.md +++ b/docs/zh-Hans/Object-Extensions.md @@ -62,7 +62,7 @@ if (user.GetProperty("IsSuperUser")) ##### 非基本属性类型 -如果您的属性类型不是原始类型(int,bool,枚举,字符串等),你需要使用 `GetProperty` 的非泛型版本,它会返回 `object`. +如果你的属性类型不是原始类型(int,bool,枚举,字符串等),你需要使用 `GetProperty` 的非泛型版本,它会返回 `object`. #### HasProperty @@ -180,7 +180,7 @@ ObjectExtensionManager.Instance 假设你已向可扩展的实体对象添加了额外的属性并使用了自动[对象到对象的映射](Object-To-Object-Mapping.md)将该实体映射到可扩展的DTO类. 在这种情况下你需要格外小心,因为额外属性可能包含**敏感数据**,这些数据对于客户端不可用. -本节提供了一些**好的做法**,可以控制对象映射的额外属性。 +本节提供了一些**好的做法**,可以控制对象映射的额外属性. ### MapExtraPropertiesTo @@ -232,7 +232,7 @@ identityUser.MapExtraPropertiesTo( #### AutoMapper集成 -如果您使用的是[AutoMapper](https://automapper.org/)库,ABP框架还提供了一种扩展方法来利用上面定义的 `MapExtraPropertiesTo` 方法. +如果你使用的是[AutoMapper](https://automapper.org/)库,ABP框架还提供了一种扩展方法来利用上面定义的 `MapExtraPropertiesTo` 方法. 你可以在映射配置文件中使用 `MapExtraProperties()` 方法. @@ -247,7 +247,7 @@ public class MyProfile : Profile } ```` -它与 `MapExtraPropertiesTo()` 方法具有相同的参数。 +它与 `MapExtraPropertiesTo()` 方法具有相同的参数. ## Entity Framework Core 数据库映射 diff --git a/docs/zh-Hans/Object-To-Object-Mapping.md b/docs/zh-Hans/Object-To-Object-Mapping.md index 57b744e0bf..1b60112cb2 100644 --- a/docs/zh-Hans/Object-To-Object-Mapping.md +++ b/docs/zh-Hans/Object-To-Object-Mapping.md @@ -168,7 +168,7 @@ public class MyProfile : Profile 假设你已经创建了一个**可重用的模块**,其中定义了AutoMapper配置文件,并在需要映射对象时使用 `IObjectMapper`. 根据[模块化](Module-Development-Basics.md)的性质,你的模块可以用于不同的应用程序. -`IObjectMapper` 是一个抽象,可以由最终应用程序替换使用另一个映射库. 这里的问题是你的可重用模块设计为使用AutoMapper,因为它为其定义映射配置文件. 这种情况下即使最终应用程序使用另一个默认对象映射库,你也要保证模块始终使用AutoMapper. +`IObjectMapper` 是一个抽象,可以由最终应用程序替换使用另一个映射库. 这里的问题是你的可重用模块设计为使用AutoMapper,因为它为其定义映射配置文件. 这种情况下即使最终应用程序使用另一个默认对象映射库,你也要保证模块始终使用AutoMapper. `IObjectMapper`将对象映射器上下文化,你可以为不同的 模块/上下文 使用不同的库. @@ -201,7 +201,7 @@ public class UserAppService : ApplicationService `UserAppService` 注入 `IObjectMapper`, 它是模块的特定对象映射器,用法与 `IObjectMapper` 完全相同. -上面的示例代码未使用 `ApplicationService` 中定义的 `ObjectMapper` 属性,而是注入了 `IObjectMapper`. 但是 `ApplicationService` 定义了可以在类构造函数中设置的 `ObjectMapperContext` 属性, 因此仍然可以使用基类属性. 示例可以进行以下重写: +上面的示例代码未使用 `ApplicationService` 中定义的 `ObjectMapper` 属性,而是注入了 `IObjectMapper`. 但是 `ApplicationService` 定义了可以在类构造函数中设置的 `ObjectMapperContext` 属性, 因此仍然可以使用基类属性. 示例可以进行以下重写: ````csharp public class UserAppService : ApplicationService diff --git a/docs/zh-Hans/Options.md b/docs/zh-Hans/Options.md index 18ccd90bed..c88ff0adda 100644 --- a/docs/zh-Hans/Options.md +++ b/docs/zh-Hans/Options.md @@ -9,7 +9,7 @@ ABP框架遵循选项模式,并定义了用于配置框架和模块的选项类( ## 配置选项 通常配置选项在 `Startup` 类的 `ConfigureServices` 方法中. 但由于ABP框架提供了模块化基础设施,因此你可以在[模块](Module-Development-Basics.md)的`ConfigureServices` 方法配置选项. -例: +例: ````csharp public override void ConfigureServices(ServiceConfigurationContext context) @@ -34,7 +34,7 @@ public class MyOptions } ```` -然后开发人员可以像上面 `AbpAuditingOptions` 示例一样配置你的选项: +然后开发人员可以像上面 `AbpAuditingOptions` 示例一样配置你的选项: ````csharp public override void ConfigureServices(ServiceConfigurationContext context) @@ -80,9 +80,9 @@ public class MyService : ITransientDependency 如果你正在开发一个模块,可能需要让开发者能够设置一些选项,并在依赖注入注册阶段使用这些选项. 你可能需要根据选项值配置其他服务或更改依赖注入的注册代码. -对于此类情况,ABP为 `IServiceCollection` 引入了 `PreConfigure` 和 `ExecutePreConfiguredActions` 扩展方法. 该模式的工作原理如下所述。 +对于此类情况,ABP为 `IServiceCollection` 引入了 `PreConfigure` 和 `ExecutePreConfiguredActions` 扩展方法. 该模式的工作原理如下所述. -1. 你的模块中定义计划选项类. 例: +1. 你的模块中定义计划选项类. 例: ````csharp public class MyPreOptions @@ -92,7 +92,7 @@ public class MyPreOptions ```` 然后任何依赖于模块的模块类都可以在其 `PreConfigureServices` 方法中使用 `PreConfigure` 方法. -例: +例: ````csharp public override void PreConfigureServices(ServiceConfigurationContext context) diff --git a/docs/zh-Hans/Samples/Microservice-Demo.md b/docs/zh-Hans/Samples/Microservice-Demo.md index 9b559797f7..40cb42cda6 100644 --- a/docs/zh-Hans/Samples/Microservice-Demo.md +++ b/docs/zh-Hans/Samples/Microservice-Demo.md @@ -51,13 +51,13 @@ ABP框架的主要目标之一就是提供[便捷的基础设施来创建微服 ### 创建数据库 -MongoDB 数据库是动态创建的,但是你需要创建 SQL server 数据库的结构。其实你可以很轻松的创建数据库,因为这个解决方案配置了使用 Entity Core Code First 来做迁移。 +MongoDB 数据库是动态创建的,但是你需要创建 SQL server 数据库的结构.其实你可以很轻松的创建数据库,因为这个解决方案配置了使用 Entity Core Code First 来做迁移. -这个解决方案中有两个 SQL server 数据库。 +这个解决方案中有两个 SQL server 数据库. #### MsDemo_Identity 数据库 -* 右键 `AuthServer.Host` 项目,然后点击 `设置为启动项目`. +* 右键 `AuthServer.Host` 项目,然后点击 `设置为启动项目`. * 打开 **程序包管理器控制台** (工具 -> NuGet 包管理器 -> 程序包管理器控制台) * 选择 `AuthServer.Host` 成为 **默认项目**. * 执行 `Update-Database` 命令. @@ -66,7 +66,7 @@ MongoDB 数据库是动态创建的,但是你需要创建 SQL server 数据库 #### MsDemo_ProductManagement -* 右键 `ProductService.Host` 项目,然后点击 `设置为启动项目`. +* 右键 `ProductService.Host` 项目,然后点击 `设置为启动项目`. * 打开 **程序包管理器控制台** (工具 -> NuGet 包管理器 -> 程序包管理器控制台) * 选择 `ProductService.Host` 成为 **默认项目**. * 执行 `Update-Database` 命令. @@ -334,7 +334,7 @@ context.Services.AddAuthentication(options => - 它需要额外的身份范围 *role*, *email* and *phone*. - 它需要API资源范围 *PublicWebSiteGateway*,*BloggingService*和*ProductService*,因为它将这些服务用作API. -IdentityServer客户端设置存储在`appsettings.json`文件中: +IdentityServer客户端设置存储在`appsettings.json`文件中: ```json "AuthServer": { @@ -348,7 +348,7 @@ IdentityServer客户端设置存储在`appsettings.json`文件中: PublicWebSite.Host项目有一个列出产品的页面 (`Pages/Products.cshtml`). 它还使用博客模块中的UI. 为此`PublicWebSiteHostModule`加入了`BloggingWebModule`(*[Volo.Blogging.Web](https://www.nuget.org/packages/Volo.Blogging.Web)* 包)的依赖项. -产品页面的屏幕截图: +产品页面的屏幕截图: ![microservice-sample-public-product-list](../images/microservice-sample-public-product-list.png) @@ -390,7 +390,7 @@ PublicWebSite.Host项目有一个列出产品的页面 (`Pages/Products.cshtml`) #### 远程服务配置 -`appsettings.json`文件中的`RemoteService`配置很简单: +`appsettings.json`文件中的`RemoteService`配置很简单: ````json "RemoteServices": { @@ -418,7 +418,7 @@ PublicWebSite.Host项目有一个列出产品的页面 (`Pages/Products.cshtml`) } ```` -此示例使用`client_credentials` 授予类型,该类型需要`ClientId`和`ClientSecret`进行身份验证过程. 还有[其他授予类型](http://docs.identityserver.io/en/latest/topics/grant_types.html). 例如, 你可以使用以下配置切换到`password`(Resource Owner Password)授予类型: +此示例使用`client_credentials` 授予类型,该类型需要`ClientId`和`ClientSecret`进行身份验证过程. 还有[其他授予类型](http://docs.identityserver.io/en/latest/topics/grant_types.html). 例如, 你可以使用以下配置切换到`password`(Resource Owner Password)授予类型: ````json "IdentityClients": { @@ -571,7 +571,7 @@ app.UseOcelot().Wait(); #### 权限管理 -后端管理应用程序提供权限管理UI(之前见过),并使用此网关获取/设置权限. 权限管理API托管在网关内,而不是单独的服务. 这是一个设计决策,但如果您愿意,它可以作为另一个微服务托管. +后端管理应用程序提供权限管理UI(之前见过),并使用此网关获取/设置权限. 权限管理API托管在网关内,而不是单独的服务. 这是一个设计决策,但如果你愿意,它可以作为另一个微服务托管. #### Dependencies @@ -1229,7 +1229,7 @@ public class ProductCodeAlreadyExistsException : BusinessException } ```` -`PM:000001`是发送给客户端的异常类型的代码,因此他们可以理解错误类型. 在这种情况下没有实现,但也可以本地化业务异常. 请参阅[异常处理文档](../Exception-Handling.md). +`PM:000001`是发送给客户端的异常类型的代码,因此他们可以理解错误类型. 在这种情况下没有实现,但也可以本地化业务异常. 请参阅[异常处理文档](../Exception-Handling.md). #### 应用层 @@ -1278,7 +1278,7 @@ public async Task UpdateAsync(Guid id, UpdateProductDto input) 分布式事件(事件总线)是一种消息传递方式,其中服务引发/触发事件,而其他服务注册/侦听这些事件,以便在发生重要事件时得到通知. ABP通过提供约定,服务和集成使分布式事件更易于使用. -您已经看到`Product`类使用以下代码行发布事件: +你已经看到`Product`类使用以下代码行发布事件: ````csharp AddDistributedEvent(new ProductStockCountChangedEto(Id, StockCount, stockCount)); @@ -1406,7 +1406,7 @@ Kibana URL默认为`http://localhost:5601/`. ABP提供自动审计日志记录,详细保存每个请求(当前用户,浏览器/客户端,执行了哪些操作,哪些实体更改,甚至实体的哪些属性已更新). 有关详细信息,请参阅[审计日志文档](../Audit-Logging.md). -所有服务和应用程序都配置为编写审核日志. 审核日志将保存到MsDemo_Identity SQL数据库中. 因此,您可以从单个点查询所有应用程序的所有审核日志. +所有服务和应用程序都配置为编写审核日志. 审核日志将保存到MsDemo_Identity SQL数据库中. 因此,你可以从单个点查询所有应用程序的所有审核日志. 审核日志记录具有`CorrelationId`属性,可用于跟踪请求. 当服务在单个Web请求中调用另一个服务时,它们都会使用相同的`CorrelationId`保存审核日志. 请参阅数据库中的`AbpAuditLogs`表. diff --git a/docs/zh-Hans/Settings.md b/docs/zh-Hans/Settings.md index 25559082f2..a4d84c91b7 100644 --- a/docs/zh-Hans/Settings.md +++ b/docs/zh-Hans/Settings.md @@ -226,6 +226,6 @@ Configure(options => ## 设置管理模块 -设置系统核心是相当独立的,不做任何关于如何管理(更改)设置值的假设. 默认的`ISettingStore`实现也是`NullSettingStore`,它为所有设置值返回null. +设置系统核心是相当独立的,不做任何关于如何管理(更改)设置值的假设. 默认的`ISettingStore`实现也是`NullSettingStore`,它为所有设置值返回null. 设置管理模块通过管理数据库中的设置值来完成逻辑(实现`ISettingStore`).有关更多信息参阅[设置管理模块](Modules/Setting-Management.md)学习更多. diff --git a/docs/zh-Hans/Specifications.md b/docs/zh-Hans/Specifications.md new file mode 100644 index 0000000000..f927c80255 --- /dev/null +++ b/docs/zh-Hans/Specifications.md @@ -0,0 +1,3 @@ +## 规约 + +TODO.. \ No newline at end of file diff --git a/docs/zh-Hans/Startup-Templates/Application.md b/docs/zh-Hans/Startup-Templates/Application.md index ecf57a19cd..4e2c3f6700 100644 --- a/docs/zh-Hans/Startup-Templates/Application.md +++ b/docs/zh-Hans/Startup-Templates/Application.md @@ -348,7 +348,7 @@ Home模块是一个可延迟加载的模块, 它加载应用程序的根地址. React 本机应用程序是用 [Expo](https://expo.io/)生成的. Expo 是一套基于 React Native 构建的工具, 帮助你快速启动一个应用程序, 尽管它有很多功能. -React Native 应用文件夹结构, 如下图所示: +React Native 应用文件夹结构, 如下图所示: ![react-native-folder-structure](../images/react-native-folder-structure.png) @@ -362,7 +362,7 @@ React Native 应用文件夹结构, 如下图所示: #### Components(组件) -可以在所有屏幕上使用的组件是在 `src/components` 文件夹中创建的. 所有组件都是作为一个能够使用 [hooks](https://reactjs.org/docs/hooks-intro.html) 的函数创建的. +可以在所有屏幕上使用的组件是在 `src/components` 文件夹中创建的. 所有组件都是作为一个能够使用 [hooks](https://reactjs.org/docs/hooks-intro.html) 的函数创建的. #### Screens(屏幕) @@ -378,50 +378,50 @@ Screens 是通过在 `src/screens` 文件夹中创建将名称分开的文件夹 #### State Management(状态管理) -[Redux](https://redux.js.org/) 被用作状态管理库. [Redux Toolkit](https://redux-toolkit.js.org/) 库被用作高效Redux开发的工具集. +[Redux](https://redux.js.org/) 被用作状态管理库. [Redux Toolkit](https://redux-toolkit.js.org/) 库被用作高效Redux开发的工具集. -在 `src/store` 文件夹中创建 Actions, reducers, sagas, selectors. 存储文件夹如下: +在 `src/store` 文件夹中创建 Actions, reducers, sagas, selectors. 存储文件夹如下: ![react-native-store-folder](../images/react-native-store-folder.png) * [**Store**](https://redux.js.org/basics/store) 在 `src/store/index.js` 文件中定义. * [**Actions**](https://redux.js.org/basics/actions/) 是将数据从应用程序发送到存储的有效信息负载. * [**Reducers**](https://redux.js.org/basics/reducers) 指定应用程序的状态如何更改以响应发送到存储的操作. -* [**Redux-Saga**](https://redux-saga.js.org/) 是一个库, 旨在使应用程序的副作用(即异步的事情, 如数据获取和不纯的事情, 如访问浏览器缓存)更容易管理. Sagas 是在 `src/store/sagas` 文件夹中创建的. +* [**Redux-Saga**](https://redux-saga.js.org/) 是一个库, 旨在使应用程序的副作用(即异步的事情, 如数据获取和不纯的事情, 如访问浏览器缓存)更容易管理. Sagas 是在 `src/store/sagas` 文件夹中创建的. * [**Reselect**](https://github.com/reduxjs/reselect) 库用于创建缓存的选择器. 选择器是在 `src/store/selectors` 文件夹中创建的. #### APIs -[Axios](https://github.com/axios/axios) 用作HTTP客户端库. Axios 实例从 `src/api/API.js` 导出 . 使用相同的配置进行HTTP调用. `src/api` 文件夹中还有为 API 调用创建的 API 文件. +[Axios](https://github.com/axios/axios) 用作HTTP客户端库. Axios 实例从 `src/api/API.js` 导出 . 使用相同的配置进行HTTP调用. `src/api` 文件夹中还有为 API 调用创建的 API 文件. #### Theming(主题) -[Native Base](https://nativebase.io/) 被用作UI组件库. 本地基本组件可以很容易地进行自定义。参见 [Native Base customize](https://docs.nativebase.io/Customize.html#Customize) 文档。我们沿着同样的路走。 +[Native Base](https://nativebase.io/) 被用作UI组件库. 本地基本组件可以很容易地进行自定义.参见[Native Base customize](https://docs.nativebase.io/Customize.html#Customize) 文档.我们沿着同样的路走. -* Native Base 主题变量在 `src/theme/variables` 文件夹中。 -* Native Base 组件样式在 `src/theme/components` 文件夹中。这些文件是用 Native Base's `ejectTheme` 脚本生成的。 -* 组件样式用 `src/theme/overrides` 文件夹下的文件覆盖。 +* Native Base 主题变量在 `src/theme/variables` 文件夹中. +* Native Base 组件样式在 `src/theme/components` 文件夹中.这些文件是用 Native Base's `ejectTheme` 脚本生成的. +* 组件样式用 `src/theme/overrides` 文件夹下的文件覆盖. #### Testing(单元测试) -将创建单元测试。 +将创建单元测试. -参见[测试概述](https://reactjs.org/docs/testing.html)文档。 +参见[测试概述](https://reactjs.org/docs/testing.html)文档. #### Depended Libraries(依赖库) -* [Native Base](https://nativebase.io/) 用作UI组件库。 -* [React Navigation](https://reactnavigation.org/) 用作导航库。 -* [Axios](https://github.com/axios/axios) 用作HTTP客户端库。 -* [Redux](https://redux.js.org/) 用作状态管理库。 -* [Redux Toolkit](https://redux-toolkit.js.org/) 库被用作高效Redux开发的工具集。 -* [Redux-Saga](https://redux-saga.js.org/) 用于管理异步进程。 -* [Redux Persist](https://github.com/rt2zz/redux-persist) 被用作状态持久化。 -* [Reselect](https://github.com/reduxjs/reselect) 用于创建缓存的选择器。 -* [i18n-js](https://github.com/fnando/i18n-js) 作为国际化库使用。 -* [expo-font](https://docs.expo.io/versions/latest/sdk/font/) 库可以轻松加载字体。 -* [Formik](https://github.com/jaredpalmer/formik) 用于构建表单。 -* [Yup](https://github.com/jquense/yup) 用于表单验证。 +* [Native Base](https://nativebase.io/) 用作UI组件库. +* [React Navigation](https://reactnavigation.org/) 用作导航库. +* [Axios](https://github.com/axios/axios) 用作HTTP客户端库. +* [Redux](https://redux.js.org/) 用作状态管理库. +* [Redux Toolkit](https://redux-toolkit.js.org/) 库被用作高效Redux开发的工具集. +* [Redux-Saga](https://redux-saga.js.org/) 用于管理异步进程. +* [Redux Persist](https://github.com/rt2zz/redux-persist) 被用作状态持久化. +* [Reselect](https://github.com/reduxjs/reselect) 用于创建缓存的选择器. +* [i18n-js](https://github.com/fnando/i18n-js) 作为国际化库使用. +* [expo-font](https://docs.expo.io/versions/latest/sdk/font/) 库可以轻松加载字体. +* [Formik](https://github.com/jaredpalmer/formik) 用于构建表单. +* [Yup](https://github.com/jquense/yup) 用于表单验证. ## 下一步是什么? diff --git a/docs/zh-Hans/Startup-Templates/Index.md b/docs/zh-Hans/Startup-Templates/Index.md index 57389e6df0..160a2b3e20 100644 --- a/docs/zh-Hans/Startup-Templates/Index.md +++ b/docs/zh-Hans/Startup-Templates/Index.md @@ -2,7 +2,7 @@ 虽然你可以从一个空项目开始并手动添加所需的包,但启动模板可以非常轻松,舒适地使用ABP框架启动新的解决方案. -单击下面列表中的名称以查看相关启动模板的文档: +单击下面列表中的名称以查看相关启动模板的文档: * [**app**](Application.md): 应用程序模板. * [**module**](Module.md): 模块/服务模板. \ No newline at end of file diff --git a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md index e1cbb73cc1..7c2db90997 100644 --- a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md +++ b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md @@ -33,7 +33,7 @@ - `Acme.BookStore.Domain`包含你的[实体](https://docs.abp.io/zh-Hans/abp/latest/Entities), [领域服务](https://docs.abp.io/zh-Hans/abp/latest/Domain-Services)和其他核心域对象. - `Acme.BookStore.Domain.Shared`包含可与客户共享的常量,枚举或其他域相关对象. -在解决方案的**领域层**(`Acme.BookStore.Domain`项目)中定义[实体](https://docs.abp.io/zh-Hans/abp/latest/Entities). 该应用程序的主要实体是`Book`. 在`Acme.BookStore.Domain`项目中创建一个名为`Book`的类,如下所示: +在解决方案的**领域层**(`Acme.BookStore.Domain`项目)中定义[实体](https://docs.abp.io/zh-Hans/abp/latest/Entities). 该应用程序的主要实体是`Book`. 在`Acme.BookStore.Domain`项目中创建一个名为`Book`的类,如下所示: ````C# using System; @@ -132,7 +132,7 @@ PM> Update-Database #### 添加示例数据 -`Update-Database`命令在数据库中创建了`AppBooks`表. 打开数据库并输入几个示例行,以便在页面上显示它们: +`Update-Database`命令在数据库中创建了`AppBooks`表. 打开数据库并输入几个示例行,以便在页面上显示它们: ![bookstore-books-table](images/bookstore-books-table.png) @@ -290,7 +290,7 @@ namespace Acme.BookStore #### Swagger UI -启动模板配置为使用[Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore)运行[swagger UI](https://swagger.io/tools/swagger-ui/). 运行应用程序并在浏览器中输入`https://localhost:XXXX/swagger/`(用您自己的端口替换XXXX)作为URL. +启动模板配置为使用[Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore)运行[swagger UI](https://swagger.io/tools/swagger-ui/). 运行应用程序并在浏览器中输入`https://localhost:XXXX/swagger/`(用你自己的端口替换XXXX)作为URL. 你会看到一些内置的接口和`Book`的接口,它们都是REST风格的: @@ -380,7 +380,7 @@ context.Menu.AddItem( ![bookstore-localization-files](images/bookstore-localization-files-v2.png) -打开`en.json`文件,将`Menu:BookStore`和`Menu:Books`键的本地化文本添加到文件末尾: +打开`en.json`文件,将`Menu:BookStore`和`Menu:Books`键的本地化文本添加到文件末尾: ````json { diff --git a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-III.md b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-III.md index a5e51134fa..e072e5a1a7 100644 --- a/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-III.md +++ b/docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-III.md @@ -14,7 +14,7 @@ ### 解决方案中的测试项目 -解决方案中有多个测试项目: +解决方案中有多个测试项目: ![bookstore-test-projects-v2](images/bookstore-test-projects-v2.png) @@ -68,7 +68,7 @@ namespace Acme.BookStore ```` * 注入`IRepository`并在`SeedAsync`中使用它来创建两个书实体作为测试数据. -* 使用`IGuidGenerator`服务创建GUID. 虽然`Guid.NewGuid()`非常适合测试,但`IGuidGenerator`在使用真实数据库时还有其他特别重要的功能(参见[Guid生成文档](../../../Guid-Generation.md)了解更多信息). +* 使用`IGuidGenerator`服务创建GUID. 虽然`Guid.NewGuid()`非常适合测试,但`IGuidGenerator`在使用真实数据库时还有其他特别重要的功能(参见[Guid生成文档](../../../Guid-Generation.md)了解更多信息). ### 测试 BookAppService diff --git a/docs/zh-Hans/UI/Angular/AddingSettingTab.md b/docs/zh-Hans/UI/Angular/AddingSettingTab.md deleted file mode 100644 index c46a559957..0000000000 --- a/docs/zh-Hans/UI/Angular/AddingSettingTab.md +++ /dev/null @@ -1,3 +0,0 @@ -## Creating a Settings Tab - -TODO... diff --git a/docs/zh-Hans/UI/Angular/Component-Replacement.md b/docs/zh-Hans/UI/Angular/Component-Replacement.md index e98ce4331e..dc7c1a33c4 100644 --- a/docs/zh-Hans/UI/Angular/Component-Replacement.md +++ b/docs/zh-Hans/UI/Angular/Component-Replacement.md @@ -2,7 +2,7 @@ 你可以将一些ABP的组件替换为你自己的自定义组件. -您可以**替换**但**不能自定义**默认ABP组件的原因是禁用或更改该组件的一部分可能会导致问题. 所以我们把这些组件称为可替换组件. +你可以**替换**但**不能自定义**默认ABP组件的原因是禁用或更改该组件的一部分可能会导致问题. 所以我们把这些组件称为可替换组件. ### 如何替换组件 diff --git a/docs/zh-Hans/UI/Angular/Config-State.md b/docs/zh-Hans/UI/Angular/Config-State.md index a022129c83..4967dd78b3 100644 --- a/docs/zh-Hans/UI/Angular/Config-State.md +++ b/docs/zh-Hans/UI/Angular/Config-State.md @@ -1,3 +1,294 @@ ## 配置状态 -TODO... \ No newline at end of file +`ConfigStateService` 是一个单例服务,即在应用程序的根级别提供,用于与 `Store` 中的应用程序配置状态进行交互. + +## 使用前 + +为了使用 `ConfigStateService`,你必须将其注入到你的类中. + +```js +import { ConfigStateService } from '@abp/ng.core'; + +@Component({ + /* class metadata here */ +}) +class DemoComponent { + constructor(private config: ConfigStateService) {} +} +``` + +你不必在模块或组件/指令级别提供 `ConfigStateService`,因为它已经在**根中**提供. + +## 选择器方法 + +`ConfigStateService` 有许多选择器方法允许你从 `Store` 获取特定或所有的配置. + +### 如何从Store获取所有的配置 + +你可以使用 `ConfigStateService` 的 `getAll` 方法从Store获取所有的配置对象. 用法如下: + +```js +// this.config is instance of ConfigStateService + +const config = this.config.getAll(); +``` + +### 如何从Store获取特定的配置 + +你可以使用 `ConfigStateService` 的 `getOne` 方法从Store获取特定的配置属性. 你需要将属性名做为参数传递给方法: + +```js +// this.config is instance of ConfigStateService + +const currentUser = this.config.getOne("currentUser"); +``` + +有时你想要获取具体信息,而不是当前用户. 例如你只想获取到 `tenantId`: + +```js +const tenantId = this.config.getDeep("currentUser.tenantId"); +``` + +或通过提供键数组作为参数: + +```js +const tenantId = this.config.getDeep(["currentUser", "tenantId"]); +``` + +`getDeep` 可以执行 `getOne` 的所有操作. 但 `getOne` 的执行效率要高一些. + +#### 配置状态属性 + +请参阅 `Config.State` 类型,你可以通过 `getOne` 和 `getDeep` 获取所有属性. 你可以在[config.ts 文件](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/core/src/lib/models/config.ts#L7)中找到. + +### 如何从Store获取应用程序信息 + +`getApplicationInfo` 方法从存储为配置状态存储的环境变量中获取应用程序信息. 你可以这样使用它: + +```js +// this.config is instance of ConfigStateService + +const appInfo = this.config.getApplicationInfo(); +``` + +该方法不会返回 `undefined` 或 `null`,而是会返回一个空对象(`{}`). 换句话说,当你使用上面代码中的 `appInfo` 属性时,永远不会出现错误. + +#### 应用程序信息属性 + +请参阅 `Config.State` 类型,你可以通过 `getApplicationInfo` 获取所有属性. 你可以在[config.ts 文件](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/core/src/lib/models/config.ts#L21)中找到. + +### 如何从Store获取 + +`getApplicationInfo` 方法从存储为配置状态存储的环境变量中获取特定的API URL. 你可以这样使用它: + +```js +// this.config is instance of ConfigStateService + +const apiUrl = this.config.getApiUrl(); +// environment.apis.default.url + +const searchUrl = this.config.getApiUrl("search"); +// environment.apis.search.url +``` + +该方法返回给定键的特定的API `url`. 如果没有Key,则使用 `default`. + +### 如何从Store获取所有的设置 + +你可以使用 `ConfigStateService` 的 `getSettings` 获取配置状态所有的设置对象. 你可以这样使用它: + +```js +// this.config is instance of ConfigStateService + +const settings = this.config.getSettings(); +``` + +实际上该方法可以通过**传递关键字**来搜索设置. + +```js +const localizationSettings = this.config.getSettings("Localization"); +/* +{ + 'Abp.Localization.DefaultLanguage': 'en' +} +*/ +``` + +请注意, **设置搜索区分大小写**. + +### 如何从Store获取特定的设置 + +你可以使用 `ConfigStateService` 的 `getSetting` 获取配置状态特定的设置. 你可以这样使用它: + +```js +// this.config is instance of ConfigStateService + +const defaultLang = this.config.getSetting("Abp.Localization.DefaultLanguage"); +// 'en' +``` + +### 如何从Store获取特定的权限 + +你可以使用 `ConfigStateService` 的 `getGrantedPolicy` 获取配置状态特定的权限. 你应该将策略key做为参数传递给方法: + +```js +// this.config is instance of ConfigStateService + +const hasIdentityPermission = this.config.getGrantedPolicy("Abp.Identity"); +// true +``` + +你还可以使用 **组合策略key** 来微调你的选择: + +```js +// this.config is instance of ConfigStateService + +const hasIdentityAndAccountPermission = this.config.getGrantedPolicy( + "Abp.Identity && Abp.Account" +); +// false + +const hasIdentityOrAccountPermission = this.config.getGrantedPolicy( + "Abp.Identity || Abp.Account" +); +// true +``` + +创建权限选择器时,请考虑以下**规则**: + +- 最多可组合两个键. +- `&&` 操作符查找两个键. +- `||` 操作符查找任意一个键. +- 空字符串 `''` 做为键将返回 `true` +- 使用没有第二个键的操作符将返回 `false` + +### 如何从Store中获取翻译 + +`ConfigStateService` 的 `getLocalization` 方法用于翻译. 这里有一些示例: + +```js +// this.config is instance of ConfigStateService + +const identity = this.config.getLocalization("AbpIdentity::Identity"); +// 'identity' + +const notFound = this.config.getLocalization("AbpIdentity::IDENTITY"); +// 'AbpIdentity::IDENTITY' + +const defaultValue = this.config.getLocalization({ + key: "AbpIdentity::IDENTITY", + defaultValue: "IDENTITY" +}); +// 'IDENTITY' +``` + +请参阅[本地化文档](./Localization.md)了解详情. + +## 分发方法 + +`ConfigStateService` 有几种分发方法,让你方便地将预定义操作分发到 `Store`. + +### 如何从服务器获取应用程序配置 + +`dispatchGetAppConfiguration` 触发对端点的请求,该端点使用应用程序状态进行响应,然后将此响应作为配置状态放置到 `Store`中. + +```js +// this.config is instance of ConfigStateService + +this.config.dispatchGetAppConfiguration(); +// returns a state stream which emits after dispatch action is complete +``` + +请注意,**你不必在应用程序启动时调用此方法**,因为在启动时已经从服务器收到了应用程序配置. + +### 如何修补路由配置 + +`dispatchPatchRouteByName` 根据名称查找路由, 并将其在 `Store` 中的配置替换为作为第二个参数传递的新配置. + +```js +// this.config is instance of ConfigStateService + +const newRouteConfig: Partial = { + name: "Home", + path: "home", + children: [ + { + name: "Dashboard", + path: "dashboard" + } + ] +}; + +this.config.dispatchPatchRouteByName("::Menu:Home", newRouteConfig); +// returns a state stream which emits after dispatch action is complete +``` + +### 如何添加新路由配置 + +`dispatchAddRoute` 向 `Store` 的配置状态添加一个新路由. 应该将路由配置做为方法参数传递. + +```js +// this.config is instance of ConfigStateService + +const newRoute: ABP.Route = { + name: "My New Page", + iconClass: "fa fa-dashboard", + path: "page", + invisible: false, + order: 2, + requiredPolicy: "MyProjectName::MyNewPage" +}; + +this.config.dispatchAddRoute(newRoute); +// returns a state stream which emits after dispatch action is complete +``` + +`newRoute` 将被放置在根级别,没有任何父路由,并且其url将存储为 `'/path'`. + +如果你想要**添加一个子路由,你可以这样做:** + +```js +// this.config is instance of ConfigStateService + +const newRoute: ABP.Route = { + parentName: "AbpAccount::Login", + name: "My New Page", + iconClass: "fa fa-dashboard", + path: "page", + invisible: false, + order: 2, + requiredPolicy: "MyProjectName::MyNewPage" +}; + +this.config.dispatchAddRoute(newRoute); +// returns a state stream which emits after dispatch action is complete +``` + +`newRoute` 做为 `'AbpAccount::Login'` 父路由的子路由被放置,它的url被设置为 `'/account/login/page'`. + +#### 路由配置属性 + +请参阅 `ABP.Route` 类型,获取可在参数中传递给 `dispatchSetEnvironment` 的所有属性. 你可以在[common.ts 文件](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/core/src/lib/models/common.ts#L27)中找到. + +### 如何设置环境 + +`dispatchSetEnvironment` 将传递给它的环境变量放在 `Store` 中的配置状态下. 使用方法如下: + +```js +// this.config is instance of ConfigStateService + +this.config.dispatchSetEnvironment({ + /* environment properties here */ +}); +// returns a state stream which emits after dispatch action is complete +``` + +注意,**你不必在应用程序启动时调用此方法**,因为环境变量已经在启动时存储了. + +#### 环境属性 + +请参阅 `Config.Environment` 类型,获取可在参数中传递给 `dispatchSetEnvironment` 的所有属性. 你可以在[config.ts 文件](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/core/src/lib/models/config.ts#L13)中找到. + +## 下一步是什么? + +* [组件替换](./Component-Replacement.md) \ No newline at end of file diff --git a/docs/zh-Hans/UI/Angular/Content-Strategy.md b/docs/zh-Hans/UI/Angular/Content-Strategy.md index 3600f2dbf4..b4430f285d 100644 --- a/docs/zh-Hans/UI/Angular/Content-Strategy.md +++ b/docs/zh-Hans/UI/Angular/Content-Strategy.md @@ -1,6 +1,6 @@ # ContentStrategy -`ContentStrategy` 是@abp/ng.core包暴露出的抽象类. 它可以帮助您创建内联脚本或样式. +`ContentStrategy` 是@abp/ng.core包暴露出的抽象类. 它可以帮助你创建内联脚本或样式. ## API diff --git a/docs/zh-Hans/UI/Angular/Context-Strategy.md b/docs/zh-Hans/UI/Angular/Context-Strategy.md index 93abfa7cef..26d8ba9270 100644 --- a/docs/zh-Hans/UI/Angular/Context-Strategy.md +++ b/docs/zh-Hans/UI/Angular/Context-Strategy.md @@ -76,7 +76,7 @@ setContext(): undefined CONTEXT_STRATEGY.None() ``` -该策略不会将任何上下文传递到投影内容。 +该策略不会将任何上下文传递到投影内容. ### Component diff --git a/docs/zh-Hans/UI/Angular/Dom-Insertion-Service.md b/docs/zh-Hans/UI/Angular/Dom-Insertion-Service.md index 2ff9f72239..e8d9420422 100644 --- a/docs/zh-Hans/UI/Angular/Dom-Insertion-Service.md +++ b/docs/zh-Hans/UI/Angular/Dom-Insertion-Service.md @@ -1,3 +1,140 @@ # Dom插入(Scripts与Styles) -TODO... \ No newline at end of file +你可以使用@abp/ng.core包提供的 `DomInsertionService` 以简单的方式的插入脚本与样式. + +## 入门 + +你不必在模块或组件级别提供 `DomInsertionService` ,因为它已经在**根中**提供. 你可以在组件,指令或服务中直接注入并使用它. + +```js +import { DomInsertionService } from '@abp/ng.core'; + +@Component({ + /* class metadata here */ +}) +class DemoComponent { + constructor(private domInsertionService: DomInsertionService) {} +} +``` + +## 用法 + +你可以使用 `DomInsertionService` 提供的 `insertContent` 方法去创建一个 `` 元素放置在 ``的末尾, `scriptElement` 类型是一个 `HTMLScriptElement`. + +请参考[ContentStrategy](./Content-Strategy.md)查看所有可用的内容策略以及如何构建自己的内容策略. + +> 重要说明: `DomInsertionService` 不会两次插入相同的内容. 为了再次添加内容你首先应该使用 `removeContent` 方法删除旧内容. + +### 如何插入Styles + +`insertContent` 方法的第一个参数需要一个 `ContentStrategy`. 如果传递 `StyleContentStrategy` 实例, `DomInsertionService` 将创建具有给定内容的 `` 元素放置在 ``的末尾, `styleElement` 类型是一个 `HTMLStyleElement`. + +请参考[ContentStrategy](./Content-Strategy.md)查看所有可用的内容策略以及如何构建自己的内容策略. +. +> 重要说明: `DomInsertionService` 不会两次插入相同的内容. 为了再次添加内容你首先应该使用 `removeContent` 方法删除旧内容. + +### 如何删除已插入的 Scripts & Styles + +如果你传递 `HTMLScriptElement` 或 `HTMLStyleElement` 做为 `removeContent` 方法的第一个参数, `DomInsertionService` 将删除给定的元素. + +```js +import { DomInsertionService, CONTENT_STRATEGY } from '@abp/ng.core'; + +@Component({ + /* class metadata here */ +}) +class DemoComponent { + private styleElement: HTMLStyleElement; + + constructor(private domInsertionService: DomInsertionService) {} + + ngOnInit() { + this.styleElement = this.domInsertionService.insertContent( + CONTENT_STRATEGY.AppendStyleToHead('body {margin: 0;}') + ); + } + + ngOnDestroy() { + this.domInsertionService.removeContent(this.styleElement); + } +} +``` + +在上面的示例中,销毁组件时,将从 `` 中删除 `` 元素. + +## API + +### insertContent + +```js +insertContent( + contentStrategy: ContentStrategy, +): T +``` + +- `contentStrategy` 是方法的重要参数,已经在上方进行说明. +- 根据给定的策略返回 `HTMLScriptElement` 或 `HTMLStyleElement`. + +### removeContent + +```js +removeContent(element: HTMLScriptElement | HTMLStyleElement): void +``` + +- `element` 参数是已插入的 `HTMLScriptElement` 或 `HTMLStyleElement` 元素,它们应由 `insertContent` 方法返回. + +### has + +```js +has(content: string): boolean +``` + +`has` 返回一个布尔值,用于表示给定的内容是否插入到DOM. + +- `content` 参数是 `HTMLScriptElement` 或 `HTMLStyleElement` 元素的内容. + +## 下一步是什么? + +- [ContentProjectionService](./Content-Projection-Service.md) \ No newline at end of file diff --git a/docs/zh-Hans/UI/Angular/HTTP-Requests.md b/docs/zh-Hans/UI/Angular/HTTP-Requests.md index d40493cd1b..47f871d6e6 100644 --- a/docs/zh-Hans/UI/Angular/HTTP-Requests.md +++ b/docs/zh-Hans/UI/Angular/HTTP-Requests.md @@ -1,3 +1,179 @@ ## HTTP请求 -TODO... \ No newline at end of file +## 关于 HttpClient + +Angular具有很棒的 `HttpClient` 与后端服务进行通信. 它位于顶层,是[XMLHttpRequest Web API](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest)的封装. 同时也是Angular建议用于任何HTTP请求的代理,在你的ABP项目中使用 `HttpClient` 是最佳做法. + +但是 `HttpClient` 将错误处理留给调用方,换句话说HTTP错误是通过手动处理的,通过挂接到返回的 `Observable` 的观察者中来处理. + +```js +getConfig() { + this.http.get(this.configUrl).subscribe( + config => this.updateConfig(config), + error => { + // Handle error here + }, + ); +} +``` + +上面的代码尽管清晰灵活,但即使将错误处理委派给Store或任何其他注入. 以这种方式处理错误也是重复性的工作. + +`HttpInterceptor` 能够捕获 `HttpErrorResponse` 并可用于集中的错误处理. 然而,在必须放置错误处理程序(也就是拦截器)的情况下,需要额外的工作以及对Angular内部机制的理解. 检查[这个issue](https://github.com/angular/angular/issues/20203)了解详情. + +## RestService + +ABP核心模块有用于HTTP请求的实用程序服务: `RestService`. 除非另有明确配置,否则它将捕获HTTP错误并调度 `RestOccurError` 操作, 然后由 `ThemeSharedModule` 引入的 `ErrorHandler` 捕获此操作. 你应该已经在应用程序中导入了此模块,在使用 `RestService` 时,默认情况下将自动处理所有HTTP错误. + +### RestService 入门 + +为了使用 `RestService`, 你必须将它注入到你的类中. + +```js +import { RestService } from '@abp/ng.core'; + +@Injectable({ + /* class metadata here */ +}) +class DemoService { + constructor(private rest: RestService) {} +} +``` + +你不必在模块或组件/指令级别提供 `estService`,因为它已经在**根中**中提供了. + +### 如何使用RestService发出请求 + +你可以使用 `RestService` 的 `request` 方法来处理HTTP请求. 示例: + +```js +getFoo(id: number) { + const request: Rest.Request = { + method: 'GET', + url: '/api/some/path/to/foo/' + id, + }; + + return this.rest.request(request); +} +``` + +`request` 方法始终返回 `Observable`. 无论何时使用 `getFoo` 方法,都可以执行以下操作: + +```js +doSomethingWithFoo(id: number) { + this.demoService.getFoo(id).subscribe( + foo => { + // Do something with foo. + } + ) +} +``` + +**你不必担心关于取消订阅**. `RestService` 在内部使用 `HttpClient`,因此它返回的每个可观察对象都是有限的可观察对象,成功或出错后将自动关闭订阅. + +如你所见,`request` 方法获取一个具有 `Rest.Reques` 类型的请求选项对象. 此泛型类型需要请求主体的接口. 当没有正文时,例如在 `GET` 或 `DELETE` 请求中,你可以传递 `null`. 示例: + +```js +postFoo(body: Foo) { + const request: Rest.Request = { + method: 'POST', + url: '/api/some/path/to/foo', + body + }; + + return this.rest.request(request); +} +``` + +你可以在[此处检查](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/core/src/lib/models/rest.ts#L23)完整的 `Rest.Request` 类型,与Angular中的[HttpRequest](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/core/src/lib/models/rest.ts#L23)类相比只有很少的改动. + +### 如何禁用RestService的默认错误处理程序 + +默认 `request` 方法始终处理错误. 让我们看看如何改变这种行为并由自己处理错误: + +```js +deleteFoo(id: number) { + const request: Rest.Request = { + method: 'DELETE', + url: '/api/some/path/to/foo/' + id, + }; + + return this.rest.request(request, { skipHandleError: true }); +} +``` + +`skipHandleError` 配置选项设置为 `true` 时,禁用错误处理程序,并返回 `observable` 引发错误,你可以在订阅中捕获该错误. + +```js +removeFooFromList(id: number) { + this.demoService.deleteFoo(id).subscribe( + foo => { + // Do something with foo. + }, + error => { + // Do something with error. + } + ) +} +``` + +### 如何从应用程序配置获取特定的API端点 + +`request` 方法接收到的另一个配置选项是 `apiName` (在v2.4中可用),它用于从应用程序配置获取特定的模块端点. + +```js +putFoo(body: Foo, id: string) { + const request: Rest.Request = { + method: 'PUT', + url: '/' + id, + body + }; + + return this.rest.request(request, {apiName: 'foo'}); +} +``` + +上面的putFoo将请求 `https://localhost:44305/api/some/path/to/foo/{id}` 当环境变量如下: + +```js +// environment.ts + +export const environment = { + apis: { + default: { + url: 'https://localhost:44305', + }, + foo: { + url: 'https://localhost:44305/api/some/path/to/foo', + }, + }, + + /* rest of the environment variables here */ +} +``` + +### 如何观察响应对象或HTTP事件而不是正文 + +`RestService` 假定你通常对响应的正文感兴趣,默认情况下将 `observe` 属性设置为 `body`. 但是有时你可能对其他内容(例如自定义标头)非常感兴趣. 为此, `request` 方法在 `config` 对象中接收 `watch` 属性. + +```js +getSomeCustomHeaderValue() { + const request: Rest.Request = { + method: 'GET', + url: '/api/some/path/that/sends/some-custom-header', + }; + + return this.rest.request>( + request, + {observe: Rest.Observe.Response}, + ).pipe( + map(response => response.headers.get('Some-Custom-Header')) + ); +} +``` + +你可以在[此处](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/core/src/lib/models/rest.ts#L10)找到 `Rest.Observe` 枚举. + +## 下一步是什么? + +* [本地化](./Localization.md) \ No newline at end of file diff --git a/docs/zh-Hans/UI/Angular/Lazy-Load-Service.md b/docs/zh-Hans/UI/Angular/Lazy-Load-Service.md index df313555a9..07753f8541 100644 --- a/docs/zh-Hans/UI/Angular/Lazy-Load-Service.md +++ b/docs/zh-Hans/UI/Angular/Lazy-Load-Service.md @@ -1,3 +1,189 @@ # 如何懒加载 Scripts 与 Styles -TODO... \ No newline at end of file +你可以使用@abp/ng.core包中的 `LazyLoadService` 以简单明了的方式延迟加载脚本和样式. + +## 入门 + +你不必在模块或组件/指令级别提供 `LazyLoadService`,因为它已经在**根中**中提供了. 你可以在组件,指令或服务中注入并使用它. + +```js +import { LazyLoadService } from '@abp/ng.core'; + +@Component({ + /* class metadata here */ +}) +class DemoComponent { + constructor(private lazyLoadService: LazyLoadService) {} +} +``` + +## 用法 + +你可以使用 `LazyLoadService` 的 `load` 方法在DOM中的所需位置创建 `