24 | {/* 面包屑导航 */}
25 |
},
29 | { href: '/' + locale + '/search', title: t('navigation.market') },
30 | { title: script.name },
31 | ]}
32 | >
33 |
34 | {script.archive == 1 && (
35 |
43 | )}
44 |
45 | {script.danger == 1 && (
46 |
53 | )}
54 |
55 | {/* 脚本导航 */}
56 |
57 |
58 |
59 |
60 | {/* 页面内容 */}
61 | {children}
62 |
63 | );
64 | }
65 |
--------------------------------------------------------------------------------
/src/app/[locale]/script-show-page/[id]/comment/components/rating/utils.ts:
--------------------------------------------------------------------------------
1 | import type { ScoreStateResponse } from '@/lib/api/services/scripts/scripts';
2 |
3 | /**
4 | * 获取评分对应的文本描述
5 | * @param rating 评分数值
6 | * @param t 翻译函数
7 | * @returns 评分描述文本
8 | */
9 | export function getRatingText(
10 | rating: number,
11 | t: (key: string) => string,
12 | ): string {
13 | switch (rating) {
14 | case 5:
15 | return t('excellent');
16 | case 4:
17 | return t('good');
18 | case 3:
19 | return t('average');
20 | case 2:
21 | return t('fair');
22 | case 1:
23 | return t('poor');
24 | default:
25 | return '';
26 | }
27 | }
28 |
29 | interface RatingStats {
30 | averageRating: number;
31 | totalRatings: number;
32 | distribution: { 5: number; 4: number; 3: number; 2: number; 1: number };
33 | }
34 |
35 | // 计算评分统计数据的辅助函数
36 | export function calculateRatingStats(
37 | scoreState: ScoreStateResponse | null,
38 | ): RatingStats {
39 | if (!scoreState) {
40 | return {
41 | averageRating: 0,
42 | totalRatings: 0,
43 | distribution: { 5: 0, 4: 0, 3: 0, 2: 0, 1: 0 },
44 | };
45 | }
46 |
47 | const distribution = { 5: 0, 4: 0, 3: 0, 2: 0, 1: 0 };
48 | let totalScore = 0;
49 | const totalRatings = scoreState.score_user_count;
50 |
51 | // 填充分布数据
52 | Object.entries(scoreState.score_group).forEach(([score, count]) => {
53 | const scoreNum = parseInt(score) / 10;
54 | if (scoreNum >= 1 && scoreNum <= 5) {
55 | distribution[scoreNum as keyof typeof distribution] = count;
56 | totalScore += scoreNum * count;
57 | }
58 | });
59 |
60 | const averageRating = totalRatings > 0 ? totalScore / totalRatings : 0;
61 |
62 | return {
63 | averageRating: parseFloat(averageRating.toFixed(1)), // 保留一位小数
64 | totalRatings,
65 | distribution,
66 | };
67 | }
68 |
--------------------------------------------------------------------------------
/deploy/helm/templates/NOTES.txt:
--------------------------------------------------------------------------------
1 | 1. Get the application URL by running these commands:
2 | {{- if .Values.ingress.enabled }}
3 | {{- range $host := .Values.ingress.hosts }}
4 | {{- range .paths }}
5 | http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
6 | {{- end }}
7 | {{- end }}
8 | {{- else if contains "NodePort" .Values.service.type }}
9 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "scriptcat-list-frontend.fullname" . }})
10 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
11 | echo http://$NODE_IP:$NODE_PORT
12 | {{- else if contains "LoadBalancer" .Values.service.type }}
13 | NOTE: It may take a few minutes for the LoadBalancer IP to be available.
14 | You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "scriptcat-list-frontend.fullname" . }}'
15 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "scriptcat-list-frontend.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
16 | echo http://$SERVICE_IP:{{ .Values.service.port }}
17 | {{- else if contains "ClusterIP" .Values.service.type }}
18 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "scriptcat-list-frontend.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
19 | export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
20 | echo "Visit http://127.0.0.1:8080 to use your application"
21 | kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
22 | {{- end }}
23 |
--------------------------------------------------------------------------------
/src/app/[locale]/notifications/page.tsx:
--------------------------------------------------------------------------------
1 | import { Suspense } from 'react';
2 | import NotificationsClient from './components/NotificationsClient';
3 | import type { Metadata } from 'next';
4 | import { getTranslations } from 'next-intl/server';
5 |
6 | // 获取通知服务
7 | async function getNotificationService() {
8 | const { notificationService } = await import(
9 | '@/lib/api/services/notification'
10 | );
11 | return notificationService;
12 | }
13 |
14 | export async function generateMetadata({
15 | searchParams,
16 | }: NotificationsPageProps): Promise