238 lines
6.3 KiB
Vue
238 lines
6.3 KiB
Vue
<script setup>
|
|
import {NInput, NSpace, NButton, NPagination, NModal, NSelect, NSpin, NPopconfirm, NEmpty, useMessage} from 'naive-ui'
|
|
import {onMounted, ref} from "vue";
|
|
import DeveloperEdit from "./DeveloperEdit.vue";
|
|
import {useRouter} from 'vue-router';
|
|
import {request, errorHandler} from '../../utils/request.js'
|
|
|
|
const message = useMessage()
|
|
const router = useRouter();
|
|
const isLoadingData = ref(false);
|
|
const showDeveloperEditModal = ref(false)
|
|
|
|
const developerListRef = ref(null)
|
|
const filterSectionRef = ref(null);
|
|
const paginationRef = ref(null)
|
|
|
|
const cardContainerRef = ref(null)
|
|
|
|
const filterName = ref(null)
|
|
const page = ref(1)
|
|
const pageSize = ref(18)
|
|
const developerList = ref([])
|
|
const editId = ref(null)
|
|
|
|
/**
|
|
* 计算高度
|
|
*/
|
|
const calculateCardHeight = () => {
|
|
const requirementListHeight = parseInt(developerListRef.value.getBoundingClientRect().height);
|
|
const filterSectionHeight = parseInt(filterSectionRef.value.getBoundingClientRect().height);
|
|
const paginationHeight = parseInt(paginationRef.value.getBoundingClientRect().height);
|
|
cardContainerRef.value.style.maxHeight = `${requirementListHeight - filterSectionHeight - paginationHeight - 55}px`;
|
|
}
|
|
|
|
|
|
const listpage = () => {
|
|
isLoadingData.value = true;
|
|
request.get('/developer/listpage', {
|
|
params: {
|
|
name: filterName.value,
|
|
page: page.value,
|
|
page_size: pageSize.value
|
|
}
|
|
}).then(res => {
|
|
developerList.value = res.data.data_list
|
|
}).catch(error => {
|
|
errorHandler(error, message, router)
|
|
}).finally(() => {
|
|
isLoadingData.value = false;
|
|
})
|
|
}
|
|
|
|
|
|
const del = (id) => {
|
|
isLoadingData.value = true;
|
|
request.delete(`/developer/delete`, {
|
|
params: {
|
|
ids: id
|
|
}
|
|
}).then(res => {
|
|
message.success('删除成功')
|
|
listpage()
|
|
}).catch(error => {
|
|
errorHandler(error, message, router)
|
|
}).finally(() => {
|
|
isLoadingData.value = false;
|
|
})
|
|
}
|
|
|
|
onMounted(() => {
|
|
setTimeout(() => {
|
|
calculateCardHeight();
|
|
listpage()
|
|
}, 500)
|
|
})
|
|
|
|
</script>
|
|
|
|
<template>
|
|
<div class="developer-list" ref="developerListRef">
|
|
<n-spin :show="isLoadingData">
|
|
<div class="filter-section" ref="filterSectionRef">
|
|
<div class="filter-form">
|
|
<n-space>
|
|
<n-space class="filter-item" align="center">
|
|
<label>姓名</label>
|
|
<n-input v-model:value="filterName"
|
|
:clearable="true"
|
|
type="text"
|
|
style="width: 120px"
|
|
placeholder="输入姓名"/>
|
|
</n-space>
|
|
</n-space>
|
|
</div>
|
|
<div class="filter-actions">
|
|
<n-space justify="space-between">
|
|
<n-button type="primary" @click="() => {
|
|
listpage()
|
|
}">搜索
|
|
</n-button>
|
|
<n-button type="info" @click="() => {
|
|
editId = null
|
|
showDeveloperEditModal = true
|
|
}">
|
|
<i class="fas fa-plus"></i>
|
|
</n-button>
|
|
</n-space>
|
|
</div>
|
|
</div>
|
|
<!-- 项目列表 -->
|
|
<div class="card-container" ref="cardContainerRef" v-show="developerList.length > 0">
|
|
<div class="card-item" v-for="developer in developerList">
|
|
<div class="name">{{ developer.name }}</div>
|
|
<div class="profile" :title="developer.profile">{{ developer.profile }}</div>
|
|
<div class="actions">
|
|
<n-space justify="space-between">
|
|
<n-space>{{ developer.post }}</n-space>
|
|
<n-space justify="end" :size="5">
|
|
<i class="fas fa-edit" @click="() => {
|
|
editId = developer.id
|
|
showDeveloperEditModal = true
|
|
}"></i>
|
|
<n-popconfirm
|
|
@positive-click="() => {
|
|
del(developer.id)
|
|
}"
|
|
positive-text="确定"
|
|
negative-text="取消"
|
|
>
|
|
<template #trigger>
|
|
<i class="fas fa-trash"></i>
|
|
</template>
|
|
确定删除吗?删除后数据无法恢复!
|
|
</n-popconfirm>
|
|
</n-space>
|
|
</n-space>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- 分页 -->
|
|
<div class="pagination" ref="paginationRef" v-show="developerList.length > 0">
|
|
<n-pagination v-model:page="page"
|
|
:page-size="pageSize"
|
|
:on-update-page="(currentPage) => {
|
|
page = currentPage
|
|
listpage()
|
|
}"/>
|
|
</div>
|
|
<div class="empty-container" v-show="developerList.length === 0">
|
|
<n-empty description="暂无数据"/>
|
|
</div>
|
|
</n-spin>
|
|
<n-modal v-model:show="showDeveloperEditModal"
|
|
preset="card"
|
|
:style="{width: '600px'}"
|
|
title="需求编辑"
|
|
:bordered="false">
|
|
<DeveloperEdit :developer-id="editId"
|
|
@on-data-edited="() => {
|
|
showDeveloperEditModal = false
|
|
listpage()
|
|
}"/>
|
|
</n-modal>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.developer-list {
|
|
height: 100%;
|
|
}
|
|
|
|
.filter-section {
|
|
display: flex;
|
|
padding: 10px;
|
|
border-bottom: 1px solid var(--border-color);
|
|
margin-bottom: 10px;
|
|
|
|
.filter-actions {
|
|
flex: 1;
|
|
margin-left: 10px;
|
|
}
|
|
}
|
|
|
|
.card-container {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, 1fr);
|
|
column-gap: 10px;
|
|
row-gap: 10px;
|
|
overflow-y: scroll;
|
|
height: 100%;
|
|
|
|
.card-item {
|
|
border: 1px solid var(--border-color);
|
|
padding: 10px;
|
|
border-radius: 2px;
|
|
height: 140px;
|
|
min-width: 0; /** 防止grid子元素扩展 **/
|
|
|
|
.name {
|
|
font-weight: bold;
|
|
}
|
|
|
|
.profile {
|
|
display: -webkit-box;
|
|
-webkit-line-clamp: 3;
|
|
-webkit-box-orient: vertical;
|
|
overflow: hidden;
|
|
line-height: 24px;
|
|
height: 72px;
|
|
word-break: break-all;
|
|
}
|
|
|
|
.actions {
|
|
margin-top: 5px;
|
|
|
|
.fas {
|
|
cursor: pointer;
|
|
}
|
|
|
|
.fa-edit:hover {
|
|
color: var(--primary-color);
|
|
}
|
|
|
|
.fa-trash:hover {
|
|
color: var(--danger-color);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.pagination {
|
|
border-top: 1px solid var(--border-color);
|
|
margin-top: 10px;
|
|
padding: 10px;
|
|
display: flex;
|
|
justify-content: center;
|
|
}
|
|
</style> |