|
|
@@ -0,0 +1,403 @@
|
|
|
+<script setup>
|
|
|
+import {onMounted, reactive, ref} from 'vue'
|
|
|
+import {ElMessage, ElMessageBox} from 'element-plus'
|
|
|
+import {Building2, Calendar, Edit, Plus, Trash2} from 'lucide-vue-next'
|
|
|
+import request from "@/utils/request.js"
|
|
|
+
|
|
|
+// 响应式数据
|
|
|
+const developmentList = ref([])
|
|
|
+const loading = ref(false)
|
|
|
+const dialogVisible = ref(false)
|
|
|
+const editMode = ref(false)
|
|
|
+const currentItem = ref(null)
|
|
|
+
|
|
|
+// 表单数据
|
|
|
+const formData = reactive({
|
|
|
+ year: '',
|
|
|
+ processDescription: ''
|
|
|
+})
|
|
|
+
|
|
|
+// 分页数据
|
|
|
+const pagination = reactive({
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 15, // 增加每页显示数量
|
|
|
+ total: 0
|
|
|
+})
|
|
|
+
|
|
|
+// 获取列表数据
|
|
|
+const getList = async () => {
|
|
|
+ loading.value = true
|
|
|
+ try {
|
|
|
+ const res = await request.get("/aboutDevelopmentHistory/findByPage", {
|
|
|
+ params: {
|
|
|
+ pageNum: pagination.pageNum,
|
|
|
+ pageSize: pagination.pageSize
|
|
|
+ }
|
|
|
+ })
|
|
|
+ if (res.code !== 200) {
|
|
|
+ ElMessage.error(res.msg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ developmentList.value = res.data.records
|
|
|
+ pagination.total = res.data.total
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error('获取数据失败')
|
|
|
+ } finally {
|
|
|
+ loading.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 添加数据
|
|
|
+const add = async (data) => {
|
|
|
+ const res = await request.post("/aboutDevelopmentHistory/save", {
|
|
|
+ year: data.year,
|
|
|
+ processDescription: data.processDescription
|
|
|
+ })
|
|
|
+ if (res.code !== 200) {
|
|
|
+ ElMessage.error(res.msg)
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ ElMessage.success(res.msg)
|
|
|
+ return true
|
|
|
+}
|
|
|
+
|
|
|
+// 更新数据
|
|
|
+const update = async (data) => {
|
|
|
+ const res = await request.post("/aboutDevelopmentHistory/update", {
|
|
|
+ id: currentItem.value.id,
|
|
|
+ year: data.year,
|
|
|
+ processDescription: data.processDescription
|
|
|
+ })
|
|
|
+ if (res.code !== 200) {
|
|
|
+ ElMessage.error(res.msg)
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ ElMessage.success(res.msg)
|
|
|
+ return true
|
|
|
+}
|
|
|
+
|
|
|
+//根据Id查询单个
|
|
|
+const getById = async (id) => {
|
|
|
+ const res = await request.get("/aboutDevelopmentHistory/getById/"+ id)
|
|
|
+ if (res.code !== 200) {
|
|
|
+ ElMessage.error(res.msg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ currentItem.value = res.data
|
|
|
+}
|
|
|
+
|
|
|
+// 删除数据
|
|
|
+const deleteBatch = async (ids) => {
|
|
|
+ const res = await request.post("/aboutDevelopmentHistory/deleteBatch", ids)
|
|
|
+ if (res.code !== 200) {
|
|
|
+ ElMessage.error(res.msg)
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ ElMessage.success(res.msg)
|
|
|
+ return true
|
|
|
+}
|
|
|
+
|
|
|
+// 打开添加对话框
|
|
|
+const openAddDialog = () => {
|
|
|
+ editMode.value = false
|
|
|
+ formData.year = ''
|
|
|
+ formData.processDescription = ''
|
|
|
+ dialogVisible.value = true
|
|
|
+}
|
|
|
+
|
|
|
+// 打开编辑对话框
|
|
|
+const openEditDialog = (item) => {
|
|
|
+ editMode.value = true
|
|
|
+ getById(item.id)
|
|
|
+ formData.year = item.year
|
|
|
+ formData.processDescription = item.processDescription
|
|
|
+ dialogVisible.value = true
|
|
|
+}
|
|
|
+
|
|
|
+// 确认提交
|
|
|
+const handleSubmit = async () => {
|
|
|
+ if (!formData.year || !formData.processDescription) {
|
|
|
+ ElMessage.warning('请填写完整信息')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const success = editMode.value
|
|
|
+ ? await update(formData)
|
|
|
+ : await add(formData)
|
|
|
+
|
|
|
+ if (success) {
|
|
|
+ dialogVisible.value = false
|
|
|
+ getList()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 删除确认
|
|
|
+const handleDelete = async (item) => {
|
|
|
+ try {
|
|
|
+ await ElMessageBox.confirm('确定要删除这条发展历程吗?', '提示', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ })
|
|
|
+
|
|
|
+ const success = await deleteBatch([item.id])
|
|
|
+ if (success) {
|
|
|
+ getList()
|
|
|
+ }
|
|
|
+ } catch {
|
|
|
+ // 用户取消删除
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 添加分页变化处理函数
|
|
|
+const handlePageChange = (page) => {
|
|
|
+ pagination.pageNum = page
|
|
|
+ getList()
|
|
|
+}
|
|
|
+
|
|
|
+const handleSizeChange = (size) => {
|
|
|
+ pagination.pageSize = size
|
|
|
+ pagination.pageNum = 1
|
|
|
+ getList()
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ getList()
|
|
|
+})
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <div class="min-h-screen bg-gradient-to-br from-blue-50 via-indigo-50 to-purple-50 p-6">
|
|
|
+ <!-- 页面头部 -->
|
|
|
+ <div class="max-w-6xl mx-auto mb-8">
|
|
|
+ <div class="text-center mb-8">
|
|
|
+ <div class="inline-flex items-center justify-center w-16 h-16 bg-gradient-to-r from-blue-500 to-purple-600 rounded-full mb-4">
|
|
|
+ <Building2 class="w-8 h-8 text-white" />
|
|
|
+ </div>
|
|
|
+ <h1 class="text-4xl font-bold bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent mb-2">
|
|
|
+ 公司发展历程
|
|
|
+ </h1>
|
|
|
+ <p class="text-gray-600 text-lg">见证我们的成长足迹,共创美好未来</p>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 添加按钮 -->
|
|
|
+ <div class="flex justify-center mb-8">
|
|
|
+ <button
|
|
|
+ @click="openAddDialog"
|
|
|
+ class="inline-flex items-center px-6 py-3 bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-full hover:from-blue-600 hover:to-purple-700 transform hover:scale-105 transition-all duration-200 shadow-lg hover:shadow-xl"
|
|
|
+ >
|
|
|
+ <Plus class="w-5 h-5 mr-2" />
|
|
|
+ 添加发展历程
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 时间线内容 -->
|
|
|
+ <div class="max-w-7xl mx-auto">
|
|
|
+ <!-- 加载状态 -->
|
|
|
+ <div v-if="loading" class="flex justify-center py-12">
|
|
|
+ <div class="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500"></div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 发展历程卡片网格布局 -->
|
|
|
+ <div v-else class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6 mb-8">
|
|
|
+ <div
|
|
|
+ v-for="(item, index) in developmentList"
|
|
|
+ :key="item.id"
|
|
|
+ class="group"
|
|
|
+ >
|
|
|
+ <div class="bg-white rounded-2xl shadow-lg hover:shadow-2xl transform hover:-translate-y-2 transition-all duration-300 overflow-hidden border border-gray-100 h-80 flex flex-col">
|
|
|
+ <!-- 卡片头部 -->
|
|
|
+ <div class="bg-gradient-to-r from-blue-500 to-purple-600 p-4 relative overflow-hidden flex-shrink-0">
|
|
|
+ <div class="flex items-center justify-between relative z-10">
|
|
|
+ <div class="flex items-center text-white">
|
|
|
+ <Calendar class="w-5 h-5 mr-2" />
|
|
|
+ <span class="text-2xl font-bold">{{ item.year }}</span>
|
|
|
+ <span class="ml-2 text-blue-100">年</span>
|
|
|
+ </div>
|
|
|
+ <div class="flex space-x-2 opacity-0 group-hover:opacity-100 transition-opacity duration-200">
|
|
|
+ <button
|
|
|
+ @click="openEditDialog(item)"
|
|
|
+ class="p-2 bg-white/20 hover:bg-white/30 rounded-lg transition-colors duration-200"
|
|
|
+ >
|
|
|
+ <Edit class="w-4 h-4 text-white" />
|
|
|
+ </button>
|
|
|
+ <button
|
|
|
+ @click="handleDelete(item)"
|
|
|
+ class="p-2 bg-white/20 hover:bg-red-500/50 rounded-lg transition-colors duration-200"
|
|
|
+ >
|
|
|
+ <Trash2 class="w-4 h-4 text-white" />
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 装饰性波浪 -->
|
|
|
+ <div class="absolute -bottom-1 left-0 w-full h-4 bg-white rounded-t-full"></div>
|
|
|
+ <!-- 装饰性圆圈 -->
|
|
|
+ <div class="absolute -top-4 -right-4 w-16 h-16 bg-white/10 rounded-full"></div>
|
|
|
+ <div class="absolute -top-2 -right-2 w-8 h-8 bg-white/20 rounded-full"></div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 卡片内容 - 添加固定高度和文本截断 -->
|
|
|
+ <div class="p-6 flex-1 flex flex-col min-h-0">
|
|
|
+ <div class="flex-1 mb-4 overflow-hidden">
|
|
|
+ <p class="text-gray-700 leading-relaxed text-base line-clamp-5">
|
|
|
+ {{ item.processDescription }}
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
+ <div class="text-xs text-gray-400 border-t pt-3 flex-shrink-0">
|
|
|
+ 创建时间: {{ new Date(item.createTime).toLocaleDateString() }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 装饰性底部渐变 -->
|
|
|
+ <div class="h-1 bg-gradient-to-r from-blue-400 to-purple-500 flex-shrink-0"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 添加分页组件 -->
|
|
|
+ <div v-if="!loading && developmentList.length > 0" class="flex justify-center">
|
|
|
+ <el-pagination
|
|
|
+ v-model:current-page="pagination.pageNum"
|
|
|
+ v-model:page-size="pagination.pageSize"
|
|
|
+ :page-sizes="[12, 15, 20, 30]"
|
|
|
+ :total="pagination.total"
|
|
|
+ layout="total, sizes, prev, pager, next, jumper"
|
|
|
+ @size-change="handleSizeChange"
|
|
|
+ @current-change="handlePageChange"
|
|
|
+ class="bg-white rounded-lg shadow-md p-4"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 空状态 -->
|
|
|
+ <div v-if="!loading && developmentList.length === 0" class="text-center py-12">
|
|
|
+ <div class="w-24 h-24 bg-gray-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
|
|
+ <Building2 class="w-12 h-12 text-gray-400" />
|
|
|
+ </div>
|
|
|
+ <p class="text-gray-500 text-lg">暂无发展历程数据</p>
|
|
|
+ <p class="text-gray-400 text-sm mt-2">点击上方按钮添加第一条发展历程</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 添加/编辑对话框 -->
|
|
|
+ <el-dialog
|
|
|
+ v-model="dialogVisible"
|
|
|
+ :title="editMode ? '编辑发展历程' : '添加发展历程'"
|
|
|
+ width="500px"
|
|
|
+ :before-close="() => dialogVisible = false"
|
|
|
+ >
|
|
|
+ <div class="space-y-6">
|
|
|
+ <div>
|
|
|
+ <label class="block text-sm font-medium text-gray-700 mb-2">年份</label>
|
|
|
+ <el-input
|
|
|
+ v-model="formData.year"
|
|
|
+ type="number"
|
|
|
+ placeholder="请输入年份"
|
|
|
+ class="w-full"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <label class="block text-sm font-medium text-gray-700 mb-2">历程描述</label>
|
|
|
+ <el-input
|
|
|
+ v-model="formData.processDescription"
|
|
|
+ type="textarea"
|
|
|
+ :rows="4"
|
|
|
+ placeholder="请输入发展历程描述"
|
|
|
+ class="w-full"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <template #footer>
|
|
|
+ <div class="flex justify-end space-x-3">
|
|
|
+ <el-button @click="dialogVisible = false">取消</el-button>
|
|
|
+ <el-button type="primary" @click="handleSubmit">
|
|
|
+ {{ editMode ? '更新' : '添加' }}
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+/* 自定义滚动条 */
|
|
|
+::-webkit-scrollbar {
|
|
|
+ width: 6px;
|
|
|
+}
|
|
|
+
|
|
|
+::-webkit-scrollbar-track {
|
|
|
+ background: #f1f1f1;
|
|
|
+ border-radius: 3px;
|
|
|
+}
|
|
|
+
|
|
|
+::-webkit-scrollbar-thumb {
|
|
|
+ background: linear-gradient(to bottom, #3b82f6, #8b5cf6);
|
|
|
+ border-radius: 3px;
|
|
|
+}
|
|
|
+
|
|
|
+::-webkit-scrollbar-thumb:hover {
|
|
|
+ background: linear-gradient(to bottom, #2563eb, #7c3aed);
|
|
|
+}
|
|
|
+
|
|
|
+/* 卡片动画 */
|
|
|
+@keyframes slideInLeft {
|
|
|
+ from {
|
|
|
+ opacity: 0;
|
|
|
+ transform: translateX(-50px);
|
|
|
+ }
|
|
|
+ to {
|
|
|
+ opacity: 1;
|
|
|
+ transform: translateX(0);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+@keyframes slideInRight {
|
|
|
+ from {
|
|
|
+ opacity: 0;
|
|
|
+ transform: translateX(50px);
|
|
|
+ }
|
|
|
+ to {
|
|
|
+ opacity: 1;
|
|
|
+ transform: translateX(0);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+@keyframes fadeInUp {
|
|
|
+ from {
|
|
|
+ opacity: 0;
|
|
|
+ transform: translateY(30px);
|
|
|
+ }
|
|
|
+ to {
|
|
|
+ opacity: 1;
|
|
|
+ transform: translateY(0);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.group {
|
|
|
+ animation: fadeInUp 0.6s ease-out;
|
|
|
+ animation-fill-mode: both;
|
|
|
+}
|
|
|
+
|
|
|
+.group:nth-child(1) { animation-delay: 0.1s; }
|
|
|
+.group:nth-child(2) { animation-delay: 0.2s; }
|
|
|
+.group:nth-child(3) { animation-delay: 0.3s; }
|
|
|
+.group:nth-child(4) { animation-delay: 0.4s; }
|
|
|
+.group:nth-child(5) { animation-delay: 0.5s; }
|
|
|
+.group:nth-child(6) { animation-delay: 0.6s; }
|
|
|
+
|
|
|
+/* 分页组件样式优化 */
|
|
|
+:deep(.el-pagination) {
|
|
|
+ --el-pagination-button-color: #6366f1;
|
|
|
+ --el-pagination-hover-color: #4f46e5;
|
|
|
+}
|
|
|
+
|
|
|
+/* 添加文本截断样式 */
|
|
|
+.line-clamp-5 {
|
|
|
+ display: -webkit-box;
|
|
|
+ -webkit-line-clamp: 5;
|
|
|
+ -webkit-box-orient: vertical;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+}
|
|
|
+</style>
|