shop-front-end/src/views/user/qy/index.vue

278 lines
6.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import { ref, watch } from "vue";
import tree from "./tree.vue";
import { useHook } from "./hook";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import BalanceEditModal from "./BalanceEditModal.vue";
import Search from "@iconify-icons/ep/search";
import Refresh from "@iconify-icons/ep/refresh";
import View from "@iconify-icons/ep/view";
defineOptions({
name: "QyUser"
});
const formRef = ref();
const {
searchFormParams,
onSearch,
pageLoading,
dataList,
pagination,
getList,
resetForm,
handleViewDetail,
handleModifyBalance,
balanceVisible,
selectedUser,
roleOptions,
} = useHook();
const handleTabChange = (roleId) => {
searchFormParams.sysRoleId = roleId;
onSearch();
};
watch(
() => searchFormParams.mainDepartment,
() => {
onSearch();
}
);
</script>
<template>
<div class="main">
<tree class="w-[17%] float-left" v-model="searchFormParams.mainDepartment" />
<div class="float-right w-[82%]">
<BalanceEditModal v-model:visible="balanceVisible" :row="selectedUser" @refresh="getList" />
<div class="search-form-container">
<el-form ref="formRef" :inline="true" :model="searchFormParams"
class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px]">
<el-form-item label="姓名:" prop="name">
<el-input @keyup.enter.native.prevent="onSearch" v-model="searchFormParams.name" placeholder="请输入" clearable
class="!w-[160px]" />
</el-form-item>
<el-form-item>
<el-button type="primary" :icon="useRenderIcon(Search)" :loading="pageLoading" @click="onSearch">
搜索
</el-button>
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)">
重置
</el-button>
</el-form-item>
</el-form>
<div class="custom-tabs">
<button class="tab-btn" :class="{ 'active': searchFormParams.sysRoleId === undefined }"
@click="handleTabChange(undefined)">
全部
</button>
<button v-for="role in roleOptions" :key="role.roleId" class="tab-btn"
:class="{ 'active': searchFormParams.sysRoleId === role.roleId }" @click="handleTabChange(role.roleId)">
{{ role.roleName }}
</button>
</div>
</div>
<div class="grid-container">
<el-row :gutter="12">
<el-col v-for="(item, index) in dataList" :key="index" :xs="24" :sm="12" :md="8" :lg="6">
<el-card class="user-card" :body-style="{ padding: '8px 20px' }">
<div class="card-wrapper">
<div class="card-content">
<el-avatar :size="80" :src="item.avatar" fit="cover" shape="square" class="avatar">
<template v-if="!item.avatar">
<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="48" fill="#f5f5f5" stroke="#e0e0e0" stroke-width="1" />
<circle cx="50" cy="40" r="12" fill="#9e9e9e" />
<rect x="40" y="52" width="20" height="30" rx="2" fill="#9e9e9e" />
</svg>
</template>
</el-avatar>
<div class="user-info">
<div class="name">姓名{{ item.name }}</div>
<div class="tel">电话{{ item.mobile }}</div>
<div class="balance">余额{{ item.balance }}</div>
</div>
</div>
<div class="card-gap"></div>
<div class="card-footer">
<el-divider class="divider" />
<el-button class="detail-btn" :icon="useRenderIcon(View)" @click="handleViewDetail(item)" />
</div>
</div>
</el-card>
</el-col>
</el-row>
<div class="pagination-wrapper">
<el-pagination background layout="prev, pager, next" :page-size="pagination.pageSize"
:total="pagination.total" v-model:current-page="pagination.currentPage" @current-change="getList"
@size-change="getList" />
</div>
</div>
</div>
</div>
</template>
<style scoped lang="scss">
:deep(.el-dropdown-menu__item i) {
margin: 0;
}
.search-form-container {
.search-form {
:deep(.el-form-item) {
margin-bottom: 12px;
}
}
.custom-tabs {
padding: 0 20px;
background: var(--el-bg-color);
border-radius: 4px;
display: flex;
gap: 12px;
.tab-btn {
padding: 4px 10px;
border: none;
background: transparent;
cursor: pointer;
color: var(--el-text-color-regular);
position: relative;
border-radius: 4px 4px 0 0;
font-size: 14px;
transition: color 0.2s ease;
&.active {
color: var(--el-color-primary);
background-color: #f0f2f5;
border-bottom: none;
z-index: 1;
&::before,
&::after {
content: '';
position: absolute;
bottom: -6px;
width: 18px;
height: 18px;
background: transparent;
}
&::before {
left: -18px;
border-bottom-right-radius: 18px;
box-shadow: 9px 0 0 0 #f0f2f5;
}
&::after {
right: -18px;
border-bottom-left-radius: 18px;
box-shadow: -9px 0 0 0 #f0f2f5;
}
}
&:hover {
color: var(--el-color-primary);
text-shadow: 0 0 1px rgba(64, 158, 255, 0.3);
}
}
}
}
.user-card {
margin-bottom: 12px;
min-height: 210px;
display: flex;
flex-direction: column;
justify-content: space-between;
.card-content {
flex: 1;
display: flex;
flex-direction: row;
margin: 15px 0px;
gap: 15px;
.avatar {
align-self: flex-start;
}
.user-info {
text-align: left;
flex: 1;
.name,
.tel,
.balance {
font-size: 14px;
color: #606266;
margin-bottom: 6px;
line-height: 1.5;
}
.name {
font-weight: 500;
color: #303133;
}
.balance {
font-family: monospace;
color: #67c23a;
}
}
}
.card-footer {
margin-top: auto;
.divider {
margin: 2px 0px;
}
.detail-btn {
width: 100%;
border: 0;
padding: 12px 0;
}
}
.card-gap {
flex-grow: 1;
min-height: 40px;
margin-top: auto;
}
}
.grid-container {
margin: 12px 0;
padding-bottom: 0px;
position: relative;
.el-row {
margin-bottom: -20px;
}
}
.pagination-wrapper {
position: relative;
background: var(--el-bg-color);
padding: 8px 12px;
margin-top: 20px;
text-align: center;
:deep(.el-pagination) {
margin: 0;
padding: 0;
}
}
.card-wrapper {
display: flex;
flex-direction: column;
}
</style>