大型企业官网全栈解决方案

54 阅读6分钟

项目结构

/company-website/
├── admin/                 # 后台管理目录
│   ├── css/
│   ├── js/
│   ├── uploads/           # 上传文件目录
│   ├── index.php          # 后台首页
│   ├── login.php          # 登录页面
│   └── ...                # 其他后台页面
├── api/                   # API接口目录
│   ├── v1/                # API版本
│   │   ├── news.php       # 新闻API
│   │   ├── products.php   # 产品API
│   │   └── ...           # 其他API
│   └── config.php         # API配置
├── assets/                # 前端静态资源
│   ├── css/
│   ├── js/
│   ├── images/
│   └── uploads/           # 前端访问的上传文件
├── includes/              # 公共包含文件
│   ├── config.php         # 数据库配置
│   ├── functions.php      # 公共函数
│   └── db.php             # 数据库连接
├── pages/                 # 独立页面目录
│   ├── index.php          # 首页
│   ├── about.php          # 关于我们
│   ├── news.php           # 新闻中心
│   ├── products.php       # 产品中心
│   └── contact.php        # 联系我们
├── .htaccess              # Apache伪静态规则
├── web.config             # IIS伪静态规则
└── index.php              # 前端入口文件

1. 数据库设计 (MySQL)

首先创建数据库和表:

