use docker
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-11-03 21:03:28 +08:00
parent a528b78e43
commit 5cf100c111
28 changed files with 145 additions and 189 deletions

7
.dockerignore Normal file
View File

@@ -0,0 +1,7 @@
Dockerfile
.dockerignore
node_modules
npm-debug.log
README.md
.next
.git

View File

@@ -7,35 +7,14 @@ platform:
os: linux os: linux
arch: amd64 arch: amd64
volumes:
- name: debian-dist
host:
path: /home/debian/dist
steps: steps:
- name: build - name: build
image: node:23-alpine image: plugins/docker
commands: settings:
- npm ci repo: learn-languages
- npm run build tags:
- latest
- name: package dry_run: true
image: node:23-alpine
environment:
ZHIPU_API_KEY:
from_secret: zhipu_api_key
commands:
- apk add zip
- mkdir -p .next/standalone/.next
- cp -r public .next/standalone
- cp -r .next/static .next/standalone/.next
- cd .next/standalone
- echo "$ZHIPU_API_KEY" > zhipu_api_key.txt
- rm -f /dist/learn-languages.zip
- zip -r /dist/learn-languages.zip .
volumes:
- name: debian-dist
path: /dist
- name: deploy - name: deploy
image: appleboy/drone-ssh image: appleboy/drone-ssh
@@ -48,24 +27,8 @@ steps:
from_secret: ssh_password from_secret: ssh_password
port: 22 port: 22
script: script:
- cd ~/ - cd ~/docker/learn-languages
- rm -rf learn-languages - docker-compose restart || docker-compose up -d
- mkdir learn-languages
- unzip -d learn-languages dist/learn-languages.zip
- cd learn-languages
- npm i
- |
if pm2 list | grep -q learn-languages; then
echo "进程 learn-languages 已在pm2中运行正在重启..."
ZHIPU_API_KEY=`cat zhipu_api_key.txt` PORT=3030 pm2 restart "learn-languages"
else
echo "进程 learn-languages 未在pm2中运行正在启动..."
ZHIPU_API_KEY=`cat zhipu_api_key.txt` PORT=3030 pm2 start "./server.js" --name "learn-languages"
fi
- pm2 save
- cd ~/
- rm -rf dist
- mkdir dist
debug: true debug: true
trigger: trigger:

2
.gitignore vendored
View File

@@ -41,3 +41,5 @@ yarn-error.log*
next-env.d.ts next-env.d.ts
.env .env
build.sh

66
Dockerfile Normal file
View File

@@ -0,0 +1,66 @@
# syntax=docker.io/docker/dockerfile:1
FROM node:23-alpine AS base
# Install dependencies only when needed
FROM base AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app
# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* .npmrc* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \
else echo "Lockfile not found." && exit 1; \
fi
# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry during the build.
ENV NEXT_TELEMETRY_DISABLED=1
RUN \
if [ -f yarn.lock ]; then yarn run build; \
elif [ -f package-lock.json ]; then npm run build; \
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm run build; \
else echo "Lockfile not found." && exit 1; \
fi
# Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production
# Uncomment the following line in case you want to disable telemetry during runtime.
ENV NEXT_TELEMETRY_DISABLED=1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT=3000
# server.js is created by next build from the standalone output
# https://nextjs.org/docs/pages/api-reference/config/next-config-js/output
ENV HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]

122
package-lock.json generated
View File

