@rolatech/angular-course 17.3.1 → 17.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/index.mjs +2 -1
- package/esm2022/lib/components/schedule-item/schedule-item.component.mjs +4 -4
- package/esm2022/lib/pages/course-manage/course-manage-content/course-manage-content.component.mjs +12 -0
- package/esm2022/lib/pages/course-manage/course-manage-details/course-manage-details.component.mjs +159 -0
- package/esm2022/lib/pages/course-manage/course-manage-info/course-manage-info.component.mjs +139 -0
- package/esm2022/lib/pages/course-manage/course-manage-layout/course-manage-layout.component.mjs +68 -0
- package/esm2022/lib/pages/course-manage/course-manage-media/course-manage-media.component.mjs +137 -0
- package/esm2022/lib/pages/course-manage/course-manage-pricing/course-manage-pricing.component.mjs +126 -0
- package/esm2022/lib/pages/course-manage/course-manage-schedule/course-manage-schedule.component.mjs +126 -0
- package/esm2022/lib/pages/course-manage/course-manage-section/course-manage-section.component.mjs +342 -0
- package/esm2022/lib/pages/course-manage/course-manage.routes.mjs +40 -0
- package/esm2022/lib/services/booking.service.mjs +24 -0
- package/esm2022/lib/services/instructor.service.mjs +24 -0
- package/fesm2022/{rolatech-angular-course-course-index.component-Bm6Sg8zH.mjs → rolatech-angular-course-course-index.component-BiS-U0WO.mjs} +5 -4
- package/fesm2022/{rolatech-angular-course-course-index.component-Bm6Sg8zH.mjs.map → rolatech-angular-course-course-index.component-BiS-U0WO.mjs.map} +1 -1
- package/fesm2022/{rolatech-angular-course-rolatech-angular-course-D-_W2GtF.mjs → rolatech-angular-course-rolatech-angular-course-DhmJ0teX.mjs} +1098 -16
- package/fesm2022/rolatech-angular-course-rolatech-angular-course-DhmJ0teX.mjs.map +1 -0
- package/fesm2022/rolatech-angular-course.mjs +2 -1
- package/fesm2022/rolatech-angular-course.mjs.map +1 -1
- package/index.d.ts +1 -0
- package/lib/components/schedule-item/schedule-item.component.d.ts +1 -1
- package/lib/pages/course-manage/course-manage-content/course-manage-content.component.d.ts +5 -0
- package/lib/pages/course-manage/course-manage-details/course-manage-details.component.d.ts +29 -0
- package/lib/pages/course-manage/course-manage-info/course-manage-info.component.d.ts +36 -0
- package/lib/pages/course-manage/course-manage-layout/course-manage-layout.component.d.ts +26 -0
- package/lib/pages/course-manage/course-manage-media/course-manage-media.component.d.ts +29 -0
- package/lib/pages/course-manage/course-manage-pricing/course-manage-pricing.component.d.ts +27 -0
- package/lib/pages/course-manage/course-manage-schedule/course-manage-schedule.component.d.ts +27 -0
- package/lib/pages/course-manage/course-manage-section/course-manage-section.component.d.ts +37 -0
- package/lib/pages/course-manage/course-manage.routes.d.ts +2 -0
- package/lib/services/booking.service.d.ts +9 -0
- package/lib/services/instructor.service.d.ts +9 -0
- package/package.json +1 -1
- package/themes/_default.scss +1 -1
- package/fesm2022/rolatech-angular-course-rolatech-angular-course-D-_W2GtF.mjs.map +0 -1
|
@@ -4,13 +4,13 @@ import * as i6 from '@angular/forms';
|
|
|
4
4
|
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
|
|
5
5
|
import { CommonModule, NgClass, DatePipe, isPlatformBrowser, ViewportScroller } from '@angular/common';
|
|
6
6
|
import * as i1$3 from '@angular/router';
|
|
7
|
-
import { RouterModule, RouterLink, ActivatedRoute, Router } from '@angular/router';
|
|
7
|
+
import { RouterModule, RouterLink, ActivatedRoute, Router, RouterLinkActive, RouterOutlet } from '@angular/router';
|
|
8
8
|
import { BaseService, DialogService } from '@rolatech/angular-services';
|
|
9
9
|
import * as i2 from '@angular/material/icon';
|
|
10
10
|
import { MatIconModule } from '@angular/material/icon';
|
|
11
11
|
import * as i1$2 from '@angular/material/dialog';
|
|
12
12
|
import { MatDialog, MAT_DIALOG_DATA, MatDialogClose } from '@angular/material/dialog';
|
|
13
|
-
import { ImagePreviewDialogComponent, ThumbnailComponent, IconButtonComponent, AngularComponentsModule, ImageComponent, MediaListComponent, MediaListItemComponent, BaseComponent, AppContainerComponent, ListComponent } from '@rolatech/angular-components';
|
|
13
|
+
import { ImagePreviewDialogComponent, ThumbnailComponent, IconButtonComponent, AngularComponentsModule, ImageComponent, MediaListComponent, MediaListItemComponent, BaseComponent, AppContainerComponent, ListComponent, ConfirmationDialogComponent, ToolbarComponent } from '@rolatech/angular-components';
|
|
14
14
|
import * as i3 from '@angular/material/button';
|
|
15
15
|
import { MatButtonModule } from '@angular/material/button';
|
|
16
16
|
import * as i1 from '@angular/material/expansion';
|
|
@@ -20,10 +20,10 @@ import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
|
20
20
|
import { DurationPipe, AngularCommonModule } from '@rolatech/angular-common';
|
|
21
21
|
import * as i5$1 from '@angular/material/divider';
|
|
22
22
|
import { MatDividerModule } from '@angular/material/divider';
|
|
23
|
-
import * as i7
|
|
23
|
+
import * as i7 from '@angular/material/stepper';
|
|
24
24
|
import { MatStepperModule, MatStepper } from '@angular/material/stepper';
|
|
25
25
|
import { MomentDateAdapter } from '@angular/material-moment-adapter';
|
|
26
|
-
import * as
|
|
26
|
+
import * as i6$2 from '@angular/material/core';
|
|
27
27
|
import { DateAdapter, MAT_DATE_LOCALE, MAT_DATE_FORMATS, MatOptionModule } from '@angular/material/core';
|
|
28
28
|
import moment from 'moment';
|
|
29
29
|
import * as i6$1 from '@angular/material/select';
|
|
@@ -40,9 +40,10 @@ import * as i3$3 from '@angular/material/snack-bar';
|
|
|
40
40
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
|
41
41
|
import * as i4 from '@angular/material/progress-bar';
|
|
42
42
|
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
|
43
|
-
import { first, remove, findLastIndex } from 'lodash';
|
|
43
|
+
import { first, remove, findLastIndex, findIndex, clone } from 'lodash';
|
|
44
44
|
import { AuthService, AuthUserService } from '@rolatech/angular-auth';
|
|
45
45
|
import { CommentsComponent } from '@rolatech/angular-comment';
|
|
46
|
+
import { Observable, from, concatMap, take } from 'rxjs';
|
|
46
47
|
|
|
47
48
|
var CourseStatus;
|
|
48
49
|
(function (CourseStatus) {
|
|
@@ -709,7 +710,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImpor
|
|
|
709
710
|
args: [{ selector: 'rolatech-course-section-item', standalone: true, imports: [MatIconModule, FormsModule, MatButtonModule, IconButtonComponent], template: "<div class=\"flex flex-col grow\">\n @if (section().id !== editId()) {\n <div>\n <div class=\"flex justify-between items-center cursor-pointer\" (click)=\"isExpand = !isExpand\">\n <div class=\"w-full flex items-center gap-3 pl-3\">\n <span>{{ section().title }}</span>\n <button mat-icon-button class=\"max-w-8 max-h-8 !p-1\" (click)=\"onEdit(section())\">\n <mat-icon>edit</mat-icon>\n </button>\n <button mat-icon-button class=\"max-w-8 max-h-8 !p-1\" (click)=\"onDelete(section())\">\n <mat-icon>delete</mat-icon>\n </button>\n </div>\n <!-- <rolatech-icon-button (click)=\"isExpand = !isExpand\">{{\n isExpand ? 'expand_less' : 'expand_more'\n }}</rolatech-icon-button> -->\n <button mat-icon-button class=\"max-w-8 max-h-8 !p-1\">\n <mat-icon>{{ isExpand ? 'expand_less' : 'expand_more' }}</mat-icon>\n </button>\n </div>\n @if (isExpand) {\n <div>\n <ng-content></ng-content>\n </div>\n }\n </div>\n } @else {\n <div class=\"flex flex-col justify-between items-center\">\n <input\n type=\"text\"\n class=\"bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-md focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500\"\n placeholder=\"\u6807\u9898\"\n [(ngModel)]=\"section().title\"\n />\n <div class=\"w-full flex flex-row justify-end p-4 gap-3\">\n <button mat-button (click)=\"onCancel(section())\">\u53D6\u6D88</button>\n <button mat-flat-button color=\"primary\" (click)=\"onSave(section())\">\u4FDD\u5B58</button>\n </div>\n </div>\n }\n <!-- <mat-form-field appearance=\"fill\">\n <mat-label>\u63CF\u8FF0</mat-label>\n <input matInput placeholder=\"\u63CF\u8FF0\" [(ngModel)]=\"section.description\" />\n </mat-form-field> -->\n</div>\n" }]
|
|
710
711
|
}] });
|
|
711
712
|
|
|
712
|
-
const
|
|
713
|
+
const COURSE_SCHEDULE_DATE_FORMATS = {
|
|
713
714
|
parse: {
|
|
714
715
|
dateInput: 'YYYY-MM-DD',
|
|
715
716
|
},
|
|
@@ -780,9 +781,9 @@ class ScheduleItemComponent {
|
|
|
780
781
|
useClass: MomentDateAdapter,
|
|
781
782
|
deps: [MAT_DATE_LOCALE],
|
|
782
783
|
},
|
|
783
|
-
{ provide: MAT_DATE_FORMATS, useValue:
|
|
784
|
+
{ provide: MAT_DATE_FORMATS, useValue: COURSE_SCHEDULE_DATE_FORMATS },
|
|
784
785
|
DatePipe,
|
|
785
|
-
], ngImport: i0, template: "<div class=\"flex flex-col py-3\">\n <mat-form-field appearance=\"fill\">\n <mat-label> \u6807\u9898 </mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"schedule.title\" name=\"title\" required />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label> \u5185\u5BB9 </mat-label>\n <textarea\n matInput\n type=\"text\"\n [(ngModel)]=\"schedule.content\"\n name=\"content\"\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"3\"\n required\n ></textarea>\n </mat-form-field>\n <div class=\"flex flex-row gap-3\">\n <mat-form-field appearance=\"fill\">\n <mat-label>\u5F00\u59CB\u65E5\u671F</mat-label>\n <input\n matInput\n [matDatepicker]=\"picker\"\n (focus)=\"picker.open()\"\n name=\"startAt\"\n [(ngModel)]=\"schedule.startDate\"\n (ngModelChange)=\"startDateChanged($event)\"\n (dateInput)=\"schedule.startDate = $event.value.format('YYYY-MM-DD')\"\n readonly\n required\n />\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label>\u5F00\u59CB\u65F6\u95F4</mat-label>\n <mat-select [(ngModel)]=\"schedule.startTime\" (selectionChange)=\"startTimeChanged($event)\" required readonly>\n @for (d of date; track d) {\n <mat-option [value]=\"d\">\n {{ d }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n <div class=\"flex flex-row gap-3\">\n <mat-form-field appearance=\"fill\">\n <mat-label>\u7ED3\u675F\u65E5\u671F</mat-label>\n <input\n matInput\n [matDatepicker]=\"picker2\"\n name=\"endAt\"\n (focus)=\"picker2.open()\"\n (ngModelChange)=\"endDateChanged($event)\"\n [(ngModel)]=\"schedule.endDate\"\n (dateInput)=\"schedule.endDate = $event.value.format('YYYY-MM-DD')\"\n readonly\n required\n />\n <mat-datepicker-toggle matIconSuffix [for]=\"picker2\"></mat-datepicker-toggle>\n <mat-datepicker #picker2></mat-datepicker>\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label>\u7ED3\u675F\u65F6\u95F4</mat-label>\n <mat-select [(ngModel)]=\"schedule.endTime\" (selectionChange)=\"endTimeChanged($event)\" required readonly>\n @for (d of date; track d) {\n <mat-option [value]=\"d\">\n {{ d }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n</div>\n@if (actions()) {\n <div class=\"flex flex-row justify-end p-4\">\n <button mat-button (click)=\"onDelete(schedule)\">\u5220\u9664</button>\n <button mat-button (click)=\"onSave(schedule)\">\u4FDD\u5B58</button>\n </div>\n}\n<mat-divider></mat-divider>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i1$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i2$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i3$1.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i6.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TextFieldModule }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i5.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i5.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i5.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type:
|
|
786
|
+
], ngImport: i0, template: "<div class=\"flex flex-col py-3\">\n <mat-form-field appearance=\"fill\">\n <mat-label> \u6807\u9898 </mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"schedule.title\" name=\"title\" required />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label> \u5185\u5BB9 </mat-label>\n <textarea\n matInput\n type=\"text\"\n [(ngModel)]=\"schedule.content\"\n name=\"content\"\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"3\"\n required\n ></textarea>\n </mat-form-field>\n <div class=\"flex flex-row gap-3\">\n <mat-form-field appearance=\"fill\">\n <mat-label>\u5F00\u59CB\u65E5\u671F</mat-label>\n <input\n matInput\n [matDatepicker]=\"picker\"\n (focus)=\"picker.open()\"\n name=\"startAt\"\n [(ngModel)]=\"schedule.startDate\"\n (ngModelChange)=\"startDateChanged($event)\"\n (dateInput)=\"schedule.startDate = $event.value.format('YYYY-MM-DD')\"\n readonly\n required\n />\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label>\u5F00\u59CB\u65F6\u95F4</mat-label>\n <mat-select [(ngModel)]=\"schedule.startTime\" (selectionChange)=\"startTimeChanged($event)\" required readonly>\n @for (d of date; track d) {\n <mat-option [value]=\"d\">\n {{ d }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n <div class=\"flex flex-row gap-3\">\n <mat-form-field appearance=\"fill\">\n <mat-label>\u7ED3\u675F\u65E5\u671F</mat-label>\n <input\n matInput\n [matDatepicker]=\"picker2\"\n name=\"endAt\"\n (focus)=\"picker2.open()\"\n (ngModelChange)=\"endDateChanged($event)\"\n [(ngModel)]=\"schedule.endDate\"\n (dateInput)=\"schedule.endDate = $event.value.format('YYYY-MM-DD')\"\n readonly\n required\n />\n <mat-datepicker-toggle matIconSuffix [for]=\"picker2\"></mat-datepicker-toggle>\n <mat-datepicker #picker2></mat-datepicker>\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label>\u7ED3\u675F\u65F6\u95F4</mat-label>\n <mat-select [(ngModel)]=\"schedule.endTime\" (selectionChange)=\"endTimeChanged($event)\" required readonly>\n @for (d of date; track d) {\n <mat-option [value]=\"d\">\n {{ d }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n</div>\n@if (actions()) {\n <div class=\"flex flex-row justify-end p-4\">\n <button mat-button (click)=\"onDelete(schedule)\">\u5220\u9664</button>\n <button mat-button (click)=\"onSave(schedule)\">\u4FDD\u5B58</button>\n </div>\n}\n<mat-divider></mat-divider>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i1$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i2$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i3$1.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i6.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TextFieldModule }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i5.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i5.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i5.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i5$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }] }); }
|
|
786
787
|
}
|
|
787
788
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: ScheduleItemComponent, decorators: [{
|
|
788
789
|
type: Component,
|
|
@@ -792,7 +793,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImpor
|
|
|
792
793
|
useClass: MomentDateAdapter,
|
|
793
794
|
deps: [MAT_DATE_LOCALE],
|
|
794
795
|
},
|
|
795
|
-
{ provide: MAT_DATE_FORMATS, useValue:
|
|
796
|
+
{ provide: MAT_DATE_FORMATS, useValue: COURSE_SCHEDULE_DATE_FORMATS },
|
|
796
797
|
DatePipe,
|
|
797
798
|
], standalone: true, imports: [
|
|
798
799
|
NgClass,
|
|
@@ -1134,7 +1135,7 @@ class CoursePricingDialogComponent {
|
|
|
1134
1135
|
});
|
|
1135
1136
|
}
|
|
1136
1137
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CoursePricingDialogComponent, deps: [{ token: i1$2.MatDialogRef }, { token: MAT_DIALOG_DATA }, { token: CourseService }, { token: i3$3.MatSnackBar }, { token: i1$2.MatDialog }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1137
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.1", type: CoursePricingDialogComponent, isStandalone: true, selector: "rolatech-course-pricing-dialog", ngImport: i0, template: "<div class=\"flex flex-col h-full overflow-hidden\">\n <div class=\"h-16 flex justify-between items-center px-5\">\n @if (data.title) {\n <div class=\"text-md font-medium\">{{ data.title }}</div>\n }\n <div class=\"cursor-pointer\" (click)=\"close()\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </div>\n </div>\n <mat-divider></mat-divider>\n <div class=\"flex-1 overflow-hidden mt-3 overflow-y-auto w-2/3 max-h-[55vh]\">\n <form #detailForm=\"ngForm\" class=\"p-3\">\n <ng-template matStepLabel>\u8BE6\u60C5</ng-template>\n @for (item of pricing; track item) {\n <rolatech-pricing-item [pricing]=\"item\"> </rolatech-pricing-item>\n }\n <div class=\"mb-6\">\n <button mat-button (click)=\"addPricing()\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u4EF7\u683C</span>\n </button>\n </div>\n </form>\n </div>\n <mat-divider></mat-divider>\n <div class=\"h-16 flex justify-end items-center px-5\">\n <button mat-button [mat-dialog-close]=\"pricing\" cdkFocusInitial>\u4FDD\u5B58</button>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i5$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i6.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i6.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i6.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatStepperModule }, { kind: "directive", type: i7
|
|
1138
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.1", type: CoursePricingDialogComponent, isStandalone: true, selector: "rolatech-course-pricing-dialog", ngImport: i0, template: "<div class=\"flex flex-col h-full overflow-hidden\">\n <div class=\"h-16 flex justify-between items-center px-5\">\n @if (data.title) {\n <div class=\"text-md font-medium\">{{ data.title }}</div>\n }\n <div class=\"cursor-pointer\" (click)=\"close()\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </div>\n </div>\n <mat-divider></mat-divider>\n <div class=\"flex-1 overflow-hidden mt-3 overflow-y-auto w-2/3 max-h-[55vh]\">\n <form #detailForm=\"ngForm\" class=\"p-3\">\n <ng-template matStepLabel>\u8BE6\u60C5</ng-template>\n @for (item of pricing; track item) {\n <rolatech-pricing-item [pricing]=\"item\"> </rolatech-pricing-item>\n }\n <div class=\"mb-6\">\n <button mat-button (click)=\"addPricing()\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u4EF7\u683C</span>\n </button>\n </div>\n </form>\n </div>\n <mat-divider></mat-divider>\n <div class=\"h-16 flex justify-end items-center px-5\">\n <button mat-button [mat-dialog-close]=\"pricing\" cdkFocusInitial>\u4FDD\u5B58</button>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i5$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i6.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i6.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i6.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatStepperModule }, { kind: "directive", type: i7.MatStepLabel, selector: "[matStepLabel]" }, { kind: "component", type: PricingItemComponent, selector: "rolatech-pricing-item", inputs: ["actions", "pricing"], outputs: ["pricingChange", "delete", "save"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }] }); }
|
|
1138
1139
|
}
|
|
1139
1140
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CoursePricingDialogComponent, decorators: [{
|
|
1140
1141
|
type: Component,
|
|
@@ -1178,7 +1179,7 @@ class CourseScheduleDialogComponent {
|
|
|
1178
1179
|
});
|
|
1179
1180
|
}
|
|
1180
1181
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CourseScheduleDialogComponent, deps: [{ token: i1$2.MatDialogRef }, { token: MAT_DIALOG_DATA }, { token: CourseService }, { token: i3$3.MatSnackBar }, { token: i1$2.MatDialog }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1181
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.1", type: CourseScheduleDialogComponent, isStandalone: true, selector: "rolatech-course-schedule-dialog", ngImport: i0, template: "<div class=\"flex flex-col h-full overflow-hidden\">\n <div class=\"h-16 flex justify-between items-center px-5\">\n @if (data.title) {\n <div class=\"text-md font-medium\">{{ data.title }}</div>\n }\n <div class=\"cursor-pointer\" (click)=\"close()\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </div>\n </div>\n <mat-divider></mat-divider>\n <div class=\"flex-1 overflow-hidden mt-3 overflow-y-auto\">\n <form #detailForm=\"ngForm\" class=\"p-3\">\n <ng-template matStepLabel>\u8BE6\u60C5</ng-template>\n @for (item of schedule; track item) {\n <rolatech-schedule-item [value]=\"item\"></rolatech-schedule-item>\n }\n <div class=\"mb-6\">\n <button mat-button (click)=\"addSchedule()\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u8BFE\u8868</span>\n </button>\n </div>\n </form>\n </div>\n <mat-divider></mat-divider>\n <div class=\"h-16 flex justify-end items-center px-5\">\n <button mat-button [mat-dialog-close]=\"schedule\" cdkFocusInitial>\u4FDD\u5B58</button>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i5$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i6.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i6.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i6.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatStepperModule }, { kind: "directive", type: i7
|
|
1182
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.1", type: CourseScheduleDialogComponent, isStandalone: true, selector: "rolatech-course-schedule-dialog", ngImport: i0, template: "<div class=\"flex flex-col h-full overflow-hidden\">\n <div class=\"h-16 flex justify-between items-center px-5\">\n @if (data.title) {\n <div class=\"text-md font-medium\">{{ data.title }}</div>\n }\n <div class=\"cursor-pointer\" (click)=\"close()\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </div>\n </div>\n <mat-divider></mat-divider>\n <div class=\"flex-1 overflow-hidden mt-3 overflow-y-auto\">\n <form #detailForm=\"ngForm\" class=\"p-3\">\n <ng-template matStepLabel>\u8BE6\u60C5</ng-template>\n @for (item of schedule; track item) {\n <rolatech-schedule-item [value]=\"item\"></rolatech-schedule-item>\n }\n <div class=\"mb-6\">\n <button mat-button (click)=\"addSchedule()\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u8BFE\u8868</span>\n </button>\n </div>\n </form>\n </div>\n <mat-divider></mat-divider>\n <div class=\"h-16 flex justify-end items-center px-5\">\n <button mat-button [mat-dialog-close]=\"schedule\" cdkFocusInitial>\u4FDD\u5B58</button>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i5$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i6.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i6.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i6.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatStepperModule }, { kind: "directive", type: i7.MatStepLabel, selector: "[matStepLabel]" }, { kind: "component", type: ScheduleItemComponent, selector: "rolatech-schedule-item", inputs: ["value", "actions"], outputs: ["delete", "save"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }] }); }
|
|
1182
1183
|
}
|
|
1183
1184
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CourseScheduleDialogComponent, decorators: [{
|
|
1184
1185
|
type: Component,
|
|
@@ -1302,7 +1303,7 @@ class CourseDetailsDialogComponent {
|
|
|
1302
1303
|
});
|
|
1303
1304
|
}
|
|
1304
1305
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CourseDetailsDialogComponent, deps: [{ token: i1$2.MatDialogRef }, { token: MAT_DIALOG_DATA }, { token: CourseService }, { token: i3$3.MatSnackBar }, { token: i1$2.MatDialog }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1305
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.1", type: CourseDetailsDialogComponent, isStandalone: true, selector: "rolatech-course-details-dialog", ngImport: i0, template: "<div class=\"flex flex-col h-full overflow-hidden\">\n <div class=\"h-16 flex justify-between items-center px-5\">\n @if (data.title) {\n <div class=\"text-md font-medium\">{{ data.title }}</div>\n }\n <div class=\"cursor-pointer\" (click)=\"close()\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </div>\n </div>\n <mat-divider></mat-divider>\n <div class=\"flex-1 overflow-hidden mt-3 overflow-y-auto\">\n <form #detailForm=\"ngForm\" class=\"p-3\">\n <ng-template matStepLabel>\u8BE6\u60C5</ng-template>\n @for (item of details; track item) {\n <rolatech-detail-item\n [detail]=\"item\"\n (upload)=\"onDetailMediaUpload($event)\"\n (deleteMedia)=\"onDetailMediaDelete($event)\"\n (save)=\"onDetailSave($event)\"\n (delete)=\"onDetailDelete($event)\"\n ></rolatech-detail-item>\n }\n <div class=\"mb-6\">\n <button mat-button (click)=\"addDetail()\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u8BE6\u60C5</span>\n </button>\n </div>\n </form>\n </div>\n <mat-divider></mat-divider>\n <div class=\"h-16 flex justify-end items-center px-5\">\n <button mat-button [mat-dialog-close]=\"true\" cdkFocusInitial>\u4FDD\u5B58</button>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i5$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i6.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i6.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i6.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatStepperModule }, { kind: "directive", type: i7
|
|
1306
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.1", type: CourseDetailsDialogComponent, isStandalone: true, selector: "rolatech-course-details-dialog", ngImport: i0, template: "<div class=\"flex flex-col h-full overflow-hidden\">\n <div class=\"h-16 flex justify-between items-center px-5\">\n @if (data.title) {\n <div class=\"text-md font-medium\">{{ data.title }}</div>\n }\n <div class=\"cursor-pointer\" (click)=\"close()\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </div>\n </div>\n <mat-divider></mat-divider>\n <div class=\"flex-1 overflow-hidden mt-3 overflow-y-auto\">\n <form #detailForm=\"ngForm\" class=\"p-3\">\n <ng-template matStepLabel>\u8BE6\u60C5</ng-template>\n @for (item of details; track item) {\n <rolatech-detail-item\n [detail]=\"item\"\n (upload)=\"onDetailMediaUpload($event)\"\n (deleteMedia)=\"onDetailMediaDelete($event)\"\n (save)=\"onDetailSave($event)\"\n (delete)=\"onDetailDelete($event)\"\n ></rolatech-detail-item>\n }\n <div class=\"mb-6\">\n <button mat-button (click)=\"addDetail()\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u8BE6\u60C5</span>\n </button>\n </div>\n </form>\n </div>\n <mat-divider></mat-divider>\n <div class=\"h-16 flex justify-end items-center px-5\">\n <button mat-button [mat-dialog-close]=\"true\" cdkFocusInitial>\u4FDD\u5B58</button>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i5$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i6.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i6.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i6.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatStepperModule }, { kind: "directive", type: i7.MatStepLabel, selector: "[matStepLabel]" }, { kind: "component", type: DetailItemComponent, selector: "rolatech-detail-item", inputs: ["isUploading", "detail", "actions", "selectMedia"], outputs: ["upload", "delete", "save", "deleteMedia"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }] }); }
|
|
1306
1307
|
}
|
|
1307
1308
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CourseDetailsDialogComponent, decorators: [{
|
|
1308
1309
|
type: Component,
|
|
@@ -1492,7 +1493,7 @@ class CourseEditDialogComponent {
|
|
|
1492
1493
|
}
|
|
1493
1494
|
}
|
|
1494
1495
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CourseEditDialogComponent, deps: [{ token: i1$2.MatDialogRef }, { token: MAT_DIALOG_DATA }, { token: CategoryService }, { token: CourseService }, { token: i3$3.MatSnackBar }, { token: i1$2.MatDialog }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1495
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.1", type: CourseEditDialogComponent, isStandalone: true, selector: "rolatech-course-edit-dialog", viewQueries: [{ propertyName: "stepper", first: true, predicate: MatStepper, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"flex flex-col h-full overflow-hidden\">\n <div class=\"h-16 flex justify-between items-center px-5\">\n @if (data.title) {\n <div class=\"text-md font-medium\">{{ data.title }}</div>\n }\n <div class=\"cursor-pointer\" (click)=\"close()\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </div>\n </div>\n <mat-divider></mat-divider>\n <div class=\"flex-1 overflow-hidden mt-3 overflow-y-auto\">\n <mat-stepper #stepper (selectionChange)=\"onStepperChange($event)\">\n <mat-step [editable]=\"true\">\n <form #infoForm=\"ngForm\" class=\"py-3\">\n <ng-template matStepLabel>\u57FA\u672C\u4FE1\u606F</ng-template>\n <div class=\"flex flex-col\">\n <mat-form-field appearance=\"fill\">\n <mat-label> \u8BFE\u7A0B\u540D\u79F0 </mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"course.name\" name=\"name\" required />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label> \u8BFE\u7A0B\u63CF\u8FF0 </mat-label>\n <textarea\n matInput\n type=\"text\"\n [(ngModel)]=\"course.description\"\n name=\"description\"\n required\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"3\"\n ></textarea>\n </mat-form-field>\n <mat-form-field appearance=\"fill\" ngModelGroup=\"categories\">\n <mat-label>\u5206\u7C7B</mat-label>\n <mat-select\n multiple\n name=\"id\"\n [compareWith]=\"compareFn\"\n [(ngModel)]=\"course.categories\"\n #select=\"matSelect\"\n (selectionChange)=\"onSelectionChange($event)\"\n >\n @for (item of categories; track item) {\n <mat-option [value]=\"item\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label>\u7C7B\u578B</mat-label>\n <mat-select name=\"type\" [(ngModel)]=\"course.type\">\n @for (item of courseType; track item) {\n <mat-option [value]=\"item.key\">\n {{ item.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n @if (course.type.toString() !== 'ONLINE') {\n <mat-form-field appearance=\"fill\" ngModelGroup=\"classroom\">\n <mat-label>\u6559\u5BA4</mat-label>\n <mat-select [(ngModel)]=\"course.classroom\" name=\"id\">\n @for (classroom of classrooms; track classroom) {\n <mat-option [value]=\"classroom.id\">\n <div class=\"flex gap-3\">\n <span>{{ classroom.name }}</span>\n <span> {{ classroom.address }}</span>\n </div>\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n </div>\n <div>\n <div class=\"py-3\">\n <h2>\u56FE\u7247\u4FE1\u606F</h2>\n </div>\n <rolatech-media-list (upload)=\"onUpload($event)\" [isUploading]=\"isUploading\">\n @for (item of course.media; track item; let i = $index) {\n <rolatech-media-list-item [media]=\"item\" (mediaItemClick)=\"onImageClick(i)\"></rolatech-media-list-item>\n }\n </rolatech-media-list>\n </div>\n </form>\n </mat-step>\n <mat-step [editable]=\"true\">\n <form #detailForm=\"ngForm\" class=\"py-3\">\n <ng-template matStepLabel>\u8BE6\u60C5</ng-template>\n @for (item of course.details; track item) {\n <rolatech-detail-item\n [detail]=\"item\"\n (upload)=\"onDetailMediaUpload($event)\"\n (deleteMedia)=\"onDetailMediaDelete($event)\"\n (save)=\"onDetailSave($event)\"\n (delete)=\"onDetailDelete($event)\"\n ></rolatech-detail-item>\n }\n <div class=\"mb-6\">\n <button mat-button (click)=\"addDetail()\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u8BE6\u60C5</span>\n </button>\n </div>\n </form>\n </mat-step>\n <mat-step [editable]=\"true\">\n <form #pricingForm=\"ngForm\" class=\"py-3\">\n <ng-template matStepLabel>\u4EF7\u683C</ng-template>\n <div>\n @for (item of course.pricing; track item) {\n <rolatech-pricing-item [pricing]=\"item\"> </rolatech-pricing-item>\n }\n <div class=\"mb-6\">\n <button mat-button (click)=\"addPricing()\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u4EF7\u683C</span>\n </button>\n </div>\n </div>\n </form>\n </mat-step>\n <mat-step>\n <form #scheduleForm=\"ngForm\">\n <ng-template matStepLabel>\u8BFE\u8868</ng-template>\n <div class=\"flex flex-col\">\n @for (item of course.schedule; track item) {\n <rolatech-schedule-item [value]=\"item\"></rolatech-schedule-item>\n }\n <div class=\"mb-6\">\n <button mat-button (click)=\"addSchedule()\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u8BFE\u8868</span>\n </button>\n </div>\n </div>\n </form>\n </mat-step>\n </mat-stepper>\n </div>\n <mat-divider></mat-divider>\n <div class=\"h-16 flex justify-end items-center px-5\">\n @if (!firstStepper) {\n <button mat-button mat-button (click)=\"previous()\">\u4E0A\u4E00\u6B65</button>\n }\n @if (!lastStepper) {\n <button mat-button (click)=\"next()\">\u4E0B\u4E00\u6B65</button>\n }\n @if (lastStepper) {\n <button mat-button [mat-dialog-close]=\"course\" cdkFocusInitial>\u4FDD\u5B58</button>\n }\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i5$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatStepperModule }, { kind: "component", type: i7$1.MatStep, selector: "mat-step", inputs: ["color"], exportAs: ["matStep"] }, { kind: "directive", type: i7$1.MatStepLabel, selector: "[matStepLabel]" }, { kind: "component", type: i7$1.MatStepper, selector: "mat-stepper, mat-vertical-stepper, mat-horizontal-stepper, [matStepper]", inputs: ["disableRipple", "color", "labelPosition", "headerPosition", "animationDuration"], outputs: ["animationDone"], exportAs: ["matStepper", "matVerticalStepper", "matHorizontalStepper"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i6.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i6.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i6.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i6.NgModelGroup, selector: "[ngModelGroup]", inputs: ["ngModelGroup"], exportAs: ["ngModelGroup"] }, { kind: "directive", type: i6.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i2$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i3$1.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "ngmodule", type: TextFieldModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i7.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "component", type: MediaListComponent, selector: "rolatech-media-list", inputs: ["isUploading", "media", "showAdd"], outputs: ["mediaItemClick", "upload"] }, { kind: "component", type: MediaListItemComponent, selector: "rolatech-media-list-item", inputs: ["media", "uploadProgress"], outputs: ["mediaItemClick", "deleteMedia"] }, { kind: "component", type: DetailItemComponent, selector: "rolatech-detail-item", inputs: ["isUploading", "detail", "actions", "selectMedia"], outputs: ["upload", "delete", "save", "deleteMedia"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: PricingItemComponent, selector: "rolatech-pricing-item", inputs: ["actions", "pricing"], outputs: ["pricingChange", "delete", "save"] }, { kind: "component", type: ScheduleItemComponent, selector: "rolatech-schedule-item", inputs: ["value", "actions"], outputs: ["delete", "save"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }] }); }
|
|
1496
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.1", type: CourseEditDialogComponent, isStandalone: true, selector: "rolatech-course-edit-dialog", viewQueries: [{ propertyName: "stepper", first: true, predicate: MatStepper, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"flex flex-col h-full overflow-hidden\">\n <div class=\"h-16 flex justify-between items-center px-5\">\n @if (data.title) {\n <div class=\"text-md font-medium\">{{ data.title }}</div>\n }\n <div class=\"cursor-pointer\" (click)=\"close()\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </div>\n </div>\n <mat-divider></mat-divider>\n <div class=\"flex-1 overflow-hidden mt-3 overflow-y-auto\">\n <mat-stepper #stepper (selectionChange)=\"onStepperChange($event)\">\n <mat-step [editable]=\"true\">\n <form #infoForm=\"ngForm\" class=\"py-3\">\n <ng-template matStepLabel>\u57FA\u672C\u4FE1\u606F</ng-template>\n <div class=\"flex flex-col\">\n <mat-form-field appearance=\"fill\">\n <mat-label> \u8BFE\u7A0B\u540D\u79F0 </mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"course.name\" name=\"name\" required />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label> \u8BFE\u7A0B\u63CF\u8FF0 </mat-label>\n <textarea\n matInput\n type=\"text\"\n [(ngModel)]=\"course.description\"\n name=\"description\"\n required\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"3\"\n ></textarea>\n </mat-form-field>\n <mat-form-field appearance=\"fill\" ngModelGroup=\"categories\">\n <mat-label>\u5206\u7C7B</mat-label>\n <mat-select\n multiple\n name=\"id\"\n [compareWith]=\"compareFn\"\n [(ngModel)]=\"course.categories\"\n #select=\"matSelect\"\n (selectionChange)=\"onSelectionChange($event)\"\n >\n @for (item of categories; track item) {\n <mat-option [value]=\"item\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label>\u7C7B\u578B</mat-label>\n <mat-select name=\"type\" [(ngModel)]=\"course.type\">\n @for (item of courseType; track item) {\n <mat-option [value]=\"item.key\">\n {{ item.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n @if (course.type.toString() !== 'ONLINE') {\n <mat-form-field appearance=\"fill\" ngModelGroup=\"classroom\">\n <mat-label>\u6559\u5BA4</mat-label>\n <mat-select [(ngModel)]=\"course.classroom\" name=\"id\">\n @for (classroom of classrooms; track classroom) {\n <mat-option [value]=\"classroom.id\">\n <div class=\"flex gap-3\">\n <span>{{ classroom.name }}</span>\n <span> {{ classroom.address }}</span>\n </div>\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n </div>\n <div>\n <div class=\"py-3\">\n <h2>\u56FE\u7247\u4FE1\u606F</h2>\n </div>\n <rolatech-media-list (upload)=\"onUpload($event)\" [isUploading]=\"isUploading\">\n @for (item of course.media; track item; let i = $index) {\n <rolatech-media-list-item [media]=\"item\" (mediaItemClick)=\"onImageClick(i)\"></rolatech-media-list-item>\n }\n </rolatech-media-list>\n </div>\n </form>\n </mat-step>\n <mat-step [editable]=\"true\">\n <form #detailForm=\"ngForm\" class=\"py-3\">\n <ng-template matStepLabel>\u8BE6\u60C5</ng-template>\n @for (item of course.details; track item) {\n <rolatech-detail-item\n [detail]=\"item\"\n (upload)=\"onDetailMediaUpload($event)\"\n (deleteMedia)=\"onDetailMediaDelete($event)\"\n (save)=\"onDetailSave($event)\"\n (delete)=\"onDetailDelete($event)\"\n ></rolatech-detail-item>\n }\n <div class=\"mb-6\">\n <button mat-button (click)=\"addDetail()\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u8BE6\u60C5</span>\n </button>\n </div>\n </form>\n </mat-step>\n <mat-step [editable]=\"true\">\n <form #pricingForm=\"ngForm\" class=\"py-3\">\n <ng-template matStepLabel>\u4EF7\u683C</ng-template>\n <div>\n @for (item of course.pricing; track item) {\n <rolatech-pricing-item [pricing]=\"item\"> </rolatech-pricing-item>\n }\n <div class=\"mb-6\">\n <button mat-button (click)=\"addPricing()\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u4EF7\u683C</span>\n </button>\n </div>\n </div>\n </form>\n </mat-step>\n <mat-step>\n <form #scheduleForm=\"ngForm\">\n <ng-template matStepLabel>\u8BFE\u8868</ng-template>\n <div class=\"flex flex-col\">\n @for (item of course.schedule; track item) {\n <rolatech-schedule-item [value]=\"item\"></rolatech-schedule-item>\n }\n <div class=\"mb-6\">\n <button mat-button (click)=\"addSchedule()\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u8BFE\u8868</span>\n </button>\n </div>\n </div>\n </form>\n </mat-step>\n </mat-stepper>\n </div>\n <mat-divider></mat-divider>\n <div class=\"h-16 flex justify-end items-center px-5\">\n @if (!firstStepper) {\n <button mat-button mat-button (click)=\"previous()\">\u4E0A\u4E00\u6B65</button>\n }\n @if (!lastStepper) {\n <button mat-button (click)=\"next()\">\u4E0B\u4E00\u6B65</button>\n }\n @if (lastStepper) {\n <button mat-button [mat-dialog-close]=\"course\" cdkFocusInitial>\u4FDD\u5B58</button>\n }\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i5$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatStepperModule }, { kind: "component", type: i7.MatStep, selector: "mat-step", inputs: ["color"], exportAs: ["matStep"] }, { kind: "directive", type: i7.MatStepLabel, selector: "[matStepLabel]" }, { kind: "component", type: i7.MatStepper, selector: "mat-stepper, mat-vertical-stepper, mat-horizontal-stepper, [matStepper]", inputs: ["disableRipple", "color", "labelPosition", "headerPosition", "animationDuration"], outputs: ["animationDone"], exportAs: ["matStepper", "matVerticalStepper", "matHorizontalStepper"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i6.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i6.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i6.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i6.NgModelGroup, selector: "[ngModelGroup]", inputs: ["ngModelGroup"], exportAs: ["ngModelGroup"] }, { kind: "directive", type: i6.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i2$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i3$1.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "ngmodule", type: TextFieldModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "component", type: MediaListComponent, selector: "rolatech-media-list", inputs: ["isUploading", "media", "showAdd"], outputs: ["mediaItemClick", "upload"] }, { kind: "component", type: MediaListItemComponent, selector: "rolatech-media-list-item", inputs: ["media", "uploadProgress"], outputs: ["mediaItemClick", "deleteMedia"] }, { kind: "component", type: DetailItemComponent, selector: "rolatech-detail-item", inputs: ["isUploading", "detail", "actions", "selectMedia"], outputs: ["upload", "delete", "save", "deleteMedia"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: PricingItemComponent, selector: "rolatech-pricing-item", inputs: ["actions", "pricing"], outputs: ["pricingChange", "delete", "save"] }, { kind: "component", type: ScheduleItemComponent, selector: "rolatech-schedule-item", inputs: ["value", "actions"], outputs: ["delete", "save"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }] }); }
|
|
1496
1497
|
}
|
|
1497
1498
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CourseEditDialogComponent, decorators: [{
|
|
1498
1499
|
type: Component,
|
|
@@ -1928,7 +1929,7 @@ const courseRoutes = [
|
|
|
1928
1929
|
children: [
|
|
1929
1930
|
{
|
|
1930
1931
|
path: '',
|
|
1931
|
-
loadComponent: () => import('./rolatech-angular-course-course-index.component-
|
|
1932
|
+
loadComponent: () => import('./rolatech-angular-course-course-index.component-BiS-U0WO.mjs').then((x) => x.CourseIndexComponent),
|
|
1932
1933
|
},
|
|
1933
1934
|
{
|
|
1934
1935
|
path: 'categories/:id',
|
|
@@ -1950,9 +1951,1090 @@ const courseRoutes = [
|
|
|
1950
1951
|
},
|
|
1951
1952
|
];
|
|
1952
1953
|
|
|
1954
|
+
class CourseManageContentComponent {
|
|
1955
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CourseManageContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1956
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.0.1", type: CourseManageContentComponent, isStandalone: true, selector: "rolatech-course-manage-content", ngImport: i0, template: "<ng-content select=\"rolatech-toolbar\"></ng-content>\n<div class=\"p-3\">\n <ng-content></ng-content>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }] }); }
|
|
1957
|
+
}
|
|
1958
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CourseManageContentComponent, decorators: [{
|
|
1959
|
+
type: Component,
|
|
1960
|
+
args: [{ selector: 'rolatech-course-manage-content', standalone: true, imports: [CommonModule], template: "<ng-content select=\"rolatech-toolbar\"></ng-content>\n<div class=\"p-3\">\n <ng-content></ng-content>\n</div>\n" }]
|
|
1961
|
+
}] });
|
|
1962
|
+
|
|
1963
|
+
class CourseManageDetailsComponent {
|
|
1964
|
+
constructor() {
|
|
1965
|
+
this.route = inject(ActivatedRoute);
|
|
1966
|
+
this.courseService = inject(CourseService);
|
|
1967
|
+
this.dialog = inject(MatDialog);
|
|
1968
|
+
this.snackBar = inject(MatSnackBar);
|
|
1969
|
+
this.isLoading = false;
|
|
1970
|
+
this.isUploading = false;
|
|
1971
|
+
this.details = [];
|
|
1972
|
+
this.status = CourseStatus;
|
|
1973
|
+
this.courseType = CourseType;
|
|
1974
|
+
this.id = this.route.parent?.snapshot.paramMap.get('id');
|
|
1975
|
+
}
|
|
1976
|
+
ngOnInit() {
|
|
1977
|
+
this.find();
|
|
1978
|
+
}
|
|
1979
|
+
find() {
|
|
1980
|
+
this.courseService.findDetails(this.id).subscribe({
|
|
1981
|
+
next: (res) => {
|
|
1982
|
+
if (res.data) {
|
|
1983
|
+
this.details = res.data;
|
|
1984
|
+
}
|
|
1985
|
+
},
|
|
1986
|
+
});
|
|
1987
|
+
}
|
|
1988
|
+
addDetail() {
|
|
1989
|
+
if (!this.details) {
|
|
1990
|
+
this.details = [];
|
|
1991
|
+
}
|
|
1992
|
+
this.courseService
|
|
1993
|
+
.addDetail(this.id, {
|
|
1994
|
+
title: '',
|
|
1995
|
+
description: '',
|
|
1996
|
+
content: '',
|
|
1997
|
+
media: [],
|
|
1998
|
+
})
|
|
1999
|
+
.subscribe({
|
|
2000
|
+
next: (res) => {
|
|
2001
|
+
const detail = res.data;
|
|
2002
|
+
this.details.push({
|
|
2003
|
+
id: detail.id,
|
|
2004
|
+
title: '',
|
|
2005
|
+
description: '',
|
|
2006
|
+
content: '',
|
|
2007
|
+
media: [],
|
|
2008
|
+
});
|
|
2009
|
+
},
|
|
2010
|
+
error: (e) => {
|
|
2011
|
+
this.snackBar.open(e.message);
|
|
2012
|
+
},
|
|
2013
|
+
});
|
|
2014
|
+
}
|
|
2015
|
+
onDetailMediaUpload(event) {
|
|
2016
|
+
const detailId = event.id;
|
|
2017
|
+
const index = findIndex(this.details, (item) => item.id === detailId);
|
|
2018
|
+
const file = event.data.target.files[0];
|
|
2019
|
+
if (file) {
|
|
2020
|
+
const reader = new FileReader();
|
|
2021
|
+
reader.readAsDataURL(file);
|
|
2022
|
+
reader.onload = () => {
|
|
2023
|
+
if (!this.details[index].media) {
|
|
2024
|
+
this.details[index].media = [];
|
|
2025
|
+
}
|
|
2026
|
+
this.details[index].media.push({
|
|
2027
|
+
url: reader.result,
|
|
2028
|
+
alt: 'upload image',
|
|
2029
|
+
});
|
|
2030
|
+
this.details[index].isUploading = true;
|
|
2031
|
+
const formData = new FormData();
|
|
2032
|
+
formData.append('file', file);
|
|
2033
|
+
this.courseService.uploadDetailMedia(this.id, detailId, formData).subscribe({
|
|
2034
|
+
next: (res) => {
|
|
2035
|
+
this.isUploading = false;
|
|
2036
|
+
this.details[index].isUploading = false;
|
|
2037
|
+
const tmp = this.details[index].media;
|
|
2038
|
+
delete res.data.productDetail;
|
|
2039
|
+
this.details[index].media[this.details[index].media.length - 1] = res.data;
|
|
2040
|
+
},
|
|
2041
|
+
error: (e) => {
|
|
2042
|
+
this.isUploading = false;
|
|
2043
|
+
this.snackBar.open('上传失败: ' + e.message);
|
|
2044
|
+
},
|
|
2045
|
+
});
|
|
2046
|
+
};
|
|
2047
|
+
reader.onerror = (error) => {
|
|
2048
|
+
this.isUploading = false;
|
|
2049
|
+
};
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
onDetailMediaDelete(event) {
|
|
2053
|
+
const detailId = event.id;
|
|
2054
|
+
const mediaId = event.media.id;
|
|
2055
|
+
this.courseService.deleteDetailMedia(this.id, detailId, mediaId).subscribe({
|
|
2056
|
+
next: (res) => {
|
|
2057
|
+
const detail = this.details.find((item) => item.id === detailId);
|
|
2058
|
+
remove(detail.media, {
|
|
2059
|
+
id: mediaId,
|
|
2060
|
+
});
|
|
2061
|
+
},
|
|
2062
|
+
});
|
|
2063
|
+
}
|
|
2064
|
+
onDetailSave(detail) {
|
|
2065
|
+
delete detail.isUploading;
|
|
2066
|
+
this.courseService.updateDetail(this.id, detail.id, detail).subscribe({
|
|
2067
|
+
next: (res) => {
|
|
2068
|
+
this.snackBar.open('保存成功');
|
|
2069
|
+
},
|
|
2070
|
+
error: (e) => {
|
|
2071
|
+
this.snackBar.open(e.message);
|
|
2072
|
+
},
|
|
2073
|
+
});
|
|
2074
|
+
}
|
|
2075
|
+
onDetailDelete(detail) {
|
|
2076
|
+
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
|
|
2077
|
+
width: '400px',
|
|
2078
|
+
data: {
|
|
2079
|
+
title: '删除详情',
|
|
2080
|
+
message: '确定删除此详情吗?',
|
|
2081
|
+
},
|
|
2082
|
+
});
|
|
2083
|
+
dialogRef.afterClosed().subscribe((result) => {
|
|
2084
|
+
if (result) {
|
|
2085
|
+
this.courseService.deleteDetail(this.id, detail.id).subscribe({
|
|
2086
|
+
next: (res) => {
|
|
2087
|
+
this.snackBar.open(res.data);
|
|
2088
|
+
remove(this.details, {
|
|
2089
|
+
id: detail.id,
|
|
2090
|
+
});
|
|
2091
|
+
},
|
|
2092
|
+
error: (e) => {
|
|
2093
|
+
this.snackBar.open(e.message);
|
|
2094
|
+
},
|
|
2095
|
+
});
|
|
2096
|
+
}
|
|
2097
|
+
});
|
|
2098
|
+
}
|
|
2099
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CourseManageDetailsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2100
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.1", type: CourseManageDetailsComponent, isStandalone: true, selector: "rolatech-course-manage-details", ngImport: i0, template: "<rolatech-course-manage-content>\n <rolatech-toolbar title=\"\u8BE6\u60C5\" class=\"hidden sm:block\" divider> </rolatech-toolbar>\n <div>\n <div>\n @for (detail of details; track detail) {\n <rolatech-detail-item\n [detail]=\"detail\"\n (upload)=\"onDetailMediaUpload($event)\"\n (deleteMedia)=\"onDetailMediaDelete($event)\"\n (save)=\"onDetailSave($event)\"\n (delete)=\"onDetailDelete($event)\"\n [actions]=\"true\"\n ></rolatech-detail-item>\n }\n </div>\n <button mat-stroked-button (click)=\"addDetail()\" class=\"mt-3\">\n <mat-icon>add</mat-icon>\n <span>\u6DFB\u52A0\u8BE6\u60C5</span>\n </button>\n </div>\n</rolatech-course-manage-content>\n", styles: [""], dependencies: [{ kind: "component", type: DetailItemComponent, selector: "rolatech-detail-item", inputs: ["isUploading", "detail", "actions", "selectMedia"], outputs: ["upload", "delete", "save", "deleteMedia"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: CourseManageContentComponent, selector: "rolatech-course-manage-content" }] }); }
|
|
2101
|
+
}
|
|
2102
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CourseManageDetailsComponent, decorators: [{
|
|
2103
|
+
type: Component,
|
|
2104
|
+
args: [{ selector: 'rolatech-course-manage-details', standalone: true, imports: [DetailItemComponent, MatButtonModule, MatIconModule, ToolbarComponent, CourseManageContentComponent], template: "<rolatech-course-manage-content>\n <rolatech-toolbar title=\"\u8BE6\u60C5\" class=\"hidden sm:block\" divider> </rolatech-toolbar>\n <div>\n <div>\n @for (detail of details; track detail) {\n <rolatech-detail-item\n [detail]=\"detail\"\n (upload)=\"onDetailMediaUpload($event)\"\n (deleteMedia)=\"onDetailMediaDelete($event)\"\n (save)=\"onDetailSave($event)\"\n (delete)=\"onDetailDelete($event)\"\n [actions]=\"true\"\n ></rolatech-detail-item>\n }\n </div>\n <button mat-stroked-button (click)=\"addDetail()\" class=\"mt-3\">\n <mat-icon>add</mat-icon>\n <span>\u6DFB\u52A0\u8BE6\u60C5</span>\n </button>\n </div>\n</rolatech-course-manage-content>\n" }]
|
|
2105
|
+
}], ctorParameters: () => [] });
|
|
2106
|
+
|
|
2107
|
+
class CourseManageScheduleComponent {
|
|
2108
|
+
constructor() {
|
|
2109
|
+
this.route = inject(ActivatedRoute);
|
|
2110
|
+
this.courseService = inject(CourseService);
|
|
2111
|
+
this.dialog = inject(MatDialog);
|
|
2112
|
+
this.snackBar = inject(MatSnackBar);
|
|
2113
|
+
this.isLoading = false;
|
|
2114
|
+
this.schedule = [];
|
|
2115
|
+
this.status = CourseStatus;
|
|
2116
|
+
this.courseType = CourseType;
|
|
2117
|
+
this.id = this.route.parent?.snapshot.paramMap.get('id');
|
|
2118
|
+
}
|
|
2119
|
+
ngOnInit() {
|
|
2120
|
+
this.find();
|
|
2121
|
+
}
|
|
2122
|
+
find() {
|
|
2123
|
+
this.courseService.findSchedule(this.id).subscribe({
|
|
2124
|
+
next: (res) => {
|
|
2125
|
+
if (res.data) {
|
|
2126
|
+
this.schedule = res.data;
|
|
2127
|
+
}
|
|
2128
|
+
},
|
|
2129
|
+
});
|
|
2130
|
+
}
|
|
2131
|
+
addSchedule() {
|
|
2132
|
+
const dialogRef = this.dialog.open(CourseScheduleAddDialogComponent, {
|
|
2133
|
+
width: '500px',
|
|
2134
|
+
disableClose: true,
|
|
2135
|
+
data: {
|
|
2136
|
+
title: '添加课表',
|
|
2137
|
+
},
|
|
2138
|
+
});
|
|
2139
|
+
dialogRef.afterClosed().subscribe((schedule) => {
|
|
2140
|
+
if (schedule) {
|
|
2141
|
+
this.courseService.addSchedule(this.id, schedule).subscribe({
|
|
2142
|
+
next: (res) => {
|
|
2143
|
+
this.schedule.push(res.data);
|
|
2144
|
+
this.snackBar.open('添加成功');
|
|
2145
|
+
},
|
|
2146
|
+
error: (error) => {
|
|
2147
|
+
this.snackBar.open(error.message);
|
|
2148
|
+
},
|
|
2149
|
+
});
|
|
2150
|
+
}
|
|
2151
|
+
});
|
|
2152
|
+
}
|
|
2153
|
+
editSchedule() {
|
|
2154
|
+
const dialogRef = this.dialog.open(CourseScheduleDialogComponent, {
|
|
2155
|
+
width: '500px',
|
|
2156
|
+
height: '90%',
|
|
2157
|
+
data: {
|
|
2158
|
+
title: '编辑课表',
|
|
2159
|
+
courseId: this.id,
|
|
2160
|
+
schedule: this.schedule,
|
|
2161
|
+
},
|
|
2162
|
+
});
|
|
2163
|
+
dialogRef.afterClosed().subscribe((result) => {
|
|
2164
|
+
if (result) {
|
|
2165
|
+
this.courseService.addSchedule(this.id, { schedule: result }).subscribe({
|
|
2166
|
+
next: (res) => {
|
|
2167
|
+
this.snackBar.open('添加成功');
|
|
2168
|
+
},
|
|
2169
|
+
error: (error) => {
|
|
2170
|
+
this.snackBar.open(error.message);
|
|
2171
|
+
},
|
|
2172
|
+
});
|
|
2173
|
+
}
|
|
2174
|
+
});
|
|
2175
|
+
}
|
|
2176
|
+
onScheduleSave(schedule) {
|
|
2177
|
+
this.courseService.updateSchedule(this.id, schedule.id, schedule).subscribe({
|
|
2178
|
+
next: (res) => {
|
|
2179
|
+
this.snackBar.open('保存成功');
|
|
2180
|
+
},
|
|
2181
|
+
error: (e) => {
|
|
2182
|
+
this.snackBar.open(e.message);
|
|
2183
|
+
},
|
|
2184
|
+
});
|
|
2185
|
+
}
|
|
2186
|
+
onScheduleDelete(schedule) {
|
|
2187
|
+
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
|
|
2188
|
+
width: '400px',
|
|
2189
|
+
data: {
|
|
2190
|
+
title: '删除课表',
|
|
2191
|
+
message: '确定删除此课表吗?',
|
|
2192
|
+
},
|
|
2193
|
+
});
|
|
2194
|
+
dialogRef.afterClosed().subscribe((result) => {
|
|
2195
|
+
if (result) {
|
|
2196
|
+
this.courseService.deleteSchedule(this.id, schedule.id).subscribe({
|
|
2197
|
+
next: (res) => {
|
|
2198
|
+
remove(this.schedule, {
|
|
2199
|
+
id: schedule.id,
|
|
2200
|
+
});
|
|
2201
|
+
this.snackBar.open(res.data);
|
|
2202
|
+
},
|
|
2203
|
+
error: (e) => {
|
|
2204
|
+
this.snackBar.open(e.message);
|
|
2205
|
+
},
|
|
2206
|
+
});
|
|
2207
|
+
}
|
|
2208
|
+
});
|
|
2209
|
+
}
|
|
2210
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CourseManageScheduleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2211
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.1", type: CourseManageScheduleComponent, isStandalone: true, selector: "rolatech-course-manage-schedule", ngImport: i0, template: "<rolatech-course-manage-content>\n <rolatech-toolbar title=\"\u8BFE\u7A0B\u8868\" class=\"hidden sm:block\" divider> </rolatech-toolbar>\n <div>\n <div>\n @for (item of schedule; track item) {\n <rolatech-schedule-item\n [value]=\"item\"\n [actions]=\"true\"\n (save)=\"onScheduleSave($event)\"\n (delete)=\"onScheduleDelete($event)\"\n >\n </rolatech-schedule-item>\n }\n </div>\n <button mat-stroked-button (click)=\"addSchedule()\" class=\"mt-3\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u8BFE\u8868</span>\n </button>\n </div>\n</rolatech-course-manage-content>\n", styles: [""], dependencies: [{ kind: "component", type: ScheduleItemComponent, selector: "rolatech-schedule-item", inputs: ["value", "actions"], outputs: ["delete", "save"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: CourseManageContentComponent, selector: "rolatech-course-manage-content" }] }); }
|
|
2212
|
+
}
|
|
2213
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CourseManageScheduleComponent, decorators: [{
|
|
2214
|
+
type: Component,
|
|
2215
|
+
args: [{ selector: 'rolatech-course-manage-schedule', standalone: true, imports: [ScheduleItemComponent, MatButtonModule, MatIconModule, ToolbarComponent, CourseManageContentComponent], template: "<rolatech-course-manage-content>\n <rolatech-toolbar title=\"\u8BFE\u7A0B\u8868\" class=\"hidden sm:block\" divider> </rolatech-toolbar>\n <div>\n <div>\n @for (item of schedule; track item) {\n <rolatech-schedule-item\n [value]=\"item\"\n [actions]=\"true\"\n (save)=\"onScheduleSave($event)\"\n (delete)=\"onScheduleDelete($event)\"\n >\n </rolatech-schedule-item>\n }\n </div>\n <button mat-stroked-button (click)=\"addSchedule()\" class=\"mt-3\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u8BFE\u8868</span>\n </button>\n </div>\n</rolatech-course-manage-content>\n" }]
|
|
2216
|
+
}], ctorParameters: () => [] });
|
|
2217
|
+
|
|
2218
|
+
class CourseManagePricingComponent {
|
|
2219
|
+
constructor() {
|
|
2220
|
+
this.route = inject(ActivatedRoute);
|
|
2221
|
+
this.courseService = inject(CourseService);
|
|
2222
|
+
this.dialog = inject(MatDialog);
|
|
2223
|
+
this.snackBar = inject(MatSnackBar);
|
|
2224
|
+
this.isLoading = false;
|
|
2225
|
+
this.pricing = [];
|
|
2226
|
+
this.status = CourseStatus;
|
|
2227
|
+
this.courseType = CourseType;
|
|
2228
|
+
this.id = this.route.parent?.snapshot.paramMap.get('id');
|
|
2229
|
+
}
|
|
2230
|
+
ngOnInit() {
|
|
2231
|
+
this.find();
|
|
2232
|
+
}
|
|
2233
|
+
find() {
|
|
2234
|
+
this.courseService.findPricing(this.id).subscribe({
|
|
2235
|
+
next: (res) => {
|
|
2236
|
+
if (res.data) {
|
|
2237
|
+
this.pricing = res.data;
|
|
2238
|
+
}
|
|
2239
|
+
},
|
|
2240
|
+
});
|
|
2241
|
+
}
|
|
2242
|
+
editPricing() {
|
|
2243
|
+
const dialogRef = this.dialog.open(CoursePricingDialogComponent, {
|
|
2244
|
+
width: '500px',
|
|
2245
|
+
height: '90%',
|
|
2246
|
+
data: {
|
|
2247
|
+
title: '编辑价格',
|
|
2248
|
+
courseId: this.id,
|
|
2249
|
+
pricing: this.pricing,
|
|
2250
|
+
},
|
|
2251
|
+
});
|
|
2252
|
+
dialogRef.afterClosed().subscribe((result) => {
|
|
2253
|
+
if (result) {
|
|
2254
|
+
this.courseService.addPricing(this.id, { pricing: result }).subscribe({
|
|
2255
|
+
next: (res) => {
|
|
2256
|
+
this.snackBar.open('添加成功');
|
|
2257
|
+
},
|
|
2258
|
+
error: (error) => {
|
|
2259
|
+
this.snackBar.open(error.message);
|
|
2260
|
+
},
|
|
2261
|
+
});
|
|
2262
|
+
}
|
|
2263
|
+
});
|
|
2264
|
+
}
|
|
2265
|
+
addPricing() {
|
|
2266
|
+
const dialogRef = this.dialog.open(CoursePricingAddDialogComponent, {
|
|
2267
|
+
disableClose: true,
|
|
2268
|
+
width: '500px',
|
|
2269
|
+
data: {
|
|
2270
|
+
title: '添加价格',
|
|
2271
|
+
},
|
|
2272
|
+
});
|
|
2273
|
+
dialogRef.afterClosed().subscribe((pricing) => {
|
|
2274
|
+
if (pricing) {
|
|
2275
|
+
this.courseService.addPricing(this.id, { ...pricing, total: pricing.total * 100 }).subscribe({
|
|
2276
|
+
next: (res) => {
|
|
2277
|
+
this.pricing.push(res.data);
|
|
2278
|
+
this.snackBar.open('添加成功');
|
|
2279
|
+
},
|
|
2280
|
+
error: (error) => {
|
|
2281
|
+
this.snackBar.open(error.message);
|
|
2282
|
+
},
|
|
2283
|
+
});
|
|
2284
|
+
}
|
|
2285
|
+
});
|
|
2286
|
+
}
|
|
2287
|
+
onPricingSave(pricing) {
|
|
2288
|
+
this.courseService.updatePricing(this.id, pricing.id, pricing).subscribe({
|
|
2289
|
+
next: (res) => {
|
|
2290
|
+
this.snackBar.open('保存成功');
|
|
2291
|
+
},
|
|
2292
|
+
error: (e) => {
|
|
2293
|
+
this.snackBar.open(e.message);
|
|
2294
|
+
},
|
|
2295
|
+
});
|
|
2296
|
+
}
|
|
2297
|
+
onPricingDelete(pricing) {
|
|
2298
|
+
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
|
|
2299
|
+
width: '400px',
|
|
2300
|
+
data: {
|
|
2301
|
+
title: '删除价格',
|
|
2302
|
+
message: '确定删除此价格吗?',
|
|
2303
|
+
},
|
|
2304
|
+
});
|
|
2305
|
+
dialogRef.afterClosed().subscribe((result) => {
|
|
2306
|
+
if (result) {
|
|
2307
|
+
this.courseService.deletePricing(this.id, pricing.id).subscribe({
|
|
2308
|
+
next: (res) => {
|
|
2309
|
+
remove(this.pricing, {
|
|
2310
|
+
id: pricing.id,
|
|
2311
|
+
});
|
|
2312
|
+
this.snackBar.open(res.data);
|
|
2313
|
+
},
|
|
2314
|
+
error: (e) => {
|
|
2315
|
+
this.snackBar.open(e.message);
|
|
2316
|
+
},
|
|
2317
|
+
});
|
|
2318
|
+
}
|
|
2319
|
+
});
|
|
2320
|
+
}
|
|
2321
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CourseManagePricingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2322
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.1", type: CourseManagePricingComponent, isStandalone: true, selector: "rolatech-course-manage-pricing", ngImport: i0, template: "<rolatech-course-manage-content>\n <rolatech-toolbar title=\"\u4EF7\u683C\" class=\"hidden sm:block\" divider> </rolatech-toolbar>\n <div>\n <div>\n @for (item of pricing; track item) {\n <rolatech-pricing-item\n [pricing]=\"item\"\n [actions]=\"true\"\n (save)=\"onPricingSave($event)\"\n (delete)=\"onPricingDelete($event)\"\n >\n </rolatech-pricing-item>\n }\n </div>\n <button mat-stroked-button (click)=\"addPricing()\" class=\"mt-3\">\n <mat-icon>add</mat-icon>\n <span>\u6DFB\u52A0\u4EF7\u683C</span>\n </button>\n </div>\n</rolatech-course-manage-content>\n", styles: [""], dependencies: [{ kind: "component", type: PricingItemComponent, selector: "rolatech-pricing-item", inputs: ["actions", "pricing"], outputs: ["pricingChange", "delete", "save"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: CourseManageContentComponent, selector: "rolatech-course-manage-content" }] }); }
|
|
2323
|
+
}
|
|
2324
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CourseManagePricingComponent, decorators: [{
|
|
2325
|
+
type: Component,
|
|
2326
|
+
args: [{ selector: 'rolatech-course-manage-pricing', standalone: true, imports: [PricingItemComponent, MatButtonModule, MatIconModule, ToolbarComponent, CourseManageContentComponent], template: "<rolatech-course-manage-content>\n <rolatech-toolbar title=\"\u4EF7\u683C\" class=\"hidden sm:block\" divider> </rolatech-toolbar>\n <div>\n <div>\n @for (item of pricing; track item) {\n <rolatech-pricing-item\n [pricing]=\"item\"\n [actions]=\"true\"\n (save)=\"onPricingSave($event)\"\n (delete)=\"onPricingDelete($event)\"\n >\n </rolatech-pricing-item>\n }\n </div>\n <button mat-stroked-button (click)=\"addPricing()\" class=\"mt-3\">\n <mat-icon>add</mat-icon>\n <span>\u6DFB\u52A0\u4EF7\u683C</span>\n </button>\n </div>\n</rolatech-course-manage-content>\n" }]
|
|
2327
|
+
}], ctorParameters: () => [] });
|
|
2328
|
+
|
|
2329
|
+
class BookingService extends BaseService {
|
|
2330
|
+
init() {
|
|
2331
|
+
this.endpoint = 'partners/bookings';
|
|
2332
|
+
super.init();
|
|
2333
|
+
}
|
|
2334
|
+
items(options) {
|
|
2335
|
+
return this.http.get(`${this.actionUrl}/items`, {
|
|
2336
|
+
params: options,
|
|
2337
|
+
withCredentials: true,
|
|
2338
|
+
});
|
|
2339
|
+
}
|
|
2340
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: BookingService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2341
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: BookingService, providedIn: 'root' }); }
|
|
2342
|
+
}
|
|
2343
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: BookingService, decorators: [{
|
|
2344
|
+
type: Injectable,
|
|
2345
|
+
args: [{
|
|
2346
|
+
providedIn: 'root',
|
|
2347
|
+
}]
|
|
2348
|
+
}] });
|
|
2349
|
+
|
|
2350
|
+
class InstructorService extends BaseService {
|
|
2351
|
+
init() {
|
|
2352
|
+
this.endpoint = 'instructors';
|
|
2353
|
+
super.init();
|
|
2354
|
+
}
|
|
2355
|
+
findMyClassrooms(options) {
|
|
2356
|
+
return this.http.get(`${this.actionUrl}/classrooms/me`, {
|
|
2357
|
+
params: options,
|
|
2358
|
+
withCredentials: true,
|
|
2359
|
+
});
|
|
2360
|
+
}
|
|
2361
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: InstructorService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2362
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: InstructorService, providedIn: 'root' }); }
|
|
2363
|
+
}
|
|
2364
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: InstructorService, decorators: [{
|
|
2365
|
+
type: Injectable,
|
|
2366
|
+
args: [{
|
|
2367
|
+
providedIn: 'root',
|
|
2368
|
+
}]
|
|
2369
|
+
}] });
|
|
2370
|
+
|
|
2371
|
+
class CourseManageInfoComponent extends BaseComponent {
|
|
2372
|
+
constructor() {
|
|
2373
|
+
super(...arguments);
|
|
2374
|
+
this.courseService = inject(CourseService);
|
|
2375
|
+
this.instructorService = inject(InstructorService);
|
|
2376
|
+
this.categoryService = inject(CategoryService);
|
|
2377
|
+
this.bookingService = inject(BookingService);
|
|
2378
|
+
this.isLoading = false;
|
|
2379
|
+
this.status = CourseStatus;
|
|
2380
|
+
this.courseType = [
|
|
2381
|
+
{
|
|
2382
|
+
key: 'ONLINE',
|
|
2383
|
+
value: '线上',
|
|
2384
|
+
},
|
|
2385
|
+
{
|
|
2386
|
+
key: 'OFFLINE',
|
|
2387
|
+
value: '线下',
|
|
2388
|
+
},
|
|
2389
|
+
{
|
|
2390
|
+
key: 'MIXED',
|
|
2391
|
+
value: '混合',
|
|
2392
|
+
},
|
|
2393
|
+
];
|
|
2394
|
+
}
|
|
2395
|
+
ngOnInit() {
|
|
2396
|
+
this.id = this.route.parent?.snapshot.paramMap.get('id');
|
|
2397
|
+
this.find();
|
|
2398
|
+
this.categoryService.find({}).subscribe({
|
|
2399
|
+
next: (res) => {
|
|
2400
|
+
this.categories = res.data;
|
|
2401
|
+
},
|
|
2402
|
+
});
|
|
2403
|
+
this.findClassrooms();
|
|
2404
|
+
this.findBookedClassrooms();
|
|
2405
|
+
}
|
|
2406
|
+
findBookedClassrooms() {
|
|
2407
|
+
this.bookingService.items({ status: 'paid' }).subscribe({
|
|
2408
|
+
next: (res) => {
|
|
2409
|
+
this.bookedClassrooms = res.data;
|
|
2410
|
+
},
|
|
2411
|
+
});
|
|
2412
|
+
}
|
|
2413
|
+
findClassrooms() {
|
|
2414
|
+
this.instructorService.findMyClassrooms({}).subscribe({
|
|
2415
|
+
next: (res) => {
|
|
2416
|
+
this.classrooms = res.data;
|
|
2417
|
+
},
|
|
2418
|
+
});
|
|
2419
|
+
}
|
|
2420
|
+
find() {
|
|
2421
|
+
this.courseService.get(this.id).subscribe({
|
|
2422
|
+
next: (res) => {
|
|
2423
|
+
this.course = res.data;
|
|
2424
|
+
},
|
|
2425
|
+
});
|
|
2426
|
+
}
|
|
2427
|
+
compareFn(o1, o2) {
|
|
2428
|
+
return o1.id === o2?.id;
|
|
2429
|
+
}
|
|
2430
|
+
compareClassroom(o1, o2) {
|
|
2431
|
+
if (o1.room) {
|
|
2432
|
+
return (o1.latitude === o2?.latitude &&
|
|
2433
|
+
o1.longitude === o2?.longitude &&
|
|
2434
|
+
o1.room === o2.room &&
|
|
2435
|
+
o1.startAt === o2.startAt &&
|
|
2436
|
+
o1.endAt === o2.endAt);
|
|
2437
|
+
}
|
|
2438
|
+
else {
|
|
2439
|
+
return o1.latitude === o2?.latitude && o1.longitude === o2?.longitude;
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2442
|
+
onSelectionChange(event) {
|
|
2443
|
+
this.selectedCategoyIds = event.value;
|
|
2444
|
+
}
|
|
2445
|
+
onClassroomSelected(event) {
|
|
2446
|
+
this.selectedClassroom = event.value;
|
|
2447
|
+
}
|
|
2448
|
+
update() {
|
|
2449
|
+
const { name, description, categories, type, classroom } = this.course;
|
|
2450
|
+
const finalClassroom = clone(classroom);
|
|
2451
|
+
finalClassroom.address = classroom.room ? classroom.address + ' ' + classroom.room + '室' : classroom.address;
|
|
2452
|
+
const data = {
|
|
2453
|
+
name,
|
|
2454
|
+
description,
|
|
2455
|
+
categories,
|
|
2456
|
+
type,
|
|
2457
|
+
classroom: finalClassroom,
|
|
2458
|
+
};
|
|
2459
|
+
this.courseService.update(this.id, data).subscribe({
|
|
2460
|
+
next: (res) => {
|
|
2461
|
+
this.snackBarService.open('保存成功');
|
|
2462
|
+
// this.router.navigate([`../${res.data.id}`], { relativeTo: this.route });
|
|
2463
|
+
},
|
|
2464
|
+
error: (e) => {
|
|
2465
|
+
this.snackBarService.open(e.message);
|
|
2466
|
+
},
|
|
2467
|
+
});
|
|
2468
|
+
}
|
|
2469
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CourseManageInfoComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
2470
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.1", type: CourseManageInfoComponent, isStandalone: true, selector: "rolatech-course-manage-info", usesInheritance: true, ngImport: i0, template: "<rolatech-course-manage-content>\n <rolatech-toolbar title=\"\u57FA\u672C\u4FE1\u606F\" class=\"hidden sm:block\" divider></rolatech-toolbar>\n @if (course) {\n <div class=\"flex flex-col\">\n <form #courseForm=\"ngForm\" (ngSubmit)=\"update()\">\n <mat-form-field appearance=\"fill\">\n <mat-label> \u8BFE\u7A0B\u540D\u79F0 </mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"course.name\" name=\"name\" required />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label> \u8BFE\u7A0B\u63CF\u8FF0 </mat-label>\n <textarea\n matInput\n type=\"text\"\n [(ngModel)]=\"course.description\"\n name=\"description\"\n required\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"3\"\n ></textarea>\n </mat-form-field>\n <mat-form-field appearance=\"fill\" ngModelGroup=\"categories\" required>\n <mat-label>\u5206\u7C7B</mat-label>\n <mat-select\n multiple\n name=\"id\"\n [compareWith]=\"compareFn\"\n [(ngModel)]=\"course.categories\"\n #select=\"matSelect\"\n (selectionChange)=\"onSelectionChange($event)\"\n >\n @for (item of categories; track item) {\n <mat-option [value]=\"item\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label>\u7C7B\u578B</mat-label>\n <mat-select name=\"type\" [(ngModel)]=\"course.type\" required>\n @for (item of courseType; track item) {\n <mat-option [value]=\"item.key\">\n {{ item.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n @if (course.type && course.type.toString() !== 'ONLINE') {\n <mat-form-field appearance=\"fill\" ngModelGroup=\"classroom\">\n <mat-label>\u6559\u5BA4</mat-label>\n <mat-select\n name=\"id\"\n [(ngModel)]=\"course.classroom\"\n [compareWith]=\"compareClassroom\"\n (selectionChange)=\"onClassroomSelected($event)\"\n required\n >\n <mat-optgroup label=\"\u81EA\u6709\u6559\u5BA4\">\n @for (classroom of classrooms; track classroom) {\n <mat-option [value]=\"classroom\">\n <div class=\"flex gap-3\">\n <span>{{ classroom.name }}</span>\n <span> {{ classroom.address }}</span>\n </div>\n </mat-option>\n }\n </mat-optgroup>\n <mat-optgroup label=\"\u5DF2\u8D2D\u6559\u5BA4\">\n @for (item of bookedClassrooms; track item) {\n <mat-option [value]=\"item\">\n <div class=\"flex flex-col py-3\">\n <span class=\"font-bold\"> {{ item.address }} {{ item.room }}\u5BA4</span>\n <span class=\"text-md font-thin\"> {{ item.startAt }} - {{ item.endAt }}</span>\n </div>\n </mat-option>\n }\n </mat-optgroup>\n </mat-select>\n </mat-form-field>\n }\n </form>\n </div>\n <div>\n <button mat-flat-button type=\"primary\" (click)=\"update()\">\u4FDD\u5B58</button>\n </div>\n }\n</rolatech-course-manage-content>\n", styles: ["mat-form-field{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i6.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i6.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i6.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i6.NgModelGroup, selector: "[ngModelGroup]", inputs: ["ngModelGroup"], exportAs: ["ngModelGroup"] }, { kind: "directive", type: i6.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i2$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i3$1.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "ngmodule", type: TextFieldModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i6$2.MatOptgroup, selector: "mat-optgroup", inputs: ["label", "disabled"], exportAs: ["matOptgroup"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: CourseManageContentComponent, selector: "rolatech-course-manage-content" }] }); }
|
|
2471
|
+
}
|
|
2472
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CourseManageInfoComponent, decorators: [{
|
|
2473
|
+
type: Component,
|
|
2474
|
+
args: [{ selector: 'rolatech-course-manage-info', standalone: true, imports: [
|
|
2475
|
+
FormsModule,
|
|
2476
|
+
MatFormFieldModule,
|
|
2477
|
+
MatInputModule,
|
|
2478
|
+
TextFieldModule,
|
|
2479
|
+
MatSelectModule,
|
|
2480
|
+
MatOptionModule,
|
|
2481
|
+
MatButtonModule,
|
|
2482
|
+
ToolbarComponent,
|
|
2483
|
+
CourseManageContentComponent,
|
|
2484
|
+
], template: "<rolatech-course-manage-content>\n <rolatech-toolbar title=\"\u57FA\u672C\u4FE1\u606F\" class=\"hidden sm:block\" divider></rolatech-toolbar>\n @if (course) {\n <div class=\"flex flex-col\">\n <form #courseForm=\"ngForm\" (ngSubmit)=\"update()\">\n <mat-form-field appearance=\"fill\">\n <mat-label> \u8BFE\u7A0B\u540D\u79F0 </mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"course.name\" name=\"name\" required />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label> \u8BFE\u7A0B\u63CF\u8FF0 </mat-label>\n <textarea\n matInput\n type=\"text\"\n [(ngModel)]=\"course.description\"\n name=\"description\"\n required\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"3\"\n ></textarea>\n </mat-form-field>\n <mat-form-field appearance=\"fill\" ngModelGroup=\"categories\" required>\n <mat-label>\u5206\u7C7B</mat-label>\n <mat-select\n multiple\n name=\"id\"\n [compareWith]=\"compareFn\"\n [(ngModel)]=\"course.categories\"\n #select=\"matSelect\"\n (selectionChange)=\"onSelectionChange($event)\"\n >\n @for (item of categories; track item) {\n <mat-option [value]=\"item\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label>\u7C7B\u578B</mat-label>\n <mat-select name=\"type\" [(ngModel)]=\"course.type\" required>\n @for (item of courseType; track item) {\n <mat-option [value]=\"item.key\">\n {{ item.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n @if (course.type && course.type.toString() !== 'ONLINE') {\n <mat-form-field appearance=\"fill\" ngModelGroup=\"classroom\">\n <mat-label>\u6559\u5BA4</mat-label>\n <mat-select\n name=\"id\"\n [(ngModel)]=\"course.classroom\"\n [compareWith]=\"compareClassroom\"\n (selectionChange)=\"onClassroomSelected($event)\"\n required\n >\n <mat-optgroup label=\"\u81EA\u6709\u6559\u5BA4\">\n @for (classroom of classrooms; track classroom) {\n <mat-option [value]=\"classroom\">\n <div class=\"flex gap-3\">\n <span>{{ classroom.name }}</span>\n <span> {{ classroom.address }}</span>\n </div>\n </mat-option>\n }\n </mat-optgroup>\n <mat-optgroup label=\"\u5DF2\u8D2D\u6559\u5BA4\">\n @for (item of bookedClassrooms; track item) {\n <mat-option [value]=\"item\">\n <div class=\"flex flex-col py-3\">\n <span class=\"font-bold\"> {{ item.address }} {{ item.room }}\u5BA4</span>\n <span class=\"text-md font-thin\"> {{ item.startAt }} - {{ item.endAt }}</span>\n </div>\n </mat-option>\n }\n </mat-optgroup>\n </mat-select>\n </mat-form-field>\n }\n </form>\n </div>\n <div>\n <button mat-flat-button type=\"primary\" (click)=\"update()\">\u4FDD\u5B58</button>\n </div>\n }\n</rolatech-course-manage-content>\n", styles: ["mat-form-field{width:100%}\n"] }]
|
|
2485
|
+
}] });
|
|
2486
|
+
|
|
2487
|
+
const SIZE = 10 * 1024 * 1024; // file slice size 10MB
|
|
2488
|
+
class CourseManageMediaComponent {
|
|
2489
|
+
constructor() {
|
|
2490
|
+
this.route = inject(ActivatedRoute);
|
|
2491
|
+
this.courseService = inject(CourseService);
|
|
2492
|
+
this.dialog = inject(MatDialog);
|
|
2493
|
+
this.snackBar = inject(MatSnackBar);
|
|
2494
|
+
this.isUploading = false;
|
|
2495
|
+
this.isLoading = false;
|
|
2496
|
+
this.media = [];
|
|
2497
|
+
this.status = CourseStatus;
|
|
2498
|
+
this.courseType = CourseType;
|
|
2499
|
+
this.id = this.route.parent?.snapshot.paramMap.get('id');
|
|
2500
|
+
}
|
|
2501
|
+
ngOnInit() {
|
|
2502
|
+
this.find();
|
|
2503
|
+
}
|
|
2504
|
+
find() {
|
|
2505
|
+
this.courseService.get(this.id).subscribe({
|
|
2506
|
+
next: (res) => {
|
|
2507
|
+
this.media = res.data.media || [];
|
|
2508
|
+
},
|
|
2509
|
+
});
|
|
2510
|
+
}
|
|
2511
|
+
onImageClick(i) {
|
|
2512
|
+
const dialogRef = this.dialog.open(ImagePreviewDialogComponent, {
|
|
2513
|
+
maxWidth: '80vw',
|
|
2514
|
+
maxHeight: '80vh',
|
|
2515
|
+
height: '80%',
|
|
2516
|
+
width: '80%',
|
|
2517
|
+
panelClass: 'full-screen-modal',
|
|
2518
|
+
data: {
|
|
2519
|
+
media: this.media,
|
|
2520
|
+
selected: i,
|
|
2521
|
+
},
|
|
2522
|
+
});
|
|
2523
|
+
dialogRef.afterClosed().subscribe((result) => { });
|
|
2524
|
+
}
|
|
2525
|
+
createFileChunk(file, size = SIZE) {
|
|
2526
|
+
const fileChunkList = [];
|
|
2527
|
+
let cur = 0;
|
|
2528
|
+
while (cur < file.size) {
|
|
2529
|
+
fileChunkList.push({ file: file.slice(cur, cur + size) });
|
|
2530
|
+
cur += size;
|
|
2531
|
+
}
|
|
2532
|
+
return fileChunkList;
|
|
2533
|
+
}
|
|
2534
|
+
onUploadMedia2(event) {
|
|
2535
|
+
const file = event.target.files[0];
|
|
2536
|
+
const reader = new FileReader();
|
|
2537
|
+
reader.onload = (e) => { };
|
|
2538
|
+
const fileChunkList = this.createFileChunk(file);
|
|
2539
|
+
fileChunkList.forEach((item) => { });
|
|
2540
|
+
}
|
|
2541
|
+
onUploadMedia(event) {
|
|
2542
|
+
const file = event.target.files[0];
|
|
2543
|
+
// 5MB * 1024 * 1024 = 5242880
|
|
2544
|
+
// if (file?.size > 5242880) {
|
|
2545
|
+
// this.snackBar.open('尺寸过大, 请修改后上传');
|
|
2546
|
+
// this.isUploading = false;
|
|
2547
|
+
// return;
|
|
2548
|
+
// }
|
|
2549
|
+
if (file) {
|
|
2550
|
+
const reader = new FileReader();
|
|
2551
|
+
const formData = new FormData();
|
|
2552
|
+
formData.append('file', file);
|
|
2553
|
+
reader.readAsDataURL(file);
|
|
2554
|
+
reader.onload = () => {
|
|
2555
|
+
const img = new Image();
|
|
2556
|
+
img.onload = () => {
|
|
2557
|
+
this.media.push({
|
|
2558
|
+
url: img.src,
|
|
2559
|
+
alt: 'upload image',
|
|
2560
|
+
width: img.width,
|
|
2561
|
+
height: img.height,
|
|
2562
|
+
});
|
|
2563
|
+
this.isUploading = true;
|
|
2564
|
+
};
|
|
2565
|
+
img.src = reader.result; // This is the data URL
|
|
2566
|
+
};
|
|
2567
|
+
this.courseService.uploadMedia(this.id, formData).subscribe({
|
|
2568
|
+
next: (res) => {
|
|
2569
|
+
this.isUploading = false;
|
|
2570
|
+
const index = findLastIndex(this.media);
|
|
2571
|
+
// Replace item at index using native splice
|
|
2572
|
+
this.media.splice(index, 1, res.data);
|
|
2573
|
+
},
|
|
2574
|
+
error: (e) => {
|
|
2575
|
+
this.isUploading = false;
|
|
2576
|
+
this.snackBar.open('上传失败: ' + e.message);
|
|
2577
|
+
},
|
|
2578
|
+
});
|
|
2579
|
+
reader.onerror = (error) => {
|
|
2580
|
+
this.isUploading = false;
|
|
2581
|
+
};
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2584
|
+
onMediaDelete(item) {
|
|
2585
|
+
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
|
|
2586
|
+
width: '400px',
|
|
2587
|
+
data: {
|
|
2588
|
+
title: '删除图片',
|
|
2589
|
+
message: '确定删除这张课程图片吗?',
|
|
2590
|
+
},
|
|
2591
|
+
});
|
|
2592
|
+
dialogRef.afterClosed().subscribe((result) => {
|
|
2593
|
+
if (result) {
|
|
2594
|
+
this.courseService.deleteMedia(this.id, item.id).subscribe({
|
|
2595
|
+
next: (res) => {
|
|
2596
|
+
this.media = this.media.filter((m) => m.id !== item.id);
|
|
2597
|
+
this.snackBar.open('删除成功');
|
|
2598
|
+
},
|
|
2599
|
+
error: (e) => {
|
|
2600
|
+
this.snackBar.open(e.message);
|
|
2601
|
+
},
|
|
2602
|
+
});
|
|
2603
|
+
}
|
|
2604
|
+
});
|
|
2605
|
+
}
|
|
2606
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CourseManageMediaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2607
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.1", type: CourseManageMediaComponent, isStandalone: true, selector: "rolatech-course-manage-media", ngImport: i0, template: "<rolatech-course-manage-content>\n <rolatech-toolbar title=\"\u56FE\u7247\u4FE1\u606F\" class=\"hidden sm:block\" divider></rolatech-toolbar>\n <div>\n <p class=\"text-gray-600\">*\u56FE\u7247\u6587\u4EF6\u5927\u5C0F\u9650\u5236\u57285MB\u4EE5\u4E0B*</p>\n <rolatech-media-list (upload)=\"onUploadMedia($event)\" [isUploading]=\"isUploading\">\n @for (item of media; track item; let i = $index) {\n <rolatech-media-list-item\n [media]=\"item\"\n (mediaItemClick)=\"onImageClick(i)\"\n (deleteMedia)=\"onMediaDelete(item)\"\n ></rolatech-media-list-item>\n }\n </rolatech-media-list>\n </div>\n</rolatech-course-manage-content>\n", styles: [""], dependencies: [{ kind: "component", type: MediaListComponent, selector: "rolatech-media-list", inputs: ["isUploading", "media", "showAdd"], outputs: ["mediaItemClick", "upload"] }, { kind: "component", type: MediaListItemComponent, selector: "rolatech-media-list-item", inputs: ["media", "uploadProgress"], outputs: ["mediaItemClick", "deleteMedia"] }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: CourseManageContentComponent, selector: "rolatech-course-manage-content" }] }); }
|
|
2608
|
+
}
|
|
2609
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CourseManageMediaComponent, decorators: [{
|
|
2610
|
+
type: Component,
|
|
2611
|
+
args: [{ selector: 'rolatech-course-manage-media', standalone: true, imports: [MediaListComponent, MediaListItemComponent, ToolbarComponent, CourseManageContentComponent], template: "<rolatech-course-manage-content>\n <rolatech-toolbar title=\"\u56FE\u7247\u4FE1\u606F\" class=\"hidden sm:block\" divider></rolatech-toolbar>\n <div>\n <p class=\"text-gray-600\">*\u56FE\u7247\u6587\u4EF6\u5927\u5C0F\u9650\u5236\u57285MB\u4EE5\u4E0B*</p>\n <rolatech-media-list (upload)=\"onUploadMedia($event)\" [isUploading]=\"isUploading\">\n @for (item of media; track item; let i = $index) {\n <rolatech-media-list-item\n [media]=\"item\"\n (mediaItemClick)=\"onImageClick(i)\"\n (deleteMedia)=\"onMediaDelete(item)\"\n ></rolatech-media-list-item>\n }\n </rolatech-media-list>\n </div>\n</rolatech-course-manage-content>\n" }]
|
|
2612
|
+
}], ctorParameters: () => [] });
|
|
2613
|
+
|
|
2614
|
+
class CourseManageSectionComponent extends BaseComponent {
|
|
2615
|
+
constructor() {
|
|
2616
|
+
super(...arguments);
|
|
2617
|
+
this.courseService = inject(CourseService);
|
|
2618
|
+
this.sections = [];
|
|
2619
|
+
this.hasUnsaved = false;
|
|
2620
|
+
this.editId = '';
|
|
2621
|
+
this.lectureEditId = '';
|
|
2622
|
+
this.chunkSize = 5 * 1024 * 1024; // 切片大小
|
|
2623
|
+
this.fileIndex = 0; // 当前正在被遍历的文件下标
|
|
2624
|
+
}
|
|
2625
|
+
ngOnInit() {
|
|
2626
|
+
this.id = this.route.parent?.snapshot.paramMap.get('id');
|
|
2627
|
+
this.find();
|
|
2628
|
+
}
|
|
2629
|
+
find() {
|
|
2630
|
+
this.courseService.getCourseSection(this.id).subscribe({
|
|
2631
|
+
next: (res) => {
|
|
2632
|
+
if (res.data) {
|
|
2633
|
+
this.sections = res.data;
|
|
2634
|
+
}
|
|
2635
|
+
},
|
|
2636
|
+
});
|
|
2637
|
+
}
|
|
2638
|
+
addSection() {
|
|
2639
|
+
const section = {
|
|
2640
|
+
title: '',
|
|
2641
|
+
description: '',
|
|
2642
|
+
};
|
|
2643
|
+
this.courseService.addCourseSection(this.id, section).subscribe({
|
|
2644
|
+
next: (res) => {
|
|
2645
|
+
this.sections.push(res.data);
|
|
2646
|
+
this.editId = res.data.id;
|
|
2647
|
+
},
|
|
2648
|
+
});
|
|
2649
|
+
this.hasUnsaved = false;
|
|
2650
|
+
}
|
|
2651
|
+
onCancel(event) {
|
|
2652
|
+
this.sections.pop();
|
|
2653
|
+
this.hasUnsaved = false;
|
|
2654
|
+
}
|
|
2655
|
+
onSectionSave(event) {
|
|
2656
|
+
const { id } = event;
|
|
2657
|
+
this.courseService.updateCourseSection(id, event).subscribe({
|
|
2658
|
+
next: (res) => {
|
|
2659
|
+
this.hasUnsaved = false;
|
|
2660
|
+
this.snackBarService.open('保存成功');
|
|
2661
|
+
},
|
|
2662
|
+
});
|
|
2663
|
+
this.hasUnsaved = false;
|
|
2664
|
+
}
|
|
2665
|
+
onSectionEdit(event) {
|
|
2666
|
+
this.editId = event.id;
|
|
2667
|
+
// this.editIndex = this.sections.find((item: any) => item.id === event.id);
|
|
2668
|
+
}
|
|
2669
|
+
onSectionDelete(event) {
|
|
2670
|
+
const { id } = event;
|
|
2671
|
+
const options = {
|
|
2672
|
+
title: '确认删除吗',
|
|
2673
|
+
message: '删除这个章节吗?',
|
|
2674
|
+
cancelText: '取消',
|
|
2675
|
+
confirmText: '确认',
|
|
2676
|
+
};
|
|
2677
|
+
this.dialogService.open(options);
|
|
2678
|
+
this.dialogService.confirmed().subscribe({
|
|
2679
|
+
next: (res) => {
|
|
2680
|
+
if (res) {
|
|
2681
|
+
const data = {
|
|
2682
|
+
name: res,
|
|
2683
|
+
};
|
|
2684
|
+
this.courseService.deleteCourseSection(id).subscribe({
|
|
2685
|
+
next: (res) => {
|
|
2686
|
+
this.sections.pop();
|
|
2687
|
+
this.hasUnsaved = false;
|
|
2688
|
+
this.snackBarService.open(res.data);
|
|
2689
|
+
},
|
|
2690
|
+
error: (error) => {
|
|
2691
|
+
this.snackBarService.open(error.message);
|
|
2692
|
+
},
|
|
2693
|
+
});
|
|
2694
|
+
}
|
|
2695
|
+
},
|
|
2696
|
+
});
|
|
2697
|
+
}
|
|
2698
|
+
addLecture(section) {
|
|
2699
|
+
const lecture = {
|
|
2700
|
+
title: '',
|
|
2701
|
+
type: 'VIDEO',
|
|
2702
|
+
};
|
|
2703
|
+
this.courseService.addLecture(section.id, lecture).subscribe({
|
|
2704
|
+
next: (res) => {
|
|
2705
|
+
this.lectureEditId = res.data.id;
|
|
2706
|
+
if (section.lectures) {
|
|
2707
|
+
section.lectures.push(res.data);
|
|
2708
|
+
}
|
|
2709
|
+
else {
|
|
2710
|
+
const lectures = [];
|
|
2711
|
+
lectures.push(res.data);
|
|
2712
|
+
section.lectures = lectures;
|
|
2713
|
+
}
|
|
2714
|
+
},
|
|
2715
|
+
});
|
|
2716
|
+
}
|
|
2717
|
+
onAddLecture(event) { }
|
|
2718
|
+
onLectureSave(lecture) {
|
|
2719
|
+
this.courseService.updateLecture(lecture.id, lecture).subscribe({
|
|
2720
|
+
next: (res) => {
|
|
2721
|
+
this.snackBarService.open('保存成功');
|
|
2722
|
+
},
|
|
2723
|
+
});
|
|
2724
|
+
}
|
|
2725
|
+
onLectureEdit(lecture) { }
|
|
2726
|
+
onMediaEdit(lecture, video) {
|
|
2727
|
+
const { id } = lecture;
|
|
2728
|
+
const options = {
|
|
2729
|
+
title: lecture.title,
|
|
2730
|
+
cancelText: '取消',
|
|
2731
|
+
confirmText: '保存',
|
|
2732
|
+
data: lecture,
|
|
2733
|
+
width: '80vw',
|
|
2734
|
+
height: '100%',
|
|
2735
|
+
component: CourseSectionLectureVideoDialogComponent,
|
|
2736
|
+
};
|
|
2737
|
+
this.dialogService.open(options);
|
|
2738
|
+
this.dialogService.confirmed().subscribe({
|
|
2739
|
+
next: (res) => {
|
|
2740
|
+
if (res) {
|
|
2741
|
+
// this.courseService.deleteLecture(id).subscribe({
|
|
2742
|
+
// next: (res) => {},
|
|
2743
|
+
// error: (error) => {
|
|
2744
|
+
// this.snackBarService.open(error.message);
|
|
2745
|
+
// },
|
|
2746
|
+
// });
|
|
2747
|
+
}
|
|
2748
|
+
},
|
|
2749
|
+
});
|
|
2750
|
+
}
|
|
2751
|
+
onLectureDelete(section, lecture) {
|
|
2752
|
+
const { id } = lecture;
|
|
2753
|
+
const options = {
|
|
2754
|
+
title: '确认删除吗',
|
|
2755
|
+
message: '删除这一小节吗?',
|
|
2756
|
+
cancelText: '取消',
|
|
2757
|
+
confirmText: '确认',
|
|
2758
|
+
};
|
|
2759
|
+
this.dialogService.open(options);
|
|
2760
|
+
this.dialogService.confirmed().subscribe({
|
|
2761
|
+
next: (res) => {
|
|
2762
|
+
if (res) {
|
|
2763
|
+
this.courseService.deleteLecture(id).subscribe({
|
|
2764
|
+
next: (res) => {
|
|
2765
|
+
const index = section.lectures.findIndex((item) => item.id === id);
|
|
2766
|
+
section.lectures.splice(index, 1);
|
|
2767
|
+
this.hasUnsaved = false;
|
|
2768
|
+
this.snackBarService.open(res.data);
|
|
2769
|
+
},
|
|
2770
|
+
error: (error) => {
|
|
2771
|
+
this.snackBarService.open(error.message);
|
|
2772
|
+
},
|
|
2773
|
+
});
|
|
2774
|
+
}
|
|
2775
|
+
},
|
|
2776
|
+
});
|
|
2777
|
+
}
|
|
2778
|
+
onMediaUploadInit(lecture, event) {
|
|
2779
|
+
const file = event.data.target.files[0];
|
|
2780
|
+
if (!file) {
|
|
2781
|
+
return;
|
|
2782
|
+
}
|
|
2783
|
+
const item = {
|
|
2784
|
+
url: URL.createObjectURL(file),
|
|
2785
|
+
};
|
|
2786
|
+
lecture.item = item;
|
|
2787
|
+
lecture.isUploading = true;
|
|
2788
|
+
lecture.item.progress = 0;
|
|
2789
|
+
const reader = new FileReader();
|
|
2790
|
+
if (reader.readyState === FileReader.EMPTY) {
|
|
2791
|
+
reader.onload = async (e) => {
|
|
2792
|
+
const fileBuffer = e.target.result;
|
|
2793
|
+
crypto.subtle.digest('SHA-256', fileBuffer).then((res) => {
|
|
2794
|
+
const hashArray = Array.from(new Uint8Array(res));
|
|
2795
|
+
const hashHex = hashArray.map((byte) => byte.toString(16).padStart(2, '0')).join('');
|
|
2796
|
+
const data = { hash: hashHex, filename: file.name, fileType: file.type };
|
|
2797
|
+
this.courseService.uploadVideoInit(lecture.id, data).subscribe({
|
|
2798
|
+
next: (res) => {
|
|
2799
|
+
this.uploadPart(lecture, res.data.uploadId, file);
|
|
2800
|
+
},
|
|
2801
|
+
error: (e) => { },
|
|
2802
|
+
});
|
|
2803
|
+
});
|
|
2804
|
+
};
|
|
2805
|
+
reader.onerror = (error) => { };
|
|
2806
|
+
reader.readAsArrayBuffer(file);
|
|
2807
|
+
}
|
|
2808
|
+
}
|
|
2809
|
+
uploadFile(lecture, file, index, uploadId) {
|
|
2810
|
+
const reader = new FileReader();
|
|
2811
|
+
return new Observable((observer) => {
|
|
2812
|
+
reader.readAsArrayBuffer(file);
|
|
2813
|
+
reader.onload = (e) => {
|
|
2814
|
+
const fileBuffer = e.target.result;
|
|
2815
|
+
crypto.subtle.digest('SHA-256', fileBuffer).then((res) => {
|
|
2816
|
+
const hashArray = Array.from(new Uint8Array(res));
|
|
2817
|
+
const hashHex = hashArray.map((byte) => byte.toString(16).padStart(2, '0')).join('');
|
|
2818
|
+
const formData = new FormData();
|
|
2819
|
+
formData.append('file', file);
|
|
2820
|
+
formData.append('uploadId', uploadId);
|
|
2821
|
+
formData.append('number', index + 1);
|
|
2822
|
+
formData.append('hash', hashHex);
|
|
2823
|
+
this.courseService.uploadVideoPartsToLecture(lecture.id, formData).subscribe({
|
|
2824
|
+
next: (res) => {
|
|
2825
|
+
observer.next(res);
|
|
2826
|
+
observer.complete();
|
|
2827
|
+
},
|
|
2828
|
+
error: (e) => {
|
|
2829
|
+
this.snackBarService.open('上传失败: ' + e.message);
|
|
2830
|
+
},
|
|
2831
|
+
});
|
|
2832
|
+
});
|
|
2833
|
+
};
|
|
2834
|
+
reader.onerror = (error) => {
|
|
2835
|
+
this.snackBarService.open('上传失败: ' + error);
|
|
2836
|
+
};
|
|
2837
|
+
});
|
|
2838
|
+
}
|
|
2839
|
+
uploadPart(lecture, uploadId, file) {
|
|
2840
|
+
let uploadedCount = 0;
|
|
2841
|
+
const fileChunkList = this.createFileChunk(file);
|
|
2842
|
+
const numberOfChunks = fileChunkList.length;
|
|
2843
|
+
from(fileChunkList)
|
|
2844
|
+
.pipe(concatMap((val, index) => this.uploadFile(lecture, val.file, index, uploadId)), take(numberOfChunks))
|
|
2845
|
+
.subscribe((res) => {
|
|
2846
|
+
uploadedCount++;
|
|
2847
|
+
const p = ((uploadedCount / numberOfChunks) * 100).toFixed(0);
|
|
2848
|
+
lecture.item.progress = parseFloat(p);
|
|
2849
|
+
if (uploadedCount === numberOfChunks) {
|
|
2850
|
+
console.log('done');
|
|
2851
|
+
this.completePartUpload(lecture, { uploadId });
|
|
2852
|
+
}
|
|
2853
|
+
});
|
|
2854
|
+
}
|
|
2855
|
+
completePartUpload(lecture, data) {
|
|
2856
|
+
data.duration = lecture.item.duration;
|
|
2857
|
+
this.courseService.completePartUpload(lecture.id, data).subscribe({
|
|
2858
|
+
next: (res) => {
|
|
2859
|
+
lecture.isUploading = false;
|
|
2860
|
+
lecture.item.id = res.data.id;
|
|
2861
|
+
},
|
|
2862
|
+
error: (e) => {
|
|
2863
|
+
this.snackBarService.open('上传失败: ' + e.message);
|
|
2864
|
+
},
|
|
2865
|
+
});
|
|
2866
|
+
}
|
|
2867
|
+
onMediaUpload(lecture, event) {
|
|
2868
|
+
const lectureId = event.id;
|
|
2869
|
+
const file = event.data.target.files[0];
|
|
2870
|
+
if (!file) {
|
|
2871
|
+
return;
|
|
2872
|
+
}
|
|
2873
|
+
const reader = new FileReader();
|
|
2874
|
+
reader.readAsDataURL(file);
|
|
2875
|
+
reader.onload = () => {
|
|
2876
|
+
const formData = new FormData();
|
|
2877
|
+
formData.append('file', file);
|
|
2878
|
+
this.courseService.uploadVideoToLecture(lectureId, formData).subscribe({
|
|
2879
|
+
next: (res) => {
|
|
2880
|
+
lecture.isUploading = false;
|
|
2881
|
+
lecture.item = res.data;
|
|
2882
|
+
},
|
|
2883
|
+
error: (e) => {
|
|
2884
|
+
lecture.isUploading = false;
|
|
2885
|
+
this.snackBarService.open('上传失败: ' + e.message);
|
|
2886
|
+
},
|
|
2887
|
+
});
|
|
2888
|
+
};
|
|
2889
|
+
reader.onerror = (error) => { };
|
|
2890
|
+
}
|
|
2891
|
+
onMediaDelete(lecture, event) {
|
|
2892
|
+
// lecture.item = null;
|
|
2893
|
+
const { id } = event;
|
|
2894
|
+
const options = {
|
|
2895
|
+
title: '确认删除吗',
|
|
2896
|
+
message: '删除这个视频吗?',
|
|
2897
|
+
cancelText: '取消',
|
|
2898
|
+
confirmText: '确认',
|
|
2899
|
+
};
|
|
2900
|
+
this.dialogService.open(options);
|
|
2901
|
+
this.dialogService.confirmed().subscribe({
|
|
2902
|
+
next: (res) => {
|
|
2903
|
+
if (res) {
|
|
2904
|
+
this.courseService.deleteLectureVideo(id).subscribe({
|
|
2905
|
+
next: (res) => {
|
|
2906
|
+
lecture.item = null;
|
|
2907
|
+
this.snackBarService.open(res.data);
|
|
2908
|
+
},
|
|
2909
|
+
error: (error) => {
|
|
2910
|
+
this.snackBarService.open(error.message);
|
|
2911
|
+
},
|
|
2912
|
+
});
|
|
2913
|
+
}
|
|
2914
|
+
},
|
|
2915
|
+
});
|
|
2916
|
+
}
|
|
2917
|
+
createFileChunk(file, size = this.chunkSize) {
|
|
2918
|
+
const fileChunkList = [];
|
|
2919
|
+
let count = 0;
|
|
2920
|
+
while (count < file.size) {
|
|
2921
|
+
fileChunkList.push({
|
|
2922
|
+
file: file.slice(count, count + size),
|
|
2923
|
+
});
|
|
2924
|
+
count += size;
|
|
2925
|
+
}
|
|
2926
|
+
return fileChunkList;
|
|
2927
|
+
}
|
|
2928
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CourseManageSectionComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
2929
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.1", type: CourseManageSectionComponent, isStandalone: true, selector: "rolatech-course-manage-section", usesInheritance: true, ngImport: i0, template: "<rolatech-course-manage-content>\n <rolatech-toolbar title=\"\u7AE0\u8282\" class=\"hidden sm:block\" divider> </rolatech-toolbar>\n <div>\n <div>\n @for (section of sections; track $index) {\n <div class=\"bg-gray-100 p-2 mb-2 rounded-lg\">\n <rolatech-course-section-item\n [section]=\"section\"\n (edit)=\"onSectionEdit($event)\"\n (save)=\"onSectionSave($event)\"\n (delete)=\"onSectionDelete($event)\"\n [editId]=\"editId\"\n >\n <div class=\"bg-white sm:ml-8 mt-3 rounded-md divide-y divide-dashed\">\n @if (section?.lectures) {\n @for (lecture of section.lectures; track $index) {\n <div>\n <rolatech-course-section-lecture-item\n [lecture]=\"lecture\"\n (save)=\"onLectureSave($event)\"\n (delete)=\"onLectureDelete(section, $event)\"\n (edit)=\"onLectureEdit($event)\"\n (upload)=\"onMediaUploadInit(lecture, $event)\"\n (mediaEdit)=\"onMediaEdit(lecture, $event)\"\n (deleteMedia)=\"onMediaDelete(lecture, $event)\"\n [editId]=\"lectureEditId\"\n ></rolatech-course-section-lecture-item>\n </div>\n }\n }\n <div class=\"p-2\">\n <button mat-flat-button (click)=\"addLecture(section)\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u5C0F\u8282</span>\n </button>\n </div>\n </div>\n </rolatech-course-section-item>\n </div>\n }\n </div>\n @if (!hasUnsaved) {\n <button mat-stroked-button (click)=\"addSection()\" class=\"mt-3\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u7AE0\u8282</span>\n </button>\n }\n </div>\n</rolatech-course-manage-content>\n", styles: [""], dependencies: [{ kind: "component", type: CourseSectionItemComponent, selector: "rolatech-course-section-item", inputs: ["section", "actions", "hasUnsaved", "editId"], outputs: ["sectionChange", "actionsChange", "hasUnsavedChange", "editIdChange", "save", "cancel", "delete", "edit", "addLecture"] }, { kind: "component", type: CourseSectionLectureItemComponent, selector: "rolatech-course-section-lecture-item", inputs: ["progress", "lecture", "actions", "hasUnsaved", "editId"], outputs: ["editIdChange", "save", "cancel", "delete", "edit", "mediaEdit", "thumbnailUpload", "upload", "deleteMedia"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatProgressBarModule }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: CourseManageContentComponent, selector: "rolatech-course-manage-content" }] }); }
|
|
2930
|
+
}
|
|
2931
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CourseManageSectionComponent, decorators: [{
|
|
2932
|
+
type: Component,
|
|
2933
|
+
args: [{ selector: 'rolatech-course-manage-section', standalone: true, imports: [
|
|
2934
|
+
CourseSectionItemComponent,
|
|
2935
|
+
CourseSectionLectureItemComponent,
|
|
2936
|
+
MatButtonModule,
|
|
2937
|
+
MatIconModule,
|
|
2938
|
+
MatProgressBarModule,
|
|
2939
|
+
ToolbarComponent,
|
|
2940
|
+
CourseManageContentComponent,
|
|
2941
|
+
], template: "<rolatech-course-manage-content>\n <rolatech-toolbar title=\"\u7AE0\u8282\" class=\"hidden sm:block\" divider> </rolatech-toolbar>\n <div>\n <div>\n @for (section of sections; track $index) {\n <div class=\"bg-gray-100 p-2 mb-2 rounded-lg\">\n <rolatech-course-section-item\n [section]=\"section\"\n (edit)=\"onSectionEdit($event)\"\n (save)=\"onSectionSave($event)\"\n (delete)=\"onSectionDelete($event)\"\n [editId]=\"editId\"\n >\n <div class=\"bg-white sm:ml-8 mt-3 rounded-md divide-y divide-dashed\">\n @if (section?.lectures) {\n @for (lecture of section.lectures; track $index) {\n <div>\n <rolatech-course-section-lecture-item\n [lecture]=\"lecture\"\n (save)=\"onLectureSave($event)\"\n (delete)=\"onLectureDelete(section, $event)\"\n (edit)=\"onLectureEdit($event)\"\n (upload)=\"onMediaUploadInit(lecture, $event)\"\n (mediaEdit)=\"onMediaEdit(lecture, $event)\"\n (deleteMedia)=\"onMediaDelete(lecture, $event)\"\n [editId]=\"lectureEditId\"\n ></rolatech-course-section-lecture-item>\n </div>\n }\n }\n <div class=\"p-2\">\n <button mat-flat-button (click)=\"addLecture(section)\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u5C0F\u8282</span>\n </button>\n </div>\n </div>\n </rolatech-course-section-item>\n </div>\n }\n </div>\n @if (!hasUnsaved) {\n <button mat-stroked-button (click)=\"addSection()\" class=\"mt-3\">\n <mat-icon>add</mat-icon>\n <span>\u589E\u52A0\u7AE0\u8282</span>\n </button>\n }\n </div>\n</rolatech-course-manage-content>\n" }]
|
|
2942
|
+
}] });
|
|
2943
|
+
|
|
2944
|
+
class CourseManageLayoutComponent {
|
|
2945
|
+
constructor() {
|
|
2946
|
+
this.submitted = false;
|
|
2947
|
+
this.accepted = false;
|
|
2948
|
+
this.isDraft = false;
|
|
2949
|
+
this.route = inject(ActivatedRoute);
|
|
2950
|
+
this.courseService = inject(CourseService);
|
|
2951
|
+
this.dialog = inject(MatDialog);
|
|
2952
|
+
this.snackBar = inject(MatSnackBar);
|
|
2953
|
+
this.id = this.route.parent?.snapshot.paramMap.get('id');
|
|
2954
|
+
}
|
|
2955
|
+
ngOnInit() {
|
|
2956
|
+
this.get();
|
|
2957
|
+
}
|
|
2958
|
+
get() {
|
|
2959
|
+
this.courseService.get(this.id).subscribe({
|
|
2960
|
+
next: (res) => {
|
|
2961
|
+
this.course = res.data;
|
|
2962
|
+
this.updateStatus();
|
|
2963
|
+
},
|
|
2964
|
+
});
|
|
2965
|
+
}
|
|
2966
|
+
updateStatus() {
|
|
2967
|
+
this.isDraft = this.course.status.toString() === 'DRAFT' || this.course.status.toString() === 'PENDING';
|
|
2968
|
+
this.accepted = this.course.status.toString() === 'ACCEPTED';
|
|
2969
|
+
}
|
|
2970
|
+
submitForReview() {
|
|
2971
|
+
this.courseService.review(this.id).subscribe({
|
|
2972
|
+
next: (res) => {
|
|
2973
|
+
this.snackBar.open('提交成功, 等待审核');
|
|
2974
|
+
this.course.status = CourseStatus['审核中'];
|
|
2975
|
+
this.updateStatus();
|
|
2976
|
+
},
|
|
2977
|
+
error: (error) => {
|
|
2978
|
+
this.snackBar.open(error.message);
|
|
2979
|
+
},
|
|
2980
|
+
});
|
|
2981
|
+
}
|
|
2982
|
+
publish() {
|
|
2983
|
+
this.courseService.publish(this.id).subscribe({
|
|
2984
|
+
next: (res) => {
|
|
2985
|
+
this.snackBar.open('发布成功');
|
|
2986
|
+
this.course.status = CourseStatus['已发布'];
|
|
2987
|
+
this.updateStatus();
|
|
2988
|
+
},
|
|
2989
|
+
error: (error) => {
|
|
2990
|
+
this.snackBar.open(error.message);
|
|
2991
|
+
},
|
|
2992
|
+
});
|
|
2993
|
+
}
|
|
2994
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CourseManageLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2995
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.1", type: CourseManageLayoutComponent, isStandalone: true, selector: "rolatech-course-manage-layout", ngImport: i0, template: "<div class=\"flex flex-col md:flex-row m-auto\">\n <div\n class=\"min-w-[256px] px-3 flex flex-row md:flex-col md:h-full items-center md:items-start h-16 overflow-x-scroll overflow-y-hidden scrollbar-hide whitespace-pre\"\n >\n <div class=\"flex flex-row md:flex-col md:w-full\">\n <div class=\"hidden md:flex text-xl font-bold h-14 items-center px-2\">\u8BFE\u7A0B\u4FE1\u606F</div>\n <a routerLink=\"./info\" routerLinkActive=\"manage-active\" class=\"p-3\">\u57FA\u672C\u4FE1\u606F</a>\n <a routerLink=\"./media\" routerLinkActive=\"manage-active\" class=\"p-3\">\u56FE\u7247</a>\n <a routerLink=\"./details\" routerLinkActive=\"manage-active\" class=\"p-3\">\u8BE6\u60C5</a>\n </div>\n <div class=\"flex flex-row md:flex-col md:w-full\">\n <div class=\"hidden md:flex text-xl font-bold h-14 items-center px-2\">\u8BFE\u7A0B\u5185\u5BB9</div>\n <a routerLink=\"./section\" routerLinkActive=\"manage-active\" class=\"p-3\">\u7AE0\u8282</a>\n <a routerLink=\"./schedule\" routerLinkActive=\"manage-active\" class=\"p-3\">\u8BFE\u8868</a>\n </div>\n <div class=\"flex flex-row md:flex-col md:w-full\">\n <div class=\"hidden md:flex text-xl font-bold h-14 items-center px-2\">\u5176\u4ED6\u4FE1\u606F</div>\n <a routerLink=\"./pricing\" routerLinkActive=\"manage-active\" class=\"p-3\">\u4EF7\u683C</a>\n </div>\n\n @if (isDraft) {\n <div class=\"md:mt-6 ml-3 md:ml-2\">\n <!-- <button mat-stroked-button (click)=\"publish()\">\u9884\u89C8</button> -->\n <button mat-flat-button (click)=\"submitForReview()\">\u63D0\u4EA4\u5BA1\u6838</button>\n </div>\n }\n\n @if (accepted) {\n <div class=\"md:mt-6 md:ml-2\">\n <button mat-flat-button color=\"primary\" (click)=\"publish()\">\u53D1\u5E03\u8BFE\u7A0B</button>\n </div>\n }\n </div>\n <div class=\"w-full\">\n <router-outlet></router-outlet>\n </div>\n</div>\n", styles: [".manage-active{background-color:#0000000d;box-shadow:5px 0 #000 inset;font-weight:600}@media (max-width: 768px){.manage-active{box-shadow:inset 0 -4px #000}}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] }); }
|
|
2996
|
+
}
|
|
2997
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: CourseManageLayoutComponent, decorators: [{
|
|
2998
|
+
type: Component,
|
|
2999
|
+
args: [{ selector: 'rolatech-course-manage-layout', standalone: true, imports: [RouterLink, RouterLinkActive, MatButtonModule, RouterOutlet, CourseManageContentComponent], template: "<div class=\"flex flex-col md:flex-row m-auto\">\n <div\n class=\"min-w-[256px] px-3 flex flex-row md:flex-col md:h-full items-center md:items-start h-16 overflow-x-scroll overflow-y-hidden scrollbar-hide whitespace-pre\"\n >\n <div class=\"flex flex-row md:flex-col md:w-full\">\n <div class=\"hidden md:flex text-xl font-bold h-14 items-center px-2\">\u8BFE\u7A0B\u4FE1\u606F</div>\n <a routerLink=\"./info\" routerLinkActive=\"manage-active\" class=\"p-3\">\u57FA\u672C\u4FE1\u606F</a>\n <a routerLink=\"./media\" routerLinkActive=\"manage-active\" class=\"p-3\">\u56FE\u7247</a>\n <a routerLink=\"./details\" routerLinkActive=\"manage-active\" class=\"p-3\">\u8BE6\u60C5</a>\n </div>\n <div class=\"flex flex-row md:flex-col md:w-full\">\n <div class=\"hidden md:flex text-xl font-bold h-14 items-center px-2\">\u8BFE\u7A0B\u5185\u5BB9</div>\n <a routerLink=\"./section\" routerLinkActive=\"manage-active\" class=\"p-3\">\u7AE0\u8282</a>\n <a routerLink=\"./schedule\" routerLinkActive=\"manage-active\" class=\"p-3\">\u8BFE\u8868</a>\n </div>\n <div class=\"flex flex-row md:flex-col md:w-full\">\n <div class=\"hidden md:flex text-xl font-bold h-14 items-center px-2\">\u5176\u4ED6\u4FE1\u606F</div>\n <a routerLink=\"./pricing\" routerLinkActive=\"manage-active\" class=\"p-3\">\u4EF7\u683C</a>\n </div>\n\n @if (isDraft) {\n <div class=\"md:mt-6 ml-3 md:ml-2\">\n <!-- <button mat-stroked-button (click)=\"publish()\">\u9884\u89C8</button> -->\n <button mat-flat-button (click)=\"submitForReview()\">\u63D0\u4EA4\u5BA1\u6838</button>\n </div>\n }\n\n @if (accepted) {\n <div class=\"md:mt-6 md:ml-2\">\n <button mat-flat-button color=\"primary\" (click)=\"publish()\">\u53D1\u5E03\u8BFE\u7A0B</button>\n </div>\n }\n </div>\n <div class=\"w-full\">\n <router-outlet></router-outlet>\n </div>\n</div>\n", styles: [".manage-active{background-color:#0000000d;box-shadow:5px 0 #000 inset;font-weight:600}@media (max-width: 768px){.manage-active{box-shadow:inset 0 -4px #000}}\n"] }]
|
|
3000
|
+
}], ctorParameters: () => [] });
|
|
3001
|
+
|
|
3002
|
+
const courseManageRoutes = [
|
|
3003
|
+
{
|
|
3004
|
+
path: '',
|
|
3005
|
+
component: CourseManageLayoutComponent,
|
|
3006
|
+
children: [
|
|
3007
|
+
{
|
|
3008
|
+
path: 'info',
|
|
3009
|
+
component: CourseManageInfoComponent,
|
|
3010
|
+
},
|
|
3011
|
+
{
|
|
3012
|
+
path: 'media',
|
|
3013
|
+
component: CourseManageMediaComponent,
|
|
3014
|
+
},
|
|
3015
|
+
{
|
|
3016
|
+
path: 'details',
|
|
3017
|
+
component: CourseManageDetailsComponent,
|
|
3018
|
+
},
|
|
3019
|
+
{
|
|
3020
|
+
path: 'pricing',
|
|
3021
|
+
component: CourseManagePricingComponent,
|
|
3022
|
+
},
|
|
3023
|
+
{
|
|
3024
|
+
path: 'schedule',
|
|
3025
|
+
component: CourseManageScheduleComponent,
|
|
3026
|
+
},
|
|
3027
|
+
{
|
|
3028
|
+
path: 'section',
|
|
3029
|
+
component: CourseManageSectionComponent,
|
|
3030
|
+
},
|
|
3031
|
+
],
|
|
3032
|
+
},
|
|
3033
|
+
];
|
|
3034
|
+
|
|
1953
3035
|
/**
|
|
1954
3036
|
* Generated bundle index. Do not edit.
|
|
1955
3037
|
*/
|
|
1956
3038
|
|
|
1957
|
-
export {
|
|
1958
|
-
//# sourceMappingURL=rolatech-angular-course-rolatech-angular-course-
|
|
3039
|
+
export { CourseDetailsComponent as A, CourseMediaOwnerRendererComponent as B, CourseService as C, CourseSectionLectureVideoDialogComponent as D, ScheduleItemComponent as E, DetailItemComponent as F, courseItem_component as G, PricingItemComponent as P, ScheduleDate as S, CategoryService as a, courseManageRoutes as b, courseRoutes as c, CourseStatus as d, CourseRequestStatus as e, CourseType as f, CourseReviewStatus as g, CourseSectionLectureContentType as h, CoursePreviewComponent as i, CourseInfoComponent as j, CourseMediaComponent as k, CoursePricingComponent as l, CourseActionComponent as m, CourseScheduleComponent as n, CourseSectionsComponent as o, provideAngulaCourse as p, CourseSectionItemComponent as q, CourseSectionLectureItemComponent as r, CourseSectionLectureVideoItemComponent as s, CourseItemComponent as t, CoursePricingAddDialogComponent as u, CourseScheduleAddDialogComponent as v, CoursePricingDialogComponent as w, CourseScheduleDialogComponent as x, CourseDetailsDialogComponent as y, CourseEditDialogComponent as z };
|
|
3040
|
+
//# sourceMappingURL=rolatech-angular-course-rolatech-angular-course-DhmJ0teX.mjs.map
|