mcbaiyun 5 сар өмнө
parent
commit
c9e32005b9

+ 44 - 0
src/api/bookborrowing/book/index.js

@@ -0,0 +1,44 @@
+import service from "@/utils/http";
+
+export function queryInfo(params) {
+  return service.request({
+    url: "/api/v1/bookborrowing/bookInfo/queryInfo",
+    method: "get",
+    params,
+  });
+}
+
+export function add(data) {
+  return service.request({
+    url: "/api/v1/bookborrowing/bookInfo/add",
+    method: "post",
+    data,
+    headers: { "Content-Type": "application/json;charset=UTF-8" },
+  });
+}
+
+export function edit(data) {
+  return service.request({
+    url: "/api/v1/bookborrowing/bookInfo/edit",
+    method: "put",
+    data,
+    headers: { "Content-Type": "application/json;charset=UTF-8" },
+  });
+}
+
+export function del(params) {
+  return service.request({
+    url: "/api/v1/bookborrowing/bookInfo/delete/" + params,
+    method: "delete",
+    params: {},
+  });
+}
+
+export function batchDelete(params) {
+  return service.request({
+    url: "/api/v1/bookborrowing/bookInfo/batchDelete",
+    method: "delete",
+    data: params,
+    headers: { "Content-Type": "application/json;charset=UTF-8" },
+  });
+}

+ 14 - 0
src/layouts/index.vue

@@ -67,6 +67,20 @@ const handleClose = (key, keyPath) => {
             <span>班级管理</span>
           </el-menu-item>
         </el-sub-menu>
+        <el-sub-menu index="/bookborrowing"> 
+          <template #title>
+            <el-icon>
+              <Setting />
+            </el-icon>
+            <span>图书借阅</span>
+          </template>
+          <el-menu-item index="/bookborrowing/book">
+            <el-icon>
+              <Menu />
+            </el-icon>
+            <span>图书管理</span>
+          </el-menu-item>
+        </el-sub-menu>
       </el-menu>
     </el-aside>
     <el-container class="app-cent-container">

+ 26 - 13
src/router/index.js

@@ -37,23 +37,36 @@ const router = createRouter({
           ],
         },
         {
-          path: '/educational',
-          name: 'educational',
-          redirect: '/educational/student',
-          component: () => import('@/views/educational/index.vue'), // 假设有一个父级布局组件
+          path: "/educational",
+          name: "educational",
+          redirect: "/educational/student",
+          component: () => import("@/views/educational/index.vue"),
           children: [
             {
-              path: 'student',
-              name: 'student',
-              component: () => import('@/views/educational/student/index.vue')
+              path: "student",
+              name: "student",
+              component: () => import("@/views/educational/student/index.vue"),
             },
             {
-              path: 'class',
-              name: 'class',
-              component: () => import('@/views/educational/class/index.vue')
-            }
-          ]
-        }
+              path: "class",
+              name: "class",
+              component: () => import("@/views/educational/class/index.vue"),
+            },
+          ],
+        },
+        {
+          path: "/bookborrowing",
+          name: "bookborrowing",
+          redirect: "/bookborrowing/book",
+          component: () => import("@/views/bookborrowing/index.vue"),
+          children: [
+            {
+              path: "book",
+              name: "book",
+              component: () => import("@/views/bookborrowing/book/index.vue"),
+            },
+          ],
+        },
       ],
     },
   ],

+ 97 - 0
src/stores/bookborrowing/book/index.js

