# 站点配置功能
## 1. 创建 SiteController
### 1.1 执行命令
```bash
php artisan make:controller Admin/SiteController
```
### 1.2 文件路径
`app/Http/Controllers/Admin/SiteController.php`
### 1.3 完整代码
```php
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Site;
use Illuminate\Http\Request;
class SiteController extends Controller
{
public function index()
{
$site = Site::first();
return response()->json($site);
}
public function update(Request $request)
{
$validated = $request->validate([
'site_name' => 'required|string|max:255',
'site_logo' => 'nullable|string|max:500',
'site_keywords' => 'nullable|string|max:500',
'site_description' => 'nullable|string',
]);
$site = Site::first();
if ($site) {
$site->update($validated);
} else {
$site = Site::create($validated);
}
return response()->json($site);
}
}
```
### 1.4 代码说明
| 方法 | 路由 | 作用 |
|------|------|------|
| `index` | GET /api/admin/site | 获取站点配置 |
| `update` | PUT /api/admin/site | 更新站点配置 |
---
## 2. 添加 API 路由
### 2.1 文件路径
`routes/api.php`
### 2.2 完整代码
```php
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Admin\AuthController;
use App\Http\Controllers\Admin\PageController;
use App\Http\Controllers\Admin\SiteController;
// 无需认证的路由
Route::post('/admin/login', [AuthController::class, 'login']);
// 需要认证的路由
Route::middleware('auth:sanctum')->prefix('admin')->group(function () {
Route::get('/user', [AuthController::class, 'user']);
Route::post('/logout', [AuthController::class, 'logout']);
// 页面管理
Route::get('/pages', [PageController::class, 'index']);
Route::post('/pages', [PageController::class, 'store']);
Route::get('/pages/{id}', [PageController::class, 'show']);
Route::put('/pages/{id}', [PageController::class, 'update']);
Route::delete('/pages/{id}', [PageController::class, 'destroy']);
// 站点配置
Route::get('/site', [SiteController::class, 'index']);
Route::put('/site', [SiteController::class, 'update']);
});
```
---
## 3. 创建站点配置 API 封装
### 3.1 文件路径
`resources\js\admin\api\site.ts`
### 3.2 完整代码
```typescript
import axios from 'axios';
export interface Site {
id: number;
site_name: string;
site_logo: string | null;
site_keywords: string | null;
site_description: string | null;
created_at: string;
updated_at: string;
}
export const siteApi = {
get: () => axios.get<Site>('/api/admin/site'),
update: (data: Partial<Site>) => axios.put<Site>('/api/admin/site', data),
};
```
### 3.3 代码说明
| 方法 | 作用 |
|------|------|
| `get` | 获取站点配置 |
| `update` | 更新站点配置 |
---
## 4. 创建站点配置 Store
### 4.1 文件路径
`resources\js\admin\stores\site.ts`
### 4.2 完整代码
```typescript
import { defineStore } from 'pinia';
import { ref } from 'vue';
import { siteApi, type Site } from '../api/site';
import { ElMessage } from 'element-plus';
export const useSiteStore = defineStore('site', () => {
const site = ref<Site | null>(null);
const loading = ref(false);
const fetchSite = async () => {
loading.value = true;
try {
const response = await siteApi.get();
site.value = response.data;
} catch (error) {
ElMessage.error('获取站点配置失败');
} finally {
loading.value = false;
}
};
const updateSite = async (data: Partial<Site>) => {
loading.value = true;
try {
const response = await siteApi.update(data);
site.value = response.data;
ElMessage.success('保存成功');
return response.data;
} catch (error) {
ElMessage.error('保存失败');
throw error;
} finally {
loading.value = false;
}
};
return {
site,
loading,
fetchSite,
updateSite,
};
});
```
---
## 5. 修改 SiteSettings.vue 实现站点配置表单
### 5.1 文件路径
`resources\js\admin\views\SiteSettings.vue`
### 5.2 完整代码
```vue
<template>
<div>
<el-card v-loading="siteStore.loading">
<template #header>
<div>
<span>站点配置</span>
<el-button type="primary" @click="handleSubmit" :loading="submitting">
保存配置
</el-button>
</div>
</template>
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
<el-form-item label="网站名称" prop="site_name">
<el-input v-model="form.site_name" placeholder="请输入网站名称" />
</el-form-item>
<el-form-item label="网站 Logo" prop="site_logo">
<el-input v-model="form.site_logo" placeholder="例如: /logo.png" />
<div>Logo 路径,相对于 public 目录</div>
</el-form-item>
<el-form-item label="SEO 关键词" prop="site_keywords">
<el-input
v-model="form.site_keywords"
type="textarea"
:rows="2"
placeholder="多个关键词用英文逗号分隔"
/>
</el-form-item>
<el-form-item label="SEO 描述" prop="site_description">
<el-input
v-model="form.site_description"
type="textarea"
:rows="3"
placeholder="请输入网站描述"
/>
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script setup>
import { ref, reactive, onMounted, watch } from 'vue';
import { useSiteStore } from '../stores/site';
const siteStore = useSiteStore();
const formRef = ref();
const submitting = ref(false);
const form = reactive({
site_name: '',
site_logo: '',
site_keywords: '',
site_description: '',
});
const rules = {
site_name: [{ required: true, message: '请输入网站名称', trigger: 'blur' }],
};
watch(
() => siteStore.site,
(newSite) => {
if (newSite) {
form.site_name = newSite.site_name || '';
form.site_logo = newSite.site_logo || '';
form.site_keywords = newSite.site_keywords || '';
form.site_description = newSite.site_description || '';
}
},
{ immediate: true }
);
const handleSubmit = async () => {
if (!formRef.value) return;
await formRef.value.validate(async (valid: boolean) => {
if (!valid) return;
submitting.value = true;
try {
await siteStore.updateSite(form);
} finally {
submitting.value = false;
}
});
};
onMounted(() => {
siteStore.fetchSite();
});
</script>
<style scoped>
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.form-tip {
font-size: 12px;
color: #909399;
margin-top: 4px;
}
</style>
```
### 5.3 代码说明
| 代码 | 作用 |
|------|------|
| `watch` | 监听 store 数据变化,自动更新表单 |
| `fetchSite` | 组件挂载时获取站点配置 |
| `updateSite` | 提交表单时更新站点配置 |
| `v-loading` | 加载状态显示 |
| `form-tip` | 辅助说明文字 |
---
## 6. 编译验证
### 6.1 执行命令
```bash
npm run build
```
### 6.2 预期结果
编译成功,无报错。
---
## 7. 访问测试
浏览器打开:`http://engine-api.test/admin/site`
预期结果:
- 显示站点配置表单
- 表单自动回填已有配置数据
- 修改后点击「保存配置」提示成功
---
## 8. 验证结果
| 验证项 | 预期结果 | 实际结果 |
|--------|---------|---------|
| 编译 | 无报错 | ✅ 通过 |
| 站点配置表单 | 正常显示 | ✅ 通过 |
| 数据回填 | 显示已有配置 | ✅ 通过 |
| 网站名称 | 可编辑保存 | ✅ 通过 |
| Logo 路径 | 可编辑保存 | ✅ 通过 |
| SEO 关键词 | 可编辑保存 | ✅ 通过 |
| SEO 描述 | 可编辑保存 | ✅ 通过 |
| 保存按钮 | 点击后保存成功 | ✅ 通过 |