init commit

This commit is contained in:
2025-05-27 17:31:00 +08:00
commit 3edaf56d39
49 changed files with 8185 additions and 0 deletions

3
.bolt/config.json Normal file
View File

@ -0,0 +1,3 @@
{
"template": "bolt-vite-react-ts"
}

5
.bolt/prompt Normal file
View File

@ -0,0 +1,5 @@
For all designs I ask you to make, have them be beautiful, not cookie cutter. Make webpages that are fully featured and worthy for production.
By default, this template supports JSX syntax with Tailwind CSS classes, React hooks, and Lucide React for icons. Do not install other packages for UI themes, icons, etc unless absolutely necessary or I request them.
Use icons from lucide-react for logos.

25
.gitignore vendored Normal file
View File

@ -0,0 +1,25 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
.env

Binary file not shown.

Binary file not shown.

386
app.py Normal file
View File

@ -0,0 +1,386 @@
from flask import Flask, render_template, request, redirect, url_for, flash, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, TextAreaField, SubmitField
from wtforms.validators import DataRequired, Length
from flask_ckeditor import CKEditor, CKEditorField
from datetime import datetime
import os
from dotenv import load_dotenv
load_dotenv()
app = Flask(__name__)
app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'your-secret-key')
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL', 'mysql+pymysql://user:password@localhost/liehoo_db')
app.config['UPLOAD_FOLDER'] = 'static/uploads'
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16MB max file size
db = SQLAlchemy(app)
login_manager = LoginManager(app)
login_manager.login_view = 'login'
ckeditor = CKEditor(app)
# Models
class User(UserMixin, db.Model):
__tablename__ = 'user'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
password = db.Column(db.String(120), nullable=False)
articles = db.relationship('Article', backref='author', lazy=True)
class Article(db.Model):
__tablename__ = 'article'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(200), nullable=False)
content = db.Column(db.Text, nullable=False)
created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow, onupdate=datetime.utcnow)
author_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
# Forms
class LoginForm(FlaskForm):
username = StringField('用户名', validators=[DataRequired()])
password = PasswordField('密码', validators=[DataRequired()])
submit = SubmitField('登录')
class ArticleForm(FlaskForm):
title = StringField('标题', validators=[DataRequired(), Length(max=200)])
content = CKEditorField('内容', validators=[DataRequired()])
submit = SubmitField('发布')
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
# 默认路由 - 首页
@app.route('/')
def index():
featured_article = Article.query.order_by(Article.created_at.desc()).first()
latest_articles = Article.query.order_by(Article.created_at.desc()).limit(4).all()
return render_template('index.html', featured_article=featured_article, latest_articles=latest_articles)
# 文章详情页路由
@app.route('/article/<int:id>')
def article_detail(id):
article = Article.query.get_or_404(id)
return render_template('article.html', article=article)
@app.route('/login', methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('admin'))
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user and user.password == form.password.data: # In production, use proper password hashing
login_user(user)
return redirect(url_for('admin'))
flash('用户名或密码错误')
return render_template('login.html', form=form)
@app.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('login'))
@app.route('/admin')
@login_required
def admin():
articles = Article.query.order_by(Article.created_at.desc()).all()
return render_template('admin.html', articles=articles)
@app.route('/admin/article/new', methods=['GET', 'POST'])
@login_required
def new_article():
form = ArticleForm()
if form.validate_on_submit():
article = Article(
title=form.title.data,
content=form.content.data,
author_id=current_user.id
)
db.session.add(article)
db.session.commit()
flash('文章发布成功')
return redirect(url_for('admin'))
return render_template('article_form.html', form=form)
@app.route('/admin/article/<int:id>/edit', methods=['GET', 'POST'])
@login_required
def edit_article(id):
article = Article.query.get_or_404(id)
form = ArticleForm(obj=article)
if form.validate_on_submit():
article.title = form.title.data
article.content = form.content.data
article.updated_at = datetime.utcnow()
db.session.commit()
flash('文章更新成功')
return redirect(url_for('admin'))
return render_template('article_form.html', form=form, article=article)
@app.route('/admin/article/<int:id>/delete', methods=['POST'])
@login_required
def delete_article(id):
article = Article.query.get_or_404(id)
db.session.delete(article)
db.session.commit()
flash('文章已删除')
return redirect(url_for('admin'))
@app.route('/api/articles/latest')
def latest_articles():
articles = Article.query.order_by(Article.created_at.desc()).limit(5).all()
return jsonify([{
'id': article.id,
'title': article.title,
'created_at': article.created_at.strftime('%Y-%m-%d')
} for article in articles])
# 网络营销业务线 - 腾讯广告事业部
@app.route('/services/marketing/tencent/information-flow')
def information_flow():
return render_template('submenu_page.html', title='信息流')
@app.route('/services/marketing/tencent/short-video')
def short_video():
return render_template('submenu_page.html', title='短视频')
@app.route('/services/marketing/tencent/search')
def search():
return render_template('submenu_page.html', title='搜索(搜狗)')
# 网络营销业务线 - 平台媒体事业部
@app.route('/services/marketing/platform/kuaishou')
def kuaishou():
return render_template('submenu_page.html', title='快手项目部')
@app.route('/services/marketing/platform/360')
def platform_360():
return render_template('submenu_page.html', title='360项目部')
@app.route('/services/marketing/platform/ali')
def ali():
return render_template('submenu_page.html', title='阿里汇川项目部')
@app.route('/services/marketing/platform/gaode')
def gaode():
return render_template('submenu_page.html', title='高德项目部')
# 软件管理业务线
@app.route('/services/software/yonyou')
def yonyou():
return render_template('submenu_page.html', title='用友事业部')
@app.route('/services/software/dingtalk')
def dingtalk():
return render_template('submenu_page.html', title='钉钉项目部')
@app.route('/services/software/wecom')
def wecom():
return render_template('submenu_page.html', title='企微项目部')
@app.route('/services/software/feishu')
def feishu():
return render_template('submenu_page.html', title='飞书项目部')
@app.route('/services/software/youzan')
def youzan():
return render_template('submenu_page.html', title='有赞项目部')
@app.route('/services/software/crm')
def crm():
return render_template('submenu_page.html', title='CRM项目部')
@app.route('/services/software/development')
def development():
return render_template('submenu_page.html', title='技术开发部')
# 财税法务业务线
@app.route('/services/legal/badun-legal')
def badun_legal():
return render_template('submenu_page.html', title='八盾法务')
@app.route('/services/legal/badun-asset')
def badun_asset():
return render_template('submenu_page.html', title='八盾资产')
@app.route('/services/legal/beike-finance')
def beike_finance():
return render_template('submenu_page.html', title='贝壳财税')
# 直播电商事业部
@app.route('/ecommerce/live/selection')
def selection():
return render_template('submenu_page.html', title='选品招商')
@app.route('/ecommerce/live/traceability')
def traceability():
return render_template('submenu_page.html', title='溯源专场')
@app.route('/ecommerce/live/supply-chain')
def supply_chain():
return render_template('submenu_page.html', title='供应链金融')
# 达人运营事业部
@app.route('/ecommerce/talent/business')
def talent_business():
return render_template('submenu_page.html', title='达人商务')
@app.route('/ecommerce/talent/account')
def account_operation():
return render_template('submenu_page.html', title='账号运营')
@app.route('/ecommerce/talent/live')
def live_operation():
return render_template('submenu_page.html', title='直播运营')
# 平台电商事业部
@app.route('/ecommerce/platform/pinduoduo')
def pinduoduo():
return render_template('submenu_page.html', title='拼多多项目部')
@app.route('/ecommerce/platform/taotian')
def taotian():
return render_template('submenu_page.html', title='淘天项目部')
@app.route('/ecommerce/platform/jd')
def jd():
return render_template('submenu_page.html', title='京东项目部')
# 文旅与大健康
@app.route('/tourism-health/yueke')
def yueke():
return render_template('submenu_page.html', title='悦客嘉酒店管理')
@app.route('/tourism-health/stem-cell')
def stem_cell():
return render_template('submenu_page.html', title='昆大干细胞')
@app.route('/tourism-health/massage')
def massage():
return render_template('submenu_page.html', title='邱氏百年中医推拿')
@app.route('/tourism-health/dental')
def dental():
return render_template('submenu_page.html', title='袋鼠齿盟')
# 平台运营管理
@app.route('/platform/changqi')
def changqi():
return render_template('submenu_page.html', title='长企网')
@app.route('/platform/badun')
def badun():
return render_template('submenu_page.html', title='八盾资产')
@app.route('/platform/limao')
def limao():
return render_template('submenu_page.html', title='礼猫猫')
@app.route('/platform/yunfang')
def yunfang():
return render_template('submenu_page.html', title='云纺科技园')
@app.route('/platform/cell-park')
def cell_park():
return render_template('submenu_page.html', title='昆明细胞产业园')
@app.route('/platform/digital')
def digital():
return render_template('submenu_page.html', title='云南数字企业平台')
@app.route('/platform/association')
def association():
return render_template('submenu_page.html', title='云南省互联网零售业协会')
# 品牌与投资
@app.route('/brand/jiabeijia')
def jiabeijia():
return render_template('submenu_page.html', title='佳贝佳')
@app.route('/brand/beicheng')
def beicheng():
return render_template('submenu_page.html', title='贝成教育')
@app.route('/brand/xiaohua')
def xiaohua():
return render_template('submenu_page.html', title='云南小花')
@app.route('/brand/guoxiaofu')
def guoxiaofu():
return render_template('submenu_page.html', title='果小福')
@app.route('/brand/xiaxiong')
def xiaxiong():
return render_template('submenu_page.html', title='夏小熊')
if __name__ == '__main__':
with app.app_context():
db.create_all()
if not User.query.filter_by(username='admin').first():
admin = User(username='admin', password='admin123')
db.session.add(admin)
db.session.commit()
app.run(debug=True, host='0.0.0.0', port=5000)

4
create.py Normal file
View File

@ -0,0 +1,4 @@
from flask import app
from app import db, User

181
css/carousel.css Normal file
View File

