Explorar o código

启动时自动检测环境变量是否有变化

liuziting hai 5 meses
pai
achega
6018265c85

+ 69 - 0
ENV_RELOAD_SOLUTION.md

@@ -0,0 +1,69 @@
+# 环境变量自动刷新解决方案
+
+## 问题描述
+
+当修改 `.env` 文件后,网站仍然使用缓存的旧配置,需要手动点击重置才能加载最新的环境变量配置。
+
+## 解决方案
+
+### 自动刷新机制
+
+-   应用启动时自动检测环境变量是否有变化
+-   如果检测到变化,自动清除配置缓存并刷新页面
+-   无需用户手动操作,完全自动化处理
+
+### 使用方法
+
+#### 自动刷新(推荐)
+
+1. 修改 `.env` 文件
+2. 刷新浏览器页面或重新打开网站
+3. 系统会自动检测到变化并刷新页面应用最新配置
+
+#### 手动重置(备用方案)
+
+1. 修改 `.env` 文件
+2. 打开设置页面(点击右上角设置图标)
+3. 点击"恢复默认"按钮
+4. 手动刷新浏览器页面
+
+## 技术实现
+
+### 环境变量监听器 (`src/utils/envWatcher.js`)
+
+-   在应用启动时创建环境变量快照
+-   将快照存储在 localStorage 中
+-   下次启动时比较快照检测变化
+-   自动清除缓存并刷新页面
+
+### 设置存储优化 (`src/stores/settings.js`)
+
+-   添加 `reloadEnvSettings()` 方法
+-   优化重置逻辑,确保读取最新配置
+
+### 应用启动集成 (`src/main.ts`)
+
+-   在应用挂载前检查环境变量变化
+-   自动执行刷新操作
+
+## 工作流程
+
+1. **首次访问**:创建环境变量快照并存储
+2. **修改.env 文件**:环境变量发生变化
+3. **再次访问**:
+    - 检测到环境变量变化
+    - 自动清除 localStorage 中的配置缓存
+    - 自动刷新页面
+    - 应用加载最新的环境变量配置
+
+## 注意事项
+
+1. **Vite 环境变量特性**:Vite 的环境变量在构建时确定,运行时无法动态更新,因此需要刷新页面
+2. **缓存机制**:系统会缓存用户的自定义配置,只有在检测到环境变量变化时才会清除缓存
+3. **自动化处理**:用户无需手动操作,系统会自动处理环境变量的更新
+
+## 最佳实践
+
+1. 修改 `.env` 文件后,直接刷新浏览器页面即可
+2. 系统会自动检测并应用最新配置
+3. 如果遇到问题,可以使用设置页面的"恢复默认"功能作为备用方案

+ 3 - 0
README_EN.md

@@ -82,6 +82,8 @@ npm run preview
 
 
 #### You can switch any request address and model that complies with the OpenAI standard
 #### You can switch any request address and model that complies with the OpenAI standard
 
 