CREATE DATABASE company_website CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 管理员表
CREATE TABLE admins (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL,
    password VARCHAR(255) NOT NULL,
    email VARCHAR(100) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 新闻表
CREATE TABLE news (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    content TEXT NOT NULL,
    image VARCHAR(255),
    category VARCHAR(50),
    status TINYINT DEFAULT 1,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

-- 产品表
CREATE TABLE products (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    description TEXT,
    price DECIMAL(10,2),
    image VARCHAR(255),
    category VARCHAR(50),
    status TINYINT DEFAULT 1,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

-- 页面内容表
CREATE TABLE pages (
    id INT AUTO_INCREMENT PRIMARY KEY,
    slug VARCHAR(50) NOT NULL,
    title VARCHAR(255) NOT NULL,
    content TEXT,
    meta_title VARCHAR(255),
    meta_description VARCHAR(255),
    status TINYINT DEFAULT 1,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

-- 插入初始管理员
INSERT INTO admins (username, password, email) VALUES 
('admin', '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 'admin@company.com');

2. 配置文件 (includes/config.php)

<?php
// 数据库配置
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASS', 'password');
define('DB_NAME', 'company_website');

// 网站配置
define('SITE_URL', 'http://localhost/company-website');
define('SITE_NAME', '企业官网');
define('UPLOAD_DIR', 'uploads/');
define('ADMIN_EMAIL', 'admin@company.com');

// 开启错误报告
error_reporting(E_ALL);
ini_set('display_errors', 1);

// 时区设置
date_default_timezone_set('Asia/Shanghai');

// 开启会话
session_start();
?>

3. 数据库连接 (includes/db.php)

<?php
require_once 'config.php';

class Database {
    private $conn;

    public function __construct() {
        $this->conn = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
        
        if ($this->conn->connect_error) {
            die("数据库连接失败: " . $this->conn->connect_error);
        }
        
        $this->conn->set_charset("utf8mb4");
    }

    public function getConnection() {
        return $this->conn;
    }

    public function query($sql) {
        return $this->conn->query($sql);
    }

    public function prepare($sql) {
        return $this->conn->prepare($sql);
    }

    public function lastInsertId() {
        return $this->conn->insert_id;
    }

    public function escape($str) {
        return $this->conn->real_escape_string($str);
    }

    public function __destruct() {
        $this->conn->close();
    }
}

// 公共函数
function redirect($url) {
    header("Location: $url");
    exit();
}

function isLoggedIn() {
    return isset($_SESSION['admin_id']);
}

function sanitize($data) {
    $data = trim($data);
    $data = stripslashes($data);
    $data = htmlspecialchars($data);
    return $data;
}
?>

4. 前端入口 (index.php)

<?php
require_once 'includes/db.php';

// 路由处理
$request = $_SERVER['REQUEST_URI'];
$page = str_replace('/company-website/', '', $request);

// 去除查询字符串
if (strpos($page, '?') !== false) {
    $page = substr($page, 0, strpos($page, '?'));
}

// 默认页面
if (empty($page) || $page == '/') {
    $page = 'index';
}

// 检查页面是否存在
$pageFile = 'pages/' . $page . '.php';

if (file_exists($pageFile)) {
    // 获取页面数据
    $db = new Database();
    $slug = ($page == 'index') ? 'home' : $page;
    $stmt = $db->prepare("SELECT * FROM pages WHERE slug = ? AND status = 1");
    $stmt->bind_param("s", $slug);
    $stmt->execute();
    $result = $stmt->get_result();
    $pageData = $result->fetch_assoc();
    $stmt->close();

    // 包含公共头部
    include 'includes/header.php';
    
    // 包含页面内容
    include $pageFile;
    
    // 包含公共底部
    include 'includes/footer.php';
} else {
    // 404页面
    header("HTTP/1.0 404 Not Found");
    include 'pages/404.php';
}
?>

5. 公共头部 (includes/header.php)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><?php echo isset($pageData['meta_title']) ? $pageData['meta_title'] : SITE_NAME; ?></title>
    <meta name="description" content="<?php echo isset($pageData['meta_description']) ? $pageData['meta_description'] : SITE_NAME; ?>">
    
    <!-- CSS -->
    <link rel="stylesheet" href="assets/css/bootstrap.min.css">
    <link rel="stylesheet" href="assets/css/font-awesome.min.css">
    <link rel="stylesheet" href="assets/css/style.css">
    
    <!-- Favicon -->
    <link rel="icon" href="assets/images/favicon.ico" type="image/x-icon">
</head>
<body>
    <header class="header">
        <nav class="navbar navbar-expand-lg navbar-light bg-light">
            <div class="container">
                <a class="navbar-brand" href="<?php echo SITE_URL; ?>"><?php echo SITE_NAME; ?></a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="collapse navbar-collapse" id="navbarNav">
                    <ul class="navbar-nav ml-auto">
                        <li class="nav-item <?php echo ($page == 'index') ? 'active' : ''; ?>">
                            <a class="nav-link" href="<?php echo SITE_URL; ?>">首页</a>
                        </li>
                        <li class="nav-item <?php echo ($page == 'about') ? 'active' : ''; ?>">
                            <a class="nav-link" href="<?php echo SITE_URL; ?>/about">关于我们</a>
                        </li>
                        <li class="nav-item <?php echo ($page == 'products') ? 'active' : ''; ?>">
                            <a class="nav-link" href="<?php echo SITE_URL; ?>/products">产品中心</a>
                        </li>
                        <li class="nav-item <?php echo ($page == 'news') ? 'active' : ''; ?>">
                            <a class="nav-link" href="<?php echo SITE_URL; ?>/news">新闻中心</a>
                        </li>
                        <li class="nav-item <?php echo ($page == 'contact') ? 'active' : ''; ?>">
                            <a class="nav-link" href="<?php echo SITE_URL; ?>/contact">联系我们</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>

    <main class="main-content">

6. 公共底部 (includes/footer.php)

    </main>

    <footer class="footer bg-dark text-white py-5">
        <div class="container">
            <div class="row">
                <div class="col-md-4">
                    <h5>关于我们</h5>
                    <p>企业简介和核心价值观</p>
                </div>
                <div class="col-md-4">
                    <h5>快速链接</h5>
                    <ul class="list-unstyled">
                        <li><a href="<?php echo SITE_URL; ?>/about">关于我们</a></li>
                        <li><a href="<?php echo SITE_URL; ?>/products">产品中心</a></li>
                        <li><a href="<?php echo SITE_URL; ?>/news">新闻中心</a></li>
                        <li><a href="<?php echo SITE_URL; ?>/contact">联系我们</a></li>
                    </ul>
                </div>
                <div class="col-md-4">
                    <h5>联系我们</h5>
                    <address>
                        <p><i class="fa fa-map-marker"></i> 地址:北京市朝阳区某某路123号</p>
                        <p><i class="fa fa-phone"></i> 电话:010-12345678</p>
                        <p><i class="fa fa-envelope"></i> 邮箱:info@company.com</p>
                    </address>
                </div>
            </div>
            <hr>
            <div class="text-center">
                <p>&copy; <?php echo date('Y'); ?> <?php echo SITE_NAME; ?> 版权所有</p>
            </div>
        </div>
    </footer>

    <!-- JavaScript -->
    <script src="assets/js/jquery-3.5.1.min.js"></script>
    <script src="assets/js/bootstrap.bundle.min.js"></script>
    <script src="assets/js/main.js"></script>
</body>
</html>

7. 示例页面 (pages/about.php)

<?php
// 设置页面特定的标题和描述
$pageTitle = "关于我们 - " . SITE_NAME;
$pageDescription = "了解我们公司的历史、使命和价值观";

// 如果数据库中有页面数据,使用数据库中的数据
if (isset($pageData)) {
    $pageTitle = $pageData['title'] . " - " . SITE_NAME;
    $pageDescription = $pageData['meta_description'];
}
?>

<section class="about-section py-5">
    <div class="container">
        <div class="row">
            <div class="col-lg-6">
                <h1 class="mb-4"><?php echo isset($pageData['title']) ? $pageData['title'] : '关于我们'; ?></h1>
                <div class="about-content">
                    <?php echo isset($pageData['content']) ? $pageData['content'] : '<p>这里是默认的关于我们内容...</p>'; ?>
                </div>
            </div>
            <div class="col-lg-6">
                <img src="assets/images/about.jpg" alt="关于我们" class="img-fluid rounded">
            </div>
        </div>
        
        <div class="row mt-5">
            <div class="col-12">
                <h2 class="text-center mb-4">我们的团队</h2>
            </div>
            <!-- 团队成员可以通过后台添加,这里只是示例 -->
            <div class="col-md-4 mb-4">
                <div class="card">
                    <img src="assets/images/team1.jpg" class="card-img-top" alt="团队成员">
                    <div class="card-body">
                        <h5 class="card-title">张三</h5>
                        <p class="card-text">CEO/创始人</p>
                    </div>
                </div>
            </div>
            <div class="col-md-4 mb-4">
                <div class="card">
                    <img src="assets/images/team2.jpg" class="card-img-top" alt="团队成员">
                    <div class="card-body">
                        <h5 class="card-title">李四</h5>
                        <p class="card-text">技术总监</p>
                    </div>
                </div>
            </div>
            <div class="col-md-4 mb-4">
                <div class="card">
                    <img src="assets/images/team3.jpg" class="card-img-top" alt="团队成员">
                    <div class="card-body">
                        <h5 class="card-title">王五</h5>
                        <p class="card-text">市场总监</p>
                    </div>
                </div>
            </div>
        </div>
    </div>
</section>

8. 后台登录 (admin/login.php)

<?php
require_once '../includes/db.php';

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $username = sanitize($_POST['username']);
    $password = sanitize($_POST['password']);
    
    $db = new Database();
    $stmt = $db->prepare("SELECT id, username, password FROM admins WHERE username = ?");
    $stmt->bind_param("s", $username);
    $stmt->execute();
    $result = $stmt->get_result();
    
    if ($result->num_rows == 1) {
        $admin = $result->fetch_assoc();
        if (password_verify($password, $admin['password'])) {
            $_SESSION['admin_id'] = $admin['id'];
            $_SESSION['admin_username'] = $admin['username'];
            redirect('index.php');
        } else {
            $error = "用户名或密码错误";
        }
    } else {
        $error = "用户名或密码错误";
    }
    $stmt->close();
}
?>

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>后台登录 - <?php echo SITE_NAME; ?></title>
    <link rel="stylesheet" href="css/bootstrap.min.css">
    <link rel="stylesheet" href="css/login.css">
</head>
<body>
    <div class="login-container">
        <div class="card login-card">
            <div class="card-body">
                <h2 class="text-center mb-4">后台管理系统</h2>
                <?php if (isset($error)): ?>
                    <div class="alert alert-danger"><?php echo $error; ?></div>
                <?php endif; ?>
                <form method="POST">
                    <div class="form-group">
                        <label for="username">用户名</label>
                        <input type="text" class="form-control" id="username" name="username" required>
                    </div>
                    <div class="form-group">
                        <label for="password">密码</label>
                        <input type="password" class="form-control" id="password" name="password" required>
                    </div>
                    <button type="submit" class="btn btn-primary btn-block">登录</button>
                </form>
            </div>
        </div>
    </div>
</body>
</html>

9. 后台首页 (admin/index.php)

<?php
require_once '../includes/db.php';

if (!isLoggedIn()) {
    redirect('login.php');
}

$db = new Database();

// 获取统计数据
$newsCount = $db->query("SELECT COUNT(*) FROM news")->fetch_row()[0];
$productsCount = $db->query("SELECT COUNT(*) FROM products")->fetch_row()[0];
$pagesCount = $db->query("SELECT COUNT(*) FROM pages")->fetch_row()[0];
?>

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>后台管理 - <?php echo SITE_NAME; ?></title>
    <link rel="stylesheet" href="css/bootstrap.min.css">
    <link rel="stylesheet" href="css/font-awesome.min.css">
    <link rel="stylesheet" href="css/admin.css">
</head>
<body>
    <div class="wrapper">
        <!-- 侧边栏 -->
        <nav id="sidebar">
            <div class="sidebar-header">
                <h3><?php echo SITE_NAME; ?></h3>
            </div>
            
            <ul class="list-unstyled components">
                <li class="active">
                    <a href="index.php"><i class="fa fa-dashboard"></i> 控制面板</a>
                </li>
                <li>
                    <a href="#pageSubmenu" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
                        <i class="fa fa-file-text"></i> 页面管理
                    </a>
                    <ul class="collapse list-unstyled" id="pageSubmenu">
                        <li><a href="pages.php">所有页面</a></li>
                        <li><a href="page-add.php">添加页面</a></li>
                    </ul>
                </li>
                <li>
                    <a href="news.php"><i class="fa fa-newspaper-o"></i> 新闻管理</a>
                </li>
                <li>
                    <a href="products.php"><i class="fa fa-product-hunt"></i> 产品管理</a>
                </li>
                <li>
                    <a href="settings.php"><i class="fa fa-cog"></i> 系统设置</a>
                </li>
            </ul>
        </nav>

        <!-- 页面内容 -->
        <div id="content">
            <!-- 顶部导航 -->
            <nav class="navbar navbar-expand-lg navbar-light bg-light">
                <div class="container-fluid">
                    <button type="button" id="sidebarCollapse" class="btn btn-info">
                        <i class="fa fa-align-left"></i>
                    </button>
                    
                    <ul class="nav navbar-nav ml-auto">
                        <li class="nav-item">
                            <a class="nav-link" href="../" target="_blank"><i class="fa fa-globe"></i> 查看网站</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" href="logout.php"><i class="fa fa-sign-out"></i> 退出</a>
                        </li>
                    </ul>
                </div>
            </nav>

            <!-- 主要内容 -->
            <div class="container-fluid">
                <h2 class="mb-4">控制面板</h2>
                
                <div class="row">
                    <div class="col-md-4 mb-4">
                        <div class="card text-white bg-primary">
                            <div class="card-body">
                                <div class="d-flex justify-content-between align-items-center">
                                    <div>
                                        <h5 class="card-title">新闻数量</h5>
                                        <h2 class="mb-0"><?php echo $newsCount; ?></h2>
                                    </div>
                                    <i class="fa fa-newspaper-o fa-3x"></i>
                                </div>
                            </div>
                            <div class="card-footer">
                                <a href="news.php" class="text-white">查看所有新闻 <i class="fa fa-arrow-right"></i></a>
                            </div>
                        </div>
                    </div>
                    
                    <div class="col-md-4 mb-4">
                        <div class="card text-white bg-success">
                            <div class="card-body">
                                <div class="d-flex justify-content-between align-items-center">
                                    <div>
                                        <h5 class="card-title">产品数量</h5>
                                        <h2 class="mb-0"><?php echo $productsCount; ?></h2>
                                    </div>
                                    <i class="fa fa-product-hunt fa-3x"></i>
                                </div>
                            </div>
                            <div class="card-footer">
                                <a href="products.php" class="text-white">查看所有产品 <i class="fa fa-arrow-right"></i></a>
                            </div>
                        </div>
                    </div>
                    
                    <div class="col-md-4 mb-4">
                        <div class="card text-white bg-info">
                            <div class="card-body">
                                <div class="d-flex justify-content-between align-items-center">
                                    <div>
                                        <h5 class="card-title">页面数量</h5>
                                        <h2 class="mb-0"><?php echo $pagesCount; ?></h2>
                                    </div>
                                    <i class="fa fa-file-text fa-3x"></i>
                                </div>
                            </div>
                            <div class="card-footer">
                                <a href="pages.php" class="text-white">查看所有页面 <i class="fa fa-arrow-right"></i></a>
                            </div>
                        </div>
                    </div>
                </div>
                
                <div class="card mb-4">
                    <div class="card-header">
                        <h5 class="mb-0">最近活动</h5>
                    </div>
                    <div class="card-body">
                        <p>这里是最近的活动记录...</p>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script src="js/jquery-3.5.1.min.js"></script>
    <script src="js/bootstrap.bundle.min.js"></script>
    <script src="js/admin.js"></script>
</body>
</html>

10. 新闻管理 (admin/news.php)

<?php
require_once '../includes/db.php';

if (!isLoggedIn()) {
    redirect('login.php');
}

$db = new Database();

// 删除新闻
if (isset($_GET['delete'])) {
    $id = intval($_GET['delete']);
    $stmt = $db->prepare("DELETE FROM news WHERE id = ?");
    $stmt->bind_param("i", $id);
    $stmt->execute();
    $stmt->close();
    
    $_SESSION['message'] = "新闻已删除";
    redirect('news.php');
}

// 获取所有新闻
$news = $db->query("SELECT * FROM news ORDER BY created_at DESC");
?>

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>新闻管理 - <?php echo SITE_NAME; ?></title>
    <link rel="stylesheet" href="css/bootstrap.min.css">
    <link rel="stylesheet" href="css/font-awesome.min.css">
    <link rel="stylesheet" href="css/admin.css">
</head>
<body>
    <div class="wrapper">
        <?php include 'sidebar.php'; ?>

        <div id="content">
            <?php include 'navbar.php'; ?>

            <div class="container-fluid">
                <h2 class="mb-4">新闻管理</h2>
                
                <?php if (isset($_SESSION['message'])): ?>
                    <div class="alert alert-success"><?php echo $_SESSION['message']; unset($_SESSION['message']); ?></div>
                <?php endif; ?>
                
                <div class="card mb-4">
                    <div class="card-header">
                        <div class="d-flex justify-content-between align-items-center">
                            <h5 class="mb-0">新闻列表</h5>
                            <a href="news-add.php" class="btn btn-primary btn-sm"><i class="fa fa-plus"></i> 添加新闻</a>
                        </div>
                    </div>
                    <div class="card-body">
                        <div class="table-responsive">
                            <table class="table table-striped table-bordered">
                                <thead>
                                    <tr>
                                        <th>ID</th>
                                        <th>标题</th>
                                        <th>分类</th>
                                        <th>发布时间</th>
                                        <th>状态</th>
                                        <th>操作</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <?php while ($row = $news->fetch_assoc()): ?>
                                    <tr>
                                        <td><?php echo $row['id']; ?></td>
                                        <td><?php echo $row['title']; ?></td>
                                        <td><?php echo $row['category']; ?></td>
                                        <td><?php echo date('Y-m-d H:i', strtotime($row['created_at'])); ?></td>
                                        <td>
                                            <?php if ($row['status'] == 1): ?>
                                                <span class="badge badge-success">发布</span>
                                            <?php else: ?>
                                                <span class="badge badge-secondary">草稿</span>
                                            <?php endif; ?>
                                        </td>
                                        <td>
                                            <a href="news-edit.php?id=<?php echo $row['id']; ?>" class="btn btn-sm btn-info"><i class="fa fa-edit"></i></a>
                                            <a href="news.php?delete=<?php echo $row['id']; ?>" class="btn btn-sm btn-danger" onclick="return confirm('确定删除吗?')"><i class="fa fa-trash"></i></a>
                                        </td>
                                    </tr>
                                    <?php endwhile; ?>
                                </tbody>
                            </table>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script src="js/jquery-3.5.1.min.js"></script>
    <script src="js/bootstrap.bundle.min.js"></script>
    <script src="js/admin.js"></script>
</body>
</html>

11. 添加新闻 (admin/news-add.php)

<?php
require_once '../includes/db.php';

if (!isLoggedIn()) {
    redirect('login.php');
}

$db = new Database();

// 处理表单提交
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $title = sanitize($_POST['title']);
    $content = sanitize($_POST['content']);
    $category = sanitize($_POST['category']);
    $status = isset($_POST['status']) ? 1 : 0;
    
    // 处理图片上传
    $image = '';
    if (isset($_FILES['image']) && $_FILES['image']['error'] == UPLOAD_ERR_OK) {
        $uploadDir = '../' . UPLOAD_DIR;
        $uploadFile = $uploadDir . basename($_FILES['image']['name']);
        
        // 检查文件类型
        $imageFileType = strtolower(pathinfo($uploadFile, PATHINFO_EXTENSION));
        $allowedTypes = ['jpg', 'jpeg', 'png', 'gif'];
        
        if (in_array($imageFileType, $allowedTypes)) {
            // 生成唯一文件名
            $newFilename = uniqid() . '.' . $imageFileType;
            $uploadFile = $uploadDir . $newFilename;
            
            if (move_uploaded_file($_FILES['image']['tmp_name'], $uploadFile)) {
                $image = UPLOAD_DIR . $newFilename;
            }
        }
    }
    
    // 插入数据库
    $stmt = $db->prepare("INSERT INTO news (title, content, image, category, status) VALUES (?, ?, ?, ?, ?)");
    $stmt->bind_param("ssssi", $title, $content, $image, $category, $status);
    
    if ($stmt->execute()) {
        $_SESSION['message'] = "新闻添加成功";
        redirect('news.php');
    } else {
        $error = "添加新闻失败: " . $stmt->error;
    }
    
    $stmt->close();
}
?>

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>添加新闻 - <?php echo SITE_NAME; ?></title>
    <link rel="stylesheet" href="css/bootstrap.min.css">
    <link rel="stylesheet" href="css/font-awesome.min.css">
    <link rel="stylesheet" href="css/admin.css">
    <link rel="stylesheet" href="css/summernote-bs4.css">
</head>
<body>
    <div class="wrapper">
        <?php include 'sidebar.php'; ?>

        <div id="content">
            <?php include 'navbar.php'; ?>

            <div class="container-fluid">
                <h2 class="mb-4">添加新闻</h2>
                
                <?php if (isset($error)): ?>
                    <div class="alert alert-danger"><?php echo $error; ?></div>
                <?php endif; ?>
                
                <div class="card mb-4">
                    <div class="card-body">
                        <form method="POST" enctype="multipart/form-data">
                            <div class="form-group">
                                <label for="title">标题</label>
                                <input type="text" class="form-control" id="title" name="title" required>
                            </div>
                            
                            <div class="form-group">
                                <label for="content">内容</label>
                                <textarea class="form-control" id="content" name="content" rows="10" required></textarea>
                            </div>
                            
                            <div class="form-group">
                                <label for="category">分类</label>
                                <select class="form-control" id="category" name="category">
                                    <option value="公司新闻">公司新闻</option>
                                    <option value="行业动态">行业动态</option>
                                    <option value="产品资讯">产品资讯</option>
                                </select>
                            </div>
                            
                            <div class="form-group">
                                <label for="image">封面图片</label>
                                <input type="file" class="form-control-file" id="image" name="image">
                                <small class="form-text text-muted">支持 JPG, PNG, GIF 格式,大小不超过 2MB</small>
                            </div>
                            
                            <div class="form-group form-check">
                                <input type="checkbox" class="form-check-input" id="status" name="status" checked>
                                <label class="form-check-label" for="status">发布</label>
                            </div>
                            
                            <button type="submit" class="btn btn-primary">保存</button>
                            <a href="news.php" class="btn btn-secondary">取消</a>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script src="js/jquery-3.5.1.min.js"></script>
    <script src="js/bootstrap.bundle.min.js"></script>
    <script src="js/summernote-bs4.min.js"></script>
    <script src="js/admin.js"></script>
    
    <script>
        $(document).ready(function() {
            $('#content').summernote({
                height: 300,
                toolbar: [
                    ['style', ['bold', 'italic', 'underline', 'clear']],
                    ['font', ['strikethrough', 'superscript', 'subscript']],
                    ['fontsize', ['fontsize']],
                    ['color', ['color']],
                    ['para', ['ul', 'ol', 'paragraph']],
                    ['height', ['height']],
                    ['insert', ['link', 'picture', 'video', 'table', 'hr']],
                    ['view', ['fullscreen', 'codeview', 'help']]
                ]
            });
        });
    </script>
</body>
</html>

12. API 接口 (api/v1/news.php)

<?php
header('Content-Type: application/json');
require_once '../../includes/db.php';

$db = new Database();

// 设置默认响应
$response = [
    'status' => 'error',
    'message' => 'Invalid request',
    'data' => []
];

// 获取请求方法
$method = $_SERVER['REQUEST_METHOD'];

try {
    switch ($method) {
        case 'GET':
            // 获取新闻列表或单个新闻
            if (isset($_GET['id'])) {
                // 获取单个新闻
                $id = intval($_GET['id']);
                $stmt = $db->prepare("SELECT id, title, content, image, category, created_at FROM news WHERE id = ? AND status = 1");
                $stmt->bind_param("i", $id);
                $stmt->execute();
                $result = $stmt->get_result();
                
                if ($result->num_rows > 0) {
                    $response['status'] = 'success';
                    $response['message'] = 'News found';
                    $response['data'] = $result->fetch_assoc();
                } else {
                    $response['message'] = 'News not found';
                }
                
                $stmt->close();
            } else {
                // 获取新闻列表
                $page = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
                $limit = isset($_GET['limit']) ? max(1, intval($_GET['limit'])) : 10;
                $offset = ($page - 1) * $limit;
                
                // 获取总数
                $total = $db->query("SELECT COUNT(*) FROM news WHERE status = 1")->fetch_row()[0];
                
                // 获取新闻
                $stmt = $db->prepare("SELECT id, title, content, image, category, created_at FROM news WHERE status = 1 ORDER BY created_at DESC LIMIT ? OFFSET ?");
                $stmt->bind_param("ii", $limit, $offset);
                $stmt->execute();
                $result = $stmt->get_result();
                
                $news = [];
                while ($row = $result->fetch_assoc()) {
                    $news[] = $row;
                }
                
                $response['status'] = 'success';
                $response['message'] = 'News list';
                $response['data'] = [
                    'news' => $news,
                    'pagination' => [
                        'total' => $total,
                        'page' => $page,
                        'limit' => $limit,
                        'total_pages' => ceil($total / $limit)
                    ]
                ];
                
                $stmt->close();
            }
            break;
            
        case 'POST':
            // 创建新闻 (需要认证)
            if (!isset($_SERVER['HTTP_AUTHORIZATION']) {
                $response['message'] = 'Authentication required';
                break;
            }
            
            // 验证API密钥
            $apiKey = str_replace('Bearer ', '', $_SERVER['HTTP_AUTHORIZATION']);
            $validKey = 'your-secret-api-key'; // 应该从配置中获取
            
            if ($apiKey !== $validKey) {
                $response['message'] = 'Invalid API key';
                break;
            }
            
            // 获取输入数据
            $input = json_decode(file_get_contents('php://input'), true);
            
            if (!isset($input['title']) || !isset($input['content'])) {
                $response['message'] = 'Title and content are required';
                break;
            }
            
            $title = sanitize($input['title']);
            $content = sanitize($input['content']);
            $category = isset($input['category']) ? sanitize($input['category']) : '公司新闻';
            $status = isset($input['status']) ? intval($input['status']) : 1;
            $image = isset($input['image']) ? sanitize($input['image']) : '';
            
            // 插入数据库
            $stmt = $db->prepare("INSERT INTO news (title, content, image, category, status) VALUES (?, ?, ?, ?, ?)");
            $stmt->bind_param("ssssi", $title, $content, $image, $category, $status);
            
            if ($stmt->execute()) {
                $response['status'] = 'success';
                $response['message'] = 'News created successfully';
                $response['data'] = ['id' => $stmt->insert_id];
            } else {
                $response['message'] = 'Failed to create news';
            }
            
            $stmt->close();
            break;
            
        default:
            $response['message'] = 'Method not allowed';
            break;
    }
} catch (Exception $e) {
    $response['message'] = $e->getMessage();
}

// 输出JSON响应
echo json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
?>

13. 伪静态配置

Apache (.htaccess)

<IfModule mod_rewrite.c>
    RewriteEngine On
    
    # 后台伪静态排除
    RewriteRule ^admin/ - [L]
    
    # API伪静态排除
    RewriteRule ^api/ - [L]
    
    # 静态资源排除
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} !\.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ [NC]
    
    # 前端路由
    RewriteRule ^([a-zA-Z0-9_-]+)/?$ index.php?page=$1 [L,QSA]
    RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/?$ index.php?page=$1&action=$2 [L,QSA]
</IfModule>

IIS (web.config)

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <!-- 排除后台和API -->
                <rule name="Exclude Admin" stopProcessing="true">
                    <match url="^admin/" ignoreCase="false" />
                    <action type="None" />
                </rule>
                <rule name="Exclude API" stopProcessing="true">
                    <match url="^api/" ignoreCase="false" />
                    <action type="None" />
                </rule>
                
                <!-- 排除静态资源 -->
                <rule name="Exclude Static Files" stopProcessing="true">
                    <match url="\.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$" ignoreCase="true" />
                    <action type="None" />
                </rule>
                
                <!-- 前端路由规则 -->
                <rule name="Frontend Routes" stopProcessing="true">
                    <match url="^([a-zA-Z0-9_-]+)/?$" ignoreCase="false" />
                    <action type="Rewrite" url="index.php?page={R:1}" appendQueryString="true" />
                </rule>
                <rule name="Frontend Routes with Action" stopProcessing="true">
                    <match url="^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/?$" ignoreCase="false" />
                    <action type="Rewrite" url="index.php?page={R:1}&amp;action={R:2}" appendQueryString="true" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>

14. 宝塔面板伪静态设置

在宝塔面板中,选择网站 -> 设置 -> 伪静态,然后根据服务器类型选择:

对于Apache

直接复制上面的.htaccess内容即可。

对于Nginx

location / {
    try_files $uri $uri/ /index.php?$query_string;
}

location /admin/ {
    try_files $uri $uri/ /admin/index.php?$query_string;
}

location /api/ {
    try_files $uri $uri/ /api/index.php?$query_string;
}

location ~ \.php$ {
    fastcgi_pass unix:/tmp/php-cgi.sock;
    fastcgi_index index.php;
    include fastcgi.conf;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
    expires max;
    add_header Cache-Control "public, no-transform";
}

15. 前端JavaScript (assets/js/main.js)

$(document).ready(function() {
    // 初始化工具提示
    $('[data-toggle="tooltip"]').tooltip();
    
    // 初始化弹出框
    $('[data-toggle="popover"]').popover();
    
    // 平滑滚动
    $('a[href*="#"]').on('click', function(e) {
        e.preventDefault();
        
        $('html, body').animate(
            {
                scrollTop: $($(this).attr('href')).offset().top,
            },
            500,
            'linear'
        );
    });
    
    // 新闻加载更多
    $('#load-more-news').on('click', function() {
        const button = $(this);
        const page = parseInt(button.data('page')) || 1;
        
        button.text('加载中...').prop('disabled', true);
        
        $.ajax({
            url: 'api/v1/news',
            data: { page: page + 1, limit: 5 },
            dataType: 'json',
            success: function(response) {
                if (response.status === 'success') {
                    const news = response.data.news;
                    
                    if (news.length > 0) {
                        let html = '';
                        
                        news.forEach(function(item) {
                            html += `
                                <div class="col-md-4 mb-4">
                                    <div class="card news-card">
                                        <img src="${item.image || 'assets/images/news-default.jpg'}" class="card-img-top" alt="${item.title}">
                                        <div class="card-body">
                                            <h5 class="card-title">${item.title}</h5>
                                            <p class="card-text">${item.content.substring(0, 100)}...</p>
                                            <a href="news/${item.id}" class="btn btn-primary">阅读更多</a>
                                        </div>
                                        <div class="card-footer text-muted">
                                            ${new Date(item.created_at).toLocaleDateString()}
                                        </div>
                                    </div>
                                </div>
                            `;
                        });
                        
                        $('#news-container').append(html);
                        button.data('page', page + 1).text('加载更多').prop('disabled', false);
                        
                        if (response.data.pagination.page >= response.data.pagination.total_pages) {
                            button.hide();
                        }
                    } else {
                        button.text('没有更多新闻').prop('disabled', true);
                    }
                }
            },
            error: function() {
                button.text('加载失败').prop('disabled', false);
            }
        });
    });
    
    // 联系表单提交
    $('#contact-form').on('submit', function(e) {
        e.preventDefault();
        
        const form = $(this);
        const button = form.find('button[type="submit"]');
        const originalText = button.text();
        
        button.text('发送中...').prop('disabled', true);
        
        $.ajax({
            url: 'api/v1/contact',
            method: 'POST',
            data: form.serialize(),
            dataType: 'json',
            success: function(response) {
                if (response.status === 'success') {
                    form[0].reset();
                    $('#form-message').html(`
                        <div class="alert alert-success">
                            ${response.message}
                        </div>
                    `);
                } else {
                    $('#form-message').html(`
                        <div class="alert alert-danger">
                            ${response.message}
                        </div>
                    `);
                }
            },
            error: function() {
                $('#form-message').html(`
                    <div class="alert alert-danger">
                        发送失败,请稍后再试
                    </div>
                `);
            },
            complete: function() {
                button.text(originalText).prop('disabled', false);
            }
        });
    });
});

总结

这个解决方案提供了完整的全栈企业官网实现,包括:

  1. 前端部分:使用HTML5、CSS3和JavaScript实现响应式设计
  2. 后端部分:PHP实现后台管理功能,包括内容增删改查和文件上传
  3. API接口:JSON格式的RESTful API,便于前后端分离和移动端调用
  4. 数据库:MySQL数据库设计和管理
  5. 伪静态:支持Apache、IIS和Nginx的伪静态规则
  6. 安全性:管理员认证、输入过滤和防SQL注入

您可以根据实际需求进一步扩展和定制这个解决方案。 更多详情:baijiahao.baidu.com/s?id=183050…