@ -0,0 +1,181 @@
/* 轮播图样式 */
.carousel-container {
position: relative;
width: 100%;
height: 100vh;
overflow: hidden;
margin-top: 110px;
}
.carousel-slides {
width: 100%;
height: 100%;
position: relative;
}
.carousel-slide {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
transition: opacity 1s ease;
z-index: 1;
}
.carousel-slide.active {
opacity: 1;
z-index: 2;
}
.carousel-slide img {
width: 100%;
height: 100%;
object-fit: cover;
}
.carousel-caption {
position: absolute;
bottom: 25%;
left: 10%;
max-width: 600px;
color: #fff;
text-align: left;
padding: 30px;
background-color: rgba(0, 0, 0, 0.5);
border-radius: 5px;
transform: translateY(20px);
opacity: 0;
transition: opacity 0.8s ease, transform 0.8s ease;
transition-delay: 0.3s;
}
.carousel-slide.active .carousel-caption {
opacity: 1;
transform: translateY(0);
}
.carousel-caption h2 {
font-size: 36px;
margin-bottom: 15px;
font-weight: bold;
}
.carousel-caption p {
font-size: 18px;
line-height: 1.6;
}
/* 轮播控制按钮 */
.carousel-controls {
position: absolute;
top: 50%;
width: 100%;
display: flex;
justify-content: space-between;
padding: 0 20px;
transform: translateY(-50%);
z-index: 10;
}
.carousel-control {
background-color: rgba(0, 0, 0, 0.5);
color: #fff;
border: none;
width: 50px;
height: 50px;
border-radius: 50%;
font-size: 24px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: background-color 0.3s ease;
}
.carousel-control:hover {
background-color: rgba(0, 0, 0, 0.8);
}
/* 轮播指示器 */
.carousel-indicators {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 10px;
z-index: 10;
}
.indicator {
width: 12px;
height: 12px;
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.5);
border: none;
cursor: pointer;
transition: background-color 0.3s ease, transform 0.3s ease;
}
.indicator.active {
background-color: #fff;
transform: scale(1.2);
}
/* 响应式设计 */
@media (max-width: 992px) {
.carousel-container {
margin-top: 80px;
height: 70vh;
}
.carousel-caption {
left: 5%;
max-width: 90%;
bottom: 20%;
}
.carousel-caption h2 {
font-size: 28px;
}
.carousel-caption p {
font-size: 16px;
}
}
@media (max-width: 768px) {
.carousel-container {
height: 60vh;
}
.carousel-controls {
display: none;
}
.carousel-caption h2 {
font-size: 24px;
}
.carousel-caption p {
font-size: 14px;
}
}
@media (max-width: 576px) {
.carousel-container {
height: 50vh;
}
.carousel-caption {
padding: 15px;
bottom: 15%;
}
.carousel-caption h2 {
font-size: 20px;
margin-bottom: 8px;
}
}

140
css/footer.css Normal file
View File

@ -0,0 +1,140 @@
/* 页脚样式 */
.footer {
background-color: #2F558C;
color: #fff;
}
/* 页脚主要部分 */
.footer-main {
padding: 50px 0;
}
.footer-content {
display: flex;
justify-content: space-between;
}
/* 页脚logo */
.footer-logo {
flex: 1;
max-width: 400px;
}
.footer-logo img {
max-height: 60px;
margin-bottom: 20px;
}
.footer-logo h2 {
font-size: 24px;
font-weight: bold;
margin-bottom: 10px;
}
.company-slogan {
color: rgba(255, 255, 255, 0.8);
margin-bottom: 20px;
}
/* 页脚联系信息 */
.footer-contact {
flex: 1;
max-width: 500px;
}
.footer-contact h3 {
font-size: 18px;
margin-bottom: 20px;
position: relative;
padding-bottom: 10px;
}
.footer-contact h3::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 40px;
height: 2px;
background-color: #fff;
}
.footer-contact ul {
margin-bottom: 20px;
}
.footer-contact ul li {
margin-bottom: 12px;
display: flex;
align-items: flex-start;
}
.footer-contact ul li i {
margin-top: 3px;
}
/* 社交媒体图标 */
.social-media {
display: flex;
gap: 15px;
}
.social-media a {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
background-color: rgba(255, 255, 255, 0.1);
border-radius: 50%;
transition: background-color 0.3s ease;
}
.social-media a:hover {
background-color: rgba(255, 255, 255, 0.2);
}
/* 页脚底部 */
.footer-bottom {
background-color: #1a365d;
padding: 15px 0;
}
.footer-bottom .container {
display: flex;
justify-content: center;
align-items: center;
gap: 30px;
}
.copyright, .icp {
font-size: 14px;
color: rgba(255, 255, 255, 0.7);
}
/* 响应式设计 */
@media (max-width: 992px) {
.footer-content {
flex-direction: column;
gap: 30px;
}
.footer-logo, .footer-contact {
max-width: 100%;
}
}
@media (max-width: 768px) {
.footer-main {
padding: 40px 0;
}
.footer-bottom .container {
flex-direction: column;
gap: 5px;
}
.copyright, .icp {
text-align: center;
}
}

278
css/navigation.css Normal file
View File

@ -0,0 +1,278 @@
/* 导航栏样式 */
.header {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 110px;
background: linear-gradient(rgb(47, 85, 140), rgba(47, 85, 140, 0.49), rgba(52, 94, 156, 0.04));
color: #fff;
z-index: 1000;
transition: background-color 0.3s ease;
}
.header .container {
display: flex;
justify-content: space-between;
align-items: center;
height: 100%;
}
/* Logo样式 */
.logo {
display: flex;
align-items: center;
}
.logo img {
max-height: 50px;
margin-right: 15px;
}
.logo h1 {
font-size: 24px;
font-weight: bold;
white-space: nowrap;
}
/* 主导航菜单 */
.main-nav {
position: relative;
height: 100%;
display: flex;
flex-direction: column;
justify-content: flex-start;
padding-top: 10px;
}
.nav-menu {
display: flex;
flex-direction: column;
align-items: flex-end;
height: 100%;
}
.nav-top {
display: flex;
gap: 20px;
margin-bottom: 15px;
height: 30%;
}
.nav-bottom {
display: flex;
gap: 20px;
height: 70%;
align-items: flex-start;
}
.nav-item {
position: relative;
}
.nav-link {
display: block;
color: #fff;
font-size: 16px;
font-weight: 500;
padding: 10px 15px;
transition: color 0.3s ease;
}
.nav-link:hover {
color: #f0f0f0;
}
/* 下拉菜单通用样式 */
.dropdown-menu,
.sub-dropdown,
.sub-sub-dropdown,
.sub-sub-sub-dropdown {
position: absolute;
background-color: #fff;
min-width: 200px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
opacity: 0;
visibility: hidden;
transform: translateY(10px);
transition: all 0.3s ease;
border-radius: 4px;
}
/* 一级下拉菜单 */
.dropdown-menu {
top: 100%;
left: 0;
z-index: 100;
}
.nav-item:hover > .dropdown-menu {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
/* 二级下拉菜单 */
.sub-dropdown {
top: 0;
left: 100%;
z-index: 101;
}
/* 三级下拉菜单 */
.sub-sub-dropdown {
top: 0;
left: 100%;
z-index: 102;
}
/* 四级下拉菜单 */
.sub-sub-sub-dropdown {
top: 0;
left: 100%;
z-index: 103;
}
/* 下拉菜单项通用样式 */
.dropdown-item,
.sub-dropdown-item,
.sub-sub-dropdown-item,
.sub-sub-sub-dropdown-item {
position: relative;
border-bottom: 1px solid #f0f0f0;
}
.dropdown-item:last-child,
.sub-dropdown-item:last-child,
.sub-sub-dropdown-item:last-child,
.sub-sub-sub-dropdown-item:last-child {
border-bottom: none;
}
.dropdown-item > a,
.sub-dropdown-item > a,
.sub-sub-dropdown-item > a,
.sub-sub-sub-dropdown-item > a {
display: block;
padding: 12px 16px;
color: #333;
transition: background-color 0.3s ease, color 0.3s ease;
}
.dropdown-item > a:hover,
.sub-dropdown-item > a:hover,
.sub-sub-dropdown-item > a:hover,
.sub-sub-sub-dropdown-item > a:hover {
background-color: #f8f9fa;
color: #2F558C;
}
/* 显示子菜单 */
.dropdown-item:hover > .sub-dropdown,
.sub-dropdown-item:hover > .sub-sub-dropdown,
.sub-sub-dropdown-item:hover > .sub-sub-sub-dropdown {
opacity: 1;
visibility: visible;
transform: translateX(0);
}
/* 移动端菜单按钮 */
.menu-toggle {
display: none;
background: none;
border: none;
color: #fff;
font-size: 24px;
cursor: pointer;
padding: 10px;
}
/* 响应式设计 */
@media (max-width: 1200px) {
.nav-link {
padding: 10px 10px;
}
}
@media (max-width: 992px) {
.header {
height: 80px;
}
.logo h1 {
font-size: 20px;
}
.menu-toggle {
display: block;
}
.nav-menu {
position: absolute;
top: 80px;
left: 0;
width: 100%;
background-color: #2F558C;
flex-direction: column;
align-items: flex-start;
padding: 20px 0;
display: none;
}
.nav-menu.active {
display: flex;
}
.nav-top,
.nav-bottom {
flex-direction: column;
width: 100%;
gap: 0;
margin: 0;
height: auto;
}
.nav-item {
width: 100%;
margin-left: 0;
}
.nav-link {
padding: 12px 20px;
}
.dropdown-menu,
.sub-dropdown,
.sub-sub-dropdown,
.sub-sub-sub-dropdown {
position: static;
opacity: 1;
visibility: visible;
transform: none;
box-shadow: none;
width: 100%;
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease;
}
.nav-item.active > .dropdown-menu,
.dropdown-item.active > .sub-dropdown,
.sub-dropdown-item.active > .sub-sub-dropdown,
.sub-sub-dropdown-item.active > .sub-sub-sub-dropdown {
max-height: 500px;
}
.dropdown-item > a,
.sub-dropdown-item > a,
.sub-sub-dropdown-item > a,
.sub-sub-sub-dropdown-item > a {
padding-left: 30px;
}
.sub-dropdown,
.sub-sub-dropdown,
.sub-sub-sub-dropdown {
padding-left: 20px;
}
}

192
css/news.css Normal file
View File

@ -0,0 +1,192 @@
/* 新闻动态样式 */
.news-section {
padding: 60px 0;
background-color: #fff;
}
.news-container {
display: flex;
gap: 30px;
margin-top: 40px;
}
/* 特色新闻 */
.featured-news {
flex: 2;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.08);
overflow: hidden;
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.featured-news:hover {
transform: translateY(-5px);
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.12);
}
.news-image {
width: 100%;
height: 300px;
overflow: hidden;
}
.news-image img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.5s ease;
}
.featured-news:hover .news-image img {
transform: scale(1.05);
}
.news-content {
padding: 25px;
}
.news-title {
font-size: 22px;
font-weight: bold;
color: #333;
margin-bottom: 10px;
line-height: 1.3;
}
.news-date {
font-size: 14px;
color: #666;
margin-bottom: 15px;
}
.news-summary {
color: #555;
line-height: 1.6;
margin-bottom: 20px;
}
.read-more {
display: inline-block;
color: #2F558C;
font-weight: 500;
position: relative;
padding-right: 20px;
}
.read-more::after {
content: '→';
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
transition: transform 0.3s ease;
}
.read-more:hover::after {
transform: translate(5px, -50%);
}
/* 新闻列表 */
.news-list {
flex: 1;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.08);
padding: 25px;
}
.news-list h3 {
font-size: 20px;
color: #2F558C;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 2px solid #f0f0f0;
}
.news-list ul li {
padding: 15px 0;
border-bottom: 1px solid #f0f0f0;
}
.news-list ul li:last-child {
border-bottom: none;
}
.news-list ul li a {
display: block;
color: #333;
font-weight: 500;
line-height: 1.4;
margin-bottom: 5px;
transition: color 0.3s ease;
}
.news-list ul li a:hover {
color: #2F558C;
}
.list-date {
display: block;
font-size: 13px;
color: #666;
}
.view-all {
display: block;
text-align: center;
margin-top: 20px;
padding: 10px;
background-color: #f8f9fa;
color: #2F558C;
border-radius: 4px;
transition: background-color 0.3s ease;
}
.view-all:hover {
background-color: #e9ecef;
}
/* 响应式设计 */
@media (max-width: 992px) {
.news-container {
flex-direction: column;
}
.featured-news, .news-list {
flex: none;
width: 100%;
}
.news-image {
height: 250px;
}
}
@media (max-width: 768px) {
.news-section {
padding: 40px 0;
}
.news-title {
font-size: 20px;
}
.news-image {
height: 200px;
}
}
@media (max-width: 576px) {
.news-content {
padding: 15px;
}
.news-list {
padding: 15px;
}
.news-image {
height: 180px;
}
}