+> **🚀 Recommended Provider**: This project recommends using [302.ai](https://302.ai/) AI API services - stable, reliable, supports multiple mainstream large models, and cost-effective!
+
 ```env
 ```env
 # Text Generation API (lingyiwanwu.AI)
 # Text Generation API (lingyiwanwu.AI)
 VITE_TEXT_GENERATION_BASE_URL=https://api.lingyiwanwu.com/v1/
 VITE_TEXT_GENERATION_BASE_URL=https://api.lingyiwanwu.com/v1/
@@ -154,5 +156,6 @@ src/
 
 
 -   [Vue.js](https://vuejs.org/) - Progressive JavaScript framework
 -   [Vue.js](https://vuejs.org/) - Progressive JavaScript framework
 -   [Tailwind CSS](https://tailwindcss.com/) - Utility-first CSS framework
 -   [Tailwind CSS](https://tailwindcss.com/) - Utility-first CSS framework
+-   [302.ai](https://302.ai/) - **Official Partner** 🚀 Providing stable and reliable AI API services for this project
 -   [01.AI](https://www.lingyiwanwu.com/) - Recipe generation API
 -   [01.AI](https://www.lingyiwanwu.com/) - Recipe generation API
 -   [Zhipu AI](https://open.bigmodel.cn/) - Image generation API
 -   [Zhipu AI](https://open.bigmodel.cn/) - Image generation API

+ 40 - 0
src/components/SettingsModal.vue

@@ -11,6 +11,46 @@
             </div>
             </div>
 
 
             <div class="space-y-8">
             <div class="space-y-8">
+                <!-- 302.ai 推荐广告 -->
+                <div class="hidden bg-gradient-to-r from-blue-50 to-purple-50 border-2 border-blue-200 rounded-lg p-4">
+                    <div class="flex items-start gap-4">
+                        <div class="flex-shrink-0">
+                            <div class="w-12 h-12 bg-gradient-to-br from-blue-500 to-purple-600 rounded-lg flex items-center justify-center">
+                                <span class="text-white text-lg font-bold">302</span>
+                            </div>
+                        </div>
+                        <div class="flex-1">
+                            <div class="flex items-center gap-2 mb-2">
+                                <h3 class="text-lg font-semibold text-gray-800">🚀 推荐API服务商</h3>
+                            </div>
+                            <p class="text-sm text-gray-600 mb-3">
+                                本项目正在使用 <strong>302.ai</strong> 提供的高质量AI API服务。302.ai 提供稳定可靠的AI模型接口,支持多种主流大模型,价格优惠,服务稳定。
+                            </p>
+                            <div class="flex flex-wrap gap-2 mb-3">
+                                <span class="bg-green-100 text-green-800 text-xs px-2 py-1 rounded">✓ 多模型支持</span>
+                                <span class="bg-green-100 text-green-800 text-xs px-2 py-1 rounded">✓ 价格优惠</span>
+                                <span class="bg-green-100 text-green-800 text-xs px-2 py-1 rounded">✓ 服务稳定</span>
+                                <span class="bg-green-100 text-green-800 text-xs px-2 py-1 rounded">✓ 快速接入</span>
+                            </div>
+                            <a
+                                href="https://302.ai/"
+                                target="_blank"
+                                class="inline-flex items-center gap-2 bg-blue-500 hover:bg-blue-600 text-white text-sm px-4 py-2 rounded-lg transition-colors"
+                            >
+                                <span>访问 302.ai</span>
+                                <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
+                                    <path
+                                        stroke-linecap="round"
+                                        stroke-linejoin="round"
+                                        stroke-width="2"
+                                        d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
+                                    ></path>
+                                </svg>
+                            </a>
+                        </div>
+                    </div>
+                </div>
+
                 <!-- 菜谱生成模型配置 -->
                 <!-- 菜谱生成模型配置 -->
                 <div class="border rounded-lg p-4">
                 <div class="border rounded-lg p-4">
                     <h3 class="text-lg font-semibold text-gray-800 mb-4 flex items-center">
                     <h3 class="text-lg font-semibold text-gray-800 mb-4 flex items-center">

+ 9 - 1
src/main.ts

@@ -11,6 +11,7 @@ import HowToCook from './views/HowToCook.vue'
 import SauceDesign from './views/SauceDesign.vue'
 import SauceDesign from './views/SauceDesign.vue'
 import FortuneCooking from './views/FortuneCooking.vue'
 import FortuneCooking from './views/FortuneCooking.vue'
 import SettingsDemo from './views/SettingsDemo.vue'
 import SettingsDemo from './views/SettingsDemo.vue'
+import { autoRefreshEnvSettings } from './utils/envWatcher'
 import './style.css'
 import './style.css'
 
 
 const routes = [
 const routes = [
@@ -31,4 +32,11 @@ const router = createRouter({
     routes
     routes
 })
 })
 
 
-createApp(App).use(router).mount('#app')
+// 初始化应用
+const app = createApp(App).use(router)
+
+// 在应用挂载前检查环境变量变化并自动刷新
+autoRefreshEnvSettings()
+
+// 挂载应用
+app.mount('#app')

+ 58 - 3
src/stores/settings.js

@@ -16,6 +16,25 @@ const getDefaultSettings = () => ({
     }
     }
 })
 })
 
 
+// 动态获取最新的环境变量配置(用于重置功能)
+const getLatestEnvSettings = () => {
+    // 强制重新读取环境变量
+    return {
+        textGeneration: {
+            baseUrl: import.meta.env.VITE_TEXT_GENERATION_BASE_URL || 'https://api.lingyiwanwu.com/v1/',
+            apiKey: import.meta.env.VITE_TEXT_GENERATION_API_KEY || '',
+            model: import.meta.env.VITE_TEXT_GENERATION_MODEL || 'yi-lightning',
+            temperature: parseFloat(import.meta.env.VITE_TEXT_GENERATION_TEMPERATURE) || 0.7,
+            timeout: parseInt(import.meta.env.VITE_TEXT_GENERATION_TIMEOUT) || 300000
+        },
+        imageGeneration: {
+            baseUrl: import.meta.env.VITE_IMAGE_GENERATION_BASE_URL || 'https://open.bigmodel.cn/api/paas/v4/',
+            apiKey: import.meta.env.VITE_IMAGE_GENERATION_API_KEY || '',
+            model: import.meta.env.VITE_IMAGE_GENERATION_MODEL || 'cogview-3-flash'
+        }
+    }
+}
+
 // 存储键名
 // 存储键名
 const STORAGE_KEY = 'yifan-fengshen-settings'
 const STORAGE_KEY = 'yifan-fengshen-settings'
 
 
@@ -90,12 +109,48 @@ export const useSettingsStore = () => {
 
 
             // 重置为默认设置
             // 重置为默认设置
             resetToDefault: () => {
             resetToDefault: () => {
-                const defaultSettings = getDefaultSettings()
-                Object.assign(settings.textGeneration, defaultSettings.textGeneration)
-                Object.assign(settings.imageGeneration, defaultSettings.imageGeneration)
+                const latestSettings = getLatestEnvSettings()
+                Object.assign(settings.textGeneration, latestSettings.textGeneration)
+                Object.assign(settings.imageGeneration, latestSettings.imageGeneration)
                 saveToStorage()
                 saveToStorage()
             },
             },
 
 
+            // 重新加载环境变量配置(用于.env文件修改后的刷新)
+            reloadEnvSettings: () => {
+                // 清除localStorage中的设置,强制重新读取环境变量
+                localStorage.removeItem(STORAGE_KEY)
+
+                // 重新获取最新的环境变量
+                const latestSettings = getLatestEnvSettings()
+                Object.assign(settings.textGeneration, latestSettings.textGeneration)
+                Object.assign(settings.imageGeneration, latestSettings.imageGeneration)
+
+                // 不保存到localStorage,让下次启动时重新读取环境变量
+                console.log('已重新加载环境变量配置,请刷新页面以应用最新配置')
+                return latestSettings
+            },
+
+            // 检查环境变量是否有更新
+            checkEnvUpdates: () => {
+                const currentEnv = getLatestEnvSettings()
+                const currentSettings = settings
+
+                // 比较当前设置和环境变量是否一致
+                const hasUpdates =
+                    currentEnv.textGeneration.baseUrl !== currentSettings.textGeneration.baseUrl ||
+                    currentEnv.textGeneration.apiKey !== currentSettings.textGeneration.apiKey ||
+                    currentEnv.textGeneration.model !== currentSettings.textGeneration.model ||
+                    currentEnv.imageGeneration.baseUrl !== currentSettings.imageGeneration.baseUrl ||
+                    currentEnv.imageGeneration.apiKey !== currentSettings.imageGeneration.apiKey ||
+                    currentEnv.imageGeneration.model !== currentSettings.imageGeneration.model
+
+                return {
+                    hasUpdates,
+                    currentEnv,
+                    currentSettings
+                }
+            },
+
             // 清除所有设置
             // 清除所有设置
             clearSettings: () => {
             clearSettings: () => {
                 try {
                 try {

+ 30 - 0
src/utils/envWatcher.d.ts

@@ -0,0 +1,30 @@
+// 环境变量监听工具类型声明
+
+export interface EnvSnapshot {
+    [key: string]: string
+}
+
+export interface EnvCheckResult {
+    hasChanged: boolean
+    oldSnapshot?: EnvSnapshot
+    newSnapshot?: EnvSnapshot
+    snapshot?: EnvSnapshot
+}
+
+/**
+ * 初始化环境变量监听
+ * @returns 检查结果,包含是否有变化和快照信息
+ */
+export declare function initEnvWatcher(): EnvCheckResult
+
+/**
+ * 手动检查环境变量变化
+ * @returns 检查结果,包含是否有变化和新旧快照
+ */
+export declare function checkEnvChanges(): EnvCheckResult
+
+/**
+ * 自动刷新环境变量配置
+ * @returns 是否执行了刷新
+ */
+export declare function autoRefreshEnvSettings(): boolean

+ 114 - 0
src/utils/envWatcher.js

@@ -0,0 +1,114 @@
+// 环境变量监听工具
+
+// 环境变量键名列表
+const ENV_KEYS = [
+    'VITE_TEXT_GENERATION_BASE_URL',
+    'VITE_TEXT_GENERATION_API_KEY',
+    'VITE_TEXT_GENERATION_MODEL',
+    'VITE_TEXT_GENERATION_TEMPERATURE',
+    'VITE_TEXT_GENERATION_TIMEOUT',
+    'VITE_IMAGE_GENERATION_BASE_URL',
+    'VITE_IMAGE_GENERATION_API_KEY',
+    'VITE_IMAGE_GENERATION_MODEL'
+]
+
+// 获取当前环境变量快照
+const getCurrentEnvSnapshot = () => {
+    const snapshot = {}
+    ENV_KEYS.forEach(key => {
+        snapshot[key] = import.meta.env[key] || ''
+    })
+    return snapshot
+}
+
+// 比较环境变量是否有变化
+const hasEnvChanged = (oldSnapshot, newSnapshot) => {
+    if (!oldSnapshot) return false
+
+    return ENV_KEYS.some(key => oldSnapshot[key] !== newSnapshot[key])
+}
+
+// 初始化环境变量监听
+export const initEnvWatcher = () => {
+    const currentSnapshot = getCurrentEnvSnapshot()
+
+    // 在localStorage中存储环境变量快照
+    const storageKey = 'yifan-fengshen-env-snapshot'
+    const storedSnapshot = localStorage.getItem(storageKey)
+
+    if (storedSnapshot) {
+        try {
+            const parsedSnapshot = JSON.parse(storedSnapshot)
+
+            if (hasEnvChanged(parsedSnapshot, currentSnapshot)) {
+                console.log('检测到环境变量变化')
+                // 更新存储的快照
+                localStorage.setItem(storageKey, JSON.stringify(currentSnapshot))
+                return {
+                    hasChanged: true,
+                    oldSnapshot: parsedSnapshot,
+                    newSnapshot: currentSnapshot
+                }
+            }
+        } catch (error) {
+            console.warn('解析环境变量快照失败:', error)
+        }
+    }
+
+    // 更新存储的快照
+    localStorage.setItem(storageKey, JSON.stringify(currentSnapshot))
+
+    return {
+        hasChanged: false,
+        snapshot: currentSnapshot
+    }
+}
+
+// 手动检查环境变量变化
+export const checkEnvChanges = () => {
+    const currentSnapshot = getCurrentEnvSnapshot()
+    const storageKey = 'yifan-fengshen-env-snapshot'
+    const storedSnapshot = localStorage.getItem(storageKey)
+
+    let hasChanged = false
+    let oldSnapshot = null
+
+    if (storedSnapshot) {
+        try {
+            oldSnapshot = JSON.parse(storedSnapshot)
+            hasChanged = hasEnvChanged(oldSnapshot, currentSnapshot)
+        } catch (error) {
+            console.warn('解析环境变量快照失败:', error)
+        }
+    }
+
+    if (hasChanged) {
+        // 更新存储的快照
+        localStorage.setItem(storageKey, JSON.stringify(currentSnapshot))
+    }
+
+    return {
+        hasChanged,
+        oldSnapshot,
+        newSnapshot: currentSnapshot
+    }
+}
+
+// 自动刷新环境变量配置
+export const autoRefreshEnvSettings = () => {
+    const result = initEnvWatcher()
+
+    if (result.hasChanged) {
+        console.log('检测到环境变量变化,自动刷新配置')
+
+        // 清除localStorage中的设置缓存,让应用重新读取环境变量
+        localStorage.removeItem('yifan-fengshen-settings')
+
+        // 自动刷新页面以应用最新配置
+        window.location.reload()
+
+        return true
+    }
+
+    return false
+}

+ 106 - 0
src/views/About.vue

@@ -4,6 +4,111 @@
         <GlobalNavigation />
         <GlobalNavigation />
 
 
         <div class="max-w-7xl mx-auto space-y-6">
         <div class="max-w-7xl mx-auto space-y-6">
+            <!-- API服务商推荐 -->
+            <div class="relative hidden">
+                <div class="bg-gradient-to-r from-blue-500 to-cyan-500 text-white px-4 py-2 rounded-t-lg border-2 border-[#0A0910] border-b-0 inline-block mb-0">
+                    <span class="font-bold text-lg">🚀 API服务商</span>
+                </div>
+                <div class="bg-white border-2 border-[#0A0910] rounded-lg rounded-tl-none p-6">
+                    <div class="mt-4">
+                        <div class="flex items-center gap-2 mb-6">
+                            <span class="text-2xl">⚡</span>
+                            <div>
+                                <p class="text-gray-700 text-sm font-medium">本项目AI服务提供商</p>
+                                <p class="text-gray-500 text-xs">为您推荐优质的AI API服务</p>
+                            </div>
+                        </div>
+
+                        <!-- 302.ai 推荐卡片 -->
+                        <div
+                            class="bg-gradient-to-br from-blue-50 to-purple-50 border-3 border-blue-300 rounded-xl p-6 mb-6 shadow-lg hover:shadow-xl transition-all duration-300 transform"
+                        >
+                            <div class="flex items-start gap-6">
+                                <div class="flex-shrink-0">
+                                    <div
+                                        class="w-16 h-16 bg-gradient-to-br from-blue-500 to-purple-600 rounded-xl flex items-center justify-center border-2 border-white shadow-lg"
+                                    >
+                                        <span class="text-white text-xl font-bold">302</span>
+                                    </div>
+                                </div>
+                                <div class="flex-1">
+                                    <div class="flex items-center gap-3 mb-3">
+                                        <h3 class="text-xl font-bold text-gray-800">302.ai</h3>
+                                        <span class="bg-gradient-to-r from-orange-400 to-red-500 text-white text-xs px-3 py-1 rounded-full font-medium animate-pulse"
+                                            >官方合作伙伴</span
+                                        >
+                                    </div>
+                                    <p class="text-gray-700 text-sm mb-4 leading-relaxed">
+                                        <strong>302.ai</strong> 是本项目的官方API服务提供商,为"一饭封神"提供稳定可靠的AI大模型服务。
+                                        支持多种主流AI模型,包括GPT、Claude、DeepSeek等,提供高质量的文本生成和图像生成能力。
+                                    </p>
+
+                                    <div class="grid grid-cols-2 md:grid-cols-4 gap-3 mb-4">
+                                        <div class="bg-white rounded-lg p-3 border border-blue-200">
+                                            <div class="text-center">
+                                                <div class="text-blue-500 text-lg mb-1">🤖</div>
+                                                <div class="text-xs font-medium text-gray-700">多模型支持</div>
+                                            </div>
+                                        </div>
+                                        <div class="bg-white rounded-lg p-3 border border-green-200">
+                                            <div class="text-center">
+                                                <div class="text-green-500 text-lg mb-1">💰</div>
+                                                <div class="text-xs font-medium text-gray-700">价格优惠</div>
+                                            </div>
+                                        </div>
+                                        <div class="bg-white rounded-lg p-3 border border-purple-200">
+                                            <div class="text-center">
+                                                <div class="text-purple-500 text-lg mb-1">⚡</div>
+                                                <div class="text-xs font-medium text-gray-700">响应快速</div>
+                                            </div>
+                                        </div>
+                                        <div class="bg-white rounded-lg p-3 border border-orange-200">
+                                            <div class="text-center">
+                                                <div class="text-orange-500 text-lg mb-1">🛡️</div>
+                                                <div class="text-xs font-medium text-gray-700">服务稳定</div>
+                                            </div>
+                                        </div>
+                                    </div>
+
+                                    <div class="flex flex-wrap items-center gap-3">
+                                        <a
+                                            href="https://302.ai/"
+                                            target="_blank"
+                                            class="inline-flex items-center gap-2 bg-gradient-to-r from-blue-500 to-purple-600 hover:from-blue-600 hover:to-purple-700 text-white text-sm px-6 py-3 rounded-lg transition-all duration-300 transform hover:scale-105 shadow-lg"
+                                        >
+                                            <span class="font-medium">访问 302.ai</span>
+                                            <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
+                                                <path
+                                                    stroke-linecap="round"
+                                                    stroke-linejoin="round"
+                                                    stroke-width="2"
+                                                    d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
+                                                ></path>
+                                            </svg>
+                                        </a>
+                                        <div class="text-xs text-gray-500">
+                                            <span class="inline-flex items-center gap-1">
+                                                <div class="w-2 h-2 bg-green-400 rounded-full animate-pulse"></div>
+                                                正在为本项目提供AI服务
+                                            </span>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+
+                        <div class="bg-gradient-to-r from-gray-50 to-blue-50 border-2 border-gray-200 rounded-lg p-4">
+                            <div class="flex items-center gap-3">
+                                <div class="text-2xl">💡</div>
+                                <div>
+                                    <p class="text-sm font-medium text-gray-800">为什么选择 302.ai?</p>
+                                    <p class="text-xs text-gray-600">本项目经过多家API服务商对比测试,302.ai 在稳定性、响应速度和成本控制方面表现优异,是我们的首选合作伙伴。</p>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
             <!-- 关于作者 -->
             <!-- 关于作者 -->
             <div class="relative mt-6">
             <div class="relative mt-6">
                 <div class="bg-indigo-500 text-white px-4 py-2 rounded-t-lg border-2 border-[#0A0910] border-b-0 inline-block mb-0">
                 <div class="bg-indigo-500 text-white px-4 py-2 rounded-t-lg border-2 border-[#0A0910] border-b-0 inline-block mb-0">
@@ -101,6 +206,7 @@
                     </div>
                     </div>
                 </div>
                 </div>
             </div>
             </div>
+
             <!-- 项目简介 -->
             <!-- 项目简介 -->
             <div class="relative">
             <div class="relative">
                 <div class="bg-blue-500 text-white px-4 py-2 rounded-t-lg border-2 border-[#0A0910] border-b-0 inline-block mb-0">
                 <div class="bg-blue-500 text-white px-4 py-2 rounded-t-lg border-2 border-[#0A0910] border-b-0 inline-block mb-0">