调试,测试并调整修改了代码及结构
This commit is contained in:
@@ -1,618 +0,0 @@
|
||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<%
|
||||
com.chinasofti.model.Employee currentEmployee = (com.chinasofti.model.Employee) session.getAttribute("currentEmployee");
|
||||
if (currentEmployee == null) {
|
||||
response.sendRedirect(request.getContextPath() + "/Login.jsp");
|
||||
return;
|
||||
}
|
||||
String positionDesc = "";
|
||||
switch (currentEmployee.getPosition()) {
|
||||
case 1: positionDesc = "馆员"; break;
|
||||
case 2: positionDesc = "工作人员"; break;
|
||||
case 3: positionDesc = "经理"; break;
|
||||
}
|
||||
String empJson = String.format(
|
||||
"{\"id\":\"%s\",\"name\":\"%s\",\"position\":\"%s\"}",
|
||||
currentEmployee.getEmployeeCode(),
|
||||
currentEmployee.getName(),
|
||||
positionDesc
|
||||
);
|
||||
request.setAttribute("empJson", empJson);
|
||||
%>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>员工门户 · 职位驱动</title>
|
||||
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
|
||||
<style>
|
||||
/* 样式完全保留,与原来相同,此处省略 */
|
||||
* { margin:0; padding:0; box-sizing:border-box; }
|
||||
body { background:#eef2f6; font-family:'Inter',sans-serif; display:flex; align-items:center; justify-content:center; min-height:100vh; padding:1rem; }
|
||||
#app { width:100%; max-width:1400px; }
|
||||
.app-container { background:white; border-radius:32px; box-shadow:0 30px 50px -20px rgba(0,0,0,0.2); overflow:hidden; }
|
||||
.employee-header { display:flex; align-items:center; justify-content:space-between; padding:1.2rem 2rem; background:#fff; border-bottom:1px solid #eaf0f6; flex-wrap:wrap; gap:1rem; }
|
||||
.employee-info { display:flex; align-items:center; gap:2rem; flex-wrap:wrap; }
|
||||
.info-item { background:#f0f6fe; padding:0.4rem 1.2rem; border-radius:40px; font-weight:500; color:#1a2b3c; }
|
||||
.position-selector { display:flex; align-items:center; gap:1rem; }
|
||||
.position-selector label { font-weight:600; color:#3a4e66; font-size:0.9rem; }
|
||||
.position-dropdown { padding:0.5rem 2rem 0.5rem 1.2rem; border:1.5px solid #d0ddee; border-radius:40px; font-size:1rem; background:white; cursor:pointer; outline:none; font-weight:500; color:#1a2b3c; }
|
||||
.position-dropdown:focus { border-color:#7c8ea0; }
|
||||
.main-content { padding:2rem; }
|
||||
.section-card { background:#f9fcff; border-radius:24px; padding:1.6rem 1.8rem; border:1px solid #e6edf5; margin-bottom:2rem; }
|
||||
.section-title { font-size:1.2rem; font-weight:600; color:#1e3b5c; margin-bottom:1.5rem; display:flex; align-items:center; gap:0.5rem; }
|
||||
.form-row { display:flex; flex-wrap:wrap; gap:1rem; align-items:flex-end; margin-bottom:1.5rem; }
|
||||
.form-field { flex:1 1 160px; }
|
||||
.form-field label { display:block; font-size:0.75rem; font-weight:600; text-transform:uppercase; color:#5f748b; margin-bottom:0.3rem; }
|
||||
.form-field input, .form-field select { width:100%; padding:0.6rem 1rem; border:1.5px solid #d8e2ee; border-radius:30px; font-size:0.95rem; background:white; }
|
||||
.form-field input:focus, .form-field select:focus { outline:none; border-color:#7e99b3; }
|
||||
.btn { background:#2c3e50; color:white; border:none; padding:0.6rem 1.8rem; border-radius:30px; font-weight:500; cursor:pointer; font-size:0.95rem; transition:background 0.15s; height:fit-content; border:1px solid transparent; }
|
||||
.btn:hover { background:#1a2b3c; }
|
||||
.btn-outline { background:white; color:#2c3e50; border:1.5px solid #d0ddee; }
|
||||
.btn-outline:hover { background:#f2f6fc; border-color:#a0b8cf; }
|
||||
.btn-sm { padding:0.3rem 1rem; font-size:0.8rem; }
|
||||
.table-wrapper { overflow-x:auto; border-radius:18px; background:white; box-shadow:0 4px 12px rgba(0,0,0,0.02); margin-top:1.5rem; }
|
||||
table { width:100%; border-collapse:collapse; font-size:0.9rem; min-width:800px; }
|
||||
th { background:#eef4fa; color:#1d3b5c; font-weight:600; padding:1rem 0.8rem; text-align:left; }
|
||||
td { padding:1rem 0.8rem; border-bottom:1px solid #eef3f8; color:#1f2f40; }
|
||||
.action-cell { display:flex; gap:0.5rem; flex-wrap:wrap; }
|
||||
.badge { background:#c9dff3; color:#144a70; padding:0.2rem 0.8rem; border-radius:30px; font-size:0.75rem; font-weight:600; display:inline-block; }
|
||||
.grid-2col { display:grid; grid-template-columns:1fr 1fr; gap:2rem; }
|
||||
@media (max-width:800px) { .grid-2col { grid-template-columns:1fr; } }
|
||||
.empty-placeholder { text-align:center; padding:2rem; background:white; border-radius:18px; color:#8f9fb1; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
<div class="app-container">
|
||||
<!-- 头部:员工信息 + 职位下拉 -->
|
||||
<div class="employee-header">
|
||||
<div class="employee-info">
|
||||
<span class="info-item">🆔 工号:{{ employee.id }}</span>
|
||||
<span class="info-item">👤 姓名:{{ employee.name }}</span>
|
||||
<span class="info-item">📌 职位:{{ employee.position }}</span>
|
||||
</div>
|
||||
<div class="position-selector">
|
||||
<label for="positionSelect">切换职位(模拟权限):</label>
|
||||
<select id="positionSelect" v-model="selectedPosition" class="position-dropdown">
|
||||
<option value="馆员">馆员 (staff)</option>
|
||||
<option value="工作人员">工作人员 (worker)</option>
|
||||
<option value="经理">经理 (manager)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 主区域:根据 selectedPosition 渲染不同功能 -->
|
||||
<div class="main-content">
|
||||
<!-- 馆员视图:图书增删改查 -->
|
||||
<div v-if="selectedPosition === '馆员'">
|
||||
<div class="section-card">
|
||||
<div class="section-title">📚 图书管理 · 馆员</div>
|
||||
<div class="form-row">
|
||||
<div class="form-field">
|
||||
<label>ISBN</label>
|
||||
<input v-model="bookForm.isbn" type="text" placeholder="ISBN" />
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label>书名</label>
|
||||
<input v-model="bookForm.title" type="text" placeholder="书名" />
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label>作者</label>
|
||||
<input v-model="bookForm.author" type="text" placeholder="作者" />
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label>出版社</label>
|
||||
<input v-model="bookForm.publisher" type="text" placeholder="出版社" />
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label>出版年</label>
|
||||
<input v-model.number="bookForm.publishYear" type="number" placeholder="2025" />
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label>总库存</label>
|
||||
<input v-model.number="bookForm.totalStock" type="number" placeholder="库存" />
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label>面向群体</label>
|
||||
<select v-model="bookForm.targetAudience">
|
||||
<option value="通用">通用</option>
|
||||
<option value="儿童">儿童</option>
|
||||
<option value="成人">成人</option>
|
||||
<option value="老年">老年</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label>简介</label>
|
||||
<input v-model="bookForm.description" type="text" placeholder="简介" />
|
||||
</div>
|
||||
<button class="btn" @click="addBook">添加图书</button>
|
||||
</div>
|
||||
<div class="table-wrapper">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>book_id</th><th>ISBN</th><th>书名</th><th>作者</th><th>出版社</th><th>出版年</th><th>总库存</th><th>已借</th><th>儿童书</th><th>简介</th><th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="book in books" :key="book.id">
|
||||
<td>{{ book.id }}</td>
|
||||
<td>{{ book.isbn }}</td>
|
||||
<td>{{ book.title }}</td>
|
||||
<td>{{ book.author }}</td>
|
||||
<td>{{ book.publisher }}</td>
|
||||
<td>{{ book.publishYear }}</td>
|
||||
<td>{{ book.totalStock }}</td>
|
||||
<td>{{ book.borrowedCount || 0 }}</td>
|
||||
<td><span v-if="book.targetAudience === '儿童'" class="badge">儿童</span><span v-else>通用</span></td>
|
||||
<td>{{ book.description || '—' }}</td>
|
||||
<td class="action-cell">
|
||||
<button class="btn btn-sm" @click="editBook(book)">编辑</button>
|
||||
<button class="btn btn-sm btn-outline" @click="deleteBook(book)">删除</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 工作人员视图:帮助注册 + 借阅/归还 -->
|
||||
<div v-else-if="selectedPosition === '工作人员'">
|
||||
<div class="grid-2col">
|
||||
<!-- 左侧:特殊群体读者注册 -->
|
||||
<div class="section-card">
|
||||
<div class="section-title">👥 帮助注册(老年/特殊群体)</div>
|
||||
<div class="form-field" style="margin-bottom: 1rem;">
|
||||
<label>证号</label>
|
||||
<input v-model="registerForm.cardNumber" placeholder="例如 R2025001" />
|
||||
</div>
|
||||
<div class="form-field" style="margin-bottom: 1rem;">
|
||||
<label>姓名</label>
|
||||
<input v-model="registerForm.name" placeholder="姓名" />
|
||||
</div>
|
||||
<div class="form-field" style="margin-bottom: 1rem;">
|
||||
<label>年龄(选填)</label>
|
||||
<input v-model.number="registerForm.age" type="number" placeholder="年龄" />
|
||||
</div>
|
||||
<div class="form-field" style="margin-bottom: 1rem;">
|
||||
<label>读者类型</label>
|
||||
<select v-model="registerForm.type">
|
||||
<option>老年</option>
|
||||
<option>成人</option>
|
||||
<option>儿童</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-field" style="margin-bottom: 1.5rem;">
|
||||
<label>联系方式</label>
|
||||
<input v-model="registerForm.contact" placeholder="手机/邮箱" />
|
||||
</div>
|
||||
<button class="btn" @click="staffRegister">注册读者</button>
|
||||
</div>
|
||||
|
||||
<!-- 右侧:借阅/归还(基于读者账号) -->
|
||||
<div class="section-card">
|
||||
<div class="section-title">📖 代借阅/归还</div>
|
||||
<div class="form-row" style="margin-bottom: 1.5rem;">
|
||||
<div class="form-field" style="flex:2;">
|
||||
<label>读者证号</label>
|
||||
<input v-model="borrowerAccount" placeholder="如 R2024001" />
|
||||
</div>
|
||||
<button class="btn" @click="searchBorrowedStaff">查询借阅</button>
|
||||
</div>
|
||||
<div class="table-wrapper">
|
||||
<table>
|
||||
<thead><tr><th>借阅ID</th><th>ISBN</th><th>书名</th><th>作者</th><th>借阅日</th><th>应还日</th><th>操作</th></tr></thead>
|
||||
<tbody>
|
||||
<tr v-if="staffBorrowedList.length === 0"><td colspan="7" class="empty-placeholder">暂无借阅记录</td></tr>
|
||||
<tr v-for="item in staffBorrowedList" :key="item.borrowId">
|
||||
<td>{{ item.borrowId }}</td><td>{{ item.isbn }}</td><td>{{ item.bookTitle }}</td><td>{{ item.author }}</td>
|
||||
<td>{{ item.borrowDate }}</td><td>{{ item.dueDate }}</td>
|
||||
<td><button class="btn btn-sm" @click="returnBookStaff(item)">归还</button></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div style="margin-top:1.5rem;">
|
||||
<div class="form-row">
|
||||
<div class="form-field">
|
||||
<label>ISBN/书名</label>
|
||||
<input v-model="quickBorrowIsbn" placeholder="输入ISBN或书名" />
|
||||
</div>
|
||||
<button class="btn" @click="quickBorrow">快速借书</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 经理视图:活动增删改查 + 员工注册 -->
|
||||
<div v-else-if="selectedPosition === '经理'">
|
||||
<div class="grid-2col">
|
||||
<!-- 左侧:活动管理 -->
|
||||
<div class="section-card">
|
||||
<div class="section-title">🎉 活动管理</div>
|
||||
<div class="form-row">
|
||||
<div class="form-field">
|
||||
<label>活动名称</label>
|
||||
<input v-model="activityForm.name" />
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label>开始时间</label>
|
||||
<input v-model="activityForm.startTime" placeholder="2025-05-10 15:00" />
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label>结束时间</label>
|
||||
<input v-model="activityForm.endTime" placeholder="2025-05-10 17:00" />
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label>地点</label>
|
||||
<input v-model="activityForm.location" />
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label>简介</label>
|
||||
<input v-model="activityForm.description" />
|
||||
</div>
|
||||
<button class="btn btn-sm" @click="addActivity">添加</button>
|
||||
</div>
|
||||
<div class="table-wrapper">
|
||||
<table>
|
||||
<thead><tr><th>名称</th><th>时间</th><th>地点</th><th>简介</th><th>操作</th></tr></thead>
|
||||
<tbody>
|
||||
<tr v-for="act in activities" :key="act.id">
|
||||
<td>{{ act.name }}</td><td>{{ act.startTime }}</td><td>{{ act.location }}</td><td>{{ act.description }}</td>
|
||||
<td class="action-cell">
|
||||
<button class="btn btn-sm" @click="editActivity(act)">编辑</button>
|
||||
<button class="btn btn-sm btn-outline" @click="deleteActivity(act)">删除</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧:新员工注册 -->
|
||||
<div class="section-card">
|
||||
<div class="section-title">👔 新员工注册</div>
|
||||
<div class="form-field" style="margin-bottom:1rem;">
|
||||
<label>工号</label>
|
||||
<input v-model="newEmployee.employeeCode" placeholder="如 E001" />
|
||||
</div>
|
||||
<div class="form-field" style="margin-bottom:1rem;">
|
||||
<label>姓名</label>
|
||||
<input v-model="newEmployee.name" placeholder="姓名" />
|
||||
</div>
|
||||
<div class="form-field" style="margin-bottom:1.5rem;">
|
||||
<label>职位</label>
|
||||
<select v-model="newEmployee.position">
|
||||
<option>馆员</option>
|
||||
<option>工作人员</option>
|
||||
<option>经理</option>
|
||||
</select>
|
||||
</div>
|
||||
<button class="btn" @click="addEmployee">注册新员工</button>
|
||||
|
||||
<div style="margin-top:2rem;">
|
||||
<div class="section-title" style="margin-bottom:0.8rem;">📋 现有员工</div>
|
||||
<div class="table-wrapper">
|
||||
<table>
|
||||
<thead><tr><th>工号</th><th>姓名</th><th>职位</th></tr></thead>
|
||||
<tbody>
|
||||
<tr v-for="emp in employees" :key="emp.employeeCode">
|
||||
<td>{{ emp.employeeCode }}</td><td>{{ emp.name }}</td><td>{{ emp.positionDesc }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
const { createApp, ref, onMounted } = Vue;
|
||||
|
||||
// 从服务器端传递的初始员工数据
|
||||
const initialEmployee = ${empJson};
|
||||
|
||||
const app = createApp({
|
||||
setup() {
|
||||
const employee = ref(initialEmployee);
|
||||
const selectedPosition = ref(employee.value.position);
|
||||
|
||||
// ---------- 图书数据 ----------
|
||||
const books = ref([]);
|
||||
const bookForm = ref({
|
||||
isbn: '',
|
||||
title: '',
|
||||
author: '',
|
||||
publisher: '',
|
||||
publishYear: null,
|
||||
totalStock: null,
|
||||
targetAudience: '通用',
|
||||
description: ''
|
||||
});
|
||||
|
||||
const loadBooks = async () => {
|
||||
try {
|
||||
const response = await fetch('${pageContext.request.contextPath}/api/books');
|
||||
books.value = await response.json();
|
||||
} catch (e) {
|
||||
console.error('加载图书失败', e);
|
||||
}
|
||||
};
|
||||
|
||||
const addBook = async () => {
|
||||
const params = new URLSearchParams(bookForm.value);
|
||||
try {
|
||||
const response = await fetch('${pageContext.request.contextPath}/api/books', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: params
|
||||
});
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
alert('添加成功');
|
||||
await loadBooks();
|
||||
bookForm.value = { isbn: '', title: '', author: '', publisher: '', publishYear: null, totalStock: null, targetAudience: '通用', description: '' };
|
||||
} else {
|
||||
alert(result.message || '添加失败');
|
||||
}
|
||||
} catch (e) {
|
||||
alert('网络错误');
|
||||
}
|
||||
};
|
||||
|
||||
const editBook = (book) => {
|
||||
alert('编辑功能待实现,请直接使用更新接口');
|
||||
};
|
||||
|
||||
const deleteBook = async (book) => {
|
||||
if (!confirm('确定删除吗?')) return;
|
||||
try {
|
||||
const response = await fetch('${pageContext.request.contextPath}/api/books/' + book.id, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
alert('删除成功');
|
||||
await loadBooks();
|
||||
} else {
|
||||
alert(result.message || '删除失败');
|
||||
}
|
||||
} catch (e) {
|
||||
alert('网络错误');
|
||||
}
|
||||
};
|
||||
|
||||
// ---------- 工作人员:注册表单 ----------
|
||||
const registerForm = ref({
|
||||
cardNumber: '',
|
||||
name: '',
|
||||
age: null,
|
||||
type: '老年',
|
||||
contact: '',
|
||||
regDate: new Date().toISOString().slice(0,10)
|
||||
});
|
||||
|
||||
const staffRegister = async () => {
|
||||
const params = new URLSearchParams(registerForm.value);
|
||||
try {
|
||||
const response = await fetch('${pageContext.request.contextPath}/api/staff/register', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: params
|
||||
});
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
alert('注册成功');
|
||||
registerForm.value = { cardNumber: '', name: '', age: null, type: '老年', contact: '', regDate: new Date().toISOString().slice(0,10) };
|
||||
} else {
|
||||
alert(result.message || '注册失败');
|
||||
}
|
||||
} catch (e) {
|
||||
alert('网络错误');
|
||||
}
|
||||
};
|
||||
|
||||
// 借阅数据
|
||||
const staffBorrowedList = ref([]);
|
||||
const borrowerAccount = ref('');
|
||||
|
||||
const searchBorrowedStaff = async () => {
|
||||
if (!borrowerAccount.value) {
|
||||
alert('请输入读者证号');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const response = await fetch('${pageContext.request.contextPath}/api/borrows?readerCard=' + encodeURIComponent(borrowerAccount.value));
|
||||
staffBorrowedList.value = await response.json();
|
||||
} catch (e) {
|
||||
alert('查询失败');
|
||||
}
|
||||
};
|
||||
|
||||
const returnBookStaff = async (item) => {
|
||||
const params = new URLSearchParams({ borrowId: item.borrowId });
|
||||
try {
|
||||
const response = await fetch('${pageContext.request.contextPath}/api/borrow', {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: params
|
||||
});
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
alert('归还成功');
|
||||
await searchBorrowedStaff();
|
||||
} else {
|
||||
alert(result.message || '归还失败');
|
||||
}
|
||||
} catch (e) {
|
||||
alert('网络错误');
|
||||
}
|
||||
};
|
||||
|
||||
const quickBorrowIsbn = ref('');
|
||||
const quickBorrow = async () => {
|
||||
if (!borrowerAccount.value) {
|
||||
alert('请先输入读者证号');
|
||||
return;
|
||||
}
|
||||
const params = new URLSearchParams({
|
||||
readerCard: borrowerAccount.value,
|
||||
isbnOrTitle: quickBorrowIsbn.value
|
||||
});
|
||||
try {
|
||||
const response = await fetch('${pageContext.request.contextPath}/api/borrow/quick', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: params
|
||||
});
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
alert('快速借书成功');
|
||||
await searchBorrowedStaff();
|
||||
quickBorrowIsbn.value = '';
|
||||
} else {
|
||||
alert(result.message || '快速借书失败');
|
||||
}
|
||||
} catch (e) {
|
||||
alert('网络错误');
|
||||
}
|
||||
};
|
||||
|
||||
// ---------- 经理:活动管理 ----------
|
||||
const activities = ref([]);
|
||||
const activityForm = ref({ name: '', startTime: '', endTime: '', location: '', description: '' });
|
||||
|
||||
const loadActivities = async () => {
|
||||
try {
|
||||
const response = await fetch('${pageContext.request.contextPath}/api/activities');
|
||||
activities.value = await response.json();
|
||||
} catch (e) {
|
||||
console.error('加载活动失败', e);
|
||||
}
|
||||
};
|
||||
|
||||
const addActivity = async () => {
|
||||
const params = new URLSearchParams(activityForm.value);
|
||||
try {
|
||||
const response = await fetch('${pageContext.request.contextPath}/api/activities', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: params
|
||||
});
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
alert('活动添加成功');
|
||||
await loadActivities();
|
||||
activityForm.value = { name: '', startTime: '', endTime: '', location: '', description: '' };
|
||||
} else {
|
||||
alert(result.message || '添加失败');
|
||||
}
|
||||
} catch (e) {
|
||||
alert('网络错误');
|
||||
}
|
||||
};
|
||||
|
||||
const editActivity = (act) => {
|
||||
alert('编辑功能待实现');
|
||||
};
|
||||
|
||||
const deleteActivity = async (act) => {
|
||||
if (!confirm('确定删除吗?')) return;
|
||||
try {
|
||||
const response = await fetch('${pageContext.request.contextPath}/api/activities/' + act.id, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
alert('删除成功');
|
||||
await loadActivities();
|
||||
} else {
|
||||
alert(result.message || '删除失败');
|
||||
}
|
||||
} catch (e) {
|
||||
alert('网络错误');
|
||||
}
|
||||
};
|
||||
|
||||
// 员工管理
|
||||
const employees = ref([]);
|
||||
const newEmployee = ref({ employeeCode: '', name: '', position: '馆员' });
|
||||
|
||||
const loadEmployees = async () => {
|
||||
try {
|
||||
const response = await fetch('${pageContext.request.contextPath}/api/employees');
|
||||
employees.value = await response.json();
|
||||
} catch (e) {
|
||||
console.error('加载员工失败', e);
|
||||
}
|
||||
};
|
||||
|
||||
const addEmployee = async () => {
|
||||
const params = new URLSearchParams(newEmployee.value);
|
||||
try {
|
||||
const response = await fetch('${pageContext.request.contextPath}/api/employees', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: params
|
||||
});
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
alert('员工注册成功');
|
||||
await loadEmployees();
|
||||
newEmployee.value = { employeeCode: '', name: '', position: '馆员' };
|
||||
} else {
|
||||
alert(result.message || '注册失败');
|
||||
}
|
||||
} catch (e) {
|
||||
alert('网络错误');
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
loadBooks();
|
||||
loadActivities();
|
||||
loadEmployees();
|
||||
});
|
||||
|
||||
return {
|
||||
employee,
|
||||
selectedPosition,
|
||||
books,
|
||||
bookForm,
|
||||
addBook,
|
||||
editBook,
|
||||
deleteBook,
|
||||
registerForm,
|
||||
staffRegister,
|
||||
staffBorrowedList,
|
||||
borrowerAccount,
|
||||
searchBorrowedStaff,
|
||||
returnBookStaff,
|
||||
quickBorrowIsbn,
|
||||
quickBorrow,
|
||||
activities,
|
||||
activityForm,
|
||||
addActivity,
|
||||
editActivity,
|
||||
deleteActivity,
|
||||
employees,
|
||||
newEmployee,
|
||||
addEmployee
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
app.mount('#app');
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user