122
css/styles.css Normal file
View File

@ -0,0 +1,122 @@
/* 基础样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', sans-serif;
font-size: 16px;
line-height: 1.5;
color: #333;
background-color: #f8f9fa;
}
.container {
width: 80%;
max-width: 1400px;
margin: 0 auto;
padding: 0 15px;
}
a {
text-decoration: none;
color: #2F558C;
transition: color 0.3s ease;
}
a:hover {
color: #1a365d;
}
ul {
list-style: none;
}
img {
max-width: 100%;
height: auto;
display: block;
}
/* 图标字体占位样式(实际应用中替换为实际图标) */
[class^="icon-"] {
display: inline-block;
width: 16px;
height: 16px;
margin-right: 8px;
background-color: #2F558C;
vertical-align: middle;
}
/* 通用按钮样式 */
.btn {
display: inline-block;
padding: 8px 16px;
background-color: #2F558C;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s ease;
}
.btn:hover {
background-color: #1a365d;
}
/* 章节标题 */
.section-title {
position: relative;
font-size: 28px;
font-weight: bold;
color: #2F558C;
margin-bottom: 32px;
text-align: center;
padding-bottom: 12px;
}
.section-title::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 60px;
height: 3px;
background-color: #2F558C;
}
/* 响应式设计 */
@media (max-width: 1200px) {
.container {
width: 90%;
}
}
@media (max-width: 992px) {
.section-title {
font-size: 24px;
}
}
@media (max-width: 768px) {
.container {
width: 95%;
}
.section-title {
font-size: 22px;
}
}
@media (max-width: 576px) {
body {
font-size: 14px;
}
.section-title {
font-size: 20px;
}
}

28
eslint.config.js Normal file
View File

@ -0,0 +1,28 @@
import js from '@eslint/js';
import globals from 'globals';
import reactHooks from 'eslint-plugin-react-hooks';
import reactRefresh from 'eslint-plugin-react-refresh';
import tseslint from 'typescript-eslint';
export default tseslint.config(
{ ignores: ['dist'] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ['**/*.{ts,tsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
}
);

263
index.html Normal file
View File

@ -0,0 +1,263 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>猎狐企服 - 数字化企业服务领导者</title>
<link rel="stylesheet" href="css/styles.css">
<link rel="stylesheet" href="css/navigation.css">
<link rel="stylesheet" href="css/carousel.css">
<link rel="stylesheet" href="css/news.css">
<link rel="stylesheet" href="css/footer.css">
</head>
<body>
<!-- 导航栏 -->
<header class="header">
<div class="container">
<div class="logo">
<img src="https://resources.jsmo.xin/templates/upload/34449/202401/1704161701959.png" alt="猎狐企服Logo">
<h1>猎狐企服</h1>
</div>
<nav class="main-nav">
<ul class="nav-menu">
<div class="nav-top">
<li class="nav-item"><a href="#" class="nav-link">关于我们</a></li>
<li class="nav-item"><a href="#" class="nav-link">新闻动态</a></li>
<li class="nav-item"><a href="#" class="nav-link">联系我们</a></li>
</div>
<div class="nav-bottom">
<!-- 一级菜单: 数字化企业服务 -->
<li class="nav-item">
<a href="#" class="nav-link">数字化企业服务</a>
<ul class="dropdown-menu">
<li class="dropdown-item">
<a href="#">网络营销业务线</a>
<ul class="sub-dropdown">
<li class="sub-dropdown-item">
<a href="#">腾讯广告事业部</a>
<ul class="sub-sub-dropdown">
<li class="sub-sub-dropdown-item"><a href="#">信息流</a></li>
<li class="sub-sub-dropdown-item"><a href="#">短视频</a></li>
<li class="sub-sub-dropdown-item"><a href="#">搜索(搜狗)</a></li>
</ul>
</li>
<li class="sub-dropdown-item">
<a href="#">平台媒体事业部</a>
<ul class="sub-sub-dropdown">
<li class="sub-sub-dropdown-item"><a href="#">快手项目部</a></li>
<li class="sub-sub-dropdown-item"><a href="#">360项目部</a></li>
<li class="sub-sub-dropdown-item"><a href="#">阿里汇川项目部</a></li>
<li class="sub-sub-dropdown-item"><a href="#">高德项目部</a></li>
</ul>
</li>
</ul>
</li>
<li class="dropdown-item">
<a href="#">软件管理业务线</a>
<ul class="sub-dropdown">
<li class="sub-dropdown-item"><a href="#">用友事业部</a></li>
<li class="sub-dropdown-item"><a href="#">钉钉项目部</a></li>
<li class="sub-dropdown-item"><a href="#">企微项目部</a></li>
<li class="sub-dropdown-item"><a href="#">飞书项目部</a></li>
<li class="sub-dropdown-item"><a href="#">有赞项目部</a></li>
<li class="sub-dropdown-item"><a href="#">CRM项目部</a></li>
<li class="sub-dropdown-item"><a href="#">技术开发部</a></li>
</ul>
</li>
<li class="dropdown-item">
<a href="#">财税法务业务线</a>
<ul class="sub-dropdown">
<li class="sub-dropdown-item"><a href="#">八盾法务</a></li>
<li class="sub-dropdown-item"><a href="#">八盾资产</a></li>
<li class="sub-dropdown-item"><a href="#">贝壳财税</a></li>
</ul>
</li>
</ul>
</li>
<!-- 一级菜单: 电商及MCN -->
<li class="nav-item">
<a href="#" class="nav-link">电商及MCN</a>
<ul class="dropdown-menu">
<li class="dropdown-item">
<a href="#">直播电商事业部</a>
<ul class="sub-dropdown">
<li class="sub-dropdown-item"><a href="#">选品招商</a></li>
<li class="sub-dropdown-item"><a href="#">溯源专场</a></li>
<li class="sub-dropdown-item"><a href="#">供应链金融</a></li>
</ul>
</li>
<li class="dropdown-item">
<a href="#">达人运营事业部</a>
<ul class="sub-dropdown">
<li class="sub-dropdown-item"><a href="#">达人商务</a></li>
<li class="sub-dropdown-item"><a href="#">账号运营</a></li>
<li class="sub-dropdown-item"><a href="#">直播运营</a></li>
</ul>
</li>
<li class="dropdown-item">
<a href="#">平台电商事业部</a>
<ul class="sub-dropdown">
<li class="sub-dropdown-item"><a href="#">拼多多项目部</a></li>
<li class="sub-dropdown-item"><a href="#">淘天项目部</a></li>
<li class="sub-dropdown-item"><a href="#">京东项目部</a></li>
</ul>
</li>
</ul>
</li>
<!-- 一级菜单: 文旅与大健康 -->
<li class="nav-item">
<a href="#" class="nav-link">文旅与大健康</a>
<ul class="dropdown-menu">
<li class="dropdown-item"><a href="#">悦客嘉酒店管理</a></li>
<li class="dropdown-item"><a href="#">昆大干细胞</a></li>
<li class="dropdown-item"><a href="#">邱氏百年中医推拿</a></li>
<li class="dropdown-item"><a href="#">袋鼠齿盟</a></li>
</ul>
</li>
<!-- 一级菜单: 平台运营管理 -->
<li class="nav-item">
<a href="#" class="nav-link">平台运营管理</a>
<ul class="dropdown-menu">
<li class="dropdown-item"><a href="#">长企网</a></li>
<li class="dropdown-item"><a href="#">八盾资产</a></li>
<li class="dropdown-item"><a href="#">礼猫猫</a></li>
<li class="dropdown-item"><a href="#">云纺科技园</a></li>
<li class="dropdown-item"><a href="#">昆明细胞产业园</a></li>
<li class="dropdown-item"><a href="#">云南数字企业平台</a></li>
<li class="dropdown-item"><a href="#">云南省互联网零售业协会</a></li>
</ul>
</li>
<!-- 一级菜单: 品牌与投资 -->
<li class="nav-item">
<a href="#" class="nav-link">品牌与投资</a>
<ul class="dropdown-menu">
<li class="dropdown-item"><a href="#">佳贝佳</a></li>
<li class="dropdown-item"><a href="#">贝成教育</a></li>
<li class="dropdown-item"><a href="#">云南小花</a></li>
<li class="dropdown-item"><a href="#">果小福</a></li>
<li class="dropdown-item"><a href="#">夏小熊</a></li>
</ul>
</li>
</div>
</ul>
</nav>
</div>
</header>
<!-- 轮播图 -->
<section class="carousel-container">
<div class="carousel-slides">
<div class="carousel-slide active">
<img src="https://resources.jsmo.xin/templates/upload/34449/202401/1705058156515.jpg" alt="企业展示1">
<div class="carousel-caption">
<h2>数字化转型领导者</h2>
<p>为企业提供全方位的数字化解决方案,助力企业实现数字化转型升级。</p>
</div>
</div>
<div class="carousel-slide">
<img src="https://resources.jsmo.xin/templates/upload/34449/202401/1705058071139.jpg" alt="企业展示2">
<div class="carousel-caption">
<h2>创新驱动发展</h2>
<p>以创新为驱动力,为企业带来持续增长的动力。</p>
</div>
</div>
<div class="carousel-slide">
<img src="https://resources.jsmo.xin/templates/upload/34449/202401/1705058127381.jpg" alt="企业展示3">
<div class="carousel-caption">
<h2>专业服务团队</h2>
<p>拥有经验丰富的专业团队,为客户提供高质量的服务支持。</p>
</div>
</div>
</div>
<div class="carousel-controls">
<button class="carousel-control prev"></button>
<button class="carousel-control next"></button>
</div>
<div class="carousel-indicators">
<button class="indicator active"></button>
<button class="indicator"></button>
<button class="indicator"></button>
</div>
</section>
<!-- 新闻动态 -->
<section class="news-section">
<div class="container">
<h2 class="section-title">新闻动态</h2>
<div class="news-container">
<div class="featured-news">
<div class="news-image">
<img src="https://images.pexels.com/photos/3184465/pexels-photo-3184465.jpeg" alt="新闻图片">
</div>
<div class="news-content">
<h3 class="news-title">公司成功举办2024年数字化转型峰会</h3>
<p class="news-date">2024-03-15</p>
<p class="news-summary">在本次峰会上,来自各行业的专家和企业代表共同探讨了数字化转型的最新趋势和实践经验,为企业数字化发展提供了新的思路和方向。</p>
<a href="#" class="read-more">阅读更多</a>
</div>
</div>
<div class="news-list">
<h3>最新动态</h3>
<ul>
<li>
<a href="#">公司与某知名企业达成战略合作</a>
<span class="list-date">2024-03-10</span>
</li>
<li>
<a href="#">新一代企业管理系统正式发布</a>
<span class="list-date">2024-03-05</span>
</li>
<li>
<a href="#">公司荣获"年度最具创新力企业"称号</a>
<span class="list-date">2024-02-28</span>
</li>
<li>
<a href="#">2024年度客户服务体系升级计划启动</a>
<span class="list-date">2024-02-20</span>
</li>
</ul>
<a href="#" class="view-all">查看全部</a>
</div>
</div>
</div>
</section>
<!-- 页脚 -->
<footer class="footer">
<div class="footer-main">
<div class="container">
<div class="footer-content">
<div class="footer-logo">
<img src="https://resources.jsmo.xin/templates/upload/34449/202401/1704161701959.png" alt="猎狐企服Logo">
<h2>猎贝狐企服</h2>
<p class="company-slogan">数字化企业服务领导者</p>
</div>
<div class="footer-contact">
<h3>联系我们</h3>
<ul>
<li><i class="icon-location"></i>地址云南省昆明市某某区某某街道123号</li>
<li><i class="icon-phone"></i>电话0871-12345678</li>
<li><i class="icon-email"></i>邮箱contact@company.com</li>
</ul>
<div class="social-media">
<a href="#"><i class="icon-weixin"></i></a>
<a href="#"><i class="icon-weibo"></i></a>
<a href="#"><i class="icon-douyin"></i></a>
</div>
</div>
</div>
</div>
</div>
<div class="footer-bottom">
<div class="container">
<p class="copyright">© 2024 猎狐企服 版权所有</p>
<p class="icp">滇ICP备12345678号-1</p>
</div>
</div>
</footer>
<script src="js/navigation.js"></script>
<script src="js/carousel.js"></script>
<script src="js/main.js"></script>
</body>
</html>

130
js/carousel.js Normal file
View File

@ -0,0 +1,130 @@
// 轮播图功能
document.addEventListener('DOMContentLoaded', function() {
const slides = document.querySelectorAll('.carousel-slide');
const indicators = document.querySelectorAll('.indicator');
const prevBtn = document.querySelector('.carousel-control.prev');
const nextBtn = document.querySelector('.carousel-control.next');
if (!slides.length) return;
let currentSlide = 0;
let slideInterval;
const slideDelay = 3000; // 3秒轮播间隔
// 初始化轮播
function startSlideshow() {
slideInterval = setInterval(nextSlide, slideDelay);
}
// 停止轮播
function stopSlideshow() {
clearInterval(slideInterval);
}
// 显示指定幻灯片
function showSlide(index) {
if (index < 0) {
index = slides.length - 1;
} else if (index >= slides.length) {
index = 0;
}
// 隐藏当前幻灯片
slides[currentSlide].classList.remove('active');
if (indicators.length) {
indicators[currentSlide].classList.remove('active');
}
// 显示新幻灯片
currentSlide = index;
slides[currentSlide].classList.add('active');
if (indicators.length) {
indicators[currentSlide].classList.add('active');
}
}
// 下一张幻灯片
function nextSlide() {
showSlide(currentSlide + 1);
}
// 上一张幻灯片
function prevSlide() {
showSlide(currentSlide - 1);
}
// 绑定指示器点击事件
if (indicators.length) {
indicators.forEach((indicator, index) => {
indicator.addEventListener('click', () => {
stopSlideshow();
showSlide(index);
startSlideshow();
});
});
}
// 绑定方向按钮点击事件
if (prevBtn) {
prevBtn.addEventListener('click', () => {
stopSlideshow();
prevSlide();
startSlideshow();
});
}
if (nextBtn) {
nextBtn.addEventListener('click', () => {
stopSlideshow();
nextSlide();
startSlideshow();
});
}
// 当鼠标悬停在轮播图上时暂停轮播
const carouselContainer = document.querySelector('.carousel-container');
if (carouselContainer) {
carouselContainer.addEventListener('mouseenter', stopSlideshow);
carouselContainer.addEventListener('mouseleave', startSlideshow);
}
// 当用户触摸屏幕时也暂停轮播
if (carouselContainer) {
carouselContainer.addEventListener('touchstart', stopSlideshow, {passive: true});
carouselContainer.addEventListener('touchend', startSlideshow, {passive: true});
}
// 添加触摸滑动支持
let touchStartX = 0;
let touchEndX = 0;
if (carouselContainer) {
carouselContainer.addEventListener('touchstart', (e) => {
touchStartX = e.changedTouches[0].screenX;
}, {passive: true});
carouselContainer.addEventListener('touchend', (e) => {
touchEndX = e.changedTouches[0].screenX;
handleSwipe();
}, {passive: true});
}
function handleSwipe() {
// 计算滑动距离
const swipeDistance = touchEndX - touchStartX;
const minSwipeDistance = 50; // 最小有效滑动距离
if (swipeDistance > minSwipeDistance) {
// 向右滑动,显示上一张
prevSlide();
} else if (swipeDistance < -minSwipeDistance) {
// 向左滑动,显示下一张
nextSlide();
}
startSlideshow();
}
// 启动轮播
startSlideshow();
});

103
js/main.js Normal file
View File

@ -0,0 +1,103 @@
// 主要功能脚本
document.addEventListener('DOMContentLoaded', function() {
// 更新页面标题
document.title = '企业名称 - 数字化企业服务领导者';
// 图片加载优化
function lazyLoadImages() {
const images = document.querySelectorAll('img');
if ('IntersectionObserver' in window) {
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const image = entry.target;
// 如果图片有data-src属性则将其加载
if (image.dataset.src) {
image.src = image.dataset.src;
image.removeAttribute('data-src');
}
imageObserver.unobserve(image);
}
});
});
images.forEach(image => {
imageObserver.observe(image);
});
}
}
// 滚动到顶部按钮
function createScrollTopButton() {
const scrollBtn = document.createElement('button');
scrollBtn.innerHTML = '↑';
scrollBtn.className = 'scroll-top-btn';
scrollBtn.style.cssText = `
position: fixed;
bottom: 20px;
right: 20px;
width: 40px;
height: 40px;
border-radius: 50%;
background-color: #2F558C;
color: white;
border: none;
display: none;
align-items: center;
justify-content: center;
font-size: 20px;
cursor: pointer;
z-index: 999;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
`;
document.body.appendChild(scrollBtn);
// 显示/隐藏按钮
window.addEventListener('scroll', () => {
if (window.scrollY > 300) {
scrollBtn.style.display = 'flex';
} else {
scrollBtn.style.display = 'none';
}
});
// 点击按钮滚动到顶部
scrollBtn.addEventListener('click', () => {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
});
}
// 平滑滚动到锚点
function setupSmoothScrolling() {
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function(e) {
const href = this.getAttribute('href');
if (href !== '#') {
e.preventDefault();
const targetElement = document.querySelector(href);
if (targetElement) {
const headerHeight = document.querySelector('.header').offsetHeight;
const targetPosition = targetElement.getBoundingClientRect().top + window.pageYOffset - headerHeight;
window.scrollTo({
top: targetPosition,
behavior: 'smooth'
});
}
}
});
});
}
// 执行所有初始化功能
lazyLoadImages();
createScrollTopButton();
setupSmoothScrolling();
});

