diff --git a/.env b/.env new file mode 100644 index 0000000..53a6945 --- /dev/null +++ b/.env @@ -0,0 +1 @@ +API_ENDPOINT=http://192.168.31.115:18080/api \ No newline at end of file diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..a102646 --- /dev/null +++ b/.env.production @@ -0,0 +1 @@ +API_ENDPOINT=https://api.memorywake.com/api \ No newline at end of file diff --git a/.gitea/workflows/prod.yaml b/.gitea/workflows/prod.yaml new file mode 100644 index 0000000..957e503 --- /dev/null +++ b/.gitea/workflows/prod.yaml @@ -0,0 +1,36 @@ +name: Prod Deploy +run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀 +on: + push: + tags: + - 'releases/*' + +jobs: + Explore-Gitea-Actions: + runs-on: self_hosted + steps: + - run: echo "🎉 The job was automatically triggered by a ${{ gitea.event_name }} event." + - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by Gitea!" + - run: echo "🔎 The name of your branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}." + - name: Check out repository code + uses: https://git.fairclip.cn/mirrors/actions-checkout@v4 + - run: echo "💡 The ${{ gitea.repository }} repository has been cloned to the runner." + - run: echo "🖥️ The workflow is now ready to test your code on the runner." + - name: List files in the repository + run: | + ls ${{ gitea.workspace }} + - name: Build Docker Image + run: | + echo "Building the Docker image..." + tag_name=${{ gitea.ref_name }} + tag_name=$(echo "${{ gitea.ref_name }}" | tr '/' '-') + docker build -t hub.fairclip.cn/memowake/memowake-front:${tag_name} -f dockerfiles/prod.Dockerfile . + docker push hub.fairclip.cn/memowake/memowake-front:${tag_name} + echo "Docker image built successfully!" + - name: Deploy + run: | + echo "Deploying the project..." + tag_name=${{ gitea.ref_name }} + tag_name=$(echo "${{ gitea.ref_name }}" | tr '/' '-') + bash ./scripts/prod_deploy.sh ${tag_name} + echo "Deploy successful!" \ No newline at end of file diff --git a/app.config.js b/app.config.js new file mode 100644 index 0000000..aee3564 --- /dev/null +++ b/app.config.js @@ -0,0 +1,7 @@ +// app.config.js +export default ({ config }) => ({ + ...config, + extra: { + API_ENDPOINT: process.env.API_ENDPOINT || "http://192.168.31.115:18080/api" + } +}); \ No newline at end of file diff --git a/app/(tabs)/download.tsx b/app/(tabs)/download.tsx new file mode 100644 index 0000000..35cd9d9 --- /dev/null +++ b/app/(tabs)/download.tsx @@ -0,0 +1,63 @@ +import AndroidLogo from '@/assets/icons/svg/android.svg'; +import AppleLogo from '@/assets/icons/svg/apple.svg'; +import MemoIP from '@/assets/icons/svg/memo-ip.svg'; +import { LinearGradient } from 'expo-linear-gradient'; +import { useTranslation } from 'react-i18next'; +import { Linking, Text, TouchableOpacity, View } from 'react-native'; + +const IOS_APP_STORE_URL = 'https://apps.apple.com/cn/app/id6748205761'; +const ANDROID_APK_URL = 'https://cdn.memorywake.com/apks/application-f086a38c-dac1-43f1-9d24-e4378c2ce121.apk'; +export default function DownloadScreen() { + const handleIOSDownload = () => { + Linking.openURL(IOS_APP_STORE_URL); + }; + + const handleAndroidDownload = () => { + Linking.openURL(ANDROID_APK_URL); + }; + + const { t } = useTranslation(); + + return ( + + + + + + + MemoWake + + + {t('desc', { ns: 'download' })} + + + + + + + + {t('ios', { ns: 'download' })} + + + + + + + {t('android', { ns: 'download' })} + + + + + ); +} diff --git a/assets/icons/svg/android.svg b/assets/icons/svg/android.svg new file mode 100644 index 0000000..59f4ee2 --- /dev/null +++ b/assets/icons/svg/android.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/svg/apple.svg b/assets/icons/svg/apple.svg new file mode 100644 index 0000000..b590be7 --- /dev/null +++ b/assets/icons/svg/apple.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dockerfiles/prod.Dockerfile b/dockerfiles/prod.Dockerfile new file mode 100644 index 0000000..84f7180 --- /dev/null +++ b/dockerfiles/prod.Dockerfile @@ -0,0 +1,18 @@ +# 第一阶段:构建 Expo Web 静态文件 +FROM docker.fairclip.cn/node:22 AS builder +WORKDIR /app +COPY package.json . +# 设置npm源 +RUN npm config set registry http://192.168.31.115:8081/repository/npm/ +RUN npm install -g expo-cli && npm install +COPY . . +RUN cp .env.production .env +ENV API_ENDPOINT=https://api.memorywake.com/api +RUN npx expo export -p web + +# 第二阶段:使用 nginx 作为 Web 服务器 +FROM docker.fairclip.cn/nginx:1.29-alpine +COPY --from=builder /app/dist /usr/share/nginx/html +COPY nginx.conf /etc/nginx/nginx.conf +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] diff --git a/i18n/index.ts b/i18n/index.ts index 8b5ff26..02374a2 100644 --- a/i18n/index.ts +++ b/i18n/index.ts @@ -17,7 +17,7 @@ i18n resources: translations, // 支持命名空间 - ns: ['common', 'example'], + ns: ['common', 'example', 'download'], defaultNS: 'common', // 设置默认语言为中文 diff --git a/i18n/locales/en/download.json b/i18n/locales/en/download.json new file mode 100644 index 0000000..faaec14 --- /dev/null +++ b/i18n/locales/en/download.json @@ -0,0 +1,6 @@ +{ + "title": "Download Our App", + "desc": "Get the full experience by downloading our app on your favorite platform.", + "ios": "Download for iOS", + "android": "Download for Android" +} \ No newline at end of file diff --git a/i18n/locales/zh/download.json b/i18n/locales/zh/download.json new file mode 100644 index 0000000..3b1a5d0 --- /dev/null +++ b/i18n/locales/zh/download.json @@ -0,0 +1,6 @@ +{ + "title": "下载我们的应用", + "desc": "在您喜欢的平台上下载我们的应用,以获得完整的体验。", + "ios": "下载 iOS 版", + "android": "下载 Android 版" +} \ No newline at end of file diff --git a/i18n/translations-generated.ts b/i18n/translations-generated.ts index be54939..4edacca 100644 --- a/i18n/translations-generated.ts +++ b/i18n/translations-generated.ts @@ -3,6 +3,7 @@ import enAdmin from './locales/en/admin.json'; import enAsk from './locales/en/ask.json'; import enCommon from './locales/en/common.json'; +import enDownload from './locales/en/download.json'; import enExample from './locales/en/example.json'; import enFairclip from './locales/en/fairclip.json'; import enLanding from './locales/en/landing.json'; @@ -12,6 +13,7 @@ import enUpload from './locales/en/upload.json'; import zhAdmin from './locales/zh/admin.json'; import zhAsk from './locales/zh/ask.json'; import zhCommon from './locales/zh/common.json'; +import zhDownload from './locales/zh/download.json'; import zhExample from './locales/zh/example.json'; import zhFairclip from './locales/zh/fairclip.json'; import zhLanding from './locales/zh/landing.json'; @@ -22,25 +24,27 @@ import zhUpload from './locales/zh/upload.json'; const translations = { en: { admin: enAdmin, + ask: enAsk, common: enCommon, + download: enDownload, example: enExample, fairclip: enFairclip, landing: enLanding, login: enLogin, personal: enPersonal, - upload: enUpload, - ask: enAsk + upload: enUpload }, zh: { admin: zhAdmin, + ask: zhAsk, common: zhCommon, + download: zhDownload, example: zhExample, fairclip: zhFairclip, landing: zhLanding, login: zhLogin, personal: zhPersonal, - upload: zhUpload, - ask: zhAsk + upload: zhUpload }, }; diff --git a/lib/server-api-util.ts b/lib/server-api-util.ts index 18d045c..b122f7f 100644 --- a/lib/server-api-util.ts +++ b/lib/server-api-util.ts @@ -1,4 +1,5 @@ import { setCredentials } from '@/features/auth/authSlice'; +import Constants from 'expo-constants'; import * as SecureStore from 'expo-secure-store'; import { Platform } from 'react-native'; import Toast from 'react-native-toast-message'; @@ -23,7 +24,8 @@ export interface PagedResult { } // 获取.env文件中的变量 -export const API_ENDPOINT = "http://192.168.31.115:18080/api" + +export const API_ENDPOINT = Constants.expoConfig?.extra?.API_ENDPOINT || "http://192.168.31.115:18080/api"; // 更新 access_token 的逻辑 - 用于React组件中 export const useAuthToken = async(message: string | null) => { diff --git a/package-lock.json b/package-lock.json index d25ad73..09f375c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8889,6 +8889,17 @@ "react": "*" } }, + "node_modules/expo-linear-gradient": { + "version": "14.1.5", + "resolved": "http://192.168.31.115:8081/repository/npm/expo-linear-gradient/-/expo-linear-gradient-14.1.5.tgz", + "integrity": "sha512-BSN3MkSGLZoHMduEnAgfhoj3xqcDWaoICgIr4cIYEx1GcHfKMhzA/O4mpZJ/WC27BP1rnAqoKfbclk1eA70ndQ==", + "license": "MIT", + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" + } + }, "node_modules/expo-linking": { "version": "7.1.7", "resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-7.1.7.tgz", diff --git a/scripts/prod_deploy.sh b/scripts/prod_deploy.sh new file mode 100644 index 0000000..4ebfc4a --- /dev/null +++ b/scripts/prod_deploy.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -x + +TAG=${1:-latest} + +CONTROLPANEL_HOST="101.132.185.243" +CONTROLPANEL_USER="ecs-user" +CONTROLPANEL_SSH_KEY="~/.ssh/id_ed25519" + +# SSH到CONTROLPANEL_HOST执行以下命令 +# helm install memowake-front . -n memowake +ssh ${CONTROLPANEL_USER}@${CONTROLPANEL_HOST} "cd /home/ecs-user/infra-deploy/memowake-front && helm upgrade memowake-front . -n memowake --set image.tag=${TAG}" \ No newline at end of file