@ -0,0 +1,53 @@
|
|||||||
|
{
|
||||||
|
"extends": [
|
||||||
|
"next/core-web-vitals",
|
||||||
|
"plugin:@typescript-eslint/recommended",
|
||||||
|
"plugin:prettier/recommended",
|
||||||
|
"eslint-config-prettier"
|
||||||
|
],
|
||||||
|
"plugins": ["prettier"],
|
||||||
|
"rules": {
|
||||||
|
"@typescript-eslint/no-explicit-any": ["off"], // 允许使用any
|
||||||
|
"@typescript-eslint/ban-ts-comment": "off", // 允许使用@ts-ignore
|
||||||
|
"@typescript-eslint/no-non-null-assertion": "off", // 允许使用非空断言
|
||||||
|
"@typescript-eslint/no-var-requires": "off", // 允许使用CommonJS的写法
|
||||||
|
"no-console": ["warn", { "allow": ["warn", "error"] }], // 提交时不允许有console.log
|
||||||
|
"no-debugger": "warn",
|
||||||
|
"import/order": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"groups": ["builtin", "external", "parent", "sibling", "index", "internal", "object", "type"], // 按照分组顺序进行排序
|
||||||
|
// 通过路径自定义分组
|
||||||
|
"pathGroups": [
|
||||||
|
{
|
||||||
|
"pattern": "react*",
|
||||||
|
"group": "builtin",
|
||||||
|
"position": "before"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pattern": "@/components/**",
|
||||||
|
"group": "parent",
|
||||||
|
"position": "before"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pattern": "@/utils/**",
|
||||||
|
"group": "parent",
|
||||||
|
"position": "after"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pattern": "@/apis/**",
|
||||||
|
"group": "parent",
|
||||||
|
"position": "after"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"pathGroupsExcludedImportTypes": ["react"],
|
||||||
|
"newlines-between": "always", // 每个分组之间换行
|
||||||
|
// 根据字母顺序对每个组内的顺序进行排序
|
||||||
|
"alphabetize": {
|
||||||
|
"order": "asc",
|
||||||
|
"caseInsensitive": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
.yarn/install-state.gz
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env*.local
|
||||||
|
|
||||||
|
# vercel
|
||||||
|
.vercel
|
||||||
|
|
||||||
|
# typescript
|
||||||
|
*.tsbuildinfo
|
||||||
|
next-env.d.ts
|
@ -0,0 +1,3 @@
|
|||||||
|
/.next/
|
||||||
|
/node_modules
|
||||||
|
.env*.local
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"endOfLine": "auto",
|
||||||
|
"printWidth": 120,
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"trailingComma": "all",
|
||||||
|
"bracketSpacing": true
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
First, run the development server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
# or
|
||||||
|
yarn dev
|
||||||
|
# or
|
||||||
|
pnpm dev
|
||||||
|
# or
|
||||||
|
bun dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Open [http://localhost:3001](http://localhost:3001) with your browser to see the result.
|
||||||
|
|
||||||
|
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
||||||
|
|
||||||
|
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
|
||||||
|
|
||||||
|
## Learn More
|
||||||
|
|
||||||
|
To learn more about Next.js, take a look at the following resources:
|
||||||
|
|
||||||
|
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||||
|
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||||
|
|
||||||
|
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
|
||||||
|
|
||||||
|
## Deploy on Vercel
|
||||||
|
|
||||||
|
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||||
|
|
||||||
|
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
|
@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: ['@commitlint/config-conventional'],
|
||||||
|
};
|
@ -0,0 +1,6 @@
|
|||||||
|
/** @type {import('next').NextConfig} */
|
||||||
|
const nextConfig = {
|
||||||
|
output: 'export',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default nextConfig;
|
@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"name": "queyue-h5",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev -p 3001",
|
||||||
|
"build": "next build",
|
||||||
|
"start": "next start -p 3001",
|
||||||
|
"lint": "eslint src --fix --ext .ts,.tsx,.js,.jsx --max-warnings 0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"lib-flexible": "^0.3.2",
|
||||||
|
"next": "14.1.3",
|
||||||
|
"react": "^18",
|
||||||
|
"react-dom": "^18"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@commitlint/cli": "^19.1.0",
|
||||||
|
"@commitlint/config-conventional": "^19.1.0",
|
||||||
|
"@types/node": "^20",
|
||||||
|
"@types/react": "^18",
|
||||||
|
"@types/react-dom": "^18",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
||||||
|
"autoprefixer": "^10.0.1",
|
||||||
|
"eslint": "^8",
|
||||||
|
"eslint-config-next": "14.1.3",
|
||||||
|
"eslint-config-prettier": "^9.1.0",
|
||||||
|
"eslint-plugin-import": "^2.29.1",
|
||||||
|
"eslint-plugin-prettier": "^5.1.3",
|
||||||
|
"husky": "^9.0.11",
|
||||||
|
"lint-staged": "^15.2.2",
|
||||||
|
"postcss": "^8",
|
||||||
|
"postcss-flexbugs-fixes": "^5.0.2",
|
||||||
|
"postcss-preset-env": "^9.5.1",
|
||||||
|
"postcss-pxtorem": "^6.1.0",
|
||||||
|
"prettier": "^3.2.5",
|
||||||
|
"tailwindcss": "^3.3.0",
|
||||||
|
"typescript": "^5.2.2"
|
||||||
|
},
|
||||||
|
"lint-staged": {
|
||||||
|
"src/**/*.{js,jsx,ts,tsx,json}": [
|
||||||
|
"npm run lint",
|
||||||
|
"prettier --write"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"browserslist": [
|
||||||
|
"iOS >= 7",
|
||||||
|
"Android >= 4"
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
module.exports = {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
'postcss-flexbugs-fixes': {},
|
||||||
|
'postcss-preset-env': {
|
||||||
|
autoprefixer: {
|
||||||
|
flexbox: 'no-2009',
|
||||||
|
},
|
||||||
|
stage: 3,
|
||||||
|
features: {
|
||||||
|
'custom-properties': false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'postcss-pxtorem': {
|
||||||
|
rootValue: 37.5,
|
||||||
|
unitPrecision: 5,
|
||||||
|
propList: ['*'],
|
||||||
|
selectorBlackList: [],
|
||||||
|
replace: true,
|
||||||
|
mediaQuery: false,
|
||||||
|
minPixelValue: 0,
|
||||||
|
exclude: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 167 KiB |
After Width: | Height: | Size: 199 KiB |
After Width: | Height: | Size: 160 KiB |
After Width: | Height: | Size: 248 KiB |
After Width: | Height: | Size: 151 KiB |
After Width: | Height: | Size: 199 KiB |
After Width: | Height: | Size: 72 KiB |
After Width: | Height: | Size: 258 KiB |
After Width: | Height: | Size: 253 KiB |
After Width: | Height: | Size: 237 KiB |
After Width: | Height: | Size: 208 KiB |
After Width: | Height: | Size: 286 KiB |
After Width: | Height: | Size: 253 KiB |
After Width: | Height: | Size: 237 KiB |
After Width: | Height: | Size: 243 KiB |
After Width: | Height: | Size: 898 B |
After Width: | Height: | Size: 276 B |
After Width: | Height: | Size: 276 B |
After Width: | Height: | Size: 506 B |
After Width: | Height: | Size: 514 B |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 507 KiB |
After Width: | Height: | Size: 11 MiB |
After Width: | Height: | Size: 7.8 MiB |
After Width: | Height: | Size: 104 KiB |
After Width: | Height: | Size: 7.3 KiB |
After Width: | Height: | Size: 716 B |
After Width: | Height: | Size: 233 KiB |
After Width: | Height: | Size: 5.0 MiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 405 B |
After Width: | Height: | Size: 49 KiB |
After Width: | Height: | Size: 5.0 MiB |
After Width: | Height: | Size: 3.7 MiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 211 B |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 792 B |
After Width: | Height: | Size: 921 B |
After Width: | Height: | Size: 391 B |
After Width: | Height: | Size: 355 B |
After Width: | Height: | Size: 276 B |
After Width: | Height: | Size: 438 B |
After Width: | Height: | Size: 619 B |
After Width: | Height: | Size: 312 B |
After Width: | Height: | Size: 236 B |
After Width: | Height: | Size: 312 B |
After Width: | Height: | Size: 747 B |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 411 B |
After Width: | Height: | Size: 211 B |
After Width: | Height: | Size: 771 B |
@ -0,0 +1,54 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import Image from 'next/image';
|
||||||
|
|
||||||
|
import { download } from '@/utils/download';
|
||||||
|
|
||||||
|
import useUA from '@/hooks/useUA';
|
||||||
|
|
||||||
|
export default function Download() {
|
||||||
|
const { inWX } = useUA();
|
||||||
|
|
||||||
|
const handleDownload = () => {
|
||||||
|
download();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className="relative max-w-screen-sm min-h-screen mx-auto flex flex-col items-center text-white font-normal bg-gradient-to-b from-[#030303] to-[#1f1f20]">
|
||||||
|
{inWX && (
|
||||||
|
<div className="absolute top-[4px] left-1/2 translate-x-[-50%] w-[339px] h-[87px] flex justify-between bg-gradient-to-r from-[#1c1c1c] to-[#1e1e1e] rounded-[6px] px-[18px] py-[19px] box-border">
|
||||||
|
<div>
|
||||||
|
<h5 className="font-medium text-[17px] leading-[23.8px] mb-[5px]">下载【雀乐】APP</h5>
|
||||||
|
<p className="text-[14px] leading-[19.6px] text-[#ffffffb2] flex items-center">
|
||||||
|
点击右上角
|
||||||
|
<Image
|
||||||
|
unoptimized
|
||||||
|
className="w-[24px] h-[24px]"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
src="/img/icon_dot.png"
|
||||||
|
alt="dot"
|
||||||
|
/>
|
||||||
|
选择在浏览器中打开
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Image className="w-[37px] h-[35px] mr-[3px]" width={37} height={35} src="/img/vector-2.svg" alt="arrow" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="flex flex-col items-center mt-[151px]">
|
||||||
|
<Image className="w-[90px] h-[90px]" width={90} height={90} src="/img/app_icon_white_bg.svg" alt="queyue" />
|
||||||
|
<p className="text-[20px] leading-[24px] font-['Fontquan-XinYiJiXiangSong-Regular'] mt-[20px] tracking-[3px]">
|
||||||
|
独立 不独于世
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
className="w-[283px] h-[48px] flex items-center justify-center bg-[#B44343] font-medium text-[17px] rounded-full mt-[44px]"
|
||||||
|
onClick={handleDownload}
|
||||||
|
>
|
||||||
|
下载【雀乐】APP
|
||||||
|
</button>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
After Width: | Height: | Size: 25 KiB |
@ -0,0 +1,51 @@
|
|||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'PingFang SC-Regular';
|
||||||
|
src: url('/fonts/ping-fang-hei-ti-zhun-jian.ttf') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'PingFang SC-Medium';
|
||||||
|
src: url('/fonts/pingfang-sc-medium.otf') format('opentype');
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'PingFang SC-Semibold';
|
||||||
|
src: url('/fonts/pingfangsc-semibold.otf') format('opentype');
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Abhaya Libre SemiBold-Regular';
|
||||||
|
src: url('/fonts/ping-fang-hei-ti-zhun-jian.ttf') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Fontquan-XinYiJiXiangSong-Regular';
|
||||||
|
src: url('/fonts/Fontquan-XinYiJiXiangSong.ttf') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--body-bg-color: #1a1a1a;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: var(--body-bg-color);
|
||||||
|
font-family: 'PingFang SC-Regular', Helvetica;
|
||||||
|
|
||||||
|
/* padding-bottom: constant(safe-area-inset-bottom);
|
||||||
|
padding-bottom: env(safe-area-inset-bottom); */
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer utilities {
|
||||||
|
.text-balance {
|
||||||
|
text-wrap: balance;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
|
import './globals.css';
|
||||||
|
|
||||||
|
export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) {
|
||||||
|
const [loaded, setLoaded] = useState(false);
|
||||||
|
|
||||||
|
const setRem = async () => {
|
||||||
|
await import('lib-flexible');
|
||||||
|
setLoaded(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setRem();
|
||||||
|
window.addEventListener('resize', setRem);
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('resize', setRem);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<html lang="zn-ch">
|
||||||
|
<head>
|
||||||
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover"
|
||||||
|
/>
|
||||||
|
<meta httpEquiv="X-UA-Compatible" content="ie=edge" />
|
||||||
|
<title>雀乐</title>
|
||||||
|
<meta name="description" content="独立 不独于世" />
|
||||||
|
</head>
|
||||||
|
<body>{loaded ? children : null}</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,176 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useRef } from 'react';
|
||||||
|
|
||||||
|
import Image from 'next/image';
|
||||||
|
import Link from 'next/link';
|
||||||
|
|
||||||
|
import { download } from '@/utils/download';
|
||||||
|
|
||||||
|
import useUA from '@/hooks/useUA';
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
const firstScreenRef = useRef<HTMLDivElement>(null);
|
||||||
|
const { inWX } = useUA();
|
||||||
|
|
||||||
|
const handleShare = () => {
|
||||||
|
alert('正在开发中,敬请期待');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDownload = () => {
|
||||||
|
download();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSlideDown = () => {
|
||||||
|
window.scrollTo({ top: firstScreenRef?.current?.offsetHeight, behavior: 'smooth' });
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className="max-w-screen-sm min-h-screen mx-auto flex flex-col items-center text-white font-normal">
|
||||||
|
{/* 首屏 */}
|
||||||
|
<div
|
||||||
|
ref={firstScreenRef}
|
||||||
|
className="relative w-full min-h-screen flex flex-col items-center bg-[url('/img/index_background.svg')] bg-center bg-cover"
|
||||||
|
>
|
||||||
|
{/* title */}
|
||||||
|
{!inWX && <h1 className="text-center text-[17px] h-[44px] leading-[44px]">雀乐</h1>}
|
||||||
|
|
||||||
|
{/* App logo */}
|
||||||
|
<div className="flex flex-col items-center absolute top-[25%]">
|
||||||
|
<Image className="w-[90px] h-[90px]" width={90} height={90} src="/img/app_icon_white_bg.svg" alt="queyue" />
|
||||||
|
<p className="text-[20px] font-['Fontquan-XinYiJiXiangSong-Regular'] mt-3 tracking-[3px]">独立 不独于世</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-full flex flex-col items-center absolute bottom-0">
|
||||||
|
<button
|
||||||
|
className="w-[283px] h-[48px] flex items-center justify-center bg-[#000000f2] font-medium text-[17px] rounded-full mb-[16px]"
|
||||||
|
onClick={handleShare}
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
className="w-[24px] h-[24px] mr-[6px]"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
src="/img/index_weChatIcon.svg"
|
||||||
|
alt="wx-share"
|
||||||
|
/>
|
||||||
|
<span>分享给好友</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="w-[283px] h-[48px] flex items-center justify-center bg-[#B44343] font-medium text-[17px] rounded-full mb-[16px]"
|
||||||
|
onClick={handleDownload}
|
||||||
|
>
|
||||||
|
下载【雀乐】APP
|
||||||
|
</button>
|
||||||
|
<button className="w-[283px] h-[48px] flex justify-center" onClick={handleSlideDown}>
|
||||||
|
<Image
|
||||||
|
className="w-[36px] h-[36px] animate-bounce"
|
||||||
|
width={36}
|
||||||
|
height={36}
|
||||||
|
src="/img/index_Dropdown.svg"
|
||||||
|
alt="download"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 第二屏 */}
|
||||||
|
<div className="relative w-full min-h-screen flex flex-col items-center bg-black">
|
||||||
|
<div className="w-[75.5%]">
|
||||||
|
<Image
|
||||||
|
className="w-[165.24px] h-[46.44px] mt-[51.58px]"
|
||||||
|
width={165.24}
|
||||||
|
height={46.44}
|
||||||
|
src="/img/handwritten_white.svg"
|
||||||
|
alt="we are back"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<p className="text-[#ffffffb2] text-[14px] leading-[26px] mt-[19.98px]">
|
||||||
|
音乐是一种态度
|
||||||
|
<br />
|
||||||
|
不论是创作者还是聆听者
|
||||||
|
<br />
|
||||||
|
它流经心灵
|
||||||
|
<br />
|
||||||
|
纵然期待影响现实的力量是种奢望
|
||||||
|
<br />
|
||||||
|
如果刚巧有些声音
|
||||||
|
<br />
|
||||||
|
会叫你记得一段往事
|
||||||
|
<br />
|
||||||
|
伤痛或是甜蜜
|
||||||
|
<br />
|
||||||
|
那记忆便有了厚厚的壳
|
||||||
|
<br />
|
||||||
|
恒久的 温暖有如初生
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<Image
|
||||||
|
className="w-[299px] h-[451.61px] mt-[26px] ml-auto mr-auto"
|
||||||
|
width={299}
|
||||||
|
height={451.61}
|
||||||
|
src="/img/index_mockup.svg"
|
||||||
|
alt="app preview"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<h5 className="text-[#ffffffb2] text-center text-[15px] leading-[21px] mt-[100px] mb-[4px]">合作联系</h5>
|
||||||
|
<p className="text-center text-[20px] font-medium leading-[33.6px]">rock@indie.cn</p>
|
||||||
|
|
||||||
|
<h5 className="text-[#ffffffb2] text-center text-[15px] leading-[21px] mt-[47px] mb-[4px]">Weibo</h5>
|
||||||
|
<p className="text-center text-[20px] font-medium leading-[33.6px] flex items-center justify-center">
|
||||||
|
<Link
|
||||||
|
className="relative"
|
||||||
|
href="https://weibo.com/1886232237?refer_flag=1001030103_"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
官方微博
|
||||||
|
<Image
|
||||||
|
className="w-[24px] h-[24px] absolute top-[50%] right-[-24px] translate-y-[-50%]"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
src="/img/icon.svg"
|
||||||
|
alt="arrow-right"
|
||||||
|
/>
|
||||||
|
</Link>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* <h5 className="text-[#ffffffb2] text-center text-[15px] leading-[21px] mt-[47px] mb-[4px]">贡献者</h5>
|
||||||
|
<p className="text-center text-[20px] font-medium leading-[33.6px] flex items-center justify-center">
|
||||||
|
<span className="relative">
|
||||||
|
加入我们
|
||||||
|
<Image
|
||||||
|
className="w-[24px] h-[24px] absolute top-[50%] right-[-24px] translate-y-[-50%]"
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
src="/img/icon.svg"
|
||||||
|
alt="arrow-right"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</p> */}
|
||||||
|
|
||||||
|
<Link
|
||||||
|
className="block w-[fit-content] mt-[68px] ml-auto mr-auto"
|
||||||
|
href="http://weixin.qq.com/r/thLfx-3EHaBirbmk90ek"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
className="w-[97.5px] h-[97.5px] mb-[10.5px] rounded-sm"
|
||||||
|
width={97.5}
|
||||||
|
height={97.5}
|
||||||
|
src="/img/index_QRCode.svg"
|
||||||
|
alt="arrow-right"
|
||||||
|
/>
|
||||||
|
<h5 className="text-[#ffffffb2] text-center text-[12px] leading-[18.8px]">雀乐公众号</h5>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<p className="text-[#ffffff33] text-center text-[9px] leading-[12.6px] mt-[53px] mb-[52px]">
|
||||||
|
粤ICP备2024190175号-1 深圳雀乐文化科技有限责任公司
|
||||||
|
<br />
|
||||||
|
Shenzhen QueYue Culture Technology Co., Ltd.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
|
import { Hosting } from '@/utils/ua';
|
||||||
|
|
||||||
|
export default function useUA() {
|
||||||
|
const [inWX, setInWX] = useState(true);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setInWX(Hosting.isWX(window?.navigator?.userAgent?.toLowerCase()));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return { inWX };
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
declare module 'lib-flexible';
|
@ -0,0 +1,9 @@
|
|||||||
|
import { Hosting } from '@/utils/ua';
|
||||||
|
|
||||||
|
// 下载
|
||||||
|
export const download = () => {
|
||||||
|
const ua = window?.navigator?.userAgent?.toLowerCase();
|
||||||
|
if (!Hosting.isWX(ua)) {
|
||||||
|
window.open('//cdn.indie.cn/release/queyue.apk', '__blank');
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,8 @@
|
|||||||
|
// 判断 H5 宿主环境
|
||||||
|
export const Hosting = {
|
||||||
|
isAndroid: (ua: any) => ua.indexOf('android') > -1 || ua.indexOf('linux') > -1,
|
||||||
|
isIPhone: (ua: any) => ua.indexOf('iphone') > -1,
|
||||||
|
isIPad: (ua: any) => ua.indexOf('ipad') > -1,
|
||||||
|
isIPod: (ua: any) => ua.indexOf('ipod') > -1,
|
||||||
|
isWX: (ua: any) => ua.indexOf('micromessenger') > -1,
|
||||||
|
};
|
@ -0,0 +1,20 @@
|
|||||||
|
import type { Config } from 'tailwindcss';
|
||||||
|
|
||||||
|
const config: Config = {
|
||||||
|
content: [
|
||||||
|
'./src/pages/**/*.{js,ts,jsx,tsx,mdx}',
|
||||||
|
'./src/components/**/*.{js,ts,jsx,tsx,mdx}',
|
||||||
|
'./src/app/**/*.{js,ts,jsx,tsx,mdx}',
|
||||||
|
'./src/modules/**/*.{js,ts,jsx,tsx,mdx}',
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
backgroundImage: {
|
||||||
|
'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
|
||||||
|
'gradient-conic': 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
};
|
||||||
|
export default config;
|
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"incremental": true,
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "next"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|