122
js/navigation.js Normal file
View File

@ -0,0 +1,122 @@
// 导航菜单功能
document.addEventListener('DOMContentLoaded', function() {
// 移动端菜单切换
const menuToggle = document.createElement('button');
menuToggle.className = 'menu-toggle';
menuToggle.innerHTML = '☰';
menuToggle.setAttribute('aria-label', '菜单');
const nav = document.querySelector('.main-nav');
const navMenu = document.querySelector('.nav-menu');
if (nav && navMenu) {
nav.insertBefore(menuToggle, navMenu);
menuToggle.addEventListener('click', function() {
navMenu.classList.toggle('active');
this.innerHTML = navMenu.classList.contains('active') ? '✕' : '☰';
});
}
// 移动端下拉菜单处理
function handleMobileDropdowns() {
if (window.innerWidth <= 992) {
// 一级菜单点击
const navItems = document.querySelectorAll('.nav-item');
navItems.forEach(item => {
const link = item.querySelector(':scope > a');
const hasDropdown = item.querySelector('.dropdown-menu');
if (link && hasDropdown) {
link.addEventListener('click', function(e) {
e.preventDefault();
item.classList.toggle('active');
// 关闭其他打开的一级菜单
navItems.forEach(otherItem => {
if (otherItem !== item) {
otherItem.classList.remove('active');
}
});
});
}
});
// 二级菜单点击
const dropdownItems = document.querySelectorAll('.dropdown-item');
dropdownItems.forEach(item => {
const link = item.querySelector(':scope > a');
const hasSubDropdown = item.querySelector('.sub-dropdown');
if (link && hasSubDropdown) {
link.addEventListener('click', function(e) {
e.preventDefault();
item.classList.toggle('active');
// 关闭其他打开的二级菜单
const siblings = Array.from(item.parentElement.children).filter(child => child !== item);
siblings.forEach(sibling => {
sibling.classList.remove('active');
});
});
}
});
// 三级菜单点击
const subDropdownItems = document.querySelectorAll('.sub-dropdown-item');
subDropdownItems.forEach(item => {
const link = item.querySelector(':scope > a');
const hasSubSubDropdown = item.querySelector('.sub-sub-dropdown');
if (link && hasSubSubDropdown) {
link.addEventListener('click', function(e) {
e.preventDefault();
item.classList.toggle('active');
// 关闭其他打开的三级菜单
const siblings = Array.from(item.parentElement.children).filter(child => child !== item);
siblings.forEach(sibling => {
sibling.classList.remove('active');
});
});
}
});
// 四级菜单点击
const subSubDropdownItems = document.querySelectorAll('.sub-sub-dropdown-item');
subSubDropdownItems.forEach(item => {
const link = item.querySelector(':scope > a');
const hasSubSubSubDropdown = item.querySelector('.sub-sub-sub-dropdown');
if (link && hasSubSubSubDropdown) {
link.addEventListener('click', function(e) {
e.preventDefault();
item.classList.toggle('active');
// 关闭其他打开的四级菜单
const siblings = Array.from(item.parentElement.children).filter(child => child !== item);
siblings.forEach(sibling => {
sibling.classList.remove('active');
});
});
}
});
}
}
// 初始加载和窗口大小改变时检查
handleMobileDropdowns();
window.addEventListener('resize', handleMobileDropdowns);
// 导航栏滚动效果
const header = document.querySelector('.header');
if (header) {
window.addEventListener('scroll', function() {
if (window.scrollY > 50) {
header.style.background = 'rgb(47, 85, 140)';
} else {
header.style.background = 'linear-gradient(rgb(47, 85, 140), rgba(47, 85, 140, 0.49), rgba(52, 94, 156, 0.04))';
}
});
}
});

4051
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

33
package.json Normal file
View File

@ -0,0 +1,33 @@
{
"name": "vite-react-typescript-starter",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"lucide-react": "^0.344.0",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@eslint/js": "^9.9.1",
"@types/react": "^18.3.5",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.3.1",
"autoprefixer": "^10.4.18",
"eslint": "^9.9.1",
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
"eslint-plugin-react-refresh": "^0.4.11",
"globals": "^15.9.0",
"postcss": "^8.4.35",
"tailwindcss": "^3.4.1",
"typescript": "^5.5.3",
"typescript-eslint": "^8.3.0",
"vite": "^5.4.2"
}
}

6
postcss.config.js Normal file
View File

@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

9
requirements.txt Normal file
View File

@ -0,0 +1,9 @@
Flask==3.0.2
Flask-SQLAlchemy==3.1.1
Flask-Login==0.6.3
Flask-WTF==1.2.1
PyMySQL==1.1.0
python-dotenv==1.0.1
Pillow==10.2.0
WTForms==3.1.2
Flask-CKEditor==0.5.1

11
src/App.tsx Normal file
View File

@ -0,0 +1,11 @@
import React from 'react';
function App() {
return (
<div className="min-h-screen bg-gray-100 flex items-center justify-center">
<p>Start prompting (or editing) to see magic happen :)</p>
</div>
);
}
export default App;

3
src/index.css Normal file
View File

@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

10
src/main.tsx Normal file
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>
);

1
src/vite-env.d.ts vendored Normal file
View File

@ -0,0 +1 @@
/// <reference types="vite/client" />

169
static/css/admin.css Normal file
View File

@ -0,0 +1,169 @@
/* 管理后台样式 */
:root {
--primary-color: #2F558C;
--secondary-color: #1a365d;
--success-color: #28a745;
--danger-color: #dc3545;
--light-gray: #f8f9fa;
--border-color: #dee2e6;
}
body {
margin: 0;
padding: 0;
font-family: 'Microsoft YaHei', sans-serif;
background-color: var(--light-gray);
}
/* 登录页面样式 */
.login-container {
max-width: 400px;
margin: 100px auto;
padding: 30px;
background: white;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.login-container h1 {
text-align: center;
color: var(--primary-color);
margin-bottom: 30px;
}
/* 管理后台布局 */
.admin-container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.admin-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
padding-bottom: 20px;
border-bottom: 1px solid var(--border-color);
}
/* 表单样式 */
.form-group {
margin-bottom: 20px;
}
.form-control {
width: 100%;
padding: 10px;
border: 1px solid var(--border-color);
border-radius: 4px;
font-size: 16px;
}
.form-control:focus {
outline: none;
border-color: var(--primary-color);
}
/* 按钮样式 */
.btn {
display: inline-block;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
text-decoration: none;
transition: background-color 0.3s;
}
.btn-primary {
background-color: var(--primary-color);
color: white;
}
.btn-primary:hover {
background-color: var(--secondary-color);
}
.btn-secondary {
background-color: var(--light-gray);
color: var(--secondary-color);
border: 1px solid var(--border-color);
}
.btn-secondary:hover {
background-color: #e9ecef;
}
.btn-danger {
background-color: var(--danger-color);
color: white;
}
.btn-danger:hover {
background-color: #c82333;
}
.btn-small {
padding: 5px 10px;
font-size: 14px;
}
/* 文章列表样式 */
.articles-list {
background: white;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.article-item {
padding: 20px;
border-bottom: 1px solid var(--border-color);
}
.article-item:last-child {
border-bottom: none;
}
.article-meta {
font-size: 14px;
color: #666;
margin: 10px 0;
}
.article-meta span {
margin-right: 20px;
}
.article-actions {
margin-top: 10px;
}
.inline-form {
display: inline;
}
/* 提示消息样式 */
.alert {
padding: 15px;
margin-bottom: 20px;
border-radius: 4px;
}
.alert-success {
background-color: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.alert-danger {
background-color: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
/* CKEditor 样式调整 */
.ck-editor__editable {
min-height: 300px;
}

70
static/css/article.css Normal file
View File

@ -0,0 +1,70 @@
/* 文章详情页样式 */
.article-container {
margin-top: 110px;
padding: 40px 0;
background-color: #fff;
}
.article-header {
margin-bottom: 30px;
}
.article-title {
font-size: 32px;
font-weight: bold;
color: #333;
margin-bottom: 20px;
text-align: left;
}
.article-meta {
text-align: right;
color: #666;
font-size: 14px;
padding-bottom: 20px;
border-bottom: 2px solid #eee;
margin-bottom: 30px;
}
.article-meta span {
margin-left: 20px;
}
.article-content {
font-size: 16px;
line-height: 1.8;
color: #333;
}
/* 响应式设计 */
@media (max-width: 992px) {
.article-container {
margin-top: 80px;
}
.article-title {
font-size: 28px;
}
}
@media (max-width: 768px) {
.article-container {
padding: 20px 0;
}
.article-title {
font-size: 24px;
}
.article-meta span {
display: block;
margin: 5px 0;
text-align: right;
}
}
@media (max-width: 576px) {
.article-title {
font-size: 20px;
}
}

181
static/css/carousel.css Normal file
View File

@ -0,0 +1,181 @@
/* 轮播图样式 */
.carousel-container {
position: relative;
width: 100%;
height: 100vh;
overflow: hidden;
margin-top: 110px;
}
.carousel-slides {
width: 100%;
height: 100%;
position: relative;
}
.carousel-slide {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
transition: opacity 1s ease;
z-index: 1;
}
.carousel-slide.active {
opacity: 1;
z-index: 2;
}
.carousel-slide img {
width: 100%;
height: 100%;
object-fit: cover;
}
.carousel-caption {
position: absolute;
bottom: 25%;
left: 10%;
max-width: 600px;
color: #fff;
text-align: left;
padding: 30px;
background-color: rgba(0, 0, 0, 0.5);
border-radius: 5px;
transform: translateY(20px);
opacity: 0;
transition: opacity 0.8s ease, transform 0.8s ease;
transition-delay: 0.3s;
}
.carousel-slide.active .carousel-caption {
opacity: 1;
transform: translateY(0);
}
.carousel-caption h2 {
font-size: 36px;
margin-bottom: 15px;
font-weight: bold;
}
.carousel-caption p {
font-size: 18px;
line-height: 1.6;
}
/* 轮播控制按钮 */
.carousel-controls {
position: absolute;
top: 50%;
width: 100%;
display: flex;
justify-content: space-between;
padding: 0 20px;
transform: translateY(-50%);
z-index: 10;
}
.carousel-control {
background-color: rgba(0, 0, 0, 0.5);
color: #fff;
border: none;
width: 50px;
height: 50px;
border-radius: 50%;
font-size: 24px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: background-color 0.3s ease;
}
.carousel-control:hover {
background-color: rgba(0, 0, 0, 0.8);
}
/* 轮播指示器 */
.carousel-indicators {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 10px;
z-index: 10;
}
.indicator {
width: 12px;
height: 12px;
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.5);
border: none;
cursor: pointer;
transition: background-color 0.3s ease, transform 0.3s ease;
}
.indicator.active {
background-color: #fff;
transform: scale(1.2);
}
/* 响应式设计 */
@media (max-width: 992px) {
.carousel-container {
margin-top: 80px;
height: 70vh;
}
.carousel-caption {
left: 5%;
max-width: 90%;
bottom: 20%;
}
.carousel-caption h2 {
font-size: 28px;
}
.carousel-caption p {
font-size: 16px;
}
}
@media (max-width: 768px) {
.carousel-container {
height: 60vh;
}
.carousel-controls {
display: none;
}
.carousel-caption h2 {
font-size: 24px;
}
.carousel-caption p {
font-size: 14px;
}
}
@media (max-width: 576px) {
.carousel-container {
height: 50vh;
}
.carousel-caption {
padding: 15px;
bottom: 15%;
}
.carousel-caption h2 {
font-size: 20px;
margin-bottom: 8px;
}
}

140
static/css/footer.css Normal file
View File

@ -0,0 +1,140 @@
/* 页脚样式 */
.footer {
background-color: #2F558C;
color: #fff;
}
/* 页脚主要部分 */
.footer-main {
padding: 50px 0;
}
.footer-content {
display: flex;
justify-content: space-between;
}
/* 页脚logo */
.footer-logo {
flex: 1;
max-width: 400px;
}
.footer-logo img {
max-height: 60px;
margin-bottom: 20px;
}
.footer-logo h2 {
font-size: 24px;
font-weight: bold;
margin-bottom: 10px;
}
.company-slogan {
color: rgba(255, 255, 255, 0.8);
margin-bottom: 20px;
}
/* 页脚联系信息 */
.footer-contact {
flex: 1;
max-width: 500px;
}
.footer-contact h3 {
font-size: 18px;
margin-bottom: 20px;
position: relative;
padding-bottom: 10px;
}
.footer-contact h3::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 40px;
height: 2px;
background-color: #fff;
}
.footer-contact ul {
margin-bottom: 20px;
}
.footer-contact ul li {
margin-bottom: 12px;
display: flex;
align-items: flex-start;
}
.footer-contact ul li i {
margin-top: 3px;
}
/* 社交媒体图标 */
.social-media {
display: flex;
gap: 15px;
}
.social-media a {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
background-color: rgba(255, 255, 255, 0.1);
border-radius: 50%;
transition: background-color 0.3s ease;
}
.social-media a:hover {
background-color: rgba(255, 255, 255, 0.2);
}
/* 页脚底部 */
.footer-bottom {
background-color: #1a365d;
padding: 15px 0;
}
.footer-bottom .container {
display: flex;
justify-content: center;
align-items: center;
gap: 30px;
}
.copyright, .icp {
font-size: 14px;
color: rgba(255, 255, 255, 0.7);
}
/* 响应式设计 */
@media (max-width: 992px) {
.footer-content {
flex-direction: column;
gap: 30px;
}
.footer-logo, .footer-contact {
max-width: 100%;
}
}
@media (max-width: 768px) {
.footer-main {
padding: 40px 0;
}
.footer-bottom .container {
flex-direction: column;
gap: 5px;
}
.copyright, .icp {
text-align: center;
}
}

278
static/css/navigation.css Normal file
View File

@ -0,0 +1,278 @@
/* 导航栏样式 */
.header {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 110px;
background: linear-gradient(rgb(47, 85, 140), rgba(47, 85, 140, 0.49), rgba(52, 94, 156, 0.04));
color: #fff;
z-index: 1000;
transition: background-color 0.3s ease;
}
.header .container {
display: flex;
justify-content: space-between;
align-items: center;
height: 100%;
}
/* Logo样式 */
.logo {
display: flex;
align-items: center;
}
.logo img {
max-height: 50px;
margin-right: 15px;
}
.logo h1 {
font-size: 24px;
font-weight: bold;
white-space: nowrap;
}
/* 主导航菜单 */
.main-nav {
position: relative;
height: 100%;
display: flex;
flex-direction: column;
justify-content: flex-start;
padding-top: 10px;
}
.nav-menu {
display: flex;
flex-direction: column;
align-items: flex-end;
height: 100%;
}
.nav-top {
display: flex;
gap: 20px;
margin-bottom: 15px;
height: 30%;
}
.nav-bottom {
display: flex;
gap: 20px;
height: 70%;
align-items: flex-start;
}
.nav-item {
position: relative;
}
.nav-link {
display: block;
color: #fff;
font-size: 16px;
font-weight: 500;
padding: 10px 15px;
transition: color 0.3s ease;
}
.nav-link:hover {
color: #f0f0f0;
}
/* 下拉菜单通用样式 */
.dropdown-menu,
.sub-dropdown,
.sub-sub-dropdown,
.sub-sub-sub-dropdown {
position: absolute;
background-color: #fff;
min-width: 200px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
opacity: 0;
visibility: hidden;
transform: translateY(10px);
transition: all 0.3s ease;
border-radius: 4px;
}
/* 一级下拉菜单 */
.dropdown-menu {
top: 100%;
left: 0;
z-index: 100;
}
.nav-item:hover > .dropdown-menu {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
/* 二级下拉菜单 */
.sub-dropdown {
top: 0;
left: 100%;
z-index: 101;
}
/* 三级下拉菜单 */
.sub-sub-dropdown {
top: 0;
left: 100%;
z-index: 102;
}
/* 四级下拉菜单 */
.sub-sub-sub-dropdown {
top: 0;
left: 100%;
z-index: 103;
}
/* 下拉菜单项通用样式 */
.dropdown-item,
.sub-dropdown-item,
.sub-sub-dropdown-item,
.sub-sub-sub-dropdown-item {
position: relative;
border-bottom: 1px solid #f0f0f0;
}
.dropdown-item:last-child,
.sub-dropdown-item:last-child,
.sub-sub-dropdown-item:last-child,
.sub-sub-sub-dropdown-item:last-child {
border-bottom: none;
}
.dropdown-item > a,
.sub-dropdown-item > a,
.sub-sub-dropdown-item > a,
.sub-sub-sub-dropdown-item > a {
display: block;
padding: 12px 16px;
color: #333;
transition: background-color 0.3s ease, color 0.3s ease;
}
.dropdown-item > a:hover,
.sub-dropdown-item > a:hover,
.sub-sub-dropdown-item > a:hover,
.sub-sub-sub-dropdown-item > a:hover {
background-color: #f8f9fa;
color: #2F558C;
}
/* 显示子菜单 */
.dropdown-item:hover > .sub-dropdown,
.sub-dropdown-item:hover > .sub-sub-dropdown,
.sub-sub-dropdown-item:hover > .sub-sub-sub-dropdown {
opacity: 1;
visibility: visible;
transform: translateX(0);
}
/* 移动端菜单按钮 */
.menu-toggle {
display: none;
background: none;
border: none;
color: #fff;
font-size: 24px;
cursor: pointer;
padding: 10px;
}
/* 响应式设计 */
@media (max-width: 1200px) {
.nav-link {
padding: 10px 10px;
}
}
@media (max-width: 992px) {
.header {
height: 80px;
}
.logo h1 {
font-size: 20px;
}
.menu-toggle {
display: block;
}
.nav-menu {
position: absolute;
top: 80px;
left: 0;
width: 100%;
background-color: #2F558C;
flex-direction: column;
align-items: flex-start;
padding: 20px 0;
display: none;
}
.nav-menu.active {
display: flex;
}
.nav-top,
.nav-bottom {
flex-direction: column;
width: 100%;
gap: 0;
margin: 0;
height: auto;
}
.nav-item {
width: 100%;
margin-left: 0;
}
.nav-link {
padding: 12px 20px;
}
.dropdown-menu,
.sub-dropdown,
.sub-sub-dropdown,
.sub-sub-sub-dropdown {
position: static;
opacity: 1;
visibility: visible;
transform: none;
box-shadow: none;
width: 100%;
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease;
}
.nav-item.active > .dropdown-menu,
.dropdown-item.active > .sub-dropdown,
.sub-dropdown-item.active > .sub-sub-dropdown,
.sub-sub-dropdown-item.active > .sub-sub-sub-dropdown {
max-height: 500px;
}
.dropdown-item > a,
.sub-dropdown-item > a,
.sub-sub-dropdown-item > a,
.sub-sub-sub-dropdown-item > a {
padding-left: 30px;
}
.sub-dropdown,
.sub-sub-dropdown,
.sub-sub-sub-dropdown {
padding-left: 20px;
}
}

192
static/css/news.css Normal file
View File

@ -0,0 +1,192 @@
/* 新闻动态样式 */
.news-section {
padding: 60px 0;
background-color: #fff;
}
.news-container {
display: flex;
gap: 30px;
margin-top: 40px;
}
/* 特色新闻 */
.featured-news {
flex: 2;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.08);
overflow: hidden;
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.featured-news:hover {
transform: translateY(-5px);
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.12);
}
.news-image {
width: 100%;
height: 300px;
overflow: hidden;
}
.news-image img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.5s ease;
}
.featured-news:hover .news-image img {
transform: scale(1.05);
}
.news-content {
padding: 25px;
}
.news-title {
font-size: 22px;
font-weight: bold;
color: #333;
margin-bottom: 10px;
line-height: 1.3;
}
.news-date {
font-size: 14px;
color: #666;
margin-bottom: 15px;
}
.news-summary {
color: #555;
line-height: 1.6;
margin-bottom: 20px;
}
.read-more {
display: inline-block;
color: #2F558C;
font-weight: 500;
position: relative;
padding-right: 20px;
}
.read-more::after {
content: '→';
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
transition: transform 0.3s ease;
}
.read-more:hover::after {
transform: translate(5px, -50%);
}
/* 新闻列表 */
.news-list {
flex: 1;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.08);
padding: 25px;
}
.news-list h3 {
font-size: 20px;
color: #2F558C;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 2px solid #f0f0f0;
}
.news-list ul li {
padding: 15px 0;
border-bottom: 1px solid #f0f0f0;
}
.news-list ul li:last-child {
border-bottom: none;
}
.news-list ul li a {
display: block;
color: #333;
font-weight: 500;
line-height: 1.4;
margin-bottom: 5px;
transition: color 0.3s ease;
}
.news-list ul li a:hover {
color: #2F558C;
}
.list-date {
display: block;
font-size: 13px;
color: #666;
}
.view-all {
display: block;
text-align: center;
margin-top: 20px;
padding: 10px;
background-color: #f8f9fa;
color: #2F558C;
border-radius: 4px;
transition: background-color 0.3s ease;
}
.view-all:hover {
background-color: #e9ecef;
}
/* 响应式设计 */
@media (max-width: 992px) {
.news-container {
flex-direction: column;
}
.featured-news, .news-list {
flex: none;
width: 100%;
}
.news-image {
height: 250px;
}
}
@media (max-width: 768px) {
.news-section {
padding: 40px 0;
}
.news-title {
font-size: 20px;
}
.news-image {
height: 200px;
}
}
@media (max-width: 576px) {
.news-content {
padding: 15px;
}
.news-list {
padding: 15px;
}
.news-image {
height: 180px;
}
}

