Commit dd531da0 by HoMeTown

feat: 首页样式

parent 5559551b
......@@ -41,9 +41,13 @@
"dependencies": {
"@nextui-org/react": "^2.4.6",
"@reactuses/core": "^5.0.19",
"@virtuoso.dev/message-list": "^1.8.3",
"clsx": "^2.1.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.26.0"
"react-router-dom": "^6.26.0",
"react-virtuoso": "^4.9.0",
"tailwind-merge": "^2.4.0"
},
"devDependencies": {
"@antfu/eslint-config": "^2.24.1",
......
......@@ -22,19 +22,15 @@ export default defineConfig({
title: '晓得. - 晓得解惑,让沟通更智能。',
favicon: './src/assets/logo.png',
appIcon: './src/assets/logo.png',
meta: [
{ description: '晓得 是一个智能助手,知晓市场脉搏,引领行业潮流,晓得AI助手全方位为您保驾护航| 晓得. - 晓得解惑,让沟通更智能。' },
{ name: 'viewport', content: 'width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' },
{ 'http-equiv': 'X-UA-Compatible', 'content': 'ie=edge' },
{ 'http-equiv': 'Cache-Control', 'content': 'no-cache' },
{ 'http-equiv': 'Pragma', 'content': 'no-cache' },
{ 'http-equiv': 'Expires', 'content': '0' },
{ name: 'keywords', content: '晓得,sdream,ai,众耳,insurebank,保险,智能,条款解析,人工智能大模型,AI聊天机器人,AI聊天,国内大模型公司,AI聊天,AI助手,context' },
{ name: 'apple-mobile-web-app-capable', content: 'yes' },
{ name: 'apple-mobile-web-app-status-bar-style', content: 'black' },
{ name: 'format-detection', content: 'telephone=no,email=no' },
{ name: 'apple-mobile-web-app-title', content: '晓得' },
],
meta: {
'viewport': 'viewport-fit=cover, width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0',
'keywords': '晓得,sdream,ai,众耳,insurebank,保险,智能,条款解析,人工智能大模型,AI聊天机器人,AI聊天,国内大模型公司,AI聊天,AI助手,context',
'description': '晓得 是一个智能助手,知晓市场脉搏,引领行业潮流,晓得AI助手全方位为您保驾护航| 晓得. - 晓得解惑,让沟通更智能。',
'apple-mobile-web-app-capable': 'yes',
'apple-mobile-web-app-status-bar-style': 'black',
'format-detection': 'telephone=no,email=no',
'apple-mobile-web-app-title': '晓得',
},
},
tools: {
// 与底层工具有关的选项
......@@ -58,7 +54,7 @@ export default defineConfig({
media: 'assets',
},
cssModules: {
localIdentName: isProd ? '[hash:base64]' : '[path][name]__[local]',
localIdentName: isProd ? '[hash:base64]' : '[local]',
},
},
source: {
......
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
<?xml version="1.0" encoding="UTF-8"?>
<svg width="110px" height="44px" viewBox="0 0 110 44" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组</title>
<defs>
<linearGradient x1="50%" y1="30.4450141%" x2="100%" y2="94.5009232%" id="linearGradient-1">
<stop stop-color="#B4F4FF" offset="0%"></stop>
<stop stop-color="#E6F6FE" stop-opacity="0" offset="100%"></stop>
</linearGradient>
<filter x="-83.3%" y="-83.3%" width="266.7%" height="266.7%" filterUnits="objectBoundingBox" id="filter-2">
<feGaussianBlur stdDeviation="20" in="SourceGraphic"></feGaussianBlur>
</filter>
</defs>
<g id="晓得---PC端页面-草稿" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="晓得-PC端---默认页" transform="translate(-944.000000, -208.000000)">
<g id="编组-4" transform="translate(751.000000, 160.000000)">
<circle id="椭圆形备份-2" fill="url(#linearGradient-1)" style="mix-blend-mode: multiply;" filter="url(#filter-2)" cx="181" cy="36" r="36"></circle>
<g id="编组" transform="translate(193.000000, 48.000000)" fill="#29B6FD" fill-rule="nonzero">
<path d="M108.428571,37.7142857 C109.296447,37.7142857 110,38.4178383 110,39.2857143 L110,42.4285714 C110,43.2964475 109.296447,44 108.428571,44 L105.285714,44 C104.417838,44 103.714286,43.2964475 103.714286,42.4285714 L103.714286,39.2857143 C103.714286,38.4178383 104.417838,37.7142857 105.285714,37.7142857 L108.428571,37.7142857 Z M69.3172289,12.8333331 C68.2893065,16.417293 66.6680662,19.6803452 64.4535095,22.6224888 L64.116876,23.0614034 L64.116876,44 L61.6362271,44 C59.5436815,44 57.8363325,42.3833077 57.7430944,40.3545968 L57.7390837,40.1797268 L57.7390837,28.9956144 C56.2563841,30.0248539 54.6573935,30.9778534 52.9421125,31.8546134 L52.2934315,32.1798246 L52.2934315,24.6052635 C57.0986526,21.8826458 60.4950769,18.0943254 62.4827034,13.2403022 L62.6450773,12.8333331 L69.3172289,12.8333331 Z M94.1063223,20.4078949 C95.1376484,20.4078949 95.9818398,21.1933103 96.0503984,22.1872517 L96.0548936,22.3180315 L96.0548936,25.425439 L93.3075371,25.425439 L93.3075371,27.5482458 L95.4800001,27.5482458 C96.5113262,27.5482458 97.3555176,28.3336612 97.4240763,29.3276025 L97.4285714,29.4583824 L97.4285714,32.5657898 L93.3075371,32.5657898 L93.3075371,39.9384988 C93.3075371,41.9897691 91.6583146,43.6634414 89.5887831,43.7548404 L89.4103945,43.758772 L82.5143512,43.758772 L82.5143512,38.4517542 L87.0278656,38.4517542 L87.0278656,32.5657898 L68.5813296,32.5657898 L68.5813296,27.5482458 L87.0278656,27.5482458 L87.0278656,25.425439 L69.5625281,25.425439 L69.5625281,20.4078949 L94.1063223,20.4078949 Z M43.7614624,23.7850881 L43.7614624,29.574561 L39.542308,29.574561 L39.542308,37.7763161 L44.2520618,37.7763161 L44.2520618,43.758772 L37.1597791,43.758772 C35.0672336,43.758772 33.3598846,42.1420797 33.2666464,40.1133688 L33.2626362,39.9384988 L33.2626362,29.574561 L28.5528824,29.574561 C27.9859676,34.40627 26.4636964,38.9695506 23.9860687,43.2644036 L23.6959488,43.758772 L15.4538797,43.758772 C18.9988557,39.4322301 21.2114025,34.8647103 22.0915205,30.0562141 L22.1750908,29.574561 L17.3672171,29.574561 L17.3672171,23.7850881 L43.7614624,23.7850881 Z M77.0686983,33.8684212 L80.5028941,42.6973686 L74.3213418,42.6973686 L70.8871468,33.8684212 L77.0686983,33.8684212 Z M12.0473361,1.78508812 C14.1398817,1.78508812 15.8472306,3.40178044 15.9404688,5.43049055 L15.944479,5.60536133 L15.944479,40.5263161 L3.89714283,40.5263161 C1.80459733,40.5263161 0.0972483192,38.909623 0.00401019899,36.8809128 L0,36.7060421 L0,5.60536133 C0,3.55409026 1.64922266,1.88041793 3.71875382,1.78901889 L3.89714283,1.78508812 L12.0473361,1.78508812 Z M10.2535265,23.7368424 L5.69095252,23.7368424 L5.69095252,34.5921051 L10.2535265,34.5921051 L10.2535265,23.7368424 Z M31.4474186,0.337719483 L31.8398981,2.99122797 L38.6378211,2.99122797 C40.7303667,2.99122797 42.4377157,4.6079203 42.5309537,6.63663122 L42.534964,6.81150118 L42.534964,8.7807017 L33.0663964,8.7807017 C33.2745295,9.59941506 33.6042988,10.5776187 34.0557043,11.7153109 L34.194775,12.0614034 L42.534964,9.98684236 L42.534964,15.5833331 L36.6968317,16.9824559 C37.5662828,18.456628 38.6830777,19.9983653 40.0472165,21.6076694 L40.4253868,22.0482458 L32.2323776,22.0482458 C31.6156241,21.1660401 30.9868559,20.2011282 30.3460731,19.1535085 L30.0246805,18.6228068 L17.5634568,21.6622805 L17.5634568,15.7280703 L27.5226238,13.3157898 C27.0592799,12.056043 26.6527184,10.7962962 26.3029393,9.53654945 L26.0998856,8.7807017 L17.465337,8.7807017 L17.465337,2.99122797 L24.8733872,2.99122797 L24.4809077,0.337719483 L31.4474186,0.337719483 Z M68.0907303,0 C65.8085971,8.40804605 60.6834967,14.703726 52.7154283,18.887039 L52.2934315,19.1052635 L52.2934315,11.5789475 C56.7415318,8.7669172 59.8470327,5.0443248 61.6099327,0.41117107 L61.7619988,0 L68.0907303,0 Z M91.0784324,0.771929668 C93.170978,0.771929668 94.878327,2.38862199 94.9715651,4.41733292 L94.975575,4.59220369 L94.975575,14.8507793 C94.975575,16.9020504 93.3263525,18.5757227 91.256821,18.6671218 L91.0784324,18.6710525 L70.6418467,18.6710525 L70.6418467,0.771929668 L91.0784324,0.771929668 Z M10.2535265,7.7192983 L5.69095252,7.7192983 L5.69095252,17.9473686 L10.2535265,17.9473686 L10.2535265,7.7192983 Z M88.5977835,11.7719297 L77.0196382,11.7719297 L77.0196382,13.991228 L88.5977835,13.991228 L88.5977835,11.7719297 Z M88.5977835,5.5 L77.0196382,5.5 L77.0196382,7.67105255 L88.5977835,7.67105255 L88.5977835,5.5 Z" id="形状结合"></path>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
'use client'
import { motion } from 'framer-motion'
import { cn } from '@/lib/utils'
interface BlurIntProps {
children: React.ReactNode
className?: string
variant?: {
hidden: { filter: string, opacity: number }
visible: { filter: string, opacity: number }
}
duration?: number
}
function BlurIn({ children, className, variant, duration = 1 }: BlurIntProps) {
const defaultVariants = {
hidden: { filter: 'blur(10px)', opacity: 0 },
visible: { filter: 'blur(0px)', opacity: 1 },
}
const combinedVariants = variant || defaultVariants
return (
<motion.h1
initial="hidden"
animate="visible"
transition={{ duration }}
variants={combinedVariants}
className={cn(
className,
'font-display text-center text-4xl font-bold tracking-[-0.02em] drop-shadow-sm md:text-7xl md:leading-[5rem]',
)}
>
{children}
</motion.h1>
)
}
export default BlurIn
.gradientBackground {
position: fixed;
top: 0px;
left: 0;
right: 0;
height: 100vh;
// background: linear-gradient( 180deg, #FFFFFF 0%, #E6F6FE 100%), radial-gradient( 159% 92% at -4% -5%, rgba(182,180,255,0.8) 0%, rgba(193,227,255,0) 100%), radial-gradient( 107% 70% at 103% -14%, rgba(205,232,255,0.8) 0%, rgba(193,227,255,0) 100%);
z-index: -1;
img {
width: 100%;
}
}
// This file is automatically generated.
// Please do not change this file!
interface CssExports {
gradientBackground: string
}
declare const cssExports: CssExports
export default cssExports
import React from 'react'
import { motion } from 'framer-motion'
import styles from './GradientBackground.module.less'
import Bg from '@/assets/bg.png'
export const GradientBackground: React.FC = () => {
return (
<motion.div
className={styles.gradientBackground}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 2, ease: 'easeOut' }}
>
<motion.img src={Bg} alt="" />
</motion.div>
)
}
export { GradientBackground } from './GradientBackground'
'use client'
import type { Variants } from 'framer-motion'
import { AnimatePresence, motion } from 'framer-motion'
import { cn } from '@/lib/utils'
interface GradualSpacingProps {
text: string
duration?: number
delayMultiple?: number
framerProps?: Variants
className?: string
}
export default function GradualSpacing({
text,
duration = 0.5,
delayMultiple = 0.04,
// eslint-disable-next-line react/no-unstable-default-props
framerProps = {
hidden: { opacity: 0, x: -20 },
visible: { opacity: 1, x: 0 },
},
className,
}: GradualSpacingProps) {
return (
<motion.div
className="flex justify-center space-x-1"
>
<AnimatePresence>
{text.split('').map((char, i) => (
<motion.h1
key={i}
initial="hidden"
animate="visible"
exit="hidden"
variants={framerProps}
transition={{ duration, delay: i * delayMultiple }}
className={cn('drop-shadow-sm ', className)}
>
{char === ' ' ? <span>&nbsp;</span> : char}
</motion.h1>
))}
</AnimatePresence>
</motion.div>
)
}
.layoutNav {
height: 100%;
position: relative;
transition: width .2s ease;
}
.collapsed {
width: 68px;
z-index: 1030;
}
.layoutNavBar {
position: absolute;
top: 50%;
right: -8px;
transform: translateY(-50%);
z-index: 101;
}
.layoutNavBarAgent {
width: 64px;
background: #FFFFFF;
......@@ -23,10 +7,4 @@
display: flex;
flex-direction: column;
align-items: center;
// box-shadow: var(--sdream-box-shadow-small);
}
.layoutNavHot {
width: 96px;
height: 100%;
}
// This file is automatically generated.
// Please do not change this file!
interface CssExports {
collapsed: string
layoutNav: string
layoutNavBar: string
layoutNavBarAgent: string
layoutNavHot: string
}
declare const cssExports: CssExports
export default cssExports
......@@ -22,20 +22,17 @@ const NAV_BAR_ITEMS = [
{ icon: '', label: '', key: 'line2' },
{ icon: Tools, label: '工具', key: 'tools' },
]
// onToggle
export const Navbar: React.FC<NavbarProps> = ({ isCollapsed }) => {
// onToggle isCollapsed
export const Navbar: React.FC<NavbarProps> = () => {
return (
<motion.nav className={`${styles.layoutNav} ${isCollapsed ? styles.collapsed : ''}`}>
<motion.div className={styles.layoutNavBar}>
<motion.div className={`${styles.layoutNavBarAgent} bg-white gap-[32px]`}>
{NAV_BAR_ITEMS.map((item) => {
return (
<NavBarItem icon={item.icon} label={item.label} key={item.key} />
)
})}
</motion.div>
<motion.nav className="w-0 sm:w-[90px] flex-shrink-0 flex flex-col items-center justify-center">
<motion.div className={`${styles.layoutNavBarAgent} sm:flex hidden w-[64px] bg-white gap-[28px]`}>
{NAV_BAR_ITEMS.map((item) => {
return (
<NavBarItem icon={item.icon} label={item.label} key={item.key} />
)
})}
</motion.div>
<motion.div className={styles.layoutNavHot}></motion.div>
</motion.nav>
)
}
// lib/utils.ts
import type { ClassValue } from 'clsx'
import clsx from 'clsx'
import { twMerge } from 'tailwind-merge'
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
.homePage {
width: 100%;
height: 100%;
}
// This file is automatically generated.
// Please do not change this file!
interface CssExports {
homePage: string
}
declare const cssExports: CssExports
export default cssExports
import type React from 'react'
import { Virtuoso } from 'react-virtuoso'
import styles from './Home.module.less'
import { QuestionList } from './components/QuestionList'
import { WelcomeWord } from './components/WelcomeWord'
import { Slogan } from './components/Slogan/Slogan'
import HomeIcon1 from '@/assets/homeIcon1.png'
import HomeIcon2 from '@/assets/homeIcon2.png'
import { GradientBackground } from '@/components/GradientBackground'
export const Home: React.FC = () => {
return <h1>首页</h1>
return (
<div className={styles.homePage}>
<GradientBackground />
<div className="h-full w-full">
<div className="box flex flex-col h-full w-full">
<div className="flex-1">
<Virtuoso
style={{ height: '100%' }}
totalCount={1}
itemContent={() => (
<div className="px-[24px] pb-[24px] pt-[42px] sm:pt-[80px] lg:pt-[180px] sm:px-0">
{/* slogan */}
<Slogan />
{/* 欢迎语 */}
<div className="gap-[20px] flex justify-center flex-row flex-wrap mt-[42px] sm:mt-[62px] lg:mt-[112px]">
<WelcomeWord />
<QuestionList title="产品问答" iconImg={HomeIcon1} />
<QuestionList title="其他问答" iconImg={HomeIcon2} />
</div>
</div>
)}
/>
</div>
<div className="mx-auto iptContainer w-full h-[132px] max-w-[1000px] flex-shrink-0 bg-[#cfc]">
123
</div>
</div>
</div>
</div>
)
}
import { Button } from '@nextui-org/react'
import type React from 'react'
import { Image } from '@nextui-org/image'
interface QuestionListProps {
title: string
iconImg: string
}
export const QuestionList: React.FC<QuestionListProps> = ({ title, iconImg }) => {
return (
<div className="h-[276px] bg-white box-border px-[20px] py-[24px] rounded-[24px] w-full sm:w-[360px] md:w-[300px]">
<h3 className="h-[32px] flex items-center">
<Image className="w-[32px] h-[32px]" src={iconImg} alt="" />
<span className="text-[18px] ml-[12px] font-medium">{title}</span>
</h3>
<ul className="mt-[18px] flex flex-col gap-[8px]">
<li>
<Button disableRipple className="w-full bg-[#F7FCFF]">
<div className="w-full text-nowrap text-ellipsis overflow-hidden">
<span className="text-[#27353c]">推荐几款60周岁还能投的医疗保推荐几款60周岁还能投的医疗保</span>
</div>
</Button>
</li>
<li>
<Button disableRipple className="w-full bg-[#F7FCFF]">
<div className="w-full text-nowrap text-ellipsis overflow-hidden">
<span className="text-[#27353c]">推荐几款60周岁还能投的医疗保推荐几款60周岁还能投的医疗保</span>
</div>
</Button>
</li>
<li>
<Button disableRipple className="w-full bg-[#F7FCFF]">
<div className="w-full text-nowrap text-ellipsis overflow-hidden">
<span className="text-[#27353c]">推荐几款60周岁还能投的医疗保推荐几款60周岁还能投的医疗保</span>
</div>
</Button>
</li>
<li>
<Button disableRipple className="w-full bg-[#F7FCFF]">
<div className="w-full text-nowrap text-ellipsis overflow-hidden">
<span className="text-[#27353c]">推荐几款60周岁还能投的医疗保推荐几款60周岁还能投的医疗保</span>
</div>
</Button>
</li>
</ul>
</div>
)
}
export { QuestionList } from './QuestionList'
import type React from 'react'
import TextLogo from '@/assets/svg/textLogo.svg?react'
import GradualSpacing from '@/components/GradualSpacing'
export const Slogan: React.FC = () => {
return (
<div className="flex flex-col items-center box-border">
<TextLogo className="text-[12px]" />
<GradualSpacing text="晓得解惑,让沟通更智能" className="mt-[36px] text-[#333] text-[28px] font-medium" />
<h3 className="text-center text-[18px] text-[#5AA9D0] font-light mt-[16px]">知晓市场脉搏,引领行业潮流,晓得AI助手全方位为您保驾护航</h3>
</div>
)
}
import { Button } from '@nextui-org/react'
import type React from 'react'
import BotImg from '@/assets/bot.png'
import BotBgImg from '@/assets/botBg.png'
export const WelcomeWord: React.FC = () => {
return (
<div className="w-full h-auto flex-shrink-0 relative sm:w-[360px] sm:h-[276px]">
<img className="absolute z-[-1] top-0 left-0" src={BotBgImg} alt="" />
<img className="w-[180px] absolute right-0 top-[-18px]" src={BotImg} alt="" />
<div className="relative z-[1] box-border px-[24px] pt-[68px]">
<h3>Hi,我是得宝</h3>
<p className="text-[#27353C] text-[15px] mt-[24px] mb-[16px]">做为您的智能保险伙伴,您有各类专业相关的问题都可以抛给我哟~让我们互相帮助共同成长吧~</p>
<Button className="bg-white text-[#20ABD9] font-medium">立即前往 ➔</Button>
</div>
</div>
)
}
export { WelcomeWord } from './WelcomeWord'
:root {
--sdream-text-primary: #27353C;
--sdream-spacing-unit: 4px;
// 其他全局 CSS 变量...
}
// 其他全局样式...
html {
height: 100%;
color: var(--sdream-text-primary);
}
body {
height: 100%;
min-width: 375px;
font-family: -apple-system, blinkmacsystemfont, "Helvetica Neue", helvetica, "segoe ui", arial, roboto, "PingFang SC", miui, "Hiragino Sans GB", "Microsoft Yahei", sans-serif;
color: var(--sdream-text-primary);
}
#root {
height: 100%;
margin: 0;
color: var(--sdream-text-primary);
}
......@@ -9,6 +9,11 @@ module.exports = {
'./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}',
],
theme: {
screens: {
sm: '480px',
md: '1090px',
lg: '1536px',
},
extend: {},
},
darkMode: 'class',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment