2nd version

This commit is contained in:
2026-04-15 17:08:17 +08:00
parent e2a2eb4666
commit cedeb8f8bc
44 changed files with 5378 additions and 346 deletions

View File

@@ -0,0 +1,9 @@
# GEMINI_API_KEY: Required for Gemini AI API calls.
# AI Studio automatically injects this at runtime from user secrets.
# Users configure this via the Secrets panel in the AI Studio UI.
GEMINI_API_KEY="MY_GEMINI_API_KEY"
# APP_URL: The URL where this applet is hosted.
# AI Studio automatically injects this at runtime with the Cloud Run service URL.
# Used for self-referential links, OAuth callbacks, and API endpoints.
APP_URL="MY_APP_URL"

8
audi-red-note-mini-app2/.gitignore vendored Normal file
View File

@@ -0,0 +1,8 @@
node_modules/
build/
dist/
coverage/
.DS_Store
*.log
.env*
!.env.example

View File

@@ -0,0 +1,20 @@
<div align="center">
<img width="1200" height="475" alt="GHBanner" src="https://github.com/user-attachments/assets/0aa67016-6eaf-458a-adb2-6e31a0763ed6" />
</div>
# Run and deploy your AI Studio app
This contains everything you need to run your app locally.
View your app in AI Studio: https://ai.studio/apps/fa80108b-2bbe-4b49-8724-64574c59a597
## Run Locally
**Prerequisites:** Node.js
1. Install dependencies:
`npm install`
2. Set the `GEMINI_API_KEY` in [.env.local](.env.local) to your Gemini API key
3. Run the app:
`npm run dev`

View File

@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My Google AI Studio App</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

View File

@@ -0,0 +1,6 @@
{
"name": "Audi A7L Details Page",
"description": "A high-fidelity mobile replication of the Audi A7L details page, featuring pioneer design elements and feature showcases.",
"requestFramePermissions": [],
"majorCapabilities": []
}

3992
audi-red-note-mini-app2/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
{
"name": "react-example",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite --port=3000 --host=0.0.0.0",
"build": "vite build",
"preview": "vite preview",
"clean": "rm -rf dist",
"lint": "tsc --noEmit"
},
"dependencies": {
"@google/genai": "^1.29.0",
"@tailwindcss/vite": "^4.1.14",
"@vitejs/plugin-react": "^5.0.4",
"lucide-react": "^0.546.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"vite": "^6.2.0",
"express": "^4.21.2",
"dotenv": "^17.2.3",
"motion": "^12.23.24"
},
"devDependencies": {
"@types/node": "^22.14.0",
"autoprefixer": "^10.4.21",
"tailwindcss": "^4.1.14",
"tsx": "^4.21.0",
"typescript": "~5.8.2",
"vite": "^6.2.0",
"@types/express": "^4.17.21"
}
}

View File