122
static/css/styles.css Normal file
View File

@ -0,0 +1,122 @@
/* 基础样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', sans-serif;
font-size: 16px;
line-height: 1.5;
color: #333;
background-color: #f8f9fa;
}
.container {
width: 80%;
max-width: 1400px;
margin: 0 auto;
padding: 0 15px;
}
a {
text-decoration: none;
color: #2F558C;
transition: color 0.3s ease;
}
a:hover {
color: #1a365d;
}
ul {
list-style: none;
}
img {
max-width: 100%;
height: auto;
display: block;
}
/* 图标字体占位样式(实际应用中替换为实际图标) */
[class^="icon-"] {
display: inline-block;
width: 16px;
height: 16px;
margin-right: 8px;
background-color: #2F558C;
vertical-align: middle;
}
/* 通用按钮样式 */
.btn {
display: inline-block;
padding: 8px 16px;
background-color: #2F558C;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s ease;
}
.btn:hover {
background-color: #1a365d;
}
/* 章节标题 */
.section-title {
position: relative;
font-size: 28px;
font-weight: bold;
color: #2F558C;
margin-bottom: 32px;
text-align: center;
padding-bottom: 12px;
}
.section-title::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 60px;
height: 3px;
background-color: #2F558C;
}
/* 响应式设计 */
@media (max-width: 1200px) {
.container {
width: 90%;
}
}
@media (max-width: 992px) {
.section-title {
font-size: 24px;
}
}
@media (max-width: 768px) {
.container {
width: 95%;
}
.section-title {
font-size: 22px;
}
}
@media (max-width: 576px) {
body {
font-size: 14px;
}
.section-title {
font-size: 20px;
}
}

56
static/css/submenu.css Normal file
View File

@ -0,0 +1,56 @@
/* 子菜单页面样式 */
.submenu-container {
margin-top: 110px;
min-height: calc(100vh - 110px - 300px); /* 减去头部和底部的高度 */
padding: 40px 0;
background-color: #fff;
}
.page-title {
font-size: 32px;
font-weight: bold;
color: #2F558C;
margin-bottom: 30px;
padding-bottom: 15px;
border-bottom: 2px solid #eee;
}
.content-placeholder {
text-align: center;
padding: 100px 0;
color: #666;
font-size: 18px;
}
/* 响应式设计 */
@media (max-width: 992px) {
.submenu-container {
margin-top: 80px;
min-height: calc(100vh - 80px - 300px);
}
.page-title {
font-size: 28px;
}
}
@media (max-width: 768px) {
.submenu-container {
padding: 20px 0;
}
.page-title {
font-size: 24px;
}
.content-placeholder {
padding: 60px 0;
font-size: 16px;
}
}
@media (max-width: 576px) {
.page-title {
font-size: 20px;
}
}

130
static/js/carousel.js Normal file
View File

@ -0,0 +1,130 @@
// 轮播图功能
document.addEventListener('DOMContentLoaded', function() {
const slides = document.querySelectorAll('.carousel-slide');
const indicators = document.querySelectorAll('.indicator');
const prevBtn = document.querySelector('.carousel-control.prev');
const nextBtn = document.querySelector('.carousel-control.next');
if (!slides.length) return;
let currentSlide = 0;
let slideInterval;
const slideDelay = 3000; // 3秒轮播间隔
// 初始化轮播
function startSlideshow() {
slideInterval = setInterval(nextSlide, slideDelay);
}
// 停止轮播
function stopSlideshow() {
clearInterval(slideInterval);
}
// 显示指定幻灯片
function showSlide(index) {
if (index < 0) {
index = slides.length - 1;
} else if (index >= slides.length) {
index = 0;
}
// 隐藏当前幻灯片
slides[currentSlide].classList.remove('active');
if (indicators.length) {
indicators[currentSlide].classList.remove('active');
}
// 显示新幻灯片
currentSlide = index;
slides[currentSlide].classList.add('active');
if (indicators.length) {
indicators[currentSlide].classList.add('active');
}
}
// 下一张幻灯片
function nextSlide() {
showSlide(currentSlide + 1);
}
// 上一张幻灯片
function prevSlide() {
showSlide(currentSlide - 1);
}
// 绑定指示器点击事件
if (indicators.length) {
indicators.forEach((indicator, index) => {
indicator.addEventListener('click', () => {
stopSlideshow();
showSlide(index);
startSlideshow();
});
});
}
// 绑定方向按钮点击事件
if (prevBtn) {
prevBtn.addEventListener('click', () => {
stopSlideshow();
prevSlide();
startSlideshow();
});
}
if (nextBtn) {
nextBtn.addEventListener('click', () => {
stopSlideshow();
nextSlide();
startSlideshow();
});
}
// 当鼠标悬停在轮播图上时暂停轮播
const carouselContainer = document.querySelector('.carousel-container');
if (carouselContainer) {
carouselContainer.addEventListener('mouseenter', stopSlideshow);
carouselContainer.addEventListener('mouseleave', startSlideshow);
}
// 当用户触摸屏幕时也暂停轮播
if (carouselContainer) {
carouselContainer.addEventListener('touchstart', stopSlideshow, {passive: true});
carouselContainer.addEventListener('touchend', startSlideshow, {passive: true});
}
// 添加触摸滑动支持
let touchStartX = 0;
let touchEndX = 0;
if (carouselContainer) {
carouselContainer.addEventListener('touchstart', (e) => {
touchStartX = e.changedTouches[0].screenX;
}, {passive: true});
carouselContainer.addEventListener('touchend', (e) => {
touchEndX = e.changedTouches[0].screenX;
handleSwipe();
}, {passive: true});
}
function handleSwipe() {
// 计算滑动距离
const swipeDistance = touchEndX - touchStartX;
const minSwipeDistance = 50; // 最小有效滑动距离
if (swipeDistance > minSwipeDistance) {
// 向右滑动,显示上一张
prevSlide();
} else if (swipeDistance < -minSwipeDistance) {
// 向左滑动,显示下一张
nextSlide();
}
startSlideshow();
}
// 启动轮播
startSlideshow();
});

