Skip to content

Commit 262e3e0

Browse files
committed
add websphere application server tutorial
1 parent d61df6b commit 262e3e0

8 files changed

Lines changed: 135 additions & 15 deletions

File tree

src/app/components/tutorials/paper-tutorial.css

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,18 @@
237237
border-bottom: 2px solid rgba(13, 148, 136, 0.15);
238238
}
239239

240+
.paper-topic-thumb--cover {
241+
padding: 0;
242+
overflow: hidden;
243+
}
244+
245+
.paper-topic-thumb--cover img {
246+
width: 100%;
247+
height: 100%;
248+
object-fit: cover;
249+
display: block;
250+
}
251+
240252
.paper-topic-body {
241253
padding: 20px;
242254
}

src/app/components/tutorials/video-tutorial-detail/video-tutorial-detail.component.css

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,53 @@
55
color: #475569;
66
line-height: 1.65;
77
}
8+
9+
.paper-external-cta {
10+
max-width: 560px;
11+
margin: 28px auto 0;
12+
padding: 24px;
13+
text-align: center;
14+
background: var(--paper-card);
15+
border: 1px solid rgba(13, 148, 136, 0.2);
16+
border-radius: 6px;
17+
box-shadow: 0 1px 1px var(--paper-shadow);
18+
}
19+
20+
.paper-external-cover {
21+
aspect-ratio: 16 / 9;
22+
border-radius: 4px;
23+
overflow: hidden;
24+
margin-bottom: 16px;
25+
border: 1px solid rgba(226, 232, 240, 0.9);
26+
}
27+
28+
.paper-external-cover img {
29+
width: 100%;
30+
height: 100%;
31+
object-fit: cover;
32+
display: block;
33+
}
34+
35+
.paper-external-hint {
36+
margin: 0 0 16px;
37+
font-size: 15px;
38+
color: var(--paper-muted);
39+
line-height: 1.55;
40+
}
41+
42+
.paper-external-btn {
43+
display: inline-block;
44+
padding: 10px 22px;
45+
font-size: 15px;
46+
font-weight: 600;
47+
text-decoration: none;
48+
color: #fff;
49+
background: var(--paper-accent);
50+
border-radius: 6px;
51+
transition: background 0.2s ease, transform 0.2s ease;
52+
}
53+
54+
.paper-external-btn:hover {
55+
background: var(--paper-accent-dark);
56+
transform: translateY(-1px);
57+
}

src/app/components/tutorials/video-tutorial-detail/video-tutorial-detail.component.html

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,20 @@ <h1 class="paper-title">{{ titleOf(tut) }}</h1>
77
<p class="paper-summary">{{ summaryOf(tut) }}</p>
88
</header>
99

10+
<section *ngIf="tut.externalUrl" class="paper-external-cta">
11+
<div *ngIf="tut.coverImage" class="paper-external-cover">
12+
<img [src]="tut.coverImage" [alt]="titleOf(tut)" />
13+
</div>
14+
<p class="paper-external-hint">{{ t('tutorials.external.hint') }}</p>
15+
<a
16+
[href]="tut.externalUrl"
17+
target="_blank"
18+
rel="noopener noreferrer"
19+
class="paper-external-btn"
20+
>{{ t('tutorials.external.open') }}</a
21+
>
22+
</section>
23+
1024
<div class="paper-video-grid" *ngIf="tut.episodes.length > 0; else emptyEpisodes">
1125
<article *ngFor="let ep of tut.episodes; let i = index" class="paper-video-card" [style.--paper-delay.ms]="70 * i">
1226
<a

src/app/components/tutorials/video-tutorials-list/video-tutorials-list.component.html

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,44 @@ <h1 class="page-title">{{ t('nav.tutorials') }}</h1>
1010
<div class="paper-inner">
1111
<p class="tutorials-list-hint">{{ t('tutorials.list.lead') }}</p>
1212
<div class="paper-topic-grid">
13-
<a
14-
*ngFor="let item of tutorials; let i = index"
15-
[routerLink]="['/tutorials', item.id]"
16-
class="paper-topic-card"
17-
[style.--paper-delay.ms]="50 * i"
18-
>
19-
<div class="paper-topic-thumb" aria-hidden="true"></div>
20-
<div class="paper-topic-body">
21-
<h2 class="paper-topic-title">{{ titleOf(item) }}</h2>
22-
<p class="paper-topic-summary">{{ summaryOf(item) }}</p>
23-
</div>
24-
</a>
13+
<ng-container *ngFor="let item of tutorials; let i = index">
14+
<a
15+
*ngIf="item.externalUrl"
16+
[href]="item.externalUrl"
17+
target="_blank"
18+
rel="noopener noreferrer"
19+
class="paper-topic-card"
20+
[style.--paper-delay.ms]="50 * i"
21+
[attr.aria-label]="cardAriaLabel(item)"
22+
>
23+
<ng-container *ngTemplateOutlet="topicCardInner; context: { $implicit: item }"></ng-container>
24+
</a>
25+
<a
26+
*ngIf="!item.externalUrl"
27+
[routerLink]="['/tutorials', item.id]"
28+
class="paper-topic-card"
29+
[style.--paper-delay.ms]="50 * i"
30+
[attr.aria-label]="cardAriaLabel(item)"
31+
>
32+
<ng-container *ngTemplateOutlet="topicCardInner; context: { $implicit: item }"></ng-container>
33+
</a>
34+
</ng-container>
2535
</div>
36+
37+
<ng-template #topicCardInner let-item>
38+
<div
39+
class="paper-topic-thumb"
40+
[class.paper-topic-thumb--cover]="!!item.coverImage"
41+
aria-hidden="true"
42+
>
43+
<img *ngIf="item.coverImage" [src]="item.coverImage" alt="" />
44+
<span *ngIf="!item.coverImage"></span>
45+
</div>
46+
<div class="paper-topic-body">
47+
<h2 class="paper-topic-title">{{ titleOf(item) }}</h2>
48+
<p class="paper-topic-summary">{{ summaryOf(item) }}</p>
49+
</div>
50+
</ng-template>
2651
</div>
2752
</div>
2853
</div>