@@ -0,0 +1,97 @@
+import { defineStore } from "pinia";
+import {
+  queryInfo,
+  add,
+  edit,
+  del,
+  batchDelete,
+} from "@/api/bookborrowing/book/index";
+import { ElMessage } from "element-plus";
+export const useBookStore = defineStore("book", {
+  state: () => ({
+    tableData: [],
+    total: 0,
+    pageNum: 1,
+    pageSize: 10,
+    loading: false,
+    dialogFormVisible: false,
+  }),
+  actions: {
+    async queryData(params) {
+      this.loading = true;
+      try {
+        const { data } = await queryInfo(params);
+        this.tableData = data.list;
+        this.total = data.total;
+      } finally {
+        this.loading = false;
+      }
+    },
+    addBook(data) {
+      return new Promise((resolve, reject) => {
+        add(data)
+          .then(({ code }) => {
+            if (code === 200) {
+              ElMessage.success("图书添加成功");
+              this.queryData({
+                pageNum: this.pageNum,
+                pageSize: this.pageSize,
+              });
+              resolve();
+            }
+          })
+          .catch((error) => {
+            reject(error);
+          });
+      });
+    },
+    editBook(data) {
+      return new Promise((resolve, reject) => {
+        edit(data)
+          .then(() => {
+            this.queryData({ pageNum: this.pageNum, pageSize: this.pageSize });
+            resolve();
+          })
+          .catch((error) => {
+            reject(error);
+          });
+      });
+    },
+    deleteBook(params) {
+      return new Promise((resolve, reject) => {
+        del(params)
+          .then(({ code }) => {
+            if (code == 200) {
+              ElMessage.success("删除成功");
+              this.queryData({
+                pageNum: this.pageNum,
+                pageSize: this.pageSize,
+              });
+            }
+            resolve();
+          })
+          .catch((error) => {
+            reject(error);
+          });
+      });
+    },
+    batchDeleteBook(params) {
+      return new Promise((resolve, reject) => {
+        batchDelete(params)
+          .then(({ code }) => {
+            if (code == 200) {
+              ElMessage.success("批量删除成功");
+              this.queryData({
+                pageNum: this.pageNum,
+                pageSize: this.pageSize,
+              });
+            }
+            resolve();
+          })
+          .catch((error) => {
+            reject(error);
+          });
+      });
+    },
+  },
+});

+ 340 - 0
src/views/bookborrowing/book/index.vue

