update a lot
This commit is contained in:
@@ -2,8 +2,6 @@
|
|||||||
.gitignore
|
.gitignore
|
||||||
node_modules
|
node_modules
|
||||||
**/node_modules
|
**/node_modules
|
||||||
frontend/dist
|
|
||||||
bin
|
|
||||||
backend/data
|
backend/data
|
||||||
data
|
data
|
||||||
*.db
|
*.db
|
||||||
|
|||||||
26
Dockerfile
26
Dockerfile
@@ -1,26 +1,18 @@
|
|||||||
# syntax=docker/dockerfile:1.7
|
# syntax=docker/dockerfile:1.7
|
||||||
|
|
||||||
FROM --platform=$BUILDPLATFORM node:20-alpine AS frontend-builder
|
# FROM --platform=$BUILDPLATFORM golang:1.24 AS backend-builder
|
||||||
WORKDIR /app/frontend
|
# WORKDIR /app/backend
|
||||||
COPY frontend/package.json frontend/pnpm-lock.yaml ./
|
# COPY backend/go.mod backend/go.sum ./
|
||||||
RUN corepack enable && pnpm install --frozen-lockfile
|
# RUN go mod download
|
||||||
COPY frontend/ ./
|
# COPY backend/ ./
|
||||||
RUN pnpm build
|
# ARG TARGETARCH
|
||||||
|
# RUN CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH:-amd64} go build -trimpath -ldflags="-s -w" -o /out/shooting-event .
|
||||||
FROM --platform=$BUILDPLATFORM golang:1.24 AS backend-builder
|
|
||||||
WORKDIR /app/backend
|
|
||||||
COPY backend/go.mod backend/go.sum ./
|
|
||||||
RUN go mod download
|
|
||||||
COPY backend/ ./
|
|
||||||
COPY --from=frontend-builder /app/frontend/dist ./web
|
|
||||||
ARG TARGETARCH
|
|
||||||
RUN CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH:-amd64} go build -trimpath -ldflags="-s -w" -o /out/shooting-event .
|
|
||||||
|
|
||||||
FROM --platform=$TARGETPLATFORM alpine:3.21
|
FROM --platform=$TARGETPLATFORM alpine:3.21
|
||||||
RUN addgroup -S app && adduser -S app -G app && apk add --no-cache ca-certificates
|
RUN addgroup -S app && adduser -S app -G app && apk add --no-cache ca-certificates
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=backend-builder /out/shooting-event /app/shooting-event
|
COPY bin/shooting-event-amd64 /app/shooting-event
|
||||||
COPY --from=backend-builder /app/backend/web /app/web
|
COPY frontend/dist /app/web
|
||||||
RUN mkdir -p /app/data && chown -R app:app /app
|
RUN mkdir -p /app/data && chown -R app:app /app
|
||||||
USER app
|
USER app
|
||||||
ENV PORT=8080
|
ENV PORT=8080
|
||||||
|
|||||||
3
Makefile
3
Makefile
@@ -36,6 +36,9 @@ build-backend:
|
|||||||
mkdir -p bin
|
mkdir -p bin
|
||||||
cd backend && $(GO) build -o ../bin/shooting-event .
|
cd backend && $(GO) build -o ../bin/shooting-event .
|
||||||
|
|
||||||
|
build-backend-amd64:
|
||||||
|
mkdir -p bin
|
||||||
|
cd backend && GOARCH=amd64 GOOS=linux $(GO) build -o ../bin/shooting-event-amd64 .
|
||||||
build: build-frontend
|
build: build-frontend
|
||||||
rm -rf backend/web
|
rm -rf backend/web
|
||||||
mkdir -p backend/web
|
mkdir -p backend/web
|
||||||
|
|||||||
@@ -132,9 +132,13 @@
|
|||||||
<tr
|
<tr
|
||||||
v-for="row in pagedPreliminaryRows"
|
v-for="row in pagedPreliminaryRows"
|
||||||
:key="'live-pre-overall-' + row.playerId"
|
:key="'live-pre-overall-' + row.playerId"
|
||||||
:class="{ 'qualified-row': isFinalist(row.playerId) }"
|
|
||||||
>
|
>
|
||||||
<td class="mono rank">{{ row.rank }}</td>
|
<td class="mono rank">
|
||||||
|
<div class="live-rank-cell">
|
||||||
|
<span>{{ row.rank }}</span>
|
||||||
|
<span v-if="prelimOverallHintLabel(row)" class="live-rank-hint">{{ prelimOverallHintLabel(row) }}</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="competitor-cell compact">
|
<div class="competitor-cell compact">
|
||||||
<img :src="playerImage(row)" :alt="row.nameAr" class="competitor-image" />
|
<img :src="playerImage(row)" :alt="row.nameAr" class="competitor-image" />
|
||||||
@@ -270,7 +274,12 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="row in pagedFinalOverallRows" :key="'live-final-overall-' + row.playerId">
|
<tr v-for="row in pagedFinalOverallRows" :key="'live-final-overall-' + row.playerId">
|
||||||
<td class="mono rank">{{ row.rank }}</td>
|
<td class="mono rank">
|
||||||
|
<div class="live-rank-cell">
|
||||||
|
<span>{{ row.rank }}</span>
|
||||||
|
<span v-if="finalOverallHintLabel(row)" class="live-rank-hint">{{ finalOverallHintLabel(row) }}</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="competitor-cell compact">
|
<div class="competitor-cell compact">
|
||||||
<img :src="playerImage(row)" :alt="row.nameAr" class="competitor-image" />
|
<img :src="playerImage(row)" :alt="row.nameAr" class="competitor-image" />
|
||||||
@@ -387,6 +396,8 @@ const props = defineProps({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const finalistIds = computed(() => new Set((props.finalists || []).map((row) => row.playerId)))
|
const finalistIds = computed(() => new Set((props.finalists || []).map((row) => row.playerId)))
|
||||||
|
const prelimTieIds = computed(() => new Set((props.prelimTieRows || []).map((row) => row.playerId)))
|
||||||
|
const finalTieIds = computed(() => new Set((props.finalTieRows || []).map((row) => row.playerId)))
|
||||||
const activeView = computed(() => props.liveSettings.activeView || 'group_live')
|
const activeView = computed(() => props.liveSettings.activeView || 'group_live')
|
||||||
const listPageIndex = ref(0)
|
const listPageIndex = ref(0)
|
||||||
const tieGroupIndex = ref(0)
|
const tieGroupIndex = ref(0)
|
||||||
@@ -488,6 +499,25 @@ function isFinalist(playerId) {
|
|||||||
return finalistIds.value.has(playerId)
|
return finalistIds.value.has(playerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isPrelimTiePlayer(playerId) {
|
||||||
|
return prelimTieIds.value.has(playerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
function isFinalTiePlayer(playerId) {
|
||||||
|
return finalTieIds.value.has(playerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
function prelimOverallHintLabel(row) {
|
||||||
|
if (isPrelimTiePlayer(row.playerId)) return props.t('labels.tieBreak')
|
||||||
|
if (isFinalist(row.playerId)) return props.t('labels.finalist')
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
function finalOverallHintLabel(row) {
|
||||||
|
if (isFinalTiePlayer(row.playerId)) return props.t('labels.tieBreak')
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() =>
|
() =>
|
||||||
`${activeView.value}|${rotationIntervalSec.value}|${rotationPlayerCount.value}|${props.prelimTieRows.length}|${props.preliminaryRows.length}|${props.finalOverallRows.length}|${props.finalTieRows.length}`,
|
`${activeView.value}|${rotationIntervalSec.value}|${rotationPlayerCount.value}|${props.prelimTieRows.length}|${props.preliminaryRows.length}|${props.finalOverallRows.length}|${props.finalTieRows.length}`,
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export const I18N = {
|
|||||||
allPlayers: 'جميع اللاعبين',
|
allPlayers: 'جميع اللاعبين',
|
||||||
top12: 'أفضل 12 متأهل',
|
top12: 'أفضل 12 متأهل',
|
||||||
finalist: 'متأهل',
|
finalist: 'متأهل',
|
||||||
|
tieBreak: 'كسر تعادل',
|
||||||
notFinalist: 'غير متأهل',
|
notFinalist: 'غير متأهل',
|
||||||
noPlayers: 'لا يوجد لاعبين بعد',
|
noPlayers: 'لا يوجد لاعبين بعد',
|
||||||
noFinalists: 'لا يوجد متأهلون بعد',
|
noFinalists: 'لا يوجد متأهلون بعد',
|
||||||
@@ -224,6 +225,7 @@ export const I18N = {
|
|||||||
allPlayers: 'All players',
|
allPlayers: 'All players',
|
||||||
top12: 'Top 12 finalists',
|
top12: 'Top 12 finalists',
|
||||||
finalist: 'Finalist',
|
finalist: 'Finalist',
|
||||||
|
tieBreak: 'Tie-break',
|
||||||
notFinalist: 'Not finalist',
|
notFinalist: 'Not finalist',
|
||||||
noPlayers: 'No players yet',
|
noPlayers: 'No players yet',
|
||||||
noFinalists: 'No finalists yet',
|
noFinalists: 'No finalists yet',
|
||||||
|
|||||||
@@ -1514,6 +1514,7 @@ select.name-input {
|
|||||||
.live-footer-slot {
|
.live-footer-slot {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
min-height: 56px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.live-footer-slot.left {
|
.live-footer-slot.left {
|
||||||
@@ -1529,18 +1530,13 @@ select.name-input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.live-footer-logo {
|
.live-footer-logo {
|
||||||
max-width: min(35vw, 200px);
|
|
||||||
padding: 8px 6px;
|
padding: 8px 6px;
|
||||||
width: auto;
|
width: auto;
|
||||||
height: auto;
|
height: 60px;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.28));
|
filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.28));
|
||||||
}
|
}
|
||||||
|
|
||||||
.live-footer-slot.right .live-footer-logo {
|
|
||||||
max-width: min(45vw, 280px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.live-tie-grid {
|
.live-tie-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||||
@@ -1897,8 +1893,20 @@ select.name-input {
|
|||||||
background: #0d1931;
|
background: #0d1931;
|
||||||
}
|
}
|
||||||
|
|
||||||
.live-screen-card .qualified-row {
|
.live-rank-cell {
|
||||||
background: rgba(0, 140, 168, 0.16);
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.live-rank-hint {
|
||||||
|
color: rgba(255, 255, 255, 0.74);
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.live-podium {
|
.live-podium {
|
||||||
@@ -2901,11 +2909,7 @@ select.name-input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.live-footer-logo {
|
.live-footer-logo {
|
||||||
max-height: 36px;
|
max-width: min(34vw, 150px);
|
||||||
}
|
|
||||||
|
|
||||||
.live-footer-slot.right .live-footer-logo {
|
|
||||||
max-width: min(40vw, 150px);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.live-tie-grid {
|
.live-tie-grid {
|
||||||
|
|||||||
Reference in New Issue
Block a user