|
|
|
@ -1,14 +1,33 @@
|
|
|
|
<template>
|
|
|
|
<template>
|
|
|
|
<div class="supply-demand-container">
|
|
|
|
<div class="library-container">
|
|
|
|
<!-- 页面标题 -->
|
|
|
|
<!-- 页面标题 -->
|
|
|
|
<div class="page-header">
|
|
|
|
<div class="page-header">
|
|
|
|
<h2 class="page-title">
|
|
|
|
<h2 class="page-title">
|
|
|
|
<i class="el-icon-s-comment"></i>
|
|
|
|
<i class="el-icon-s-comment"></i>
|
|
|
|
供需管理
|
|
|
|
图书管理
|
|
|
|
</h2>
|
|
|
|
</h2>
|
|
|
|
<div>
|
|
|
|
<el-button type="primary" icon="el-icon-plus" @click="showUploadModal = true">
|
|
|
|
<el-tag type="danger">{{ pendingCount }}</el-tag>
|
|
|
|
添加图书
|
|
|
|
<small class="text-muted">待审核</small>
|
|
|
|
</el-button>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 图书统计 -->
|
|
|
|
|
|
|
|
<div class="book-stats">
|
|
|
|
|
|
|
|
<div class="stat-card blue">
|
|
|
|
|
|
|
|
<div class="stat-number">1,247</div>
|
|
|
|
|
|
|
|
<div class="stat-label">总图书数量</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="stat-card green">
|
|
|
|
|
|
|
|
<div class="stat-number">856</div>
|
|
|
|
|
|
|
|
<div class="stat-label">可借阅</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="stat-card orange">
|
|
|
|
|
|
|
|
<div class="stat-number">391</div>
|
|
|
|
|
|
|
|
<div class="stat-label">已借出</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="stat-card purple">
|
|
|
|
|
|
|
|
<div class="stat-number">23</div>
|
|
|
|
|
|
|
|
<div class="stat-label">维护中</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
@ -16,34 +35,36 @@
|
|
|
|
<div class="search-section">
|
|
|
|
<div class="search-section">
|
|
|
|
<el-form :model="filters" inline>
|
|
|
|
<el-form :model="filters" inline>
|
|
|
|
<el-form-item>
|
|
|
|
<el-form-item>
|
|
|
|
<el-input v-model="filters.keyword" placeholder="搜索标题、内容或用户名"></el-input>
|
|
|
|
<el-input v-model="filters.keyword" placeholder="搜索书名、作者、ISBN"></el-input>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item>
|
|
|
|
<el-form-item>
|
|
|
|
<el-select v-model="filters.status" placeholder="全部状态" clearable>
|
|
|
|
<el-select v-model="filters.category" placeholder="全部分类" clearable>
|
|
|
|
<el-option label="待审核" value="pending"></el-option>
|
|
|
|
<el-option label="技术类" value="tech"></el-option>
|
|
|
|
<el-option label="已通过" value="approved"></el-option>
|
|
|
|
<el-option label="商业类" value="business"></el-option>
|
|
|
|
<el-option label="已拒绝" value="rejected"></el-option>
|
|
|
|
<el-option label="管理类" value="management"></el-option>
|
|
|
|
|
|
|
|
<el-option label="金融类" value="finance"></el-option>
|
|
|
|
</el-select>
|
|
|
|
</el-select>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item>
|
|
|
|
<el-form-item>
|
|
|
|
<el-select v-model="filters.type" placeholder="全部类型" clearable>
|
|
|
|
<el-select v-model="filters.status" placeholder="全部状态" clearable>
|
|
|
|
<el-option label="供应" value="supply"></el-option>
|
|
|
|
<el-option label="可借阅" value="available"></el-option>
|
|
|
|
<el-option label="需求" value="demand"></el-option>
|
|
|
|
<el-option label="已借出" value="borrowed"></el-option>
|
|
|
|
|
|
|
|
<el-option label="维护中" value="maintenance"></el-option>
|
|
|
|
</el-select>
|
|
|
|
</el-select>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item>
|
|
|
|
|
|
|
|
<el-date-picker v-model="filters.date" type="date" placeholder="选择日期"></el-date-picker>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
<el-form-item>
|
|
|
|
<el-form-item>
|
|
|
|
<el-button type="primary" icon="el-icon-search" @click="handleSearch">搜索</el-button>
|
|
|
|
<el-button type="primary" icon="el-icon-search" @click="handleSearch">搜索</el-button>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item>
|
|
|
|
<el-form-item>
|
|
|
|
<el-button type="success" icon="el-icon-download" @click="handleExport">导出数据</el-button>
|
|
|
|
<el-button type="success" icon="el-icon-download" @click="handleExport">导出数据</el-button>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
<el-form-item>
|
|
|
|
|
|
|
|
<el-button type="info" icon="el-icon-upload2" @click="handleImport">批量导入</el-button>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
</el-form>
|
|
|
|
</el-form>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 供需列表表格 -->
|
|
|
|
<!-- 图书列表表格 -->
|
|
|
|
<div class="table-container">
|
|
|
|
<div class="table-container">
|
|
|
|
<el-table
|
|
|
|
<el-table
|
|
|
|
:data="list"
|
|
|
|
:data="list"
|
|
|
|
@ -51,62 +72,45 @@
|
|
|
|
style="width: 100%"
|
|
|
|
style="width: 100%"
|
|
|
|
>
|
|
|
|
>
|
|
|
|
<el-table-column type="selection" width="55"></el-table-column>
|
|
|
|
<el-table-column type="selection" width="55"></el-table-column>
|
|
|
|
<el-table-column type="index" label="序号" width="80"></el-table-column>
|
|
|
|
<el-table-column label="封面" width="80">
|
|
|
|
<el-table-column label="供需信息" min-width="250">
|
|
|
|
|
|
|
|
<template slot-scope="scope">
|
|
|
|
<template slot-scope="scope">
|
|
|
|
<div class="supply-title">{{ scope.row.title }}</div>
|
|
|
|
<img :src="scope.row.cover" alt="图书封面" class="book-cover">
|
|
|
|
<div class="supply-desc">{{ scope.row.description }}</div>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
</el-table-column>
|
|
|
|
<el-table-column label="类型" width="100">
|
|
|
|
<el-table-column label="图书信息" min-width="250">
|
|
|
|
<template slot-scope="scope">
|
|
|
|
<template slot-scope="scope">
|
|
|
|
<el-tag :type="scope.row.type === 'supply' ? 'success' : 'primary'" size="small">{{ scope.row.typeText }}</el-tag>
|
|
|
|
<div class="book-title">{{ scope.row.title }}</div>
|
|
|
|
|
|
|
|
<div class="book-author">作者:{{ scope.row.author }} · 出版社:{{ scope.row.publisher }} · {{ scope.row.year }}年</div>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
</el-table-column>
|
|
|
|
<el-table-column label="发布者" width="150">
|
|
|
|
<el-table-column label="分类" width="100">
|
|
|
|
<template slot-scope="scope">
|
|
|
|
<template slot-scope="scope">
|
|
|
|
<div class="user-info">
|
|
|
|
<el-tag :type="getCategoryTagType(scope.row.category)" size="small">{{ scope.row.categoryText }}</el-tag>
|
|
|
|
<div class="user-avatar">{{ scope.row.publisher.name.charAt(0) }}</div>
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
|
|
|
<div class="user-name">{{ scope.row.publisher.name }}</div>
|
|
|
|
|
|
|
|
<div class="user-year">{{ scope.row.publisher.year }}届</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
<el-table-column label="状态" width="120">
|
|
|
|
|
|
|
|
<template slot-scope="scope">
|
|
|
|
|
|
|
|
<el-tag :type="getStatusTagType(scope.row.status)" size="small">{{ scope.row.statusText }}</el-tag>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
</el-table-column>
|
|
|
|
<el-table-column label="优先级" width="100">
|
|
|
|
<el-table-column label="ISBN" width="150">
|
|
|
|
<template slot-scope="scope">
|
|
|
|
<template slot-scope="scope">
|
|
|
|
<el-tag :type="getPriorityTagType(scope.row.priority)" size="small">{{ scope.row.priorityText }}</el-tag>
|
|
|
|
{{ scope.row.isbn }}
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
</el-table-column>
|
|
|
|
<el-table-column label="发布时间" width="150">
|
|
|
|
<el-table-column label="状态" width="100">
|
|
|
|
<template slot-scope="scope">
|
|
|
|
<template slot-scope="scope">
|
|
|
|
<div class="time-display">{{ scope.row.publishDate }}</div>
|
|
|
|
<el-tag :type="getStatusTagType(scope.row.status)" size="small">{{ scope.row.statusText }}</el-tag>
|
|
|
|
<div class="time-display-secondary">{{ scope.row.publishTime }}</div>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
</el-table-column>
|
|
|
|
<el-table-column label="审核时间" width="150">
|
|
|
|
<el-table-column label="添加时间" width="150">
|
|
|
|
<template slot-scope="scope">
|
|
|
|
<template slot-scope="scope">
|
|
|
|
<div v-if="scope.row.auditDate">
|
|
|
|
<div class="time-display">{{ scope.row.addDate }}</div>
|
|
|
|
<div class="time-display">{{ scope.row.auditDate }}</div>
|
|
|
|
<div class="time-display-secondary">{{ scope.row.addTime }}</div>
|
|
|
|
<div class="time-display-secondary">{{ scope.row.auditTime }}</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<span v-else>-</span>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
</el-table-column>
|
|
|
|
<el-table-column label="操作" width="170" fixed="right">
|
|
|
|
<el-table-column label="操作" width="200" fixed="right">
|
|
|
|
<template slot-scope="scope">
|
|
|
|
<template slot-scope="scope">
|
|
|
|
<div class="action-buttons">
|
|
|
|
<div class="action-buttons">
|
|
|
|
<el-button v-if="scope.row.status === 'pending' || scope.row.status === 'rejected'" type="success" size="mini" icon="el-icon-check" @click="handleApprove(scope.row)">通过</el-button>
|
|
|
|
|
|
|
|
<el-button v-if="scope.row.status === 'approved'" type="info" size="mini" icon="el-icon-remove-outline" @click="handleHide(scope.row)">隐藏</el-button>
|
|
|
|
|
|
|
|
<el-button type="primary" size="mini" icon="el-icon-edit" @click="handleEdit(scope.row)">编辑</el-button>
|
|
|
|
<el-button type="primary" size="mini" icon="el-icon-edit" @click="handleEdit(scope.row)">编辑</el-button>
|
|
|
|
<el-button v-if="scope.row.status === 'pending'" type="danger" size="mini" icon="el-icon-close" @click="handleReject(scope.row)">拒绝</el-button>
|
|
|
|
|
|
|
|
<el-button type="info" size="mini" icon="el-icon-view" @click="handleView(scope.row)">详情</el-button>
|
|
|
|
<el-button type="info" size="mini" icon="el-icon-view" @click="handleView(scope.row)">详情</el-button>
|
|
|
|
|
|
|
|
<el-button v-if="scope.row.status === 'borrowed'" type="warning" size="mini" icon="el-icon-refresh-left" @click="handleReturn(scope.row)">归还</el-button>
|
|
|
|
|
|
|
|
<el-button type="danger" size="mini" icon="el-icon-delete" @click="handleDelete(scope.row)">删除</el-button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
</el-table-column>
|
|
|
|
@ -125,77 +129,188 @@
|
|
|
|
:total="total"
|
|
|
|
:total="total"
|
|
|
|
></el-pagination>
|
|
|
|
></el-pagination>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 添加图书弹窗 -->
|
|
|
|
|
|
|
|
<el-dialog
|
|
|
|
|
|
|
|
title="添加图书"
|
|
|
|
|
|
|
|
:visible.sync="showUploadModal"
|
|
|
|
|
|
|
|
width="600px"
|
|
|
|
|
|
|
|
:before-close="handleCloseModal"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<el-form :model="bookForm" :rules="bookRules" ref="bookForm" label-width="100px">
|
|
|
|
|
|
|
|
<!-- 基本信息 -->
|
|
|
|
|
|
|
|
<div class="form-section">
|
|
|
|
|
|
|
|
<div class="section-title">
|
|
|
|
|
|
|
|
<i class="el-icon-info"></i>
|
|
|
|
|
|
|
|
基本信息
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
<el-row :gutter="20">
|
|
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
|
|
<el-form-item label="书名" prop="title">
|
|
|
|
|
|
|
|
<el-input v-model="bookForm.title" placeholder="请输入书名"></el-input>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
|
|
<el-form-item label="作者" prop="author">
|
|
|
|
|
|
|
|
<el-input v-model="bookForm.author" placeholder="请输入作者"></el-input>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
<el-row :gutter="20">
|
|
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
|
|
<el-form-item label="ISBN">
|
|
|
|
|
|
|
|
<el-input v-model="bookForm.isbn" placeholder="978-7-xxx-xxxxx-x"></el-input>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
|
|
<el-form-item label="出版社">
|
|
|
|
|
|
|
|
<el-input v-model="bookForm.publisher" placeholder="请输入出版社"></el-input>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
<el-row :gutter="20">
|
|
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
|
|
<el-form-item label="出版年份">
|
|
|
|
|
|
|
|
<el-input-number v-model="bookForm.year" :min="1900" :max="2030" placeholder="年份"></el-input-number>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
|
|
<el-form-item label="分类" prop="category">
|
|
|
|
|
|
|
|
<el-input v-model="bookForm.category" placeholder="请输入分类"></el-input>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
<el-form-item label="图书简介">
|
|
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
|
|
type="textarea"
|
|
|
|
|
|
|
|
v-model="bookForm.description"
|
|
|
|
|
|
|
|
:rows="3"
|
|
|
|
|
|
|
|
:maxlength="500"
|
|
|
|
|
|
|
|
placeholder="请输入图书简介"
|
|
|
|
|
|
|
|
show-word-limit
|
|
|
|
|
|
|
|
></el-input>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 封面上传 -->
|
|
|
|
|
|
|
|
<div class="form-section">
|
|
|
|
|
|
|
|
<div class="section-title">
|
|
|
|
|
|
|
|
<i class="el-icon-picture"></i>
|
|
|
|
|
|
|
|
图书封面
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="upload-area" @click="triggerCoverUpload">
|
|
|
|
|
|
|
|
<div v-if="!bookForm.cover" class="upload-placeholder">
|
|
|
|
|
|
|
|
<i class="el-icon-upload" style="font-size: 32px; color: #9ca3af; margin-bottom: 10px;"></i>
|
|
|
|
|
|
|
|
<div style="color: #374151; font-weight: 500;">点击上传图书封面</div>
|
|
|
|
|
|
|
|
<div style="color: #9ca3af; font-size: 12px; margin-top: 5px;">支持 JPG、PNG 格式,建议尺寸 300×400</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<img v-else :src="bookForm.cover" alt="封面预览" class="upload-preview">
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<input
|
|
|
|
|
|
|
|
ref="coverInput"
|
|
|
|
|
|
|
|
type="file"
|
|
|
|
|
|
|
|
accept="image/*"
|
|
|
|
|
|
|
|
style="display: none;"
|
|
|
|
|
|
|
|
@change="handleCoverUpload"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
|
|
<div slot="footer" class="dialog-footer">
|
|
|
|
|
|
|
|
<el-button @click="showUploadModal = false">取消</el-button>
|
|
|
|
|
|
|
|
<el-button type="primary" @click="saveBook">保存图书</el-button>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</el-dialog>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
<script>
|
|
|
|
export default {
|
|
|
|
import { save } from '@/api/library'
|
|
|
|
name: 'SupplyDemand',
|
|
|
|
import { uploads } from '@/api/uploads'
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
|
|
|
name: 'Library',
|
|
|
|
data() {
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
return {
|
|
|
|
pendingCount: 3,
|
|
|
|
showUploadModal: false,
|
|
|
|
filters: {
|
|
|
|
filters: {
|
|
|
|
keyword: '',
|
|
|
|
keyword: '',
|
|
|
|
status: '',
|
|
|
|
category: '',
|
|
|
|
type: '',
|
|
|
|
status: ''
|
|
|
|
date: ''
|
|
|
|
|
|
|
|
},
|
|
|
|
},
|
|
|
|
list: [
|
|
|
|
list: [
|
|
|
|
{
|
|
|
|
{
|
|
|
|
id: 1,
|
|
|
|
id: 1,
|
|
|
|
title: '提供企业管理咨询服务',
|
|
|
|
title: '深度学习实战指南',
|
|
|
|
description: '专业企业管理咨询团队,具有10年以上行业经验...',
|
|
|
|
author: '张三',
|
|
|
|
type: 'supply',
|
|
|
|
publisher: '机械工业出版社',
|
|
|
|
typeText: '供应',
|
|
|
|
year: '2023',
|
|
|
|
publisher: { name: '张总', year: '2010' },
|
|
|
|
isbn: '978-7-111-12345-6',
|
|
|
|
status: 'pending',
|
|
|
|
category: 'tech',
|
|
|
|
statusText: '待审核',
|
|
|
|
categoryText: '技术类',
|
|
|
|
priority: 'high',
|
|
|
|
status: 'available',
|
|
|
|
priorityText: '高',
|
|
|
|
statusText: '可借阅',
|
|
|
|
publishDate: '2024-01-15',
|
|
|
|
cover: 'https://via.placeholder.com/50x70/4285f4/ffffff?text=书',
|
|
|
|
publishTime: '14:30',
|
|
|
|
addDate: '2024-01-15',
|
|
|
|
auditDate: null,
|
|
|
|
addTime: '10:30'
|
|
|
|
auditTime: null
|
|
|
|
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{
|
|
|
|
id: 2,
|
|
|
|
id: 2,
|
|
|
|
title: '寻找技术合作伙伴',
|
|
|
|
title: '创业公司股权设计',
|
|
|
|
description: '我们是一家初创公司,目前在开发一款AI智能客服产品...',
|
|
|
|
author: '李四',
|
|
|
|
type: 'demand',
|
|
|
|
publisher: '中信出版社',
|
|
|
|
typeText: '需求',
|
|
|
|
year: '2023',
|
|
|
|
publisher: { name: '李经理', year: '2015' },
|
|
|
|
isbn: '978-7-508-67890-1',
|
|
|
|
status: 'approved',
|
|
|
|
category: 'business',
|
|
|
|
statusText: '已通过',
|
|
|
|
categoryText: '商业类',
|
|
|
|
priority: 'medium',
|
|
|
|
status: 'borrowed',
|
|
|
|
priorityText: '中',
|
|
|
|
statusText: '已借出',
|
|
|
|
publishDate: '2024-01-14',
|
|
|
|
cover: 'https://via.placeholder.com/50x70/ff9800/ffffff?text=书',
|
|
|
|
publishTime: '16:45',
|
|
|
|
addDate: '2024-01-14',
|
|
|
|
auditDate: '2024-01-14',
|
|
|
|
addTime: '15:20'
|
|
|
|
auditTime: '17:20'
|
|
|
|
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{
|
|
|
|
id: 3,
|
|
|
|
id: 3,
|
|
|
|
title: '投融资咨询服务',
|
|
|
|
title: '敏捷项目管理实践',
|
|
|
|
description: '专业投融资顾问,为企业提供全方位的融资解决方案...',
|
|
|
|
author: '王五',
|
|
|
|
type: 'supply',
|
|
|
|
publisher: '电子工业出版社',
|
|
|
|
typeText: '供应',
|
|
|
|
year: '2022',
|
|
|
|
publisher: { name: '王顾问', year: '2008' },
|
|
|
|
isbn: '978-7-121-34567-8',
|
|
|
|
status: 'rejected',
|
|
|
|
category: 'management',
|
|
|
|
statusText: '已拒绝',
|
|
|
|
categoryText: '管理类',
|
|
|
|
priority: 'low',
|
|
|
|
status: 'available',
|
|
|
|
priorityText: '低',
|
|
|
|
statusText: '可借阅',
|
|
|
|
publishDate: '2024-01-13',
|
|
|
|
cover: 'https://via.placeholder.com/50x70/4caf50/ffffff?text=书',
|
|
|
|
publishTime: '09:15',
|
|
|
|
addDate: '2024-01-13',
|
|
|
|
auditDate: '2024-01-13',
|
|
|
|
addTime: '09:15'
|
|
|
|
auditTime: '10:30'
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
],
|
|
|
|
],
|
|
|
|
total: 156,
|
|
|
|
total: 1247,
|
|
|
|
listQuery: {
|
|
|
|
listQuery: {
|
|
|
|
page: 1,
|
|
|
|
page: 1,
|
|
|
|
limit: 10
|
|
|
|
limit: 10
|
|
|
|
},
|
|
|
|
},
|
|
|
|
multipleSelection: []
|
|
|
|
multipleSelection: [],
|
|
|
|
|
|
|
|
bookForm: {
|
|
|
|
|
|
|
|
title: '',
|
|
|
|
|
|
|
|
author: '',
|
|
|
|
|
|
|
|
isbn: '',
|
|
|
|
|
|
|
|
publisher: '',
|
|
|
|
|
|
|
|
year: null,
|
|
|
|
|
|
|
|
category: '',
|
|
|
|
|
|
|
|
description: '',
|
|
|
|
|
|
|
|
cover: '',
|
|
|
|
|
|
|
|
cover_id: ''
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
bookRules: {
|
|
|
|
|
|
|
|
title: [
|
|
|
|
|
|
|
|
{ required: true, message: '请输入书名', trigger: 'blur' }
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
author: [
|
|
|
|
|
|
|
|
{ required: true, message: '请输入作者', trigger: 'blur' }
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
category: [
|
|
|
|
|
|
|
|
{ required: true, message: '请输入分类', trigger: 'blur' }
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
methods: {
|
|
|
|
@ -207,202 +322,417 @@
|
|
|
|
console.log('导出数据')
|
|
|
|
console.log('导出数据')
|
|
|
|
this.$message.info('数据导出中...')
|
|
|
|
this.$message.info('数据导出中...')
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
handleImport() {
|
|
|
|
|
|
|
|
console.log('批量导入')
|
|
|
|
|
|
|
|
this.$message.info('批量导入功能')
|
|
|
|
|
|
|
|
},
|
|
|
|
handleSelectionChange(val) {
|
|
|
|
handleSelectionChange(val) {
|
|
|
|
this.multipleSelection = val
|
|
|
|
this.multipleSelection = val
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
getCategoryTagType(category) {
|
|
|
|
|
|
|
|
const categoryMap = {
|
|
|
|
|
|
|
|
tech: 'primary',
|
|
|
|
|
|
|
|
business: 'success',
|
|
|
|
|
|
|
|
management: 'warning',
|
|
|
|
|
|
|
|
finance: 'danger'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return categoryMap[category] || 'info'
|
|
|
|
|
|
|
|
},
|
|
|
|
getStatusTagType(status) {
|
|
|
|
getStatusTagType(status) {
|
|
|
|
const statusMap = {
|
|
|
|
const statusMap = {
|
|
|
|
pending: 'warning',
|
|
|
|
available: 'success',
|
|
|
|
approved: 'success',
|
|
|
|
borrowed: 'warning',
|
|
|
|
rejected: 'danger'
|
|
|
|
maintenance: 'danger'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return statusMap[status]
|
|
|
|
return statusMap[status]
|
|
|
|
},
|
|
|
|
},
|
|
|
|
getPriorityTagType(priority) {
|
|
|
|
|
|
|
|
const priorityMap = {
|
|
|
|
|
|
|
|
high: 'danger',
|
|
|
|
|
|
|
|
medium: 'warning',
|
|
|
|
|
|
|
|
low: 'success'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return priorityMap[priority]
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
handleApprove(row) {
|
|
|
|
|
|
|
|
this.$confirm('确定要通过这条供需信息吗?', '提示', {
|
|
|
|
|
|
|
|
confirmButtonText: '确定',
|
|
|
|
|
|
|
|
cancelButtonText: '取消',
|
|
|
|
|
|
|
|
type: 'success'
|
|
|
|
|
|
|
|
}).then(() => {
|
|
|
|
|
|
|
|
console.log('审核通过:', row.id)
|
|
|
|
|
|
|
|
// API call here
|
|
|
|
|
|
|
|
row.status = 'approved'
|
|
|
|
|
|
|
|
row.statusText = '已通过'
|
|
|
|
|
|
|
|
this.$message.success('审核通过成功!')
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
handleEdit(row) {
|
|
|
|
handleEdit(row) {
|
|
|
|
console.log('编辑:', row.id)
|
|
|
|
console.log('编辑:', row.id)
|
|
|
|
this.$message.info('跳转到编辑页面')
|
|
|
|
this.$message.info('跳转到编辑页面')
|
|
|
|
},
|
|
|
|
},
|
|
|
|
handleReject(row) {
|
|
|
|
handleView(row) {
|
|
|
|
this.$prompt('请输入拒绝原因:', '提示', {
|
|
|
|
console.log('查看详情:', row.id)
|
|
|
|
|
|
|
|
this.$message.info('跳转到详情页面')
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
handleReturn(row) {
|
|
|
|
|
|
|
|
this.$confirm('确认这本图书已归还吗?', '提示', {
|
|
|
|
confirmButtonText: '确定',
|
|
|
|
confirmButtonText: '确定',
|
|
|
|
cancelButtonText: '取消',
|
|
|
|
cancelButtonText: '取消',
|
|
|
|
type: 'warning'
|
|
|
|
type: 'warning'
|
|
|
|
}).then(({ value }) => {
|
|
|
|
}).then(() => {
|
|
|
|
console.log('拒绝:', row.id, '原因:', value)
|
|
|
|
console.log('归还图书:', row.id)
|
|
|
|
// API call here
|
|
|
|
row.status = 'available'
|
|
|
|
row.status = 'rejected'
|
|
|
|
row.statusText = '可借阅'
|
|
|
|
row.statusText = '已拒绝'
|
|
|
|
this.$message.success('图书归还成功!')
|
|
|
|
this.$message.success('已拒绝该供需信息!')
|
|
|
|
}).catch(() => {
|
|
|
|
|
|
|
|
this.$message.info('已取消归还')
|
|
|
|
})
|
|
|
|
})
|
|
|
|
},
|
|
|
|
},
|
|
|
|
handleHide(row) {
|
|
|
|
handleDelete(row) {
|
|
|
|
this.$confirm('确定要隐藏这条供需信息吗?', '提示', {
|
|
|
|
this.$confirm('确定要删除这本图书吗?', '提示', {
|
|
|
|
confirmButtonText: '确定',
|
|
|
|
confirmButtonText: '确定',
|
|
|
|
cancelButtonText: '取消',
|
|
|
|
cancelButtonText: '取消',
|
|
|
|
type: 'info'
|
|
|
|
type: 'warning'
|
|
|
|
}).then(() => {
|
|
|
|
}).then(() => {
|
|
|
|
console.log('隐藏:', row.id)
|
|
|
|
console.log('删除图书:', row.id)
|
|
|
|
// API call here
|
|
|
|
// 这里应该调用删除API
|
|
|
|
this.$message.success('供需信息已隐藏!')
|
|
|
|
const index = this.list.findIndex(item => item.id === row.id)
|
|
|
|
|
|
|
|
if (index > -1) {
|
|
|
|
|
|
|
|
this.list.splice(index, 1)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
this.$message.success('图书删除成功!')
|
|
|
|
|
|
|
|
}).catch(() => {
|
|
|
|
|
|
|
|
this.$message.info('已取消删除')
|
|
|
|
})
|
|
|
|
})
|
|
|
|
},
|
|
|
|
},
|
|
|
|
handleView(row) {
|
|
|
|
|
|
|
|
console.log('查看详情:', row.id)
|
|
|
|
|
|
|
|
this.$message.info('跳转到详情页面')
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
handleSizeChange(val) {
|
|
|
|
handleSizeChange(val) {
|
|
|
|
this.listQuery.limit = val
|
|
|
|
this.listQuery.limit = val
|
|
|
|
// getList()
|
|
|
|
console.log('每页显示条数:', val)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
handleCurrentChange(val) {
|
|
|
|
handleCurrentChange(val) {
|
|
|
|
this.listQuery.page = val
|
|
|
|
this.listQuery.page = val
|
|
|
|
// getList()
|
|
|
|
console.log('当前页:', val)
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
handleCloseModal() {
|
|
|
|
|
|
|
|
this.resetForm()
|
|
|
|
|
|
|
|
this.showUploadModal = false
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
triggerCoverUpload() {
|
|
|
|
|
|
|
|
this.$refs.coverInput.click()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
async handleCoverUpload(event) {
|
|
|
|
|
|
|
|
const file = event.target.files[0]
|
|
|
|
|
|
|
|
if (file) {
|
|
|
|
|
|
|
|
if (!file.type.match(/^image\/(jpeg|jpg|png)$/)) {
|
|
|
|
|
|
|
|
this.$message.error('请选择 JPG 或 PNG 格式的图片')
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (file.size > 2 * 1024 * 1024) {
|
|
|
|
|
|
|
|
this.$message.error('图片大小不能超过 2MB')
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 预览
|
|
|
|
|
|
|
|
const reader = new FileReader()
|
|
|
|
|
|
|
|
reader.onload = (e) => {
|
|
|
|
|
|
|
|
this.bookForm.cover = e.target.result
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
reader.readAsDataURL(file)
|
|
|
|
|
|
|
|
// 上传
|
|
|
|
|
|
|
|
const formData = new FormData()
|
|
|
|
|
|
|
|
formData.append('file', file)
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
const res = await uploads(formData)
|
|
|
|
|
|
|
|
this.bookForm.cover_id = res.id
|
|
|
|
|
|
|
|
this.$message.success('封面上传成功')
|
|
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
|
|
this.$message.error('封面上传失败')
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
async saveBook() {
|
|
|
|
|
|
|
|
this.$refs.bookForm.validate(async (valid) => {
|
|
|
|
|
|
|
|
if (valid) {
|
|
|
|
|
|
|
|
const loading = this.$loading({
|
|
|
|
|
|
|
|
lock: true,
|
|
|
|
|
|
|
|
text: '正在保存...',
|
|
|
|
|
|
|
|
spinner: 'el-icon-loading',
|
|
|
|
|
|
|
|
background: 'rgba(0, 0, 0, 0.7)'
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
const params = {
|
|
|
|
|
|
|
|
title: this.bookForm.title,
|
|
|
|
|
|
|
|
author: this.bookForm.author,
|
|
|
|
|
|
|
|
isbn: this.bookForm.isbn,
|
|
|
|
|
|
|
|
publisher: this.bookForm.publisher,
|
|
|
|
|
|
|
|
publish_year: this.bookForm.year,
|
|
|
|
|
|
|
|
category: this.bookForm.category,
|
|
|
|
|
|
|
|
description: this.bookForm.description,
|
|
|
|
|
|
|
|
cover_id: this.bookForm.cover_id
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
console.log('params', params)
|
|
|
|
|
|
|
|
await save(params)
|
|
|
|
|
|
|
|
loading.close()
|
|
|
|
|
|
|
|
this.$message.success('图书添加成功!')
|
|
|
|
|
|
|
|
this.showUploadModal = false
|
|
|
|
|
|
|
|
this.resetForm()
|
|
|
|
|
|
|
|
// 重新获取列表或手动添加
|
|
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
|
|
loading.close()
|
|
|
|
|
|
|
|
this.$message.error('添加失败,请重试' + e.message)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
this.$message.error('请填写必填字段')
|
|
|
|
|
|
|
|
return false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
resetForm() {
|
|
|
|
|
|
|
|
this.$refs.bookForm.resetFields()
|
|
|
|
|
|
|
|
this.bookForm = {
|
|
|
|
|
|
|
|
title: '',
|
|
|
|
|
|
|
|
author: '',
|
|
|
|
|
|
|
|
isbn: '',
|
|
|
|
|
|
|
|
publisher: '',
|
|
|
|
|
|
|
|
year: null,
|
|
|
|
|
|
|
|
category: '',
|
|
|
|
|
|
|
|
description: '',
|
|
|
|
|
|
|
|
cover: '',
|
|
|
|
|
|
|
|
cover_id: ''
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
getCategoryText(category) {
|
|
|
|
|
|
|
|
const categoryMap = {
|
|
|
|
|
|
|
|
tech: '技术类',
|
|
|
|
|
|
|
|
business: '商业类',
|
|
|
|
|
|
|
|
management: '管理类',
|
|
|
|
|
|
|
|
finance: '金融类'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return categoryMap[category] || category || ''
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
}
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
<style scoped>
|
|
|
|
.supply-demand-container {
|
|
|
|
.library-container {
|
|
|
|
padding: 20px;
|
|
|
|
padding: 20px;
|
|
|
|
background-color: #fff;
|
|
|
|
background-color: #f8f9fa;
|
|
|
|
margin: 20px;
|
|
|
|
min-height: 100vh;
|
|
|
|
border-radius: 8px;
|
|
|
|
}
|
|
|
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.page-header {
|
|
|
|
.page-header {
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
justify-content: space-between;
|
|
|
|
justify-content: space-between;
|
|
|
|
align-items: center;
|
|
|
|
align-items: center;
|
|
|
|
margin-bottom: 20px;
|
|
|
|
margin-bottom: 30px;
|
|
|
|
padding-bottom: 15px;
|
|
|
|
padding-bottom: 15px;
|
|
|
|
border-bottom: 2px solid #e9ecef;
|
|
|
|
border-bottom: 2px solid #e9ecef;
|
|
|
|
|
|
|
|
background: white;
|
|
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
|
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.page-title {
|
|
|
|
.page-title {
|
|
|
|
font-size: 24px;
|
|
|
|
font-size: 24px;
|
|
|
|
font-weight: bold;
|
|
|
|
font-weight: bold;
|
|
|
|
color: #2c3e50;
|
|
|
|
color: #2c3e50;
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
align-items: center;
|
|
|
|
margin: 0;
|
|
|
|
margin: 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
i {
|
|
|
|
.page-title i {
|
|
|
|
margin-right: 10px;
|
|
|
|
margin-right: 10px;
|
|
|
|
color: #3498db;
|
|
|
|
color: #3498db;
|
|
|
|
}
|
|
|
|
font-size: 28px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.text-muted {
|
|
|
|
.book-stats {
|
|
|
|
margin-left: 5px;
|
|
|
|
display: grid;
|
|
|
|
color: #6c757d;
|
|
|
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
|
|
}
|
|
|
|
gap: 20px;
|
|
|
|
}
|
|
|
|
margin-bottom: 30px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.search-section {
|
|
|
|
.stat-card {
|
|
|
|
background: #f8f9fa;
|
|
|
|
background: white;
|
|
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
|
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
|
|
border-left: 4px solid;
|
|
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.stat-card.blue { border-left-color: #3498db; }
|
|
|
|
|
|
|
|
.stat-card.green { border-left-color: #2ecc71; }
|
|
|
|
|
|
|
|
.stat-card.orange { border-left-color: #f39c12; }
|
|
|
|
|
|
|
|
.stat-card.purple { border-left-color: #9b59b6; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.stat-number {
|
|
|
|
|
|
|
|
font-size: 28px;
|
|
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
|
|
color: #2c3e50;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.stat-label {
|
|
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
|
|
color: #7f8c8d;
|
|
|
|
|
|
|
|
margin-top: 5px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.search-section {
|
|
|
|
|
|
|
|
background: white;
|
|
|
|
padding: 20px;
|
|
|
|
padding: 20px;
|
|
|
|
border-radius: 8px;
|
|
|
|
border-radius: 8px;
|
|
|
|
margin-bottom: 20px;
|
|
|
|
margin-bottom: 20px;
|
|
|
|
}
|
|
|
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.table-container {
|
|
|
|
.table-container {
|
|
|
|
background: white;
|
|
|
|
background: white;
|
|
|
|
border-radius: 8px;
|
|
|
|
border-radius: 8px;
|
|
|
|
overflow: hidden;
|
|
|
|
overflow: hidden;
|
|
|
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
|
|
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
|
|
|
}
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.book-cover {
|
|
|
|
|
|
|
|
width: 50px;
|
|
|
|
|
|
|
|
height: 70px;
|
|
|
|
|
|
|
|
object-fit: cover;
|
|
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
|
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.supply-title {
|
|
|
|
.book-title {
|
|
|
|
font-weight: 600;
|
|
|
|
font-weight: 600;
|
|
|
|
color: #2c3e50;
|
|
|
|
color: #2c3e50;
|
|
|
|
overflow: hidden;
|
|
|
|
margin-bottom: 4px;
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
font-size: 14px;
|
|
|
|
white-space: nowrap;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.supply-desc {
|
|
|
|
.book-author {
|
|
|
|
font-size: 12px;
|
|
|
|
font-size: 12px;
|
|
|
|
color: #6c757d;
|
|
|
|
color: #7f8c8d;
|
|
|
|
overflow: hidden;
|
|
|
|
}
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
.time-display {
|
|
|
|
}
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.time-display-secondary {
|
|
|
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.action-buttons {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
|
|
gap: 5px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.action-buttons .el-button {
|
|
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.user-info {
|
|
|
|
.pagination-container {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
|
|
background: white;
|
|
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
|
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.form-section {
|
|
|
|
|
|
|
|
background: #f8f9fa;
|
|
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.section-title {
|
|
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
|
|
color: #2c3e50;
|
|
|
|
|
|
|
|
margin-bottom: 15px;
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
align-items: center;
|
|
|
|
gap: 8px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.user-avatar {
|
|
|
|
.section-title i {
|
|
|
|
width: 32px;
|
|
|
|
margin-right: 8px;
|
|
|
|
height: 32px;
|
|
|
|
color: #3498db;
|
|
|
|
border-radius: 50%;
|
|
|
|
font-size: 18px;
|
|
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.upload-area {
|
|
|
|
|
|
|
|
border: 2px dashed #d1d5db;
|
|
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
|
|
padding: 30px;
|
|
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
|
|
background: white;
|
|
|
|
|
|
|
|
min-height: 120px;
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: center;
|
|
|
|
justify-content: center;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.upload-area:hover {
|
|
|
|
|
|
|
|
border-color: #3498db;
|
|
|
|
|
|
|
|
background: rgba(52, 152, 219, 0.05);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.upload-placeholder {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.upload-preview {
|
|
|
|
|
|
|
|
max-width: 120px;
|
|
|
|
|
|
|
|
max-height: 160px;
|
|
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
|
|
object-fit: cover;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.dialog-footer {
|
|
|
|
|
|
|
|
text-align: right;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Element UI 表格样式覆盖 */
|
|
|
|
|
|
|
|
::v-deep .el-table th {
|
|
|
|
|
|
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
|
color: white;
|
|
|
|
color: white;
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
font-weight: 600;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.user-name {
|
|
|
|
::v-deep .el-table tbody tr:hover > td {
|
|
|
|
font-size: 12px;
|
|
|
|
background-color: #f8f9fa;
|
|
|
|
font-weight: 600;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.user-year {
|
|
|
|
::v-deep .el-pagination {
|
|
|
|
font-size: 11px;
|
|
|
|
text-align: center;
|
|
|
|
color: #666;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.time-display {
|
|
|
|
/* 响应式设计 */
|
|
|
|
font-size: 12px;
|
|
|
|
@media (max-width: 768px) {
|
|
|
|
|
|
|
|
.book-stats {
|
|
|
|
|
|
|
|
grid-template-columns: 1fr 1fr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.time-display-secondary {
|
|
|
|
.page-header {
|
|
|
|
font-size: 11px;
|
|
|
|
flex-direction: column;
|
|
|
|
color: #666;
|
|
|
|
gap: 15px;
|
|
|
|
|
|
|
|
text-align: center;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.action-buttons {
|
|
|
|
.action-buttons {
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
|
|
gap: 6px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.el-button {
|
|
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.search-section .el-form {
|
|
|
|
|
|
|
|
display: block;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.pagination-container {
|
|
|
|
.search-section .el-form-item {
|
|
|
|
display: flex;
|
|
|
|
margin-bottom: 10px;
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
padding: 20px 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 480px) {
|
|
|
|
|
|
|
|
.book-stats {
|
|
|
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
.library-container {
|
|
|
|
|
|
|
|
padding: 10px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
.stat-number {
|
|
|
|
|
|
|
|
font-size: 24px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
</style>
|