src/app/components/tutorials/video-tutorials-list/video-tutorials-list.component.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { RouterLink } from '@angular/router';
44
import { LanguageService } from '../../../services/language.service';
55
import { SEOService } from '../../../services/seo.service';
66
import { Subscription } from 'rxjs';
7-
import { VIDEO_TUTORIALS } from '../../../data/video-tutorials.data';
7+
import { VideoTutorial, VIDEO_TUTORIALS } from '../../../data/video-tutorials.data';
88
import { VIDEO_TUTORIALS_LIST_SEO } from '../../../config/seo.config';
99

1010
@Component({
@@ -49,4 +49,12 @@ export class VideoTutorialsListComponent implements OnInit, OnDestroy {
4949
summaryOf(t: (typeof VIDEO_TUTORIALS)[0]): string {
5050
return this.isEn() ? t.summaryEn : t.summaryZh;
5151
}
52+
53+
cardAriaLabel(t: VideoTutorial): string {
54+
const title = this.titleOf(t);
55+
if (t.externalUrl) {
56+
return this.isEn() ? `${title} (opens in new tab)` : `${title}(新窗口打开)`;
57+
}
58+
return title;
59+
}
5260
}

src/app/data/video-tutorials.data.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ export interface VideoTutorial {
2121
summaryZh: string;
2222
summaryEn: string;
2323
episodes: VideoEpisode[];
24+
/** 站外课程页;列表点击直接打开新窗口 */
25+
externalUrl?: string;
26+
/** 列表/详情封面,如 /assets/tutorials/.../overview.png */
27+
coverImage?: string;
2428
}
2529

2630
export const VIDEO_TUTORIALS: VideoTutorial[] = [
@@ -30,7 +34,9 @@ export const VIDEO_TUTORIALS: VideoTutorial[] = [
3034
titleEn: 'WebSphere Application Server',
3135
summaryZh: 'WAS 安装、配置、部署与运维要点。',
3236
summaryEn: 'Installation, configuration, deployment, and operations for WAS.',
33-
episodes: []
37+
episodes: [],
38+
externalUrl: 'https://edu.51cto.com/course/38177.html',
39+
coverImage: '/assets/tutorials/01-websphere-application-server/overview.png'
3440
},
3541
{
3642
id: 'vault',

src/app/services/language.service.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,12 @@ export class LanguageService {
2020
zh: '技术专题视频讲解,涵盖中间件、协议、AI 与工程实践。',
2121
en: 'Topic-based video tutorials: middleware, protocols, AI, and hands-on engineering.'
2222
},
23-
'tutorials.list.lead': { zh: '点击下方卡片进入对应专题。', en: 'Open a topic below to view its videos.' },
23+
'tutorials.list.lead': { zh: '点击下方卡片进入对应专题;已上线的站外课程会在新窗口打开。', en: 'Open a topic below; courses hosted elsewhere open in a new tab.' },
24+
'tutorials.external.hint': {
25+
zh: '本课程在合作平台提供完整视频,请在新窗口中打开观看。',
26+
en: 'Full videos are on a partner site—open the link in a new tab.'
27+
},
28+
'tutorials.external.open': { zh: '前往课程', en: 'Open course' },
2429
'tutorials.back': { zh: '← 返回教程列表', en: '← Back to tutorials' },
2530
'tutorials.empty': { zh: '该专题的剧集链接将陆续补充,敬请关注。', en: 'Video links for this topic will be added soon.' },
2631
'tutorials.platform.bilibili': { zh: '哔哩哔哩', en: 'Bilibili' },
192 KB
Loading

0 commit comments

Comments
 (0)