add
46
db/tb_book.sql
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
Navicat Premium Data Transfer
|
||||
|
||||
Source Server : localhost
|
||||
Source Server Type : MySQL
|
||||
Source Server Version : 50736 (5.7.36)
|
||||
Source Host : localhost:3306
|
||||
Source Schema : block-chaincopyright
|
||||
|
||||
Target Server Type : MySQL
|
||||
Target Server Version : 50736 (5.7.36)
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 22/05/2025 20:27:46
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for tb_book
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `tb_book`;
|
||||
CREATE TABLE `tb_book` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`image` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '封面',
|
||||
`isbn` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ISBN编号',
|
||||
`title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '图书标题',
|
||||
`author` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '作者',
|
||||
`publisher` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '出版社',
|
||||
`publish_date` date NULL DEFAULT NULL COMMENT '出版日期',
|
||||
`copyright_owner` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '版权持有人',
|
||||
`copyright_start_year` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '版权起始年份',
|
||||
`copyright_end_year` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '版权到期年份',
|
||||
`edition` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '版次',
|
||||
`language` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '中文' COMMENT '语言',
|
||||
`price` decimal(10, 2) NULL DEFAULT NULL COMMENT '图书定价',
|
||||
`hex` varchar(600) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '上链哈希值',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`file` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '电子数据文件地址',
|
||||
`user_id` bigint(20) NULL DEFAULT NULL,
|
||||
`status` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '已通过',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1925518111079583746 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '基于区块链的图书版权结构表' ROW_FORMAT = DYNAMIC;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
683
ui/src/pages/admin/book.vue
Normal file
@ -0,0 +1,683 @@
|
||||
<template>
|
||||
<div class="house-management-container">
|
||||
<!-- 搜索区域 -->
|
||||
<div class="search-area">
|
||||
<el-form :inline="true" :model="state.query" class="search-form">
|
||||
<el-form-item label="版权名称:" class="search-item">
|
||||
<el-input
|
||||
v-model="state.query.title"
|
||||
placeholder="请输入版权名称"
|
||||
clearable
|
||||
@input="handleSearch"
|
||||
class="search-input"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态:" class="search-item">
|
||||
<el-select clearable
|
||||
v-model="state.query.status"
|
||||
placeholder="请选择状态"
|
||||
@change="handleSearch"
|
||||
style="width: 120px">
|
||||
<el-option
|
||||
v-for="item in state.statusOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item class="action-buttons">
|
||||
<el-button type="primary" @click="init" class="query-button">
|
||||
<el-icon>
|
||||
<Search />
|
||||
</el-icon>
|
||||
<span>查询</span>
|
||||
</el-button>
|
||||
<el-button type="primary" @click="openAddDialog" class="add-button">
|
||||
<el-icon>
|
||||
<Plus />
|
||||
</el-icon>
|
||||
<span>添加</span>
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<!-- 表格区域 -->
|
||||
<div class="table-area">
|
||||
<el-table
|
||||
v-loading="state.loading"
|
||||
:data="state.list"
|
||||
stripe
|
||||
border
|
||||
class="data-table"
|
||||
empty-text="暂无数据"
|
||||
>
|
||||
<el-table-column label="封面图" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-image :src="row.image" fit="cover" class="book-image" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="isbn" label="ISBN" align="center" />
|
||||
<el-table-column prop="title" label="书名" align="center" />
|
||||
<el-table-column prop="author" label="作者" align="center" />
|
||||
<el-table-column prop="publisher" label="出版社" align="center" />
|
||||
<el-table-column prop="publishDate" label="出版日期" align="center" />
|
||||
<el-table-column prop="copyrightOwner" label="版权持有人" align="center" />
|
||||
<el-table-column prop="copyrightStartYear" label="版权开始" align="center" />
|
||||
<el-table-column prop="copyrightEndYear" label="版权到期" align="center" />
|
||||
<el-table-column prop="edition" label="版次" align="center" />
|
||||
<el-table-column prop="price" label="定价(元)" align="center" />
|
||||
<el-table-column label="状态" align="center" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="getStatusTagType(row.status)">{{ row.status }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" fixed="right" width="220" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button size="small" type="info" plain @click="showDetail(row)">详情</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
plain
|
||||
@click="edit(row)"
|
||||
v-if="row.status === '未审核'"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
type="warning"
|
||||
plain
|
||||
@click="openAuditDialog(row)"
|
||||
v-if="row.status === '未审核'"
|
||||
>
|
||||
审核
|
||||
</el-button>
|
||||
<el-popconfirm
|
||||
title="确认删除该版权信息?"
|
||||
@confirm="del(row.id)"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button size="small" type="danger" plain>删除</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<div class="pagination-container" v-if="state.query.total > 0">
|
||||
<el-pagination
|
||||
:current-page="state.query.page"
|
||||
:page-size="state.query.limit"
|
||||
:total="state.query.total"
|
||||
:page-sizes="[5,10,20,50]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
background
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handlePageChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 在template中添加详情对话框 -->
|
||||
<el-dialog
|
||||
v-model="state.detailVisible"
|
||||
title="版权详情"
|
||||
width="50%"
|
||||
class="detail-dialog"
|
||||
>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="ISBN">{{ state.detailData.isbn }}</el-descriptions-item>
|
||||
<el-descriptions-item label="书名">{{ state.detailData.title }}</el-descriptions-item>
|
||||
<el-descriptions-item label="作者">{{ state.detailData.author }}</el-descriptions-item>
|
||||
<el-descriptions-item label="出版社">{{ state.detailData.publisher }}</el-descriptions-item>
|
||||
<el-descriptions-item label="出版日期">{{ state.detailData.publishDate }}</el-descriptions-item>
|
||||
<el-descriptions-item label="版权持有人">{{ state.detailData.copyrightOwner }}</el-descriptions-item>
|
||||
<el-descriptions-item label="版权开始">{{ state.detailData.copyrightStartYear }}</el-descriptions-item>
|
||||
<el-descriptions-item label="版权到期">{{ state.detailData.copyrightEndYear }}</el-descriptions-item>
|
||||
<el-descriptions-item label="版次">{{ state.detailData.edition }}</el-descriptions-item>
|
||||
<el-descriptions-item label="定价(元)">{{ state.detailData.price }}</el-descriptions-item>
|
||||
<el-descriptions-item label="状态">
|
||||
<el-tag :type="getStatusTagType(state.detailData.status)">
|
||||
{{ state.detailData.status }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<div class="detail-image-container">
|
||||
<el-image
|
||||
:src="state.detailData.image"
|
||||
fit="contain"
|
||||
class="detail-image"
|
||||
:preview-src-list="[state.detailData.image]"
|
||||
/>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="state.detailVisible = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<!-- 在template中添加审核对话框 -->
|
||||
<el-dialog
|
||||
v-model="state.auditVisible"
|
||||
title="版权审核"
|
||||
width="40%"
|
||||
>
|
||||
<el-form :model="state.auditForm" label-width="100px">
|
||||
<el-form-item label="审核状态">
|
||||
<el-radio-group v-model="state.auditForm.status">
|
||||
<el-radio label="已同意">同意</el-radio>
|
||||
<el-radio label="已拒绝">拒绝</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="审核意见">
|
||||
<el-input
|
||||
v-model="state.auditForm.remark"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
placeholder="请输入审核意见"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="state.auditVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitAudit">提交审核</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<!-- 在template中添加表单对话框 -->
|
||||
<el-dialog
|
||||
v-model="state.dialogVisible"
|
||||
:title="state.formData.id ? '编辑版权' : '新增版权'"
|
||||
width="50%"
|
||||
class="form-dialog"
|
||||
>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="state.formData"
|
||||
:rules="state.rules"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-form-item label="ISBN" prop="isbn">
|
||||
<el-input v-model="state.formData.isbn" placeholder="请输入ISBN" />
|
||||
</el-form-item>
|
||||
<el-form-item label="书名" prop="title">
|
||||
<el-input v-model="state.formData.title" placeholder="请输入书名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="作者" prop="author">
|
||||
<el-input v-model="state.formData.author" placeholder="请输入作者" />
|
||||
</el-form-item>
|
||||
<el-form-item label="出版社" prop="publisher">
|
||||
<el-input v-model="state.formData.publisher" placeholder="请输入出版社" />
|
||||
</el-form-item>
|
||||
<el-form-item label="出版日期" prop="publishDate">
|
||||
<el-date-picker
|
||||
v-model="state.formData.publishDate"
|
||||
type="date"
|
||||
placeholder="选择出版日期"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="版权持有人" prop="copyrightOwner">
|
||||
<el-input
|
||||
v-model="state.formData.copyrightOwner"
|
||||
placeholder="请输入版权持有人"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="开始年份" prop="copyrightStartYear">
|
||||
<el-input
|
||||
v-model="state.formData.copyrightStartYear"
|
||||
placeholder="请输入版权开始年份"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="到期年份" prop="copyrightEndYear">
|
||||
<el-input
|
||||
v-model="state.formData.copyrightEndYear"
|
||||
placeholder="请输入版权到期年份"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="版次" prop="edition">
|
||||
<el-input v-model="state.formData.edition" placeholder="请输入版次" />
|
||||
</el-form-item>
|
||||
<el-form-item label="定价(元)" prop="price">
|
||||
<el-input-number
|
||||
v-model="state.formData.price"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
controls-position="right"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="封面图" prop="image">
|
||||
|
||||
<el-upload
|
||||
:action="state.path"
|
||||
list-type="picture-card"
|
||||
:show-file-list="false"
|
||||
:on-success="handleImageSuccess"
|
||||
:before-upload="beforeImageUpload"
|
||||
>
|
||||
<img
|
||||
v-if="state.formData.image"
|
||||
:src="state.formData.image"
|
||||
class="uploaded-image"
|
||||
alt="封面图片"
|
||||
/>
|
||||
<el-icon v-else class="uploader-icon">
|
||||
<Plus />
|
||||
</el-icon>
|
||||
</el-upload>
|
||||
<div class="upload-tip">建议尺寸16:9,大小不超过5MB</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="电子文件" prop="file" class="file-upload-item">
|
||||
<el-upload
|
||||
drag
|
||||
:action="state.path"
|
||||
:limit="1"
|
||||
:on-success="handleFileSuccess"
|
||||
:on-error="handleUploadError"
|
||||
:before-upload="beforeFileUpload"
|
||||
:file-list="fileList"
|
||||
>
|
||||
<el-icon class="el-icon--upload"><UploadFilled /></el-icon>
|
||||
<div class="el-upload__text">
|
||||
将图书电子文件拖到此处,或<em>点击上传</em>
|
||||
</div>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">
|
||||
支持PDF、EPUB等格式,大小不超过50MB
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="closeDialog">取消</el-button>
|
||||
<el-button type="primary" @click="saveTransaction">保存</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import type { FormInstance, UploadProps } from 'element-plus'
|
||||
import { Search, Plus, Picture, UploadFilled } from '@element-plus/icons-vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { getDecoration, getFace, getHouseType } from '~/utils/utils'
|
||||
|
||||
// 文件列表
|
||||
const fileList = ref([])
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
const state = reactive({
|
||||
path:import.meta.env.VITE_API_FRONT_BASE_URL+"/api/upload",
|
||||
route: 'sys/book',
|
||||
loading: false,
|
||||
list: [] as any[],
|
||||
dialogVisible: false,
|
||||
// 搜索 / 分页
|
||||
query: {
|
||||
total: 0,
|
||||
page: 1,
|
||||
limit: 5,
|
||||
title: '',
|
||||
status: null as number | null
|
||||
},
|
||||
// 下拉状态选项
|
||||
statusOptions: [
|
||||
{ label: '全部', value: null },
|
||||
{ label: '未审核', value: '未审核' },
|
||||
{ label: '已同意', value: '已同意' },
|
||||
{ label: '已拒绝', value: '已拒绝' }
|
||||
],
|
||||
// 表单数据
|
||||
formData: {} as Record<string, any>,
|
||||
userList: [],
|
||||
detailVisible: false,
|
||||
detailData: {} as any,
|
||||
auditVisible: false,
|
||||
auditForm: {
|
||||
id: null as number | null,
|
||||
status: '已同意',
|
||||
remark: ''
|
||||
},
|
||||
// 表单验证规则
|
||||
rules: {
|
||||
isbn: [
|
||||
{ required: true, message: '请输入ISBN', trigger: 'blur' },
|
||||
{ min: 10, max: 13, message: 'ISBN长度在10到13个字符', trigger: 'blur' }
|
||||
],
|
||||
title: [
|
||||
{ required: true, message: '请输入书名', trigger: 'blur' },
|
||||
{ max: 100, message: '书名不能超过100个字符', trigger: 'blur' }
|
||||
],
|
||||
author: [
|
||||
{ required: true, message: '请输入作者', trigger: 'blur' },
|
||||
{ max: 50, message: '作者名不能超过50个字符', trigger: 'blur' }
|
||||
],
|
||||
publisher: [
|
||||
{ required: true, message: '请输入出版社', trigger: 'blur' },
|
||||
{ max: 100, message: '出版社名称不能超过100个字符', trigger: 'blur' }
|
||||
],
|
||||
publishDate: [
|
||||
{ required: true, message: '请选择出版日期', trigger: 'change' }
|
||||
],
|
||||
copyrightOwner: [
|
||||
{ required: true, message: '请输入版权持有人', trigger: 'blur' },
|
||||
{ max: 100, message: '版权持有人不能超过100个字符', trigger: 'blur' }
|
||||
],
|
||||
copyrightStartYear: [
|
||||
{ required: true, message: '请输入版权开始年份', trigger: 'blur' },
|
||||
{ pattern: /^\d{4}$/, message: '请输入4位年份', trigger: 'blur' }
|
||||
],
|
||||
copyrightEndYear: [
|
||||
{ required: true, message: '请输入版权到期年份', trigger: 'blur' },
|
||||
{ pattern: /^\d{4}$/, message: '请输入4位年份', trigger: 'blur' }
|
||||
],
|
||||
edition: [
|
||||
{ required: true, message: '请输入版次', trigger: 'blur' },
|
||||
{ max: 20, message: '版次不能超过20个字符', trigger: 'blur' }
|
||||
],
|
||||
price: [
|
||||
{ required: true, message: '请输入定价', trigger: 'blur' },
|
||||
{ type: 'number', min: 0, message: '定价必须大于0', trigger: 'blur' }
|
||||
],
|
||||
image: [
|
||||
{ required: true, message: '请上传封面图', trigger: 'change' }
|
||||
]
|
||||
}
|
||||
})
|
||||
// 文件上传前校验
|
||||
const beforeFileUpload: UploadProps['beforeUpload'] = (file) => {
|
||||
const allowedTypes = ['application/pdf', 'application/epub+zip']
|
||||
const isAllowedType = allowedTypes.includes(file.type)
|
||||
const isLt50M = file.size / 1024 / 1024 < 50
|
||||
|
||||
if (!isAllowedType) {
|
||||
ElMessage.error('只能上传PDF或EPUB文件!')
|
||||
return false
|
||||
}
|
||||
if (!isLt50M) {
|
||||
ElMessage.error('文件大小不能超过50MB!')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
// 上传错误处理
|
||||
const handleUploadError: UploadProps['onError'] = () => {
|
||||
ElMessage.error('文件上传失败,请重试')
|
||||
}
|
||||
// 图片上传前校验
|
||||
const beforeImageUpload: UploadProps['beforeUpload'] = (file) => {
|
||||
const isImage = file.type.startsWith('image/')
|
||||
const isLt5M = file.size / 1024 / 1024 < 5
|
||||
|
||||
if (!isImage) {
|
||||
ElMessage.error('只能上传图片文件!')
|
||||
return false
|
||||
}
|
||||
if (!isLt5M) {
|
||||
ElMessage.error('图片大小不能超过5MB!')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
// 图片上传成功处理
|
||||
const handleImageSuccess: UploadProps['onSuccess'] = (response) => {
|
||||
state.formData.image = response.data.path
|
||||
}
|
||||
|
||||
// 文件上传成功处理
|
||||
const handleFileSuccess: UploadProps['onSuccess'] = (response) => {
|
||||
state.formData.file = response.data.path
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 添加新方法
|
||||
const showDetail = (row: any) => {
|
||||
state.detailData = { ...row }
|
||||
state.detailVisible = true
|
||||
}
|
||||
|
||||
const openAuditDialog = (row: any) => {
|
||||
state.auditForm = {
|
||||
id: row.id,
|
||||
status: '已同意',
|
||||
remark: ''
|
||||
}
|
||||
state.auditVisible = true
|
||||
}
|
||||
|
||||
const submitAudit = async () => {
|
||||
try {
|
||||
await adminRequest.put(`${state.route}/audit`, state.auditForm)
|
||||
ElMessage.success('审核提交成功')
|
||||
state.auditVisible = false
|
||||
init()
|
||||
} catch {
|
||||
ElMessage.error('审核提交失败')
|
||||
}
|
||||
}
|
||||
// 拉取列表
|
||||
const init = () => {
|
||||
state.loading = true
|
||||
adminRequest
|
||||
.get(`${state.route}/page`, { params: state.query })
|
||||
.then((res: any) => {
|
||||
state.list = res.data.list
|
||||
state.query.total = res.data.total
|
||||
})
|
||||
.finally(() => {
|
||||
state.loading = false
|
||||
})
|
||||
|
||||
adminRequest.get(`sys/user-front/page`, {
|
||||
params: { limit: 999 }
|
||||
}).then((res: any) => {
|
||||
state.userList = res.data.list
|
||||
})
|
||||
}
|
||||
|
||||
// 搜索重置页码
|
||||
const handleSearch = () => {
|
||||
state.query.page = 1
|
||||
init()
|
||||
}
|
||||
|
||||
// 打开新增
|
||||
const openAddDialog = () => {
|
||||
state.formData = {}
|
||||
state.dialogVisible = true
|
||||
nextTick(() => formRef.value?.clearValidate())
|
||||
}
|
||||
|
||||
// 关闭对话框
|
||||
const closeDialog = () => {
|
||||
state.dialogVisible = false
|
||||
state.formData = {}
|
||||
}
|
||||
|
||||
// 编辑
|
||||
const edit = (row: any) => {
|
||||
state.formData = { ...row }
|
||||
state.dialogVisible = true
|
||||
}
|
||||
|
||||
// 保存(新增/更新)
|
||||
const saveTransaction = () => {
|
||||
formRef.value?.validate(async valid => {
|
||||
if (!valid) return
|
||||
try {
|
||||
const req = state.formData.id
|
||||
? adminRequest.put(`${state.route}`, state.formData)
|
||||
: adminRequest.post(`${state.route}`, state.formData)
|
||||
await req
|
||||
ElMessage.success('操作成功')
|
||||
closeDialog()
|
||||
init()
|
||||
} catch {
|
||||
ElMessage.error('操作失败')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 删除
|
||||
const del = async (id: number) => {
|
||||
try {
|
||||
await adminRequest.delete(`${state.route}/${id}`)
|
||||
ElMessage.success('删除成功')
|
||||
init()
|
||||
} catch {
|
||||
ElMessage.error('删除失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 分页
|
||||
const handlePageChange = (page: number) => {
|
||||
state.query.page = page
|
||||
init()
|
||||
}
|
||||
const handleSizeChange = (size: number) => {
|
||||
state.query.limit = size
|
||||
init()
|
||||
}
|
||||
// 处理图片上传回调
|
||||
const handleImageUrl = (url: string) => {
|
||||
state.formData.image = url
|
||||
}
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
|
||||
// 获取状态标签类型
|
||||
function getStatusTagType(status: string) {
|
||||
switch (status) {
|
||||
case '已同意':
|
||||
return 'success'
|
||||
case '已拒绝':
|
||||
return 'danger'
|
||||
case '未审核':
|
||||
return 'warning'
|
||||
default:
|
||||
return 'info'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.avatar-uploader {
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
width: 150px;
|
||||
height: 200px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.avatar-uploader:hover {
|
||||
border-color: #409eff;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.avatar-uploader-icon {
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
}
|
||||
|
||||
|
||||
.house-management-container {
|
||||
padding: 20px;
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.search-area {
|
||||
margin-bottom: 20px;
|
||||
|
||||
.search-form {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.search-item {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
width: 220px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table-area {
|
||||
.data-table {
|
||||
width: 100%;
|
||||
|
||||
.house-image {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 4px;
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pagination-container {
|
||||
margin-top: 16px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.form-dialog {
|
||||
:deep(.el-dialog__body) {
|
||||
padding: 20px 30px;
|
||||
}
|
||||
|
||||
.image-uploader {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
text-align: center;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
}
|
||||
|
||||
.detail-dialog {
|
||||
.detail-image-container {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
.detail-image {
|
||||
max-width: 200px;
|
||||
max-height: 300px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<route lang="json">
|
||||
{
|
||||
"meta": {
|
||||
"layout": "admin"
|
||||
}
|
||||
}
|
||||
</route>
|
BIN
upload/095a3e746b1bc652efd4203245387c5.png
Normal file
After Width: | Height: | Size: 92 KiB |
Before Width: | Height: | Size: 758 KiB |
Before Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 25 KiB |
BIN
upload/9ff5111f-317a-40f6-9129-dce55dc0ca46.jpg
Normal file
After Width: | Height: | Size: 193 KiB |
Before Width: | Height: | Size: 134 KiB |
Before Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 220 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 176 KiB |
Before Width: | Height: | Size: 138 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 285 KiB |
Before Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 147 KiB |
Before Width: | Height: | Size: 1.6 MiB |
Before Width: | Height: | Size: 182 KiB |