本文目录导读:

我来为你全面讲解 PHP 岗位管理系统的开发,从需求分析到具体实现。
系统功能架构
核心功能模块
// 岗位管理系统功能结构 1. 岗位基础管理 - 岗位创建、编辑、删除 - 岗位编码生成 - 岗位状态管理 2. 岗位分类管理 - 部门分类 - 职级分类 - 岗位类型 3. 权限管理 - 岗位权限分配 - 数据权限控制 4. 人员关联 - 人员-岗位绑定 - 岗位编制管理
数据库设计
数据表结构
-- 岗位信息表 CREATE TABLE `positions` ( `id` int(11) NOT NULL AUTO_INCREMENT, `position_code` varchar(20) NOT NULL COMMENT '岗位编码', `position_name` varchar(50) NOT NULL COMMENT '岗位名称', `department_id` int(11) NOT NULL COMMENT '所属部门', `position_type` tinyint(4) DEFAULT '1' COMMENT '岗位类型:1管理岗 2技术岗 3职能岗', `position_level` varchar(20) DEFAULT NULL COMMENT '岗位职级', `head_count` int(11) DEFAULT '1' COMMENT '编制人数', `current_count` int(11) DEFAULT '0' COMMENT '在职人数', `description` text COMMENT '岗位描述', `requirements` text COMMENT '任职要求', `salary_min` decimal(10,2) DEFAULT NULL COMMENT '薪资下限', `salary_max` decimal(10,2) DEFAULT NULL COMMENT '薪资上限', `status` tinyint(4) DEFAULT '1' COMMENT '状态:1启用 0禁用', `created_by` int(11) DEFAULT NULL COMMENT '创建人', `created_at` datetime DEFAULT CURRENT_TIMESTAMP, `updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_position_code` (`position_code`), KEY `idx_department` (`department_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='岗位信息表'; -- 岗位-用户关联表 CREATE TABLE `position_users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `position_id` int(11) NOT NULL, `user_id` int(11) NOT NULL, `is_primary` tinyint(1) DEFAULT '1' COMMENT '是否主岗位', `start_date` date DEFAULT NULL, `end_date` date DEFAULT NULL, `status` tinyint(4) DEFAULT '1', PRIMARY KEY (`id`), UNIQUE KEY `uk_position_user` (`position_id`,`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='岗位用户关联表';
核心代码实现
岗位管理控制器
<?php
namespace App\Controllers;
use App\Models\PositionModel;
use App\Helpers\Validator;
use App\Helpers\Response;
class PositionController extends BaseController
{
protected $positionModel;
public function __construct()
{
parent::__construct();
$this->positionModel = new PositionModel();
}
/**
* 岗位列表
*/
public function index()
{
$page = $_GET['page'] ?? 1;
$limit = $_GET['limit'] ?? 20;
$keyword = $_GET['keyword'] ?? '';
$departmentId = $_GET['department_id'] ?? '';
$status = $_GET['status'] ?? '';
$where = [];
if (!empty($keyword)) {
$where['position_name LIKE'] = "%{$keyword}%";
}
if (!empty($departmentId)) {
$where['department_id'] = $departmentId;
}
if ($status !== '') {
$where['status'] = $status;
}
$result = $this->positionModel->getList($where, $page, $limit);
return Response::success($result);
}
/**
* 创建岗位
*/
public function create()
{
// 权限检查
$this->checkPermission('position:create');
// 获取并验证数据
$data = [
'position_code' => $_POST['position_code'] ?? '',
'position_name' => $_POST['position_name'] ?? '',
'department_id' => $_POST['department_id'] ?? 0,
'position_type' => $_POST['position_type'] ?? 1,
'position_level' => $_POST['position_level'] ?? '',
'head_count' => $_POST['head_count'] ?? 1,
'description' => $_POST['description'] ?? '',
'requirements' => $_POST['requirements'] ?? '',
'salary_min' => $_POST['salary_min'] ?? 0,
'salary_max' => $_POST['salary_max'] ?? 0,
];
// 验证规则
$rules = [
'position_code' => 'required|max:20|unique:positions',
'position_name' => 'required|max:50',
'department_id' => 'required|numeric',
'head_count' => 'numeric|min:1',
'salary_min' => 'numeric|min:0',
'salary_max' => 'numeric|min:0'
];
$validator = new Validator();
if (!$validator->validate($data, $rules)) {
return Response::error($validator->getErrors(), 400);
}
$data['created_by'] = $_SESSION['user_id'];
$result = $this->positionModel->create($data);
if ($result) {
// 记录操作日志
$this->logOperation('create_position', $data['position_code']);
return Response::success(['id' => $result], '创建成功');
}
return Response::error('创建失败', 500);
}
/**
* 更新岗位
*/
public function update($id)
{
$this->checkPermission('position:update');
$position = $this->positionModel->find($id);
if (!$position) {
return Response::error('岗位不存在', 404);
}
$data = [
'position_name' => $_POST['position_name'] ?? $position['position_name'],
'position_type' => $_POST['position_type'] ?? $position['position_type'],
'position_level' => $_POST['position_level'] ?? $position['position_level'],
'head_count' => $_POST['head_count'] ?? $position['head_count'],
'description' => $_POST['description'] ?? $position['description'],
'requirements' => $_POST['requirements'] ?? $position['requirements'],
'salary_min' => $_POST['salary_min'] ?? $position['salary_min'],
'salary_max' => $_POST['salary_max'] ?? $position['salary_max'],
];
$result = $this->positionModel->update($id, $data);
if ($result) {
$this->logOperation('update_position', $position['position_code']);
return Response::success($data, '更新成功');
}
return Response::error('更新失败', 500);
}
/**
* 删除岗位
*/
public function delete($id)
{
$this->checkPermission('position:delete');
// 检查是否有关联人员
$userCount = $this->positionModel->getUsersCount($id);
if ($userCount > 0) {
return Response::error('该岗位已关联人员,无法删除', 400);
}
$result = $this->positionModel->delete($id);
if ($result) {
return Response::success(null, '删除成功');
}
return Response::error('删除失败', 500);
}
/**
* 岗位分配人员
*/
public function assignUsers($positionId)
{
$this->checkPermission('position:assign');
$userId = $_POST['user_id'] ?? 0;
$action = $_POST['action'] ?? 'assign'; // assign/remove
if ($action === 'assign') {
$result = $this->positionModel->assignUser($positionId, $userId);
} else {
$result = $this->positionModel->removeUser($positionId, $userId);
}
if ($result) {
return Response::success(null, '操作成功');
}
return Response::error('操作失败', 500);
}
/**
* 导出岗位列表
*/
public function export()
{
$this->checkPermission('position:export');
$positions = $this->positionModel->getAllForExport();
// 生成Excel
$fileName = '岗位列表_' . date('YmdHis') . '.xls';
header('Content-Type: application/vnd.ms-excel');
header("Content-Disposition: attachment; filename={$fileName}");
echo $this->generateExcelContent($positions);
}
}
岗位模型
<?php
namespace App\Models;
use App\Database\Database;
use PDO;
class PositionModel extends BaseModel
{
protected $table = 'positions';
/**
* 获取岗位列表(带部门信息)
*/
public function getList($where = [], $page = 1, $limit = 20)
{
$offset = ($page - 1) * $limit;
$sql = "SELECT p.*, d.department_name,
(p.head_count - p.current_count) as available_count
FROM positions p
LEFT JOIN departments d ON p.department_id = d.id";
$conditions = [];
$params = [];
foreach ($where as $field => $value) {
if (strpos($field, ' LIKE') !== false) {
$conditions[] = "p." . str_replace(' LIKE', '', $field) . " LIKE ?";
$params[] = $value;
} else {
$conditions[] = "p.{$field} = ?";
$params[] = $value;
}
}
if (!empty($conditions)) {
$sql .= " WHERE " . implode(" AND ", $conditions);
}
$sql .= " ORDER BY p.created_at DESC LIMIT ? OFFSET ?";
$params[] = $limit;
$params[] = $offset;
$stmt = $this->db->prepare($sql);
$stmt->execute($params);
$list = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 获取总数
$countSql = "SELECT COUNT(*) FROM positions p";
if (!empty($conditions)) {
$countSql .= " WHERE " . implode(" AND ", $conditions);
}
$stmt = $this->db->prepare($countSql);
$stmt->execute(array_slice($params, 0, -2));
$total = $stmt->fetchColumn();
return [
'list' => $list,
'total' => $total,
'page' => $page,
'limit' => $limit
];
}
/**
* 分配用户到岗位
*/
public function assignUser($positionId, $userId)
{
try {
$this->db->beginTransaction();
// 检查编制
$position = $this->find($positionId);
if (!$position) {
throw new \Exception('岗位不存在');
}
if ($position['current_count'] >= $position['head_count']) {
throw new \Exception('岗位编制已满');
}
// 插入关联
$sql = "INSERT INTO position_users (position_id, user_id)
VALUES (?, ?)";
$stmt = $this->db->prepare($sql);
$stmt->execute([$positionId, $userId]);
// 更新在职人数
$sql = "UPDATE positions SET current_count = current_count + 1
WHERE id = ?";
$stmt = $this->db->prepare($sql);
$stmt->execute([$positionId]);
$this->db->commit();
return true;
} catch (\Exception $e) {
$this->db->rollBack();
throw $e;
}
}
/**
* 检查岗位编码唯一性
*/
public function checkCodeUnique($code, $excludeId = null)
{
$sql = "SELECT id FROM positions WHERE position_code = ?";
$params = [$code];
if ($excludeId) {
$sql .= " AND id != ?";
$params[] = $excludeId;
}
$stmt = $this->db->prepare($sql);
$stmt->execute($params);
return $stmt->fetchColumn() ? false : true;
}
/**
* 统计部门下岗位数
*/
public function countByDepartment($departmentId)
{
$sql = "SELECT COUNT(*) FROM positions WHERE department_id = ?";
$stmt = $this->db->prepare($sql);
$stmt->execute([$departmentId]);
return $stmt->fetchColumn();
}
}
前端页面示例
<!-- 岗位列表页面 -->
<!DOCTYPE html>
<html>
<head>岗位管理</title>
<link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css">
</head>
<body>
<div id="app">
<el-container>
<el-header>
<h2>岗位管理</h2>
</el-header>
<el-main>
<!-- 搜索区域 -->
<el-form :inline="true" class="search-form">
<el-form-item label="岗位名称">
<el-input v-model="searchForm.keyword" placeholder="请输入岗位名称"></el-input>
</el-form-item>
<el-form-item label="部门">
<el-select v-model="searchForm.department" placeholder="请选择部门">
<el-option
v-for="item in departments"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="状态">
<el-select v-model="searchForm.status">
<el-option label="全部" value=""></el-option>
<el-option label="启用" value="1"></el-option>
<el-option label="禁用" value="0"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="search">搜索</el-button>
<el-button @click="resetSearch">重置</el-button>
</el-form-item>
</el-form>
<!-- 操作按钮 -->
<div class="table-toolbar">
<el-button type="primary" @click="openCreateDialog">
<el-icon><Plus /></el-icon>新增岗位
</el-button>
<el-button @click="exportExcel">导出</el-button>
</div>
<!-- 表格 -->
<el-table :data="positionList" border stripe>
<el-table-column prop="position_code" label="岗位编码" width="120"></el-table-column>
<el-table-column prop="position_name" label="岗位名称" width="150"></el-table-column>
<el-table-column prop="department_name" label="所属部门"></el-table-column>
<el-table-column prop="position_type" label="岗位类型">
<template #default="{ row }">
<el-tag :type="getTypeTag(row.position_type)">
{{ getTypeName(row.position_type) }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="head_count" label="编制人数" width="100"></el-table-column>
<el-table-column prop="current_count" label="在职人数" width="100"></el-table-column>
<el-table-column prop="position_level" label="职级" width="80"></el-table-column>
<el-table-column prop="status" label="状态">
<template #default="{ row }">
<el-switch
v-model="row.status"
:active-value="1"
:inactive-value="0"
@change="changeStatus(row)">
</el-switch>
</template>
</el-table-column>
<el-table-column label="操作" width="200" fixed="right">
<template #default="{ row }">
<el-button link type="primary" @click="editPosition(row)">编辑</el-button>
<el-button link type="warning" @click="assignPerson(row)">人员分配</el-button>
<el-popconfirm
title="确定删除该岗位吗?"
@confirm="deletePosition(row.id)"
>
<template #reference>
<el-button link type="danger">删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<el-pagination
v-model:current-page="page"
v-model:page-size="limit"
:total="total"
:page-sizes="[10, 20, 50, 100]"
@current-change="getList"
@size-change="getList">
</el-pagination>
</el-main>
</el-container>
<!-- 新增/编辑对话框 -->
<el-dialog
v-model="dialogVisible"
:title="dialogType === 'create' ? '新增岗位' : '编辑岗位'"
width="600px">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px">
<el-form-item label="岗位编码" prop="position_code">
<el-input v-model="formData.position_code" :disabled="dialogType === 'edit'"></el-input>
</el-form-item>
<el-form-item label="岗位名称" prop="position_name">
<el-input v-model="formData.position_name"></el-input>
</el-form-item>
<el-form-item label="所属部门" prop="department_id">
<el-select v-model="formData.department_id" placeholder="请选择部门">
<el-option
v-for="item in departments"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="岗位类型" prop="position_type">
<el-radio-group v-model="formData.position_type">
<el-radio :value="1">管理岗</el-radio>
<el-radio :value="2">技术岗</el-radio>
<el-radio :value="3">职能岗</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="岗位职级">
<el-select v-model="formData.position_level">
<el-option label="初级" value="初级"></el-option>
<el-option label="中级" value="中级"></el-option>
<el-option label="高级" value="高级"></el-option>
<el-option label="资深" value="资深"></el-option>
<el-option label="专家" value="专家"></el-option>
</el-select>
</el-form-item>
<el-form-item label="编制人数" prop="head_count">
<el-input-number v-model="formData.head_count" :min="1" :max="100"></el-input-number>
</el-form-item>
<el-form-item label="薪资范围">
<div class="salary-range">
<el-input-number
v-model="formData.salary_min"
:min="0"
:max="formData.salary_max">
</el-input-number>
<span class="divider">-</span>
<el-input-number
v-model="formData.salary_max"
:min="formData.salary_min">
</el-input-number>
<span class="unit">元/月</span>
</div>
</el-form-item>
<el-form-item label="岗位描述">
<el-input
v-model="formData.description"
type="textarea"
:rows="3">
</el-input>
</el-form-item>
<el-form-item label="任职要求">
<el-input
v-model="formData.requirements"
type="textarea"
:rows="3">
</el-input>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitForm">确定</el-button>
</template>
</el-dialog>
<!-- 人员分配对话框 -->
<el-dialog v-model="assignVisible" title="人员分配" width="500px">
<div v-if="currentPosition">
<h4>{{ currentPosition.position_name }}</h4>
<p>编制人数:{{ currentPosition.head_count }},当前人数:{{ currentPosition.current_count }}</p>
<el-divider></el-divider>
<h5>已分配人员</h5>
<el-table :data="assignedUsers">
<el-table-column prop="username" label="用户名"></el-table-column>
<el-table-column prop="name" label="姓名"></el-table-column>
<el-table-column label="操作" width="80">
<template #default="{ row }">
<el-button
link
type="danger"
@click="removeUser(row.user_id)">
移除
</el-button>
</template>
</el-table-column>
</el-table>
<el-divider></el-divider>
<h5>添加人员</h5>
<div class="user-search">
<el-select
v-model="selectedUser"
filterable
remote
:remote-method="searchUsers"
placeholder="搜索用户">
<el-option
v-for="item in availableUsers"
:key="item.id"
:label="`${item.name} (${item.username})`"
:value="item.id">
</el-option>
</el-select>
<el-button type="primary" @click="assignUser">添加</el-button>
</div>
</div>
</el-dialog>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/element-plus"></script>
<script>
// Vue 应用
const { createApp, ref, onMounted, reactive } = Vue;
const app = createApp({
setup() {
// 数据定义
const positionList = ref([]);
const departments = ref([]);
const total = ref(0);
const page = ref(1);
const limit = ref(20);
const searchForm = reactive({
keyword: '',
department: '',
status: ''
});
const dialogVisible = ref(false);
const dialogType = ref('create');
const formRef = ref(null);
const formData = reactive({
position_code: '',
position_name: '',
department_id: null,
position_type: 1,
position_level: '',
head_count: 1,
description: '',
requirements: '',
salary_min: 0,
salary_max: 0
});
const formRules = {
position_code: [
{ required: true, message: '请输入岗位编码', trigger: 'blur' },
{ min: 2, max: 20, message: '长度在2-20个字符', trigger: 'blur' }
],
position_name: [
{ required: true, message: '请输入岗位名称', trigger: 'blur' }
],
department_id: [
{ required: true, message: '请选择部门', trigger: 'change' }
]
};
// 人员分配相关
const assignVisible = ref(false);
const currentPosition = ref(null);
const assignedUsers = ref([]);
const availableUsers = ref([]);
const selectedUser = ref(null);
// 方法定义
const getList = async () => {
const params = new URLSearchParams({
page: page.value,
limit: limit.value,
keyword: searchForm.keyword,
department_id: searchForm.department,
status: searchForm.status
});
try {
const response = await fetch(`/api/positions?${params}`);
const data = await response.json();
positionList.value = data.data.list;
total.value = data.data.total;
} catch (error) {
console.error('获取岗位列表失败:', error);
}
};
const getDepartments = async () => {
try {
const response = await fetch('/api/departments');
const data = await response.json();
departments.value = data.data;
} catch (error) {
console.error('获取部门列表失败:', error);
}
};
const openCreateDialog = () => {
dialogType.value = 'create';
Object.assign(formData, {
position_code: '',
position_name: '',
department_id: null,
position_type: 1,
position_level: '',
head_count: 1,
description: '',
requirements: '',
salary_min: 0,
salary_max: 0
});
dialogVisible.value = true;
};
const editPosition = (row) => {
dialogType.value = 'edit';
Object.assign(formData, row);
dialogVisible.value = true;
};
const submitForm = async () => {
try {
await formRef.value.validate();
const url = dialogType.value === 'create'
? '/api/positions'
: `/api/positions/${formData.id}`;
const method = dialogType.value === 'create' ? 'POST' : 'PUT';
const response = await fetch(url, {
method: method,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(formData)
});
const data = await response.json();
if (data.code === 0) {
dialogVisible.value = false;
ElMessage.success(data.message);
getList();
} else {
ElMessage.error(data.message);
}
} catch (error) {
console.error('提交失败:', error);
}
};
const deletePosition = async (id) => {
try {
const response = await fetch(`/api/positions/${id}`, {
method: 'DELETE'
});
const data = await response.json();
if (data.code === 0) {
ElMessage.success('删除成功');
getList();
} else {
ElMessage.error(data.message);
}
} catch (error) {
console.error('删除失败:', error);
}
};
const assignPerson = (row) => {
currentPosition.value = row;
assignVisible.value = true;
getAssignedUsers(row.id);
};
const getAssignedUsers = async (positionId) => {
try {
const response = await fetch(`/api/positions/${positionId}/users`);
const data = await response.json();
assignedUsers.value = data.data;
} catch (error) {
console.error('获取已分配人员失败:', error);
}
};
const searchUsers = async (query) => {
try {
const response = await fetch(`/api/users/search?keyword=${query}`);
const data = await response.json();
availableUsers.value = data.data;
} catch (error) {
console.error('搜索用户失败:', error);
}
};
const assignUser = async () => {
if (!selectedUser.value) {
ElMessage.warning('请选择用户');
return;
}
try {
const response = await fetch(`/api/positions/${currentPosition.value.id}/assign`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
user_id: selectedUser.value,
action: 'assign'
})
});
const data = await response.json();
if (data.code === 0) {
ElMessage.success('添加成功');
getAssignedUsers(currentPosition.value.id);
getList();
selectedUser.value = null;
} else {
ElMessage.error(data.message);
}
} catch (error) {
console.error('添加人员失败:', error);
}
};
const removeUser = async (userId) => {
try {
const response = await fetch(`/api/positions/${currentPosition.value.id}/assign`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
user_id: userId,
action: 'remove'
})
});
const data = await response.json();
if (data.code === 0) {
ElMessage.success('移除成功');
getAssignedUsers(currentPosition.value.id);
getList();
} else {
ElMessage.error(data.message);
}
} catch (error) {
console.error('移除人员失败:', error);
}
};
const search = () => {
page.value = 1;
getList();
};
const resetSearch = () => {
searchForm.keyword = '';
searchForm.department = '';
searchForm.status = '';
getList();
};
const exportExcel = () => {
window.location.href = '/api/positions/export';
};
const getTypeName = (type) => {
const types = { 1: '管理岗', 2: '技术岗', 3: '职能岗' };
return types[type] || '未知';
};
const getTypeTag = (type) => {
const tags = { 1: 'danger', 2: 'success', 3: 'warning' };
return tags[type] || 'info';
};
// 生命周期
onMounted(() => {
getList();
getDepartments();
});
return {
positionList,
departments,
total,
page,
limit,
searchForm,
dialogVisible,
dialogType,
formRef,
formData,
formRules,
assignVisible,
currentPosition,
assignedUsers,
availableUsers,
selectedUser,
getList,
openCreateDialog,
editPosition,
submitForm,
deletePosition,
assignPerson,
searchUsers,
assignUser,
removeUser,
search,
resetSearch,
exportExcel,
getTypeName,
getTypeTag
};
}
});
app.use(ElementPlus);
app.mount('#app');
</script>
<style>
.search-form {
margin-bottom: 20px;
padding: 20px;
background: #f5f7fa;
border-radius: 4px;
}
.table-toolbar {
margin-bottom: 20px;
display: flex;
justify-content: space-between;
}
.salary-range {
display: flex;
align-items: center;
gap: 10px;
}
.divider {
color: #999;
}
.unit {
color: #666;
font-size: 14px;
}
.user-search {
display: flex;
gap: 10px;
}
.user-search .el-select {
flex: 1;
}
</style>
</body>
</html>
权限控制实现
<?php
namespace App\Helpers;
class AccessControl
{
/**
* 检查用户权限
*/
public static function checkPermission($permission)
{
if (!isset($_SESSION['user_id'])) {
header('HTTP/1.1 401 Unauthorized');
echo json_encode(['error' => '未登录']);
exit;
}
// 获取用户角色权限
$sql = "SELECT p.permission_code
FROM role_permissions rp
INNER JOIN permissions p ON rp.permission_id = p.id
INNER JOIN user_roles ur ON ur.role_id = rp.role_id
WHERE ur.user_id = ?";
$db = Database::getInstance();
$stmt = $db->prepare($sql);
$stmt->execute([$_SESSION['user_id']]);
$permissions = $stmt->fetchAll(PDO::FETCH_COLUMN);
if (!in_array($permission, $permissions)) {
header('HTTP/1.1 403 Forbidden');
echo json_encode(['error' => '没有权限']);
exit;
}
}
/**
* 数据权限过滤
*/
public static function dataScope($departmentId = '')
{
$userDept = $_SESSION['department_id'] ?? '';
$userLevel = $_SESSION['user_level'] ?? '';
// 超级管理员可查看所有数据
if ($userLevel === 'super') {
return '';
}
// 部门经理可查看本部门
if ($userLevel === 'manager') {
return "department_id = {$userDept}";
}
// 普通用户仅查看自己
if ($userLevel === 'user') {
return "created_by = {$_SESSION['user_id']}";
}
return '';
}
}
最佳实践与优化
安全性优化
// SQL注入防护
// 使用预处理语句
$stmt = $db->prepare("SELECT * FROM positions WHERE id = ?");
$stmt->execute([$id]);
// XSS防护
function sanitizeOutput($data) {
return htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
}
// CSRF防护
function generateCSRFToken() {
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
return $_SESSION['csrf_token'];
}
性能优化
// 缓存热门岗位数据
class PositionCache {
public static function getHotPositions() {
$cacheKey = 'hot_positions';
$data = Redis::get($cacheKey);
if (!$data) {
$db = Database::getInstance();
$stmt = $db->query("SELECT * FROM positions WHERE status=1 ORDER BY view_count DESC LIMIT 10");
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
Redis::set($cacheKey, $data, 3600);
}
return $data;
}
}
日志记录
class OperationLog {
public static function record($action, $positionId) {
$logData = [
'user_id' => $_SESSION['user_id'],
'action' => $action,
'position_id' => $positionId,
'ip' => $_SERVER['REMOTE_ADDR'],
'user_agent' => $_SERVER['HTTP_USER_AGENT'],
'timestamp' => date('Y-m-d H:i:s')
];
// 写入日志
$db = Database::getInstance();
$sql = "INSERT INTO operation_logs (user_id, action, position_id, ip, user_agent, created_at)
VALUES (?, ?, ?, ?, ?, ?)";
$stmt = $db->prepare($sql);
$stmt->execute([
$logData['user_id'],
$logData['action'],
$logData['position_id'],
$logData['ip'],
$logData['user_agent'],
$logData['timestamp']
]);
}
}
这个岗位管理系统包含了完整的CRUD操作、人员分配、权限控制等核心功能,你可以根据实际需求扩展功能,如批量导入导出、岗位对比分析、审批流程等,如果需要特定功能的详细实现,请告诉我。