@@ -0,0 +1,340 @@
+<script setup>
+import { onMounted, ref } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { useBookStore } from '@/stores/bookborrowing/book';
+import { storeToRefs } from 'pinia';
+
+const bookStore = useBookStore();
+const { tableData, total, pageNum, pageSize } = storeToRefs(bookStore);
+
+// 选中的书籍ID数组
+const selectedBookIds = ref([]);
+
+const queryFunction = function () {
+  bookStore.queryData({
+    pageNum: pageNum.value,
+    pageSize: pageSize.value
+  });
+}
+
+// 新增书籍表单
+const bookAddFrom = ref({
+  bookName: '',
+  author: '',
+  publisher: '',
+  releaseDate: null,
+  description: '',
+  serialNumber: '',
+  coverImages: '',
+  bookEnglishName: ''
+});
+
+// 新增验证规则
+const bookAddFromRules = {
+  bookName: [{ required: true, message: '请输入书名', trigger: 'blur' }],
+  author: [{ required: true, message: '请输入作者', trigger: 'blur' }],
+  publisher: [{ required: true, message: '请输入出版社', trigger: 'blur' }]
+};
+
+// 创建表单引用
+const bookAddFromRef = ref();
+
+onMounted(() => {
+  queryFunction();
+})
+
+// 分页大小变化
+const handleSizeChange = function (val) {
+  bookStore.pageSize = val;
+  queryFunction();
+}
+
+// 当前页码变化
+const handleCurrentChange = function (val) {
+  bookStore.pageNum = val;
+  queryFunction();
+}
+
+// 新增书籍
+const handleAdd = async () => {
+  if (!bookAddFromRef.value) return
+  try {
+    const valid = await bookAddFromRef.value.validate();
+    if (valid) {
+      bookStore.addBook(bookAddFrom.value);
+      bookStore.dialogFormVisible = false;
+    }
+  } catch (error) {
+    ElMessage.error('添加书籍失败,请重试');
+  }
+};
+
+// 编辑书籍表单
+const bookEditFrom = ref({
+  id: '',
+  bookName: '',
+  author: '',
+  publisher: '',
+  releaseDate: null,
+  description: '',
+  serialNumber: '',
+  coverImages: '',
+  bookEnglishName: ''
+});
+
+// 编辑验证规则
+const bookEditFromRules = {
+  bookName: [{ required: true, message: '请输入书名', trigger: 'blur' }],
+  author: [{ required: true, message: '请输入作者', trigger: 'blur' }],
+  publisher: [{ required: true, message: '请输入出版社', trigger: 'blur' }]
+};
+
+// 编辑表单引用
+const bookEditFromRef = ref();
+
+// 编辑书籍
+const handleEdit = (row) => {
+  // 初始化编辑表单数据
+  bookEditFrom.value = { ...row };
+  // 显示编辑对话框
+  bookStore.dialogEditFormVisible = true;
+};
+
+// 提交编辑
+const handleEditSubmit = async () => {
+  if (!bookEditFromRef.value) return
+  try {
+    const valid = await bookEditFromRef.value.validate();
+    if (valid) {
+      await bookStore.editBook(bookEditFrom.value);
+      bookStore.dialogEditFormVisible = false;
+    }
+  } catch (error) {
+    ElMessage.error('编辑书籍失败,请重试');
+  }
+};
+
+// 选择行变化
+const handleSelectionChange = (rows) => {
+  // 获取选中行的ID
+  selectedBookIds.value = rows.map(row => row.id);
+};
+
+// 删除书籍
+const handleDelete = (row) => {
+  ElMessageBox.confirm('确定要删除这本书吗?', '提示', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning'
+  }).then(() => {
+    bookStore.deleteBook(row.id);
+  }).catch(() => {
+    // 用户点击取消时的处理
+  });
+};
+
+// 批量删除
+const handleBatchDelete = () => {
+  if (selectedBookIds.value.length === 0) {
+    ElMessage.warning('请至少选择一条记录进行删除');
+    return;
+  }
+  ElMessageBox.confirm('确定要批量删除选中的书籍吗?', '提示', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning'
+  }).then(() => {
+    bookStore.batchDeleteBook(selectedBookIds.value);
+  }).catch(() => {
+    // 用户点击取消时的处理
+  });
+};
+</script>
+<template>
+  <div class="data-table-container">
+    <div class="search-from">
+      <!-- 搜索表单 -->
+    </div>
+    <div class="operate-buttons">
+      <el-button size="default" type="primary" @click="bookStore.dialogFormVisible = true">
+        <i class="el-icon-plus el-icon--left"></i>新增
+      </el-button>
+      <el-button size="default" type="danger" @click="handleBatchDelete">
+        <i class="el-icon-delete el-icon--left"></i>批量删除
+      </el-button>
+    </div>
+    <div class="data-table">
+      <div class="table-container">
+        <el-table height="600" border fit stripe :data="tableData" style="width: 100%" max-height="600"
+          v-loading="bookStore.loading" element-loading-text="拼命加载中" element-loading-spinner="el-icon-loading"
+          element-loading-background="rgba(0, 0, 0, 0.1)" @selection-change="handleSelectionChange">
+          <el-table-column type="selection" width="55" />
+          <el-table-column type="index" label="序号" width="55" />
+          <el-table-column prop="bookName" label="书名" />
+          <el-table-column prop="author" label="作者" />
+          <el-table-column prop="publisher" label="出版社" />
+          <el-table-column prop="releaseDate" label="发行日期" width="160">
+          </el-table-column>
+          <el-table-column prop="serialNumber" label="序列号" />
+          <el-table-column fixed="right" label="操作" width="120">
+            <template #default="{ row }">
+              <el-button link type="primary" size="small" @click="handleEdit(row)">修改</el-button>
+              <el-button link type="danger" size="small" @click="handleDelete(row)">删除</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <div class="pagination-container">
+        <el-pagination :currentPage="pageNum" :page-sizes="[10, 20, 50, 100]" :page-size="pageSize"
+          layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="handleSizeChange"
+          @current-change="handleCurrentChange" />
+      </div>
+    </div>
+  </div>
+
+  <!-- 新增书籍对话框 -->
+  <el-dialog v-model="bookStore.dialogFormVisible" title="新增书籍" width="600" center>
+    <el-form ref="bookAddFromRef" :model="bookAddFrom" :rules="bookAddFromRules">
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="书名" prop="bookName">
+            <el-input v-model="bookAddFrom.bookName" placeholder="书名" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="作者" prop="author">
+            <el-input v-model="bookAddFrom.author" placeholder="作者" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="出版社" prop="publisher">
+            <el-input v-model="bookAddFrom.publisher" placeholder="出版社" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="发行日期">
+            <el-date-picker
+              v-model="bookAddFrom.releaseDate"
+              type="date"
+              placeholder="选择日期"
+              style="width: 100%;"
+            />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="序列号">
+            <el-input v-model="bookAddFrom.serialNumber" placeholder="序列号" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="英文名">
+            <el-input v-model="bookAddFrom.bookEnglishName" placeholder="英文名" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      
+      <el-form-item label="封面图片">
+        <el-input v-model="bookAddFrom.coverImages" placeholder="封面图片地址" />
+      </el-form-item>
+      
+      <el-form-item label="描述">
+        <el-input v-model="bookAddFrom.description" type="textarea" :rows="2" />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="bookStore.dialogFormVisible = false">取消</el-button>
+        <el-button type="primary" @click="handleAdd">
+          确定
+        </el-button>
+      </div>
+    </template>
+  </el-dialog>
+
+  <!-- 编辑书籍对话框 -->
+  <el-dialog v-model="bookStore.dialogEditFormVisible" title="编辑书籍" width="600" center>
+    <el-form ref="bookEditFromRef" :model="bookEditFrom" :rules="bookEditFromRules">
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="书名" prop="bookName">
+            <el-input v-model="bookEditFrom.bookName" placeholder="书名" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="作者" prop="author">
+            <el-input v-model="bookEditFrom.author" placeholder="作者" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="出版社" prop="publisher">
+            <el-input v-model="bookEditFrom.publisher" placeholder="出版社" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="发行日期">
+            <el-date-picker
+              v-model="bookEditFrom.releaseDate"
+              type="date"
+              placeholder="选择日期"
+              style="width: 100%;"
+            />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="序列号">
+            <el-input v-model="bookEditFrom.serialNumber" placeholder="序列号" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="英文名">
+            <el-input v-model="bookEditFrom.bookEnglishName" placeholder="英文名" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      
+      <el-form-item label="封面图片">
+        <el-input v-model="bookEditFrom.coverImages" placeholder="封面图片地址" />
+      </el-form-item>
+      
+      <el-form-item label="描述">
+        <el-input v-model="bookEditFrom.description" type="textarea" :rows="2" />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="bookStore.dialogEditFormVisible = false">取消</el-button>
+        <el-button type="primary" @click="handleEditSubmit">
+          确定
+        </el-button>
+      </div>
+    </template>
+  </el-dialog>
+</template>
+<style scoped>
+.data-table-container {
+  padding: 20px;
+}
+.el-cascader {
+  width: 100%;
+}
+.dialog-footer {
+  text-align: right;
+}
+.cover-image {
+  width: 80px;
+  height: 100px;
+  object-fit: cover;
+}
+</style>

+ 11 - 0
src/views/bookborrowing/index.vue

@@ -0,0 +1,11 @@
+<script setup>
+import Layout from '@/layouts/index.vue'
+</script>
+
+<template>
+  <router-view></router-view>
+</template>
+
+<style lang="less" scoped>
+// 保持原有样式
+</style>