Files
medical-mall/pages/mall/admin/user/label/index.uvue

417 lines
8.9 KiB
Plaintext
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.
<template>
<view class="user-label-page">
<view class="content-card">
<!-- 操作按钮行 -->
<view class="action-bar">
<button class="btn primary small" @click="onAddLabel">添加标签</button>
</view>
<!-- 标签列表表格 -->
<view class="table-container">
<!-- 表头 -->
<view class="table-header">
<view class="col col-id"><text>ID</text></view>
<view class="col col-name"><text>标签名称</text></view>
<view class="col col-ops"><text>操作</text></view>
</view>
<!-- 表格内容 -->
<view class="table-body">
<view v-for="label in labelList" :key="label.id" class="table-row">
<view class="col col-id"><text>{{ label.id }}</text></view>
<view class="col col-name"><text>{{ label.name }}</text></view>
<view class="col col-ops">
<text class="op-link" @click="onEditLabel(label)">修改</text>
<view class="op-divider">|</view>
<text class="op-link" @click="onDeleteLabel(label)">删除</text>
</view>
</view>
</view>
</view>
<!-- 分页 -->
<CommonPagination
v-if="labelList.length > 0"
:total="labelList.length"
:loading="false"
:currentPage="currentPage"
:pageSize="pageSize"
:pageSizeOptionLabels="pageSizeOptionLabels"
:pageSizeIndex="pageSizeIndex"
:visiblePages="visiblePages"
:totalPage="totalPage"
:jumpPageInput="jumpPageInput"
@page-size-change="handlePageSizeChange"
@page-change="handlePageChange"
@update:jumpPageInput="(val : string) => { jumpPageInput = val }"
@jump-page="handleJumpPage"
/>
</view>
<!-- 添加/修改标签弹窗 -->
<view class="modal-mask" v-if="showModal" @click="closeModal">
<view class="modal-content" @click.stop>
<view class="modal-header">
<text class="modal-title">{{ modalTitle }}</text>
<text class="modal-close" @click="closeModal">×</text>
</view>
<view class="modal-body">
<view class="form-item">
<view class="label-box">
<text class="required">*</text>
<text class="label">标签名称:</text>
</view>
<input
class="form-input"
v-model="formData.name"
placeholder="请输入标签名称"
autofocus
/>
</view>
</view>
<view class="modal-footer">
<button class="btn ghost" @click="closeModal">取消</button>
<button class="btn primary" @click="submitForm">确定</button>
</view>
</view>
</view>
</view>
</template>
<script setup lang="uts">
import { ref, reactive, computed } from 'vue'
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
// 标签数据
const labelList = ref([
{ id: 1, name: '新客户' },
{ id: 2, name: '老客户' },
{ id: 3, name: '活跃客户' },
{ id: 4, name: '潜在客户' }
])
// 弹窗状态
const showModal = ref(false)
const isEdit = ref(false)
const modalTitle = computed(() => isEdit.value ? '修改标签' : '添加标签')
// 表单数据
const formData = reactive({
id: 0,
name: ''
})
// 添加标签
function onAddLabel() {
isEdit.value = false
formData.id = 0
formData.name = ''
showModal.value = true
}
// 修改标签
function onEditLabel(label: any) {
isEdit.value = true
formData.id = label.id
formData.name = label.name
showModal.value = true
}
// 删除标签
function onDeleteLabel(label: any) {
uni.showModal({
title: '提示',
content: '确定要删除该标签吗?',
success: (res) => {
if (res.confirm) {
labelList.value = labelList.value.filter(item => item.id !== label.id)
uni.showToast({ title: '删除成功', icon: 'success' })
}
}
})
}
// 关闭弹窗
function closeModal() {
showModal.value = false
}
// 提交表单
function submitForm() {
if (!formData.name) {
uni.showToast({ title: '请输入标签名称', icon: 'none' })
return
}
if (isEdit.value) {
const index = labelList.value.findIndex(item => item.id === formData.id)
if (index > -1) {
labelList.value[index].name = formData.name
}
uni.showToast({ title: '修改成功', icon: 'success' })
} else {
const newId = labelList.value.length > 0 ? Math.max(...labelList.value.map(g => g.id)) + 1 : 1
labelList.value.push({
id: newId,
name: formData.name
})
uni.showToast({ title: '添加成功', icon: 'success' })
}
closeModal()
}
// 分页适配状态
const currentPage = ref(1)
const pageSize = ref(15)
let jumpPageInput = ''
const pageSizeOptions = [10, 15, 20, 30, 50]
const pageSizeOptionLabels = computed(() => pageSizeOptions.map((n: number) => `${n}条/页`))
const pageSizeIndex = computed(() => {
const idx = pageSizeOptions.indexOf(pageSize.value)
return idx >= 0 ? idx : 0
})
const totalPage = computed(() => Math.max(1, Math.ceil(labelList.value.length / pageSize.value)))
const visiblePages = computed(() => {
const t = totalPage.value
const cur = currentPage.value
if (t <= 7) return Array.from({ length: t }, (_: any, i: number) => i + 1)
if (cur <= 4) return [1, 2, 3, 4, 5, -1, t]
if (cur >= t - 3) return [1, -1, t - 4, t - 3, t - 2, t - 1, t]
return [1, -1, cur - 1, cur, cur + 1, -1, t]
})
const handlePageChange = (p: number) => { currentPage.value = p }
const handlePageSizeChange = (e: any) => {
const idx = Number(e.detail.value)
pageSize.value = pageSizeOptions[idx] ?? pageSizeOptions[0]
currentPage.value = 1
}
const handleJumpPage = () => {
const p = parseInt(jumpPageInput)
if (!isNaN(p) && p >= 1 && p <= totalPage.value) currentPage.value = p
}
</script>
<style scoped lang="scss">
.user-label-page {
/* 使用 Layout 的背景和内边距 */
min-height: 100vh;
}
.content-card {
background: #fff;
border-radius: 4px;
padding: var(--admin-card-padding);
}
.action-bar {
margin-bottom: 20px;
display: flex;
flex-direction: row;
}
/* 按钮样式 */
.btn {
height: 32px;
line-height: 32px;
padding: 0 15px;
font-size: 14px;
border-radius: 2px;
border: 1px solid #d9d9d9;
background: #fff;
color: #666;
cursor: pointer;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
width: auto;
margin: 0;
}
.btn.primary {
background-color: #1890ff;
border-color: #1890ff;
color: #fff;
}
.btn.ghost {
background-color: #fff;
border-color: #d9d9d9;
color: #666;
}
.btn.small {
height: 32px;
padding: 0 12px;
}
/* 表格样式 */
.table-container {
border: 1px solid #f0f0f0;
border-radius: 2px;
overflow: hidden;
}
.table-header {
display: flex;
flex-direction: row;
background-color: #f8faff;
border-bottom: 1px solid #f0f0f0;
}
.table-header .col {
padding: 12px 16px;
font-weight: 500;
color: #333;
font-size: 14px;
}
.table-row {
display: flex;
flex-direction: row;
border-bottom: 1px solid #f0f0f0;
}
.table-row:last-child {
border-bottom: none;
}
.table-row .col {
padding: 12px 16px;
color: #666;
font-size: 14px;
display: flex;
flex-direction: row;
align-items: center;
}
.col-id {
width: 100px;
}
.col-name {
flex: 1;
}
.col-ops {
width: 150px;
display: flex;
flex-direction: row;
justify-content: flex-end;
}
.op-link {
color: #1890ff;
cursor: pointer;
font-size: 14px;
}
.op-link:hover {
text-decoration: underline;
}
.op-divider {
margin: 0 8px;
color: #1890ff;
font-size: 12px;
opacity: 0.5;
}
/* 分页区域已迁至 CommonPagination 组件 */
/* 弹窗样式 */
.modal-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.45);
display: flex;
align-items: center;
justify-content: center;
z-index: 2000;
}
.modal-content {
width: 520px;
background: #fff;
border-radius: 4px;
overflow: hidden;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.modal-header {
padding: 16px 24px;
border-bottom: 1px solid #f0f0f0;
display: flex;
justify-content: space-between;
align-items: center;
}
.modal-title {
font-size: 16px;
font-weight: 500;
color: #333;
}
.modal-close {
font-size: 20px;
color: #999;
cursor: pointer;
&:hover {
color: #666;
}
}
.modal-body {
padding: 40px 24px;
}
.form-item {
display: flex;
align-items: center;
}
.label-box {
width: 100px;
display: flex;
justify-content: flex-end;
align-items: center;
}
.required {
color: #ff4d4f;
margin-right: 4px;
}
.label {
color: #333;
font-size: 14px;
}
.form-input {
flex: 1;
height: 32px;
padding: 4px 11px;
border: 1px solid #d9d9d9;
border-radius: 2px;
font-size: 14px;
&:focus {
border-color: #40a9ff;
outline: none;
}
}
.modal-footer {
padding: 10px 16px;
border-top: 1px solid #f0f0f0;
display: flex;
justify-content: flex-end;
gap: 8px;
}
</style>