|
|
@@ -1,497 +0,0 @@
|
|
|
-import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
|
|
|
-import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
|
|
|
-import { NzMessageService } from 'ng-zorro-antd/message';
|
|
|
-import { firstValueFrom } from 'rxjs';
|
|
|
-import { FilterItem, FilterType } from 'src/app/lib/pager/pager-filter.component';
|
|
|
-import { EpgService } from './epg.service';
|
|
|
-import { Router } from '@angular/router';
|
|
|
-import { startOfDay } from 'date-fns';
|
|
|
-
|
|
|
-@Component({
|
|
|
- selector: 'epg-content-onshelf',
|
|
|
- template: `
|
|
|
-
|
|
|
-<ng-container *ngIf="remoteUrl">
|
|
|
- <cg-pager
|
|
|
- [remoteUrl]="remoteUrl"
|
|
|
- remoteHeaderUrl="/napi/web/epgcontent/headers"
|
|
|
- [defaultOrder]="'desc'"
|
|
|
- [defaultOrderBy]="'order'"
|
|
|
- [listTemplate]="listTemplate"
|
|
|
- [pageSizeOptions]="[30, 60, 90, 120, 150, 180, 480]"
|
|
|
- [topPagination]="true"
|
|
|
- [bottomPagination]="true"
|
|
|
- [showOrder]="true"
|
|
|
- [showSearch]="true"
|
|
|
- [debug]="false"
|
|
|
- [refresh]="refreshTrigger"
|
|
|
- [filterConfig]="filterConfig"
|
|
|
- [inputFilters]="inputFilters"
|
|
|
- [inputSort]="inputSort"
|
|
|
- [orderColumns]="orderColumns"
|
|
|
- ></cg-pager>
|
|
|
-</ng-container>
|
|
|
-
|
|
|
- <ng-template #listTemplate let-list="list">
|
|
|
- <nz-table #basicTable nzSize="small" [nzFrontPagination]="false" [nzShowPagination]="false" [nzData]="list?.data" class="table table-hover table-sm table-edit">
|
|
|
- <thead>
|
|
|
- <tr>
|
|
|
- <th [nzChecked]="checked" [nzIndeterminate]="indeterminate" (nzCheckedChange)="onAllChecked(list.data, $event)"></th>
|
|
|
- <th class="text-center" i18n>作品名称</th>
|
|
|
- <th class="text-center" i18n>效果图</th>
|
|
|
- <!-- <th class="text-center" i18n>作品状态</th> -->
|
|
|
- <th class="text-center" i18n>作者</th>
|
|
|
- <th class="text-center" i18n>标签</th>
|
|
|
- <th class="text-center" i18n>状态</th>
|
|
|
- <th [nzWidth]="'100px'"class="text-center" i18n>上架栏目</th>
|
|
|
- <th [nzWidth]="'200px'" class="text-center" i18n>上架时间/计划时间</th>
|
|
|
- <th [nzWidth]="'80px'" class="text-center" i18n>操作员</th>
|
|
|
- <th [nzWidth]="'100px'" class="text-center" i18n>排序号</th>
|
|
|
- <th *can="['update', 'any', 'epgcontent']" [nzWidth]="'130px'" class="text-center" i18n>操作</th>
|
|
|
- </tr>
|
|
|
- </thead>
|
|
|
- <tbody *ngIf="basicTable.data && basicTable.data.length > 0" cdkDropList [cdkDropListDisabled]="isSpecialColumn(colId)" (cdkDropListDropped)="dragdrop($any($event), basicTable.data)">
|
|
|
- <tr *ngFor="let data of basicTable.data; let i = index" cdkDrag class="editable-row text-center" [ngClass]="{'settop': data.order > 100000, 'schedule': data.status == 500}">
|
|
|
- <td [nzChecked]="checkIdSet.has(data._id)" (nzCheckedChange)="onItemChecked(list.data, data._id, $event)"></td>
|
|
|
- <td>
|
|
|
- <a style="text-decoration:underline" (click)='onDetail(data.art._id)'>{{data.art.name}}</a>
|
|
|
- </td>
|
|
|
- <td>
|
|
|
- <img nz-image width="100px" height="100px" nzSrc={{data.art.thumb}} loading="lazy" />
|
|
|
- </td>
|
|
|
- <!-- <td>
|
|
|
- <art-status [showText]="true" [data]="data.art"></art-status>
|
|
|
- </td> -->
|
|
|
- <td>
|
|
|
- <nz-tag (click)="filter('art.user.id', [data.art.user._id])" class="clickable" >
|
|
|
- {{data.art.user?.username}}
|
|
|
- </nz-tag>
|
|
|
- </td>
|
|
|
- <td>
|
|
|
- <nz-tag *ngIf="data.lock" nzColor="magenta"> <i class="fal fa-lock"></i> </nz-tag>
|
|
|
- <ng-container *ngIf="data.art.tags">
|
|
|
- <nz-tag *ngFor="let tag of data.art.tags" class="clickable" nzColor="default" (click)="filter('art.tags', [tag])" [innerHTML]="tag"></nz-tag>
|
|
|
- </ng-container>
|
|
|
- </td>
|
|
|
- <td>
|
|
|
- <app-epg-content-status [showText]="true" [data]="data"></app-epg-content-status>
|
|
|
- </td>
|
|
|
- <td>
|
|
|
- <nz-tag *ngIf="data.column && data.column.length > 0" nzColor="#ffa500">{{data.column}}</nz-tag>
|
|
|
- <nz-tag *ngIf="!data.column" nzColor="#ff4500">others</nz-tag>
|
|
|
- </td>
|
|
|
- <td>
|
|
|
- {{data.onshelfTime | dateFormat: 'yyyy/M/d H:m:s' }}
|
|
|
- </td>
|
|
|
- <td>
|
|
|
- {{data.operator?.name || data.operator?.username}}
|
|
|
- </td>
|
|
|
- <td class="text-center">
|
|
|
- <order-edit [data]="data" [isUpdate]="isUpdate(data)" [canEdit]="!isSpecialColumn(colId)" (onChange)="updateOrder($event)"></order-edit>
|
|
|
- </td>
|
|
|
- <td *can="['update', 'any', 'epgcontent']" class="text-center">
|
|
|
- <div>
|
|
|
- <a *ngIf="!data.lock" nz-popconfirm i18n-nzPopconfirmTitle nzPopconfirmTitle="确定加锁吗?" (nzOnConfirm)="lock(data, true)" i18n>加锁</a>
|
|
|
- <a *ngIf="data.lock" nz-popconfirm i18n-nzPopconfirmTitle nzPopconfirmTitle="确定解锁吗?" (nzOnConfirm)="lock(data, false)" i18n>解锁</a>
|
|
|
- <span style="color: #dcdcdc"> | </span>
|
|
|
- <a nz-popconfirm i18n-nzPopconfirmTitle nzPopconfirmTitle="确定下架吗?" (nzOnConfirm)="unpublish([data._id])" i18n>下架</a>
|
|
|
- <span style="color: #dcdcdc"> | </span>
|
|
|
- <a *ngIf="!isSpecialColumn(colId)" (click)="setTop(data)" i18n>置顶</a>
|
|
|
- </div>
|
|
|
- <!-- <div>
|
|
|
- <a *ngIf="!isSpecialColumn(colId)" (click)="exchangeOrder(basicTable.data[i], basicTable.data[i-1])" i18n>上移</a>
|
|
|
- <nz-divider *ngIf="!isSpecialColumn(colId)" nzType="vertical"></nz-divider>
|
|
|
- <a *ngIf="!isSpecialColumn(colId)" (click)="exchangeOrder(basicTable.data[i], basicTable.data[i+1])" i18n>下移</a>
|
|
|
- </div> -->
|
|
|
- </td>
|
|
|
- </tr>
|
|
|
- </tbody>
|
|
|
- </nz-table>
|
|
|
- </ng-template>
|
|
|
-
|
|
|
- `,
|
|
|
- styles: [`
|
|
|
-
|
|
|
-.table th {
|
|
|
- font-weight: bold;
|
|
|
-}
|
|
|
-
|
|
|
-.table td a {
|
|
|
- color: dodgerblue;
|
|
|
-}
|
|
|
-
|
|
|
-.table td a:hover {
|
|
|
- color: forestgreen;
|
|
|
-}
|
|
|
-
|
|
|
-.strikethrough {
|
|
|
- background: repeating-linear-gradient(
|
|
|
- 180deg,
|
|
|
- black 0%,
|
|
|
- black 100%
|
|
|
- );
|
|
|
- background-size: 100% 1px;
|
|
|
- background-position: center;
|
|
|
- background-repeat: no-repeat;
|
|
|
-}
|
|
|
-
|
|
|
-.settop {
|
|
|
- background: blanchedalmond;
|
|
|
-}
|
|
|
-
|
|
|
-.schedule {
|
|
|
- background: #87cefa;
|
|
|
-}
|
|
|
-
|
|
|
-::ng-deep .cdk-drag-preview {
|
|
|
- display: table;
|
|
|
-}
|
|
|
-
|
|
|
-::ng-deep .cdk-drag-placeholder {
|
|
|
- opacity: 0;
|
|
|
-}
|
|
|
-
|
|
|
-.cdk-drag-preview {
|
|
|
- box-sizing: border-box;
|
|
|
- border-radius: 4px;
|
|
|
- box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),
|
|
|
- 0 8px 10px 1px rgba(0, 0, 0, 0.14),
|
|
|
- 0 3px 14px 2px rgba(0, 0, 0, 0.12);
|
|
|
-}
|
|
|
-
|
|
|
-.cdk-drag-placeholder {
|
|
|
- opacity: 0;
|
|
|
-}
|
|
|
-
|
|
|
-.cdk-drag-animating {
|
|
|
- transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
|
|
|
-}
|
|
|
-
|
|
|
- `
|
|
|
- ]
|
|
|
-})
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-export class EpgContentOnshelfComponent implements OnInit {
|
|
|
-
|
|
|
- private _epgId: string = null; // 当前选中的epgId
|
|
|
- public get epgId(): string { return this._epgId };
|
|
|
- @Input() public set epgId(value: string) {
|
|
|
- this._epgId = value;
|
|
|
- this.cleanAllChecked();
|
|
|
- }
|
|
|
-
|
|
|
- private _colId: string = null; // 当前选中的栏目id
|
|
|
- public get colId(): string { return this._colId };
|
|
|
- @Input() public set colId(value: string) {
|
|
|
- this._colId = value;
|
|
|
- if (this.isSpecialColumn(this._colId)) {
|
|
|
- this.inputSort = ['onshelfTime', 'desc'];
|
|
|
- this.orderColumns = ['onshelfTime'];
|
|
|
- } else {
|
|
|
- this.inputSort = ['order', 'desc'];
|
|
|
- this.orderColumns = ['order'];
|
|
|
- }
|
|
|
- if (this.epgId) {
|
|
|
- this.remoteUrl = value
|
|
|
- ? `/napi/web/epgcontent/${this.epgId}/onshelves?column=${value}`
|
|
|
- : `/napi/web/epgcontent/${this.epgId}/onshelves`;
|
|
|
- }
|
|
|
- this.cleanAllChecked();
|
|
|
- }
|
|
|
-
|
|
|
- _remoteUrl: string = null;
|
|
|
- get remoteUrl(): string { return this._remoteUrl;}
|
|
|
- set remoteUrl(value: string) {
|
|
|
- this._remoteUrl = value;
|
|
|
- this.refreshTrigger++;
|
|
|
- }
|
|
|
-
|
|
|
- @Output() onUnPubSuccess = new EventEmitter<any>();
|
|
|
-
|
|
|
- constructor(
|
|
|
- private router: Router,
|
|
|
- private epgService: EpgService,
|
|
|
- private message: NzMessageService,
|
|
|
- ) { }
|
|
|
-
|
|
|
- ngOnInit(): void {
|
|
|
- }
|
|
|
-
|
|
|
- inputFilters: any;
|
|
|
-
|
|
|
- refreshTrigger: number = 0;
|
|
|
-
|
|
|
- inputSort: any = ['order', 'desc'];
|
|
|
- orderColumns: any = [ 'order' ];
|
|
|
-
|
|
|
- updateSet: Set<string> = new Set();
|
|
|
-
|
|
|
- isUpdate(data: any) {
|
|
|
- return this.updateSet.has(`${this.epgId}-${this.colId}-${data._id}`);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- onDetail(artId: string) {
|
|
|
- this.router.navigate(['/pages/detail', artId]);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * 更新order
|
|
|
- * @param data : 形如:[{_id: xxx, order:xxx}]
|
|
|
- */
|
|
|
- updateOrder(data) {
|
|
|
- console.log(data);
|
|
|
- firstValueFrom(this.epgService.epgContentUpdate(this.epgId, data))
|
|
|
- .then(res => {
|
|
|
- for (let i = 0; i < data.length; i++) {
|
|
|
- this.updateSet.add(`${this.epgId}-${this.colId}-${data[i]._id}`);
|
|
|
- }
|
|
|
- this.refreshTrigger++;
|
|
|
- })
|
|
|
- .catch(err => {
|
|
|
- this.message.error(err.error?.message || err.message);
|
|
|
- console.log(err);
|
|
|
- }).then(() => {
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- // 判断某栏目是否特殊栏目(系统保留虚拟栏目)
|
|
|
- isSpecialColumn(col: string) {
|
|
|
- return [undefined, null, '', 'all', 'others'].includes(col?.toLowerCase());
|
|
|
- }
|
|
|
-
|
|
|
- filter(data, value) {
|
|
|
- console.log('filter', data, value);
|
|
|
- let filter = {};
|
|
|
- filter[data] = value;
|
|
|
- this.inputFilters = filter;
|
|
|
- }
|
|
|
-
|
|
|
- filterSchedule(date: Date) {
|
|
|
- let filter = {
|
|
|
- status: 500,
|
|
|
- onshelfTime: [startOfDay(date), startOfDay(date)]
|
|
|
- };
|
|
|
- this.inputFilters = filter;
|
|
|
- }
|
|
|
-
|
|
|
- // 置顶
|
|
|
- setTop(data) {
|
|
|
- firstValueFrom(this.epgService.epgContentSetTop(this.epgId, [data._id]))
|
|
|
- .then(res => {
|
|
|
- for (let i = 0; i < data.length; i++) {
|
|
|
- this.updateSet.add(`${this.epgId}-${this.colId}-${data[i]._id}`);
|
|
|
- }
|
|
|
- this.refreshTrigger++;
|
|
|
- })
|
|
|
- .catch(err => {
|
|
|
- this.message.error(err.error?.message || err.message);
|
|
|
- console.log(err);
|
|
|
- }).then(() => {
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- // 交换order, 用于上移/下移的操作
|
|
|
- exchangeOrder(data1, data2) {
|
|
|
- if (!data1 || !data2) return;
|
|
|
-
|
|
|
- let data = [
|
|
|
- { _id: data1._id, order: data2.order },
|
|
|
- { _id: data2._id, order: data1.order },
|
|
|
- ]
|
|
|
-
|
|
|
- this.updateOrder(data);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 下架
|
|
|
- */
|
|
|
- unpublish(idList: string[]) {
|
|
|
- let data = idList.map(e => { return { epg: this.epgId, id: e } });
|
|
|
- firstValueFrom(this.epgService.epgContentOffshelf(data))
|
|
|
- .then(res => {
|
|
|
- this.refreshTrigger++;
|
|
|
- this.message.success($localize`下架成功`);
|
|
|
- this.cleanAllChecked();
|
|
|
- this.onUnPubSuccess.emit(); // 通知外部
|
|
|
- })
|
|
|
- .catch(err => {
|
|
|
- this.message.error(err.error?.message || err.message);
|
|
|
- console.log(err);
|
|
|
- }).then(() => {
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- lock(data: any, lock: boolean) {
|
|
|
- firstValueFrom(this.epgService.epgContentUpdate(this.epgId, [{ _id: data._id, lock }]))
|
|
|
- .then(res => {
|
|
|
- data.lock = lock;
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- // 拖拽排序
|
|
|
- dragdrop(event: CdkDragDrop<string[]>, list): void {
|
|
|
- if (this.isSpecialColumn(this.colId)) {
|
|
|
- this.message.error($localize`特殊栏目不支持排序`);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- let data = [];
|
|
|
- let from = event.previousIndex, to = event.currentIndex;
|
|
|
- if (from == to) return;
|
|
|
- const target = list[from];
|
|
|
- const delta = to < from ? - 1: 1;
|
|
|
- for (let i = from; i != to; i += delta) {
|
|
|
- data.push({ _id: list[i + delta]._id, order: list[i].order });
|
|
|
- list[i] = list[i + delta];
|
|
|
- }
|
|
|
- data.push({ _id: target._id, order: list[to].order });
|
|
|
- list[to] = target;
|
|
|
-
|
|
|
- this.updateOrder(data);
|
|
|
-
|
|
|
- // moveItemInArray(list, event.previousIndex, event.currentIndex);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- checkIdSet = new Set<string>();
|
|
|
- checked = false;
|
|
|
- indeterminate = false;
|
|
|
-
|
|
|
- onItemChecked(list: any[], id: string, checked: boolean): void {
|
|
|
- this.updateCheckedSet(id, checked);
|
|
|
- this.refreshCheckedStatus(list);
|
|
|
- }
|
|
|
-
|
|
|
- updateCheckedSet(id: string, checked: boolean): void {
|
|
|
- if (checked) {
|
|
|
- this.checkIdSet.add(id);
|
|
|
- } else {
|
|
|
- this.checkIdSet.delete(id);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- refreshCheckedStatus(list: any[]): void {
|
|
|
- this.checked = list.every(item => this.checkIdSet.has(item._id));
|
|
|
- this.indeterminate = list.some(item => this.checkIdSet.has(item._id)) && !this.checked;
|
|
|
- }
|
|
|
-
|
|
|
- onAllChecked(list: any[], checked: boolean): void {
|
|
|
- list.forEach(item => this.updateCheckedSet(item._id, checked));
|
|
|
- this.refreshCheckedStatus(list);
|
|
|
- }
|
|
|
-
|
|
|
- cleanAllChecked() {
|
|
|
- this.checkIdSet.clear();
|
|
|
- this.checked = false;
|
|
|
- this.indeterminate = false;
|
|
|
- }
|
|
|
-
|
|
|
- //////////////////////////////////////////////////
|
|
|
- filterConfig: FilterItem[] = [
|
|
|
- // {
|
|
|
- // data: 'art.status',
|
|
|
- // title: $localize`作品状态`,
|
|
|
- // filterType: FilterType.radio,
|
|
|
- // options: [
|
|
|
- // // { label: '草稿', value: 1000 },
|
|
|
- // { label: $localize`需要修改`, value: 2000 },
|
|
|
- // { label: $localize`测试中`, value: 3000 },
|
|
|
- // { label: $localize`测试通过`, value: 7000 },
|
|
|
- // { label: $localize`已发布`, value: 9000 },
|
|
|
- // { label: $localize`下线`, value: 8000 },
|
|
|
- // ],
|
|
|
- // span: 4,
|
|
|
- // },
|
|
|
- {
|
|
|
- data: 'status',
|
|
|
- title: $localize`状态`,
|
|
|
- filterType: FilterType.radio,
|
|
|
- options: [
|
|
|
- { label: $localize`已上架`, value: 1000 },
|
|
|
- { label: $localize`计划上架`, value: 500 },
|
|
|
- ],
|
|
|
- span: 2,
|
|
|
- },
|
|
|
- {
|
|
|
- data: 'onshelfTime',
|
|
|
- title: $localize`上架时间`,
|
|
|
- filterType: FilterType.dateRange,
|
|
|
- span: 2,
|
|
|
- },
|
|
|
- {
|
|
|
- data: 'art.tags',
|
|
|
- title: $localize`标签`,
|
|
|
- filterType: FilterType.select,
|
|
|
- mode : 'tags',
|
|
|
- span: 2,
|
|
|
- fullWidth: true,
|
|
|
- optionsUrl : '/napi/web/art/agg/tags',
|
|
|
- },
|
|
|
- {
|
|
|
- data: 'art.user.id',
|
|
|
- title: $localize`作者`,
|
|
|
- filterType: FilterType.select,
|
|
|
- mode : 'multiple',
|
|
|
- span: 2,
|
|
|
- fullWidth: true,
|
|
|
- optionsUrl : '/napi/web/user/select/options',
|
|
|
- },
|
|
|
- {
|
|
|
- data: 'art.hasSpecial',
|
|
|
- title: $localize`彩绘`,
|
|
|
- filterType : FilterType.select,
|
|
|
- options: [
|
|
|
- { label: $localize`是`, value: true },
|
|
|
- { label: $localize`否`, value: false },
|
|
|
- ],
|
|
|
- span: 1,
|
|
|
- },
|
|
|
- {
|
|
|
- data: 'art.mystery',
|
|
|
- title: $localize`神秘图`,
|
|
|
- filterType : FilterType.select,
|
|
|
- options: [
|
|
|
- { label: $localize`是`, value: true },
|
|
|
- { label: $localize`否`, value: false },
|
|
|
- ],
|
|
|
- span: 1,
|
|
|
- },
|
|
|
- {
|
|
|
- data: 'art.ai',
|
|
|
- title: $localize`AI`,
|
|
|
- filterType : FilterType.select,
|
|
|
- options: [
|
|
|
- { label: $localize`是`, value: true },
|
|
|
- { label: $localize`否`, value: false },
|
|
|
- ],
|
|
|
- span: 1,
|
|
|
- },
|
|
|
- {
|
|
|
- data: 'art.width',
|
|
|
- title: $localize`尺寸`,
|
|
|
- filterType : FilterType.select,
|
|
|
- options: [
|
|
|
- { label: '2000', value: 2000 },
|
|
|
- { label: '1500', value: 1500 },
|
|
|
- ],
|
|
|
- span: 1,
|
|
|
- },
|
|
|
- {
|
|
|
- data: 'art.lock',
|
|
|
- title: $localize`加锁`,
|
|
|
- filterType : FilterType.select,
|
|
|
- options: [
|
|
|
- { label: $localize`是`, value: true },
|
|
|
- { label: $localize`否`, value: false },
|
|
|
- ],
|
|
|
- span: 1,
|
|
|
- },
|
|
|
-
|
|
|
- ];
|
|
|
-
|
|
|
-}
|