103
static/js/main.js Normal file
View File

@ -0,0 +1,103 @@
// 主要功能脚本
document.addEventListener('DOMContentLoaded', function() {
// 更新页面标题
document.title = '企业名称 - 数字化企业服务领导者';
// 图片加载优化
function lazyLoadImages() {
const images = document.querySelectorAll('img');
if ('IntersectionObserver' in window) {
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const image = entry.target;
// 如果图片有data-src属性则将其加载
if (image.dataset.src) {
image.src = image.dataset.src;
image.removeAttribute('data-src');
}
imageObserver.unobserve(image);
}
});
});
images.forEach(image => {
imageObserver.observe(image);
});
}
}
// 滚动到顶部按钮
function createScrollTopButton() {
const scrollBtn = document.createElement('button');
scrollBtn.innerHTML = '↑';
scrollBtn.className = 'scroll-top-btn';
scrollBtn.style.cssText = `
position: fixed;
bottom: 20px;
right: 20px;
width: 40px;
height: 40px;
border-radius: 50%;
background-color: #2F558C;
color: white;
border: none;
display: none;
align-items: center;
justify-content: center;
font-size: 20px;
cursor: pointer;
z-index: 999;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
`;
document.body.appendChild(scrollBtn);
// 显示/隐藏按钮
window.addEventListener('scroll', () => {
if (window.scrollY > 300) {
scrollBtn.style.display = 'flex';
} else {
scrollBtn.style.display = 'none';
}
});
// 点击按钮滚动到顶部
scrollBtn.addEventListener('click', () => {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
});
}
// 平滑滚动到锚点
function setupSmoothScrolling() {
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function(e) {
const href = this.getAttribute('href');
if (href !== '#') {
e.preventDefault();
const targetElement = document.querySelector(href);
if (targetElement) {
const headerHeight = document.querySelector('.header').offsetHeight;
const targetPosition = targetElement.getBoundingClientRect().top + window.pageYOffset - headerHeight;
window.scrollTo({
top: targetPosition,
behavior: 'smooth'
});
}
}
});
});
}
// 执行所有初始化功能
lazyLoadImages();
createScrollTopButton();
setupSmoothScrolling();
});

122
static/js/navigation.js Normal file
View File

@ -0,0 +1,122 @@
// 导航菜单功能
document.addEventListener('DOMContentLoaded', function() {
// 移动端菜单切换
const menuToggle = document.createElement('button');
menuToggle.className = 'menu-toggle';
menuToggle.innerHTML = '☰';
menuToggle.setAttribute('aria-label', '菜单');
const nav = document.querySelector('.main-nav');
const navMenu = document.querySelector('.nav-menu');
if (nav && navMenu) {
nav.insertBefore(menuToggle, navMenu);
menuToggle.addEventListener('click', function() {
navMenu.classList.toggle('active');
this.innerHTML = navMenu.classList.contains('active') ? '✕' : '☰';
});
}
// 移动端下拉菜单处理
function handleMobileDropdowns() {
if (window.innerWidth <= 992) {
// 一级菜单点击
const navItems = document.querySelectorAll('.nav-item');
navItems.forEach(item => {
const link = item.querySelector(':scope > a');
const hasDropdown = item.querySelector('.dropdown-menu');
if (link && hasDropdown) {
link.addEventListener('click', function(e) {
e.preventDefault();
item.classList.toggle('active');
// 关闭其他打开的一级菜单
navItems.forEach(otherItem => {
if (otherItem !== item) {
otherItem.classList.remove('active');
}
});
});
}
});
// 二级菜单点击
const dropdownItems = document.querySelectorAll('.dropdown-item');
dropdownItems.forEach(item => {
const link = item.querySelector(':scope > a');
const hasSubDropdown = item.querySelector('.sub-dropdown');
if (link && hasSubDropdown) {
link.addEventListener('click', function(e) {
e.preventDefault();
item.classList.toggle('active');
// 关闭其他打开的二级菜单
const siblings = Array.from(item.parentElement.children).filter(child => child !== item);
siblings.forEach(sibling => {
sibling.classList.remove('active');
});
});
}
});
// 三级菜单点击
const subDropdownItems = document.querySelectorAll('.sub-dropdown-item');
subDropdownItems.forEach(item => {
const link = item.querySelector(':scope > a');
const hasSubSubDropdown = item.querySelector('.sub-sub-dropdown');
if (link && hasSubSubDropdown) {
link.addEventListener('click', function(e) {
e.preventDefault();
item.classList.toggle('active');
// 关闭其他打开的三级菜单
const siblings = Array.from(item.parentElement.children).filter(child => child !== item);
siblings.forEach(sibling => {
sibling.classList.remove('active');
});
});
}
});
// 四级菜单点击
const subSubDropdownItems = document.querySelectorAll('.sub-sub-dropdown-item');
subSubDropdownItems.forEach(item => {
const link = item.querySelector(':scope > a');
const hasSubSubSubDropdown = item.querySelector('.sub-sub-sub-dropdown');
if (link && hasSubSubSubDropdown) {
link.addEventListener('click', function(e) {
e.preventDefault();
item.classList.toggle('active');
// 关闭其他打开的四级菜单
const siblings = Array.from(item.parentElement.children).filter(child => child !== item);
siblings.forEach(sibling => {
sibling.classList.remove('active');
});
});
}
});
}
}
// 初始加载和窗口大小改变时检查
handleMobileDropdowns();
window.addEventListener('resize', handleMobileDropdowns);
// 导航栏滚动效果
const header = document.querySelector('.header');
if (header) {
window.addEventListener('scroll', function() {
if (window.scrollY > 50) {
header.style.background = 'rgb(47, 85, 140)';
} else {
header.style.background = 'linear-gradient(rgb(47, 85, 140), rgba(47, 85, 140, 0.49), rgba(52, 94, 156, 0.04))';
}
});
}
});

8
tailwind.config.js Normal file
View File

@ -0,0 +1,8 @@
/** @type {import('tailwindcss').Config} */
export default {
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
theme: {
extend: {},
},
plugins: [],
};

46
templates/admin.html Normal file
View File

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>管理后台 - 猎狐企服</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/admin.css') }}">
</head>
<body>
<div class="admin-container">
<header class="admin-header">
<h1>文章管理</h1>
<nav>
<a href="{{ url_for('new_article') }}" class="btn btn-primary">发布新文章</a>
<a href="{{ url_for('logout') }}" class="btn btn-secondary">退出登录</a>
</nav>
</header>
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
<div class="alert alert-success">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
<div class="articles-list">
{% for article in articles %}
<div class="article-item">
<h2>{{ article.title }}</h2>
<div class="article-meta">
<span>发布时间: {{ article.created_at.strftime('%Y-%m-%d %H:%M') }}</span>
<span>更新时间: {{ article.updated_at.strftime('%Y-%m-%d %H:%M') }}</span>
</div>
<div class="article-actions">
<a href="{{ url_for('edit_article', id=article.id) }}" class="btn btn-small">编辑</a>
<form action="{{ url_for('delete_article', id=article.id) }}" method="POST" class="inline-form">
<button type="submit" class="btn btn-small btn-danger" onclick="return confirm('确定要删除这篇文章吗?')">删除</button>
</form>
</div>
</div>
{% endfor %}
</div>
</div>
</body>
</html>

38
templates/article.html Normal file
View File

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ article.title }} - 猎狐企服</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/navigation.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/article.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/footer.css') }}">
</head>
<body>
<!-- 导航栏 -->
{% include 'includes/header.html' %}
<!-- 文章内容 -->
<article class="article-container">
<div class="container">
<div class="article-header">
<h1 class="article-title">{{ article.title }}</h1>
<div class="article-meta">
<span>发布时间:{{ article.created_at.strftime('%Y-%m-%d %H:%M') }}</span>
<span>更新时间:{{ article.updated_at.strftime('%Y-%m-%d %H:%M') }}</span>
</div>
</div>
<div class="article-content">
{{ article.content|safe }}
</div>
</div>
</article>
<!-- 页脚 -->
{% include 'includes/footer.html' %}
<script src="{{ url_for('static', filename='js/navigation.js') }}"></script>
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
</body>
</html>

View File

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% if article %}编辑文章{% else %}发布新文章{% endif %} - 猎狐企服</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/admin.css') }}">
{{ ckeditor.load() }}
</head>
<body>
<div class="admin-container">
<header class="admin-header">
<h1>{% if article %}编辑文章{% else %}发布新文章{% endif %}</h1>
<nav>
<a href="{{ url_for('admin') }}" class="btn btn-secondary">返回列表</a>
</nav>
</header>
<form method="POST" class="article-form">
{{ form.hidden_tag() }}
<div class="form-group">
{{ form.title.label }}
{{ form.title(class="form-control") }}
</div>
<div class="form-group">
{{ form.content.label }}
{{ form.content() }}
</div>
{{ form.submit(class="btn btn-primary") }}
</form>
</div>
</body>
</html>

View File

@ -0,0 +1,33 @@
<!-- 页脚 -->
<footer class="footer">
<div class="footer-main">
<div class="container">
<div class="footer-content">
<div class="footer-logo">
<img src="https://resources.jsmo.xin/templates/upload/34449/202401/1704161701959.png" alt="猎狐企服Logo">
<h2>猎贝狐企服</h2>
<p class="company-slogan">数字化企业服务领导者</p>
</div>
<div class="footer-contact">
<h3>联系我们</h3>
<ul>
<li><i class="icon-location"></i>地址云南省昆明市某某区某某街道123号</li>
<li><i class="icon-phone"></i>电话0871-12345678</li>
<li><i class="icon-email"></i>邮箱contact@company.com</li>
</ul>
<div class="social-media">
<a href="#"><i class="icon-weixin"></i></a>
<a href="#"><i class="icon-weibo"></i></a>
<a href="#"><i class="icon-douyin"></i></a>
</div>
</div>
</div>
</div>
</div>
<div class="footer-bottom">
<div class="container">
<p class="copyright">© 2024 猎狐企服 版权所有</p>
<p class="icp">滇ICP备12345678号-1</p>
</div>
</div>
</footer>

View File