@@ -3685,7 +3685,6 @@
"version": "7.2.3", "version": "7.2.3",
"resolved": "https://mirrors.cloud.tencent.com/npm/glob/-/glob-7.2.3.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"deprecated": "Glob versions prior to v9 are no longer supported",
"license": "ISC", "license": "ISC",
"optional": true, "optional": true,
"peer": true, "peer": true,
@@ -4710,14 +4709,15 @@
} }
}, },
"node_modules/@unimodules/react-native-adapter": { "node_modules/@unimodules/react-native-adapter": {
"version": "6.3.9", "version": "6.5.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/@unimodules/react-native-adapter/-/react-native-adapter-6.3.9.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/@unimodules/react-native-adapter/-/react-native-adapter-6.5.0.tgz",
"integrity": "sha512-i9/9Si4AQ8awls+YGAKkByFbeAsOPgUNeLoYeh2SQ3ddjxJ5ZJDtq/I74clDnpDcn8zS9pYlcDJ9fgVJa39Glw==", "integrity": "sha512-F2J6gVw9a57DTVTQQunp64fqD4HVBkltOpUz1L5lEccNbQlZEA7SjnqKJzXakI7uPhhN76/n+SGb7ihzHw2swQ==",
"deprecated": "replaced by the 'expo' package, learn more: https://blog.expo.dev/whats-new-in-expo-modules-infrastructure-7a7cdda81ebc",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"dependencies": { "dependencies": {
"expo-modules-autolinking": "^0.0.3", "expo-modules-autolinking": "^0.3.2",
"invariant": "^2.2.4" "expo-modules-core": "~0.4.0"
} }
}, },
"node_modules/@unrs/resolver-binding-android-arm-eabi": { "node_modules/@unrs/resolver-binding-android-arm-eabi": {
@@ -5188,7 +5188,7 @@
"node_modules/any-promise": { "node_modules/any-promise": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/any-promise/-/any-promise-1.3.0.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/any-promise/-/any-promise-1.3.0.tgz",
"integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true "peer": true
@@ -5396,7 +5396,7 @@
"node_modules/asap": { "node_modules/asap": {
"version": "2.0.6", "version": "2.0.6",
"resolved": "https://mirrors.cloud.tencent.com/npm/asap/-/asap-2.0.6.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/asap/-/asap-2.0.6.tgz",
"integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true "peer": true
@@ -5765,7 +5765,7 @@
"node_modules/base-64": { "node_modules/base-64": {
"version": "0.1.0", "version": "0.1.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/base-64/-/base-64-0.1.0.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/base-64/-/base-64-0.1.0.tgz",
"integrity": "sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA==" "integrity": "sha1-eAqZyE59YAJgNhURxId2E78k9rs="
}, },
"node_modules/base64-js": { "node_modules/base64-js": {
"version": "1.5.1", "version": "1.5.1",
@@ -5789,9 +5789,9 @@
"optional": true "optional": true
}, },
"node_modules/baseline-browser-mapping": { "node_modules/baseline-browser-mapping": {
"version": "2.8.22", "version": "2.8.23",
"resolved": "https://mirrors.cloud.tencent.com/npm/baseline-browser-mapping/-/baseline-browser-mapping-2.8.22.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/baseline-browser-mapping/-/baseline-browser-mapping-2.8.23.tgz",
"integrity": "sha512-/tk9kky/d8T8CTXIQYASLyhAxR5VwL3zct1oAoVTaOUHwrmsGnfbRwNdEq+vOl2BN8i3PcDdP0o4Q+jjKQoFbQ==", "integrity": "sha512-616V5YX4bepJFzNyOfce5Fa8fDJMfoxzOIzDCZwaGL8MKVpFrXqfNUoIpRn9YMI5pXf/VKgzjB4htFMsFKKdiQ==",
"license": "Apache-2.0", "license": "Apache-2.0",
"optional": true, "optional": true,
"peer": true, "peer": true,
@@ -6093,17 +6093,6 @@
"url": "https://github.com/chalk/chalk?sponsor=1" "url": "https://github.com/chalk/chalk?sponsor=1"
} }
}, },
"node_modules/chownr": {
"version": "3.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/chownr/-/chownr-3.0.0.tgz",
"integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
"license": "BlueOak-1.0.0",
"optional": true,
"peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/chrome-launcher": { "node_modules/chrome-launcher": {
"version": "0.15.2", "version": "0.15.2",
"resolved": "https://mirrors.cloud.tencent.com/npm/chrome-launcher/-/chrome-launcher-0.15.2.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/chrome-launcher/-/chrome-launcher-0.15.2.tgz",
@@ -6374,7 +6363,7 @@
"node_modules/compression/node_modules/ms": { "node_modules/compression/node_modules/ms": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true "peer": true
@@ -6393,7 +6382,7 @@
"node_modules/concat-map": { "node_modules/concat-map": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"devOptional": true, "devOptional": true,
"license": "MIT" "license": "MIT"
}, },
@@ -6428,7 +6417,7 @@
"node_modules/connect/node_modules/ms": { "node_modules/connect/node_modules/ms": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true "peer": true
@@ -6803,7 +6792,7 @@
"node_modules/ee-first": { "node_modules/ee-first": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/ee-first/-/ee-first-1.1.1.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true "peer": true
@@ -6826,7 +6815,7 @@
"node_modules/encodeurl": { "node_modules/encodeurl": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://mirrors.cloud.tencent.com/npm/encodeurl/-/encodeurl-1.0.2.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true, "peer": true,
@@ -7057,7 +7046,7 @@
"node_modules/escape-html": { "node_modules/escape-html": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://mirrors.cloud.tencent.com/npm/escape-html/-/escape-html-1.0.3.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true "peer": true
@@ -7518,7 +7507,7 @@
"node_modules/etag": { "node_modules/etag": {
"version": "1.8.1", "version": "1.8.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/etag/-/etag-1.8.1.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/etag/-/etag-1.8.1.tgz",
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true, "peer": true,
@@ -7546,9 +7535,9 @@
"peer": true "peer": true
}, },
"node_modules/expo-modules-autolinking": { "node_modules/expo-modules-autolinking": {
"version": "0.0.3", "version": "0.3.4",
"resolved": "https://mirrors.cloud.tencent.com/npm/expo-modules-autolinking/-/expo-modules-autolinking-0.0.3.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/expo-modules-autolinking/-/expo-modules-autolinking-0.3.4.tgz",
"integrity": "sha512-azkCRYj/DxbK4udDuDxA9beYzQTwpJ5a9QA0bBgha2jHtWdFGF4ZZWSY+zNA5mtU3KqzYt8jWHfoqgSvKyu1Aw==", "integrity": "sha512-Mu3CIMqEAI8aNM18U/l+7CCi+afU8dERrKjDDEx/Hu7XX3v3FcnnP+NuWDLY/e9/ETzwTJaqoRoBuzhawsuLWw==",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"dependencies": { "dependencies": {
@@ -7738,7 +7727,7 @@
"node_modules/finalhandler/node_modules/ms": { "node_modules/finalhandler/node_modules/ms": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true "peer": true
@@ -7881,7 +7870,7 @@
"node_modules/fresh": { "node_modules/fresh": {
"version": "0.5.2", "version": "0.5.2",
"resolved": "https://mirrors.cloud.tencent.com/npm/fresh/-/fresh-0.5.2.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true, "peer": true,
@@ -7908,7 +7897,7 @@
"node_modules/fs.realpath": { "node_modules/fs.realpath": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/fs.realpath/-/fs.realpath-1.0.0.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
"license": "ISC", "license": "ISC",
"optional": true, "optional": true,
"peer": true "peer": true
@@ -9270,7 +9259,6 @@
"version": "7.2.3", "version": "7.2.3",
"resolved": "https://mirrors.cloud.tencent.com/npm/glob/-/glob-7.2.3.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"deprecated": "Glob versions prior to v9 are no longer supported",
"license": "ISC", "license": "ISC",
"optional": true, "optional": true,
"peer": true, "peer": true,
@@ -9768,7 +9756,7 @@
"node_modules/isomorphic-webcrypto/node_modules/react-native-securerandom": { "node_modules/isomorphic-webcrypto/node_modules/react-native-securerandom": {
"version": "0.1.1", "version": "0.1.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/react-native-securerandom/-/react-native-securerandom-0.1.1.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/react-native-securerandom/-/react-native-securerandom-0.1.1.tgz",
"integrity": "sha1-8TBiOkEsM4sK+t7bwgTFy7i/IHA=", "integrity": "sha512-CozcCx0lpBLevxiXEb86kwLRalBCHNjiGPlw3P7Fi27U6ZLdfjOCNRHD1LtBKcvPvI3TvkBXB3GOtLvqaYJLGw==",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"dependencies": { "dependencies": {
@@ -9824,7 +9812,6 @@
"version": "7.2.3", "version": "7.2.3",
"resolved": "https://mirrors.cloud.tencent.com/npm/glob/-/glob-7.2.3.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"deprecated": "Glob versions prior to v9 are no longer supported",
"license": "ISC", "license": "ISC",
"optional": true, "optional": true,
"peer": true, "peer": true,
@@ -10468,7 +10455,7 @@
"node_modules/lighthouse-logger/node_modules/ms": { "node_modules/lighthouse-logger/node_modules/ms": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true "peer": true
@@ -10776,7 +10763,7 @@
"node_modules/lodash.throttle": { "node_modules/lodash.throttle": {
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/lodash.throttle/-/lodash.throttle-4.1.1.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
"integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true "peer": true
@@ -11716,7 +11703,7 @@
"node_modules/object-assign": { "node_modules/object-assign": {
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/object-assign/-/object-assign-4.1.1.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
"devOptional": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -11864,7 +11851,7 @@
"node_modules/once": { "node_modules/once": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/once/-/once-1.4.0.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"license": "ISC", "license": "ISC",
"optional": true, "optional": true,
"peer": true, "peer": true,
@@ -11875,7 +11862,7 @@
"node_modules/onetime": { "node_modules/onetime": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/onetime/-/onetime-2.0.1.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/onetime/-/onetime-2.0.1.tgz",
"integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true, "peer": true,
@@ -12171,7 +12158,7 @@
"node_modules/path-is-absolute": { "node_modules/path-is-absolute": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true, "peer": true,
@@ -12477,7 +12464,7 @@
"node_modules/qrcode-terminal": { "node_modules/qrcode-terminal": {
"version": "0.11.0", "version": "0.11.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/qrcode-terminal/-/qrcode-terminal-0.11.0.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/qrcode-terminal/-/qrcode-terminal-0.11.0.tgz",
"integrity": "sha1-/8bCii/Av7RwUrR+I/T0RqX7254=", "integrity": "sha512-Uu7ii+FQy4Qf82G4xu7ShHhjhGahEpCWc3x8UavY3CTcWV+ufmmCtwkr7ZKsX42jdL0kr1B5FKUeqJvAn51jzQ==",
"optional": true, "optional": true,
"peer": true, "peer": true,
"bin": { "bin": {
@@ -12547,7 +12534,7 @@
"node_modules/rc/node_modules/strip-json-comments": { "node_modules/rc/node_modules/strip-json-comments": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true, "peer": true,
@@ -12747,7 +12734,7 @@
"node_modules/require-directory": { "node_modules/require-directory": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/require-directory/-/require-directory-2.1.1.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true, "peer": true,
@@ -12869,7 +12856,7 @@
"node_modules/restore-cursor": { "node_modules/restore-cursor": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/restore-cursor/-/restore-cursor-2.0.0.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/restore-cursor/-/restore-cursor-2.0.0.tgz",
"integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true, "peer": true,
@@ -12921,7 +12908,6 @@
"version": "7.2.3", "version": "7.2.3",
"resolved": "https://mirrors.cloud.tencent.com/npm/glob/-/glob-7.2.3.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"deprecated": "Glob versions prior to v9 are no longer supported",
"license": "ISC", "license": "ISC",
"optional": true, "optional": true,
"peer": true, "peer": true,
@@ -13108,7 +13094,7 @@
"node_modules/send/node_modules/debug/node_modules/ms": { "node_modules/send/node_modules/debug/node_modules/ms": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true "peer": true
@@ -13152,7 +13138,7 @@
"node_modules/serialize-error": { "node_modules/serialize-error": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/serialize-error/-/serialize-error-2.1.0.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/serialize-error/-/serialize-error-2.1.0.tgz",
"integrity": "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==", "integrity": "sha1-ULZ51WNc34Rme9yOWa9OW4HV9go=",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true, "peer": true,
@@ -13191,7 +13177,7 @@
"node_modules/serve-static/node_modules/debug/node_modules/ms": { "node_modules/serve-static/node_modules/debug/node_modules/ms": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true "peer": true
@@ -13250,7 +13236,7 @@
"node_modules/serve-static/node_modules/send/node_modules/encodeurl": { "node_modules/serve-static/node_modules/send/node_modules/encodeurl": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://mirrors.cloud.tencent.com/npm/encodeurl/-/encodeurl-1.0.2.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true, "peer": true,
@@ -13542,7 +13528,7 @@
"node_modules/source-map": { "node_modules/source-map": {
"version": "0.5.7", "version": "0.5.7",
"resolved": "https://mirrors.cloud.tencent.com/npm/source-map/-/source-map-0.5.7.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"optional": true, "optional": true,
"peer": true, "peer": true,
@@ -13585,7 +13571,7 @@
"node_modules/sprintf-js": { "node_modules/sprintf-js": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://mirrors.cloud.tencent.com/npm/sprintf-js/-/sprintf-js-1.0.3.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"optional": true, "optional": true,
"peer": true "peer": true
@@ -13678,7 +13664,7 @@
"node_modules/stream-buffers": { "node_modules/stream-buffers": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/stream-buffers/-/stream-buffers-2.2.0.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/stream-buffers/-/stream-buffers-2.2.0.tgz",
"integrity": "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==", "integrity": "sha1-kdX1Ew0c75bc+n9yaUUYh0HQnuQ=",
"license": "Unlicense", "license": "Unlicense",
"optional": true, "optional": true,
"peer": true, "peer": true,
@@ -13914,7 +13900,7 @@
"node_modules/strip-bom": { "node_modules/strip-bom": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/strip-bom/-/strip-bom-3.0.0.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/strip-bom/-/strip-bom-3.0.0.tgz",
"integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -14080,6 +14066,17 @@
"node": ">=18" "node": ">=18"
} }
}, },
"node_modules/tar/node_modules/chownr": {
"version": "3.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/chownr/-/chownr-3.0.0.tgz",
"integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
"license": "BlueOak-1.0.0",
"optional": true,
"peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/tar/node_modules/yallist": { "node_modules/tar/node_modules/yallist": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/yallist/-/yallist-5.0.0.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/yallist/-/yallist-5.0.0.tgz",
@@ -14168,7 +14165,6 @@
"version": "7.2.3", "version": "7.2.3",
"resolved": "https://mirrors.cloud.tencent.com/npm/glob/-/glob-7.2.3.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"deprecated": "Glob versions prior to v9 are no longer supported",
"license": "ISC", "license": "ISC",
"optional": true, "optional": true,
"peer": true, "peer": true,
@@ -14687,7 +14683,7 @@
"node_modules/utils-merge": { "node_modules/utils-merge": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/utils-merge/-/utils-merge-1.0.1.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/utils-merge/-/utils-merge-1.0.1.tgz",
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true, "peer": true,
@@ -14752,7 +14748,7 @@
"node_modules/wcwidth": { "node_modules/wcwidth": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/wcwidth/-/wcwidth-1.0.1.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/wcwidth/-/wcwidth-1.0.1.tgz",
"integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true, "peer": true,
@@ -14782,7 +14778,7 @@
"node_modules/webidl-conversions": { "node_modules/webidl-conversions": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=",
"license": "BSD-2-Clause" "license": "BSD-2-Clause"
}, },
"node_modules/whatwg-fetch": { "node_modules/whatwg-fetch": {
@@ -14796,7 +14792,7 @@
"node_modules/whatwg-url": { "node_modules/whatwg-url": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/whatwg-url/-/whatwg-url-5.0.0.tgz", "resolved": "https://mirrors.cloud.tencent.com/npm/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"tr46": "~0.0.3", "tr46": "~0.0.3",

View File

@@ -1,67 +0,0 @@
import { callZhipuAPI } from "@/utils";
import { NextRequest, NextResponse } from "next/server";
async function getTextinfo(text: string) {
console.log(`get textinfo of ${text}`);
const messages = [
{
role: "user",
content: `
请推断以下文本的语言、locale生成宽式国际音标IPA以JSON格式返回
[${text}]
结果如:
{
"text": "你好。",
"lang": "mandarin",
"ipa": "[ni˨˩˦ xɑʊ˨˩˦]",
"locale": "zh-CN"
}
注意:
直接返回json文本
ipa一定要加[]
lang的值是小写字母的英文的语言名称
locale如果可能有多个选取最可能的一个其中使用符号"-"
`,
},
];
try {
const response = await callZhipuAPI(messages);
let to_parse = response.choices[0].message.content.trim() as string;
if (to_parse.startsWith("`"))
to_parse = to_parse.slice(7, to_parse.length - 3);
if (to_parse.length === 0) throw Error("ai啥也每说");
return JSON.parse(to_parse);
} catch (error) {
console.error(error);
return null;
}
}
export async function GET(request: NextRequest) {
try {
const searchParams = request.nextUrl.searchParams;
const text = searchParams.get("text");
if (!text) {
return NextResponse.json(
{ error: "查询参数错误", message: "text参数是必需的" },
{ status: 400 },
);
}
const textInfo = await getTextinfo(text);
if (!textInfo) {
return NextResponse.json(
{ error: "服务暂时不可用", message: "LLM API 请求失败" },
{ status: 503 },
);
}
return NextResponse.json(textInfo, { status: 200 });
} catch (error) {
console.error("API 错误:", error);
return NextResponse.json(
{ error: "服务器内部错误", message: "请稍后重试" },
{ status: 500 },
);
}
}

View File

@@ -1,5 +1,4 @@
import type { Metadata } from "next"; import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css"; import "./globals.css";
import type { Viewport } from "next"; import type { Viewport } from "next";
import { NextIntlClientProvider } from "next-intl"; import { NextIntlClientProvider } from "next-intl";
@@ -9,16 +8,6 @@ export const viewport: Viewport = {
initialScale: 1.0, initialScale: 1.0,
}; };
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Learn Languages", title: "Learn Languages",
description: "A Website to Learn Languages", description: "A Website to Learn Languages",
@@ -32,7 +21,7 @@ export default async function RootLayout({
return ( return (
<html lang="en"> <html lang="en">
<body <body
className={`${geistSans.variable} ${geistMono.variable} antialiased`} className={`antialiased`}
> >
<NextIntlClientProvider>{children}</NextIntlClientProvider> <NextIntlClientProvider>{children}</NextIntlClientProvider>
</body> </body>

View File

@@ -43,7 +43,7 @@ export default getRequestConfig(async () => {
return locale; return locale;
})(); })();
const messagesPath = join(process.cwd(), "messages", locale); const messagesPath = join(process.cwd(), "public/messages", locale);
const messages = loadMessagesFromDir(messagesPath); const messages = loadMessagesFromDir(messagesPath);
return { return {