@@ -0,0 +1,117 @@
/**
* @license
* SPDX-License-Identifier: Apache-2.0
*/
import { ChevronLeft, MoreHorizontal, X } from 'lucide-react';
import { motion } from 'motion/react';
export default function App() {
return (
<div className="min-h-screen bg-white font-sans text-[#1a1a1a] flex flex-col max-w-md mx-auto relative overflow-hidden shadow-2xl">
{/* Status Bar */}
<div className="px-8 pt-4 pb-2 flex justify-between items-center text-sm font-semibold">
<span>9:41</span>
<div className="flex items-center gap-1.5">
<svg viewBox="0 0 24 24" className="w-4 h-4 fill-current">
<path d="M12 21l-12-18h24z" />
</svg>
<svg viewBox="0 0 24 24" className="w-4 h-4 fill-current">
<path d="M12 2L1 21h22L12 2z" />
</svg>
<div className="w-6 h-3 border border-current rounded-sm relative">
<div className="absolute inset-0.5 bg-current rounded-px w-3"></div>
</div>
</div>
</div>
{/* Navigation Bar */}
<header className="px-4 py-2 flex items-center justify-between sticky top-0 bg-white z-10">
<button className="p-2 hover:bg-gray-100 rounded-full transition-colors">
<ChevronLeft className="w-6 h-6" />
</button>
<h1 className="text-[17px] font-medium">A7L详情</h1>
<div className="flex items-center bg-gray-50 border border-gray-200 rounded-full px-3 py-1.5 gap-3">
<MoreHorizontal className="w-5 h-5 text-gray-600" />
<div className="w-px h-4 bg-gray-300"></div>
<X className="w-5 h-5 text-gray-600" />
</div>
</header>
{/* Main Content */}
<main className="flex-1 overflow-y-auto pb-32">
{/* Hero Title */}
<section className="pt-8 pb-6 text-center">
<motion.h2
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="text-[32px] font-bold tracking-tight mb-2"
>
</motion.h2>
<div className="w-12 h-[3px] bg-[#d51c2a] mx-auto"></div>
</section>
{/* Feature Sections */}
<div className="space-y-4 px-0">
{/* Feature 1 */}
<motion.section
initial={{ opacity: 0 }}
whileInView={{ opacity: 1 }}
viewport={{ once: true }}
className="bg-[#f8f9fb] rounded-t-[32px] overflow-hidden"
>
<div className="aspect-[16/9] relative overflow-hidden">
<img
src="https://images.unsplash.com/photo-1614162692292-7ac56d7f7f1e?auto=format&fit=crop&q=80&w=1000"
alt="Audi A7L Front"
className="w-full h-full object-cover mix-blend-multiply"
referrerPolicy="no-referrer"
/>
</div>
<div className="px-6 py-6">
<h3 className="text-[22px] font-normal text-gray-700">RS竞速套件</h3>
<div className="mt-6 border-b border-dotted border-gray-300 w-full"></div>
</div>
</motion.section>
{/* Feature 2 */}
<motion.section
initial={{ opacity: 0 }}
whileInView={{ opacity: 1 }}
viewport={{ once: true }}
className="bg-[#f8f9fb] rounded-t-[32px] overflow-hidden"
>
<div className="aspect-[16/9] relative overflow-hidden">
<img
src="https://images.unsplash.com/photo-1603584173870-7f3ca99a4741?auto=format&fit=crop&q=80&w=1000"
alt="Audi A7L Side"
className="w-full h-full object-cover mix-blend-multiply"
referrerPolicy="no-referrer"
/>
</div>
<div className="px-6 py-6">
<h3 className="text-[22px] font-normal text-gray-700"> </h3>
<div className="mt-6 border-b border-dotted border-gray-300 w-full"></div>
{/* Specs Preview */}
<div className="mt-4 flex justify-between text-sm text-gray-500 font-medium">
<span></span>
<span></span>
</div>
</div>
</motion.section>
</div>
</main>
{/* Footer Action */}
<footer className="fixed bottom-0 left-0 right-0 max-w-md mx-auto bg-white/80 backdrop-blur-md px-4 pt-2 pb-8 border-t border-gray-100">
<button className="w-full bg-[#1c1f23] text-white py-4 rounded-md text-[16px] font-medium active:scale-[0.98] transition-transform">
</button>
{/* Home Indicator */}
<div className="mt-6 w-32 h-1.5 bg-black/80 mx-auto rounded-full"></div>
</footer>
</div>
);
}

View File

@@ -0,0 +1 @@
@import "tailwindcss";

View File

@@ -0,0 +1,10 @@
import {StrictMode} from 'react';
import {createRoot} from 'react-dom/client';
import App from './App.tsx';
import './index.css';
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
</StrictMode>,
);

View File

@@ -0,0 +1,26 @@
{
"compilerOptions": {
"target": "ES2022",
"experimentalDecorators": true,
"useDefineForClassFields": false,
"module": "ESNext",
"lib": [
"ES2022",
"DOM",
"DOM.Iterable"
],
"skipLibCheck": true,
"moduleResolution": "bundler",
"isolatedModules": true,
"moduleDetection": "force",
"allowJs": true,
"jsx": "react-jsx",
"paths": {
"@/*": [
"./*"
]
},
"allowImportingTsExtensions": true,
"noEmit": true
}
}

View File

@@ -0,0 +1,24 @@
import tailwindcss from '@tailwindcss/vite';
import react from '@vitejs/plugin-react';
import path from 'path';
import {defineConfig, loadEnv} from 'vite';
export default defineConfig(({mode}) => {
const env = loadEnv(mode, '.', '');
return {
plugins: [react(), tailwindcss()],
define: {
'process.env.GEMINI_API_KEY': JSON.stringify(env.GEMINI_API_KEY),
},
resolve: {
alias: {
'@': path.resolve(__dirname, '.'),
},
},
server: {
// HMR is disabled in AI Studio via DISABLE_HMR env var.
// Do not modify—file watching is disabled to prevent flickering during agent edits.
hmr: process.env.DISABLE_HMR !== 'true',
},
};
});