@ -0,0 +1,141 @@
<!-- 导航栏 -->
<header class="header">
<div class="container">
<div class="logo">
<a href="{{ url_for('index') }}">
<img src="https://resources.jsmo.xin/templates/upload/34449/202401/1704161701959.png" alt="猎狐企服Logo">
<h1>猎狐企服</h1>
</a>
</div>
<nav class="main-nav">
<ul class="nav-menu">
<div class="nav-top">
<li class="nav-item"><a href="#" class="nav-link">关于我们</a></li>
<li class="nav-item"><a href="#" class="nav-link">新闻动态</a></li>
<li class="nav-item"><a href="#" class="nav-link">联系我们</a></li>
<li class="nav-item">
{% if current_user.is_authenticated %}
<a href="{{ url_for('admin') }}" class="nav-link">{{ current_user.username }}</a>
{% else %}
<a href="{{ url_for('login') }}" class="nav-link">管理员登录</a>
{% endif %}
</li>
</div>
<div class="nav-bottom">
<!-- 一级菜单: 数字化企业服务 -->
<li class="nav-item">
<a href="#" class="nav-link">数字化企业服务</a>
<ul class="dropdown-menu">
<li class="dropdown-item">
<a href="#">网络营销业务线</a>
<ul class="sub-dropdown">
<li class="sub-dropdown-item">
<a href="#">腾讯广告事业部</a>
<ul class="sub-sub-dropdown">
<li class="sub-sub-dropdown-item"><a href="{{ url_for('information_flow') }}">信息流</a></li>
<li class="sub-sub-dropdown-item"><a href="{{ url_for('short_video') }}">短视频</a></li>
<li class="sub-sub-dropdown-item"><a href="{{ url_for('search') }}">搜索(搜狗)</a></li>
</ul>
</li>
<li class="sub-dropdown-item">
<a href="#">平台媒体事业部</a>
<ul class="sub-sub-dropdown">
<li class="sub-sub-dropdown-item"><a href="{{ url_for('kuaishou') }}">快手项目部</a></li>
<li class="sub-sub-dropdown-item"><a href="{{ url_for('platform_360') }}">360项目部</a></li>
<li class="sub-sub-dropdown-item"><a href="{{ url_for('ali') }}">阿里汇川项目部</a></li>
<li class="sub-sub-dropdown-item"><a href="{{ url_for('gaode') }}">高德项目部</a></li>
</ul>
</li>
</ul>
</li>
<li class="dropdown-item">
<a href="#">软件管理业务线</a>
<ul class="sub-dropdown">
<li class="sub-dropdown-item"><a href="{{ url_for('yonyou') }}">用友事业部</a></li>
<li class="sub-dropdown-item"><a href="{{ url_for('dingtalk') }}">钉钉项目部</a></li>
<li class="sub-dropdown-item"><a href="{{ url_for('wecom') }}">企微项目部</a></li>
<li class="sub-dropdown-item"><a href="{{ url_for('feishu') }}">飞书项目部</a></li>
<li class="sub-dropdown-item"><a href="{{ url_for('youzan') }}">有赞项目部</a></li>
<li class="sub-dropdown-item"><a href="{{ url_for('crm') }}">CRM项目部</a></li>
<li class="sub-dropdown-item"><a href="{{ url_for('development') }}">技术开发部</a></li>
</ul>
</li>
<li class="dropdown-item">
<a href="#">财税法务业务线</a>
<ul class="sub-dropdown">
<li class="sub-dropdown-item"><a href="{{ url_for('badun_legal') }}">八盾法务</a></li>
<li class="sub-dropdown-item"><a href="{{ url_for('badun_asset') }}">八盾资产</a></li>
<li class="sub-dropdown-item"><a href="{{ url_for('beike_finance') }}">贝壳财税</a></li>
</ul>
</li>
</ul>
</li>
<!-- 一级菜单: 电商及MCN -->
<li class="nav-item">
<a href="#" class="nav-link">电商及MCN</a>
<ul class="dropdown-menu">
<li class="dropdown-item">
<a href="#">直播电商事业部</a>
<ul class="sub-dropdown">
<li class="sub-dropdown-item"><a href="{{ url_for('selection') }}">选品招商</a></li>
<li class="sub-dropdown-item"><a href="{{ url_for('traceability') }}">溯源专场</a></li>
<li class="sub-dropdown-item"><a href="{{ url_for('supply_chain') }}">供应链金融</a></li>
</ul>
</li>
<li class="dropdown-item">
<a href="#">达人运营事业部</a>
<ul class="sub-dropdown">
<li class="sub-dropdown-item"><a href="{{ url_for('talent_business') }}">达人商务</a></li>
<li class="sub-dropdown-item"><a href="{{ url_for('account_operation') }}">账号运营</a></li>
<li class="sub-dropdown-item"><a href="{{ url_for('live_operation') }}">直播运营</a></li>
</ul>
</li>
<li class="dropdown-item">
<a href="#">平台电商事业部</a>
<ul class="sub-dropdown">
<li class="sub-dropdown-item"><a href="{{ url_for('pinduoduo') }}">拼多多项目部</a></li>
<li class="sub-dropdown-item"><a href="{{ url_for('taotian') }}">淘天项目部</a></li>
<li class="sub-dropdown-item"><a href="{{ url_for('jd') }}">京东项目部</a></li>
</ul>
</li>
</ul>
</li>
<!-- 一级菜单: 文旅与大健康 -->
<li class="nav-item">
<a href="#" class="nav-link">文旅与大健康</a>
<ul class="dropdown-menu">
<li class="dropdown-item"><a href="{{ url_for('yueke') }}">悦客嘉酒店管理</a></li>
<li class="dropdown-item"><a href="{{ url_for('stem_cell') }}">昆大干细胞</a></li>
<li class="dropdown-item"><a href="{{ url_for('massage') }}">邱氏百年中医推拿</a></li>
<li class="dropdown-item"><a href="{{ url_for('dental') }}">袋鼠齿盟</a></li>
</ul>
</li>
<!-- 一级菜单: 平台运营管理 -->
<li class="nav-item">
<a href="#" class="nav-link">平台运营管理</a>
<ul class="dropdown-menu">
<li class="dropdown-item"><a href="{{ url_for('changqi') }}">长企网</a></li>
<li class="dropdown-item"><a href="{{ url_for('badun') }}">八盾资产</a></li>
<li class="dropdown-item"><a href="{{ url_for('limao') }}">礼猫猫</a></li>
<li class="dropdown-item"><a href="{{ url_for('yunfang') }}">云纺科技园</a></li>
<li class="dropdown-item"><a href="{{ url_for('cell_park') }}">昆明细胞产业园</a></li>
<li class="dropdown-item"><a href="{{ url_for('digital') }}">云南数字企业平台</a></li>
<li class="dropdown-item"><a href="{{ url_for('association') }}">云南省互联网零售业协会</a></li>
</ul>
</li>
<!-- 一级菜单: 品牌与投资 -->
<li class="nav-item">
<a href="#" class="nav-link">品牌与投资</a>
<ul class="dropdown-menu">
<li class="dropdown-item"><a href="{{ url_for('jiabeijia') }}">佳贝佳</a></li>
<li class="dropdown-item"><a href="{{ url_for('beicheng') }}">贝成教育</a></li>
<li class="dropdown-item"><a href="{{ url_for('xiaohua') }}">云南小花</a></li>
<li class="dropdown-item"><a href="{{ url_for('guoxiaofu') }}">果小福</a></li>
<li class="dropdown-item"><a href="{{ url_for('xiaxiong') }}">夏小熊</a></li>
</ul>
</li>
</div>
</ul>
</nav>
</div>
</header>

92
templates/index.html Normal file
View File

@ -0,0 +1,92 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>猎狐企服 - 数字化企业服务领导者</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/navigation.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/carousel.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/news.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/footer.css') }}">
</head>
<body>
{% include 'includes/header.html' %}
<!-- 轮播图 -->
<section class="carousel-container">
<div class="carousel-slides">
<div class="carousel-slide active">
<img src="https://resources.jsmo.xin/templates/upload/34449/202401/1705058156515.jpg" alt="企业展示1">
<div class="carousel-caption">
<h2>数字化转型领导者</h2>
<p>为企业提供全方位的数字化解决方案,助力企业实现数字化转型升级。</p>
</div>
</div>
<div class="carousel-slide">
<img src="https://resources.jsmo.xin/templates/upload/34449/202401/1705058071139.jpg" alt="企业展示2">
<div class="carousel-caption">
<h2>创新驱动发展</h2>
<p>以创新为驱动力,为企业带来持续增长的动力。</p>
</div>
</div>
<div class="carousel-slide">
<img src="https://resources.jsmo.xin/templates/upload/34449/202401/1705058127381.jpg" alt="企业展示3">
<div class="carousel-caption">
<h2>专业服务团队</h2>
<p>拥有经验丰富的专业团队,为客户提供高质量的服务支持。</p>
</div>
</div>
</div>
<div class="carousel-controls">
<button class="carousel-control prev"></button>
<button class="carousel-control next"></button>
</div>
<div class="carousel-indicators">
<button class="indicator active"></button>
<button class="indicator"></button>
<button class="indicator"></button>
</div>
</section>
<!-- 新闻动态 -->
<section class="news-section">
<div class="container">
<h2 class="section-title">新闻动态</h2>
<div class="news-container">
{% if featured_article %}
<div class="featured-news">
<div class="news-image">
<img src="https://images.pexels.com/photos/3184465/pexels-photo-3184465.jpeg" alt="新闻图片">
</div>
<div class="news-content">
<h3 class="news-title">{{ featured_article.title }}</h3>
<p class="news-date">{{ featured_article.created_at.strftime('%Y-%m-%d') }}</p>
<div class="news-summary">{{ featured_article.content|safe|truncate(200) }}</div>
<a href="{{ url_for('article_detail', id=featured_article.id) }}" class="read-more">阅读更多</a>
</div>
</div>
{% endif %}
<div class="news-list">
<h3>最新动态</h3>
<ul>
{% for article in latest_articles %}
<li>
<a href="{{ url_for('article_detail', id=article.id) }}">{{ article.title }}</a>
<span class="list-date">{{ article.created_at.strftime('%Y-%m-%d') }}</span>
</li>
{% endfor %}
</ul>
<a href="#" class="view-all">查看全部</a>
</div>
</div>
</div>
</section>
{% include 'includes/footer.html' %}
<script src="{{ url_for('static', filename='js/navigation.js') }}"></script>
<script src="{{ url_for('static', filename='js/carousel.js') }}"></script>
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
</body>
</html>

33
templates/login.html Normal file
View File

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>登录 - 猎狐企服管理系统</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/admin.css') }}">
</head>
<body>
<div class="login-container">
<h1>猎狐企服管理系统</h1>
<form method="POST" class="login-form">
{{ form.hidden_tag() }}
<div class="form-group">
{{ form.username.label }}
{{ form.username(class="form-control") }}
</div>
<div class="form-group">
{{ form.password.label }}
{{ form.password(class="form-control") }}
</div>
{{ form.submit(class="btn btn-primary") }}
</form>
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
<div class="alert alert-danger">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
</div>
</body>
</html>

View File

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ title }} - 猎狐企服</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/navigation.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/footer.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/submenu.css') }}">
</head>
<body>
{% include 'includes/header.html' %}
<div class="submenu-container">
<div class="container">
<h1 class="page-title">{{ title }}</h1>
<div class="content-placeholder">
<p>页面内容建设中...</p>
</div>
</div>
</div>
{% include 'includes/footer.html' %}
<script src="{{ url_for('static', filename='js/navigation.js') }}"></script>
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
</body>
</html>

24
tsconfig.app.json Normal file
View File

@ -0,0 +1,24 @@
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"]
}

7
tsconfig.json Normal file
View File

@ -0,0 +1,7 @@
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
]
}

22
tsconfig.node.json Normal file
View File

@ -0,0 +1,22 @@
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2023"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["vite.config.ts"]
}

10
vite.config.ts Normal file
View File

@ -0,0 +1,10 @@
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
optimizeDeps: {
exclude: ['lucide-react'],
},
});