调整
This commit is contained in:
1 parent
618ac4cdfb
commit
933a5abd3a
3 files changed
+372
-436
No files matched your search
@@ -751,7 +751,7 @@ onMounted(async () => {
|
||||
|
||||
.content-wrapper {
|
||||
min-height: 100%;
|
||||
padding: 0 0 calc(240rpx + env(safe-area-inset-bottom));
|
||||
padding: 0 0 150rpx;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
@@ -887,7 +887,7 @@ onMounted(async () => {
|
||||
position: fixed;
|
||||
left: 30rpx;
|
||||
right: 30rpx;
|
||||
bottom: calc(120rpx + env(safe-area-inset-bottom));
|
||||
bottom: 30rpx;
|
||||
height: 88rpx;
|
||||
background: #1989fa;
|
||||
border-radius: 44rpx;
|
||||
|
||||
@@ -1,105 +1,76 @@
|
||||
<template>
|
||||
<view class="page-container">
|
||||
<!-- 顶部状态切换 -->
|
||||
<view class="status-tabs">
|
||||
<view
|
||||
v-for="(tab, index) in tabs"
|
||||
:key="index"
|
||||
:class="['tab-item', { active: currentTab === tab.value }]"
|
||||
@tap="handleTabChange(tab.value)"
|
||||
>
|
||||
{{ tab.label }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="page-container">
|
||||
<!-- 顶部状态切换 -->
|
||||
<view class="status-tabs">
|
||||
<view
|
||||
v-for="(tab, index) in tabs"
|
||||
:key="index"
|
||||
:class="['tab-item', { active: currentTab === tab.value }]"
|
||||
@tap="handleTabChange(tab.value)"
|
||||
>
|
||||
{{ tab.label }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="visitor-list">
|
||||
<view
|
||||
v-for="(item, index) in visitorList"
|
||||
:key="item.id"
|
||||
class="visitor-item"
|
||||
@tap="goToDetail(item)"
|
||||
>
|
||||
<view class="visitor-header">
|
||||
<text class="visit-time">{{ formatDateTime(item.vStartDate) }}</text>
|
||||
<text :class="['status-tag', getStatusClass(item.checkStatus)]">{{ getStatusText(item.checkStatus) }}</text>
|
||||
</view>
|
||||
<view class="visitor-content">
|
||||
<view class="info-row">
|
||||
<text class="label">访客姓名:</text>
|
||||
<text class="value">{{ item.name }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">手机号码:</text>
|
||||
<text class="value">{{ item.mobile }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">拜访部门:</text>
|
||||
<text class="value">{{ item.deptName }}</text>
|
||||
</view>
|
||||
<view class="info-row" v-if="item.companyName">
|
||||
<text class="label">来访公司:</text>
|
||||
<text class="value">{{ item.companyName }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">拜访时间:</text>
|
||||
<text class="value">{{ formatDateTime(item.vstartDate) }} - {{ formatDateTime(item.vendDate) }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">拜访原因:</text>
|
||||
<text class="value">{{ getReasonText(item.reasonValue) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="visitor-footer">
|
||||
<template v-if="item.checkStatus === '1'">
|
||||
<view class="action-btn reject-btn" @tap="handleReject(item)">拒绝</view>
|
||||
<view class="action-btn accept-btn" @tap="handleAccept(item)">接受</view>
|
||||
</template>
|
||||
<view v-else-if="canCancel(item.checkStatus)" class="action-btn cancel-btn" @tap="handleCancel(item)">取消邀约</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="visitor-list">
|
||||
<view v-for="(item, index) in visitorList" :key="item.id" class="visitor-item" @tap="goToDetail(item)">
|
||||
<view class="visitor-header">
|
||||
<text class="visit-time">{{ formatDateTime(item.vStartDate) }}</text>
|
||||
<text :class="['status-tag', getStatusClass(item.checkStatus)]">{{ getStatusText(item.checkStatus) }}</text>
|
||||
</view>
|
||||
<view class="visitor-content">
|
||||
<view class="info-row">
|
||||
<text class="label">访客姓名:</text>
|
||||
<text class="value">{{ item.name }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">手机号码:</text>
|
||||
<text class="value">{{ item.mobile }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">拜访部门:</text>
|
||||
<text class="value">{{ item.deptName }}</text>
|
||||
</view>
|
||||
<view class="info-row" v-if="item.companyName">
|
||||
<text class="label">来访公司:</text>
|
||||
<text class="value">{{ item.companyName }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">拜访时间:</text>
|
||||
<text class="value">{{ formatDateTime(item.vstartDate) }} - {{ formatDateTime(item.vendDate) }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">拜访原因:</text>
|
||||
<text class="value">{{ getReasonText(item.reasonValue) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="visitor-footer">
|
||||
<template v-if="item.checkStatus === '1'">
|
||||
<view class="action-btn reject-btn" @tap="handleReject(item)">拒绝</view>
|
||||
<view class="action-btn accept-btn" @tap="handleAccept(item)">接受</view>
|
||||
</template>
|
||||
<view v-else-if="canCancel(item.checkStatus)" class="action-btn cancel-btn" @tap="handleCancel(item)">取消邀约</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 下拉刷新和上拉加载的提示 -->
|
||||
<view class="loading-more" v-if="loading">
|
||||
<text>加载中...</text>
|
||||
</view>
|
||||
<view class="no-more" v-if="!hasMore && visitorList.length > 0">
|
||||
<text>没有更多了</text>
|
||||
</view>
|
||||
<view class="empty" v-if="!loading && visitorList.length === 0">
|
||||
<text>暂无数据</text>
|
||||
</view>
|
||||
|
||||
<!-- 底部固定导航 -->
|
||||
<view class="bottom-nav">
|
||||
<view class="nav-item">
|
||||
<image src="/static/images/visitor/visitor-apply.png" mode="aspectFit" class="nav-icon"></image>
|
||||
<text class="nav-text active">访客申请</text>
|
||||
</view>
|
||||
<view class="nav-item">
|
||||
<image src="/static/images/visitor/visitor-record.png" mode="aspectFit" class="nav-icon"></image>
|
||||
<text class="nav-text">申请记录</text>
|
||||
</view>
|
||||
<view class="nav-item">
|
||||
<image src="/static/images/visitor/visitor-invite.png" mode="aspectFit" class="nav-icon"></image>
|
||||
<text class="nav-text">主动邀约</text>
|
||||
</view>
|
||||
<view class="nav-item">
|
||||
<image src="/static/images/visitor/visitor-invited.png" mode="aspectFit" class="nav-icon"></image>
|
||||
<text class="nav-text">邀约记录</text>
|
||||
</view>
|
||||
<view class="nav-item">
|
||||
<image src="/static/images/visitor/visitor-my.png" mode="aspectFit" class="nav-icon"></image>
|
||||
<text class="nav-text">我的</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 下拉刷新和上拉加载的提示 -->
|
||||
<view class="loading-more" v-if="loading">
|
||||
<text>加载中...</text>
|
||||
</view>
|
||||
<view class="no-more" v-if="!hasMore && visitorList.length > 0">
|
||||
<text>没有更多了</text>
|
||||
</view>
|
||||
<view class="empty" v-if="!loading && visitorList.length === 0">
|
||||
<text>暂无数据</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import visitorApi from '@/sheep/api/integrated/visitors'
|
||||
import dayjs from 'dayjs'
|
||||
import { ref, onMounted } from "vue"
|
||||
import visitorApi from "@/sheep/api/integrated/visitors"
|
||||
import dayjs from "dayjs"
|
||||
|
||||
// 定义响应式变量
|
||||
const visitorList = ref<any[]>([])
|
||||
@@ -107,439 +78,405 @@ const loading = ref(false)
|
||||
const hasMore = ref(true)
|
||||
const current = ref(1)
|
||||
const size = ref(10)
|
||||
const currentTab = ref('')
|
||||
const currentTab = ref("")
|
||||
const reasonDict = ref<any[]>([])
|
||||
|
||||
const tabs = [
|
||||
{ label: '全部', value: '' },
|
||||
{ label: '待审核', value: '1' },
|
||||
{ label: '待到访', value: '2' },
|
||||
{ label: '已取消', value: '5' }
|
||||
{ label: "全部", value: "" },
|
||||
{ label: "待审核", value: "1" },
|
||||
{ label: "待到访", value: "2" },
|
||||
{ label: "已取消", value: "5" },
|
||||
]
|
||||
|
||||
// 获取拜访原因字典
|
||||
const getReasonDict = async () => {
|
||||
try {
|
||||
const { code, data } = await visitorApi.getDictListByType(1)
|
||||
if (code === 0 && data) {
|
||||
reasonDict.value = data
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取拜访原因字典失败:', error)
|
||||
}
|
||||
try {
|
||||
const { code, data } = await visitorApi.getDictListByType(1)
|
||||
if (code === 0 && data) {
|
||||
reasonDict.value = data
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("获取拜访原因字典失败:", error)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取拜访原因文本
|
||||
const getReasonText = (value: string) => {
|
||||
const reason = reasonDict.value.find(item => item.value === value)
|
||||
return reason ? reason.label : value
|
||||
const reason = reasonDict.value.find((item) => item.value === value)
|
||||
return reason ? reason.label : value
|
||||
}
|
||||
|
||||
// 格式化日期时间
|
||||
const formatDateTime = (dateStr: string) => {
|
||||
if (!dateStr) return ''
|
||||
return dayjs(dateStr).format('YYYY/MM/DD HH:mm')
|
||||
if (!dateStr) return ""
|
||||
return dayjs(dateStr).format("YYYY/MM/DD HH:mm")
|
||||
}
|
||||
|
||||
// 获取状态文本
|
||||
const getStatusText = (status: string) => {
|
||||
const statusMap: { [key: string]: string } = {
|
||||
'1': '待审核',
|
||||
'2': '待到访',
|
||||
'5': '已取消',
|
||||
'0': '已到访'
|
||||
}
|
||||
return statusMap[status] || ''
|
||||
const statusMap: { [key: string]: string } = {
|
||||
"1": "待审核",
|
||||
"2": "待到访",
|
||||
"5": "已取消",
|
||||
"0": "已到访",
|
||||
}
|
||||
return statusMap[status] || ""
|
||||
}
|
||||
|
||||
// 获取状态样式类
|
||||
const getStatusClass = (status: string) => {
|
||||
const statusClassMap: { [key: string]: string } = {
|
||||
'1': 'status-pending',
|
||||
'2': 'status-waiting',
|
||||
'5': 'status-cancelled',
|
||||
'0': 'status-visited'
|
||||
}
|
||||
return statusClassMap[status] || ''
|
||||
const statusClassMap: { [key: string]: string } = {
|
||||
"1": "status-pending",
|
||||
"2": "status-waiting",
|
||||
"5": "status-cancelled",
|
||||
"0": "status-visited",
|
||||
}
|
||||
return statusClassMap[status] || ""
|
||||
}
|
||||
|
||||
// 判断是否可以取消
|
||||
const canCancel = (status: string) => {
|
||||
return ['1', '2'].includes(status)
|
||||
return ["1", "2"].includes(status)
|
||||
}
|
||||
|
||||
// 处理标签切换
|
||||
const handleTabChange = (value: string) => {
|
||||
if (currentTab.value === value) return
|
||||
currentTab.value = value
|
||||
getVisitorList(true)
|
||||
if (currentTab.value === value) return
|
||||
currentTab.value = value
|
||||
getVisitorList(true)
|
||||
}
|
||||
|
||||
// 获取访客列表
|
||||
const getVisitorList = async (isRefresh = false) => {
|
||||
if (isRefresh) {
|
||||
current.value = 1
|
||||
hasMore.value = true
|
||||
visitorList.value = []
|
||||
}
|
||||
if (isRefresh) {
|
||||
current.value = 1
|
||||
hasMore.value = true
|
||||
visitorList.value = []
|
||||
}
|
||||
|
||||
if (!hasMore.value || loading.value) return
|
||||
if (!hasMore.value || loading.value) return
|
||||
|
||||
loading.value = true
|
||||
try {
|
||||
// 确保先获取拜访原因字典
|
||||
if (reasonDict.value.length === 0) {
|
||||
await getReasonDict()
|
||||
}
|
||||
loading.value = true
|
||||
try {
|
||||
// 确保先获取拜访原因字典
|
||||
if (reasonDict.value.length === 0) {
|
||||
await getReasonDict()
|
||||
}
|
||||
|
||||
const { code, data } = await visitorApi.getVisitorYYList({
|
||||
current: current.value,
|
||||
size: size.value,
|
||||
checkStatus: currentTab.value || undefined
|
||||
})
|
||||
const { code, data } = await visitorApi.getVisitorYYList({
|
||||
current: current.value,
|
||||
size: size.value,
|
||||
checkStatus: currentTab.value || undefined,
|
||||
})
|
||||
|
||||
if (code === 0 && data) {
|
||||
if (isRefresh) {
|
||||
visitorList.value = data.records || []
|
||||
} else {
|
||||
visitorList.value = [...visitorList.value, ...(data.records || [])]
|
||||
}
|
||||
if (code === 0 && data) {
|
||||
if (isRefresh) {
|
||||
visitorList.value = data.records || []
|
||||
} else {
|
||||
visitorList.value = [...visitorList.value, ...(data.records || [])]
|
||||
}
|
||||
|
||||
hasMore.value = data.records.length === size.value
|
||||
if (hasMore.value) {
|
||||
current.value++
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取访客列表失败:', error)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
hasMore.value = data.records.length === size.value
|
||||
if (hasMore.value) {
|
||||
current.value++
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("获取访客列表失败:", error)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 处理取消邀约
|
||||
const handleCancel = async (item: any) => {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消该邀约吗?',
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
try {
|
||||
const { code, msg } = await visitorApi.cancelVisitor(item.id)
|
||||
if (code === 0) {
|
||||
uni.showToast({
|
||||
title: '取消成功',
|
||||
icon: 'success'
|
||||
})
|
||||
// 刷新列表
|
||||
getVisitorList(true)
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: msg || '取消失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('取消邀约失败:', error)
|
||||
uni.showToast({
|
||||
title: '取消失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
uni.showModal({
|
||||
title: "提示",
|
||||
content: "确定要取消该邀约吗?",
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
try {
|
||||
const { code, msg } = await visitorApi.cancelVisitor(item.id)
|
||||
if (code === 0) {
|
||||
uni.showToast({
|
||||
title: "取消成功",
|
||||
icon: "success",
|
||||
})
|
||||
// 刷新列表
|
||||
getVisitorList(true)
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: msg || "取消失败",
|
||||
icon: "none",
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("取消邀约失败:", error)
|
||||
uni.showToast({
|
||||
title: "取消失败",
|
||||
icon: "none",
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// 处理接受邀约
|
||||
const handleAccept = async (item: any) => {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定接受该邀约吗?',
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
try {
|
||||
const { code, msg } = await visitorApi.updateCheckStatus({
|
||||
id: item.id,
|
||||
checkStatus: '2'
|
||||
})
|
||||
if (code === 0) {
|
||||
uni.showToast({
|
||||
title: '已接受',
|
||||
icon: 'success'
|
||||
})
|
||||
// 刷新列表
|
||||
getVisitorList(true)
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: msg || '操作失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('接受邀约失败:', error)
|
||||
uni.showToast({
|
||||
title: '操作失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
uni.showModal({
|
||||
title: "提示",
|
||||
content: "确定接受该邀约吗?",
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
try {
|
||||
const { code, msg } = await visitorApi.updateCheckStatus({
|
||||
id: item.id,
|
||||
checkStatus: "2",
|
||||
})
|
||||
if (code === 0) {
|
||||
uni.showToast({
|
||||
title: "已接受",
|
||||
icon: "success",
|
||||
})
|
||||
// 刷新列表
|
||||
getVisitorList(true)
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: msg || "操作失败",
|
||||
icon: "none",
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("接受邀约失败:", error)
|
||||
uni.showToast({
|
||||
title: "操作失败",
|
||||
icon: "none",
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// 处理拒绝邀约
|
||||
const handleReject = async (item: any) => {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定拒绝该邀约吗?',
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
try {
|
||||
const { code, msg } = await visitorApi.updateCheckStatus({
|
||||
id: item.id,
|
||||
checkStatus: '3'
|
||||
})
|
||||
if (code === 0) {
|
||||
uni.showToast({
|
||||
title: '已拒绝',
|
||||
icon: 'success'
|
||||
})
|
||||
// 刷新列表
|
||||
getVisitorList(true)
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: msg || '操作失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('拒绝邀约失败:', error)
|
||||
uni.showToast({
|
||||
title: '操作失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
uni.showModal({
|
||||
title: "提示",
|
||||
content: "确定拒绝该邀约吗?",
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
try {
|
||||
const { code, msg } = await visitorApi.updateCheckStatus({
|
||||
id: item.id,
|
||||
checkStatus: "3",
|
||||
})
|
||||
if (code === 0) {
|
||||
uni.showToast({
|
||||
title: "已拒绝",
|
||||
icon: "success",
|
||||
})
|
||||
// 刷新列表
|
||||
getVisitorList(true)
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: msg || "操作失败",
|
||||
icon: "none",
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("拒绝邀约失败:", error)
|
||||
uni.showToast({
|
||||
title: "操作失败",
|
||||
icon: "none",
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// 跳转到详情页
|
||||
const goToDetail = (item: any) => {
|
||||
uni.navigateTo({
|
||||
url: `/pages/integrated/visitor/visitorDetail?token=${item.token}`
|
||||
})
|
||||
uni.navigateTo({
|
||||
url: `/pages/integrated/visitor/visitorDetail?token=${item.token}`,
|
||||
})
|
||||
}
|
||||
|
||||
// 页面生命周期钩子
|
||||
onMounted(() => {
|
||||
getReasonDict()
|
||||
getVisitorList(true)
|
||||
getReasonDict()
|
||||
getVisitorList(true)
|
||||
})
|
||||
|
||||
// 页面配置
|
||||
defineOptions({
|
||||
navigationBarTitleText: '我的邀约',
|
||||
enablePullDownRefresh: true,
|
||||
backgroundColor: '#f5f5f5'
|
||||
navigationBarTitleText: "我的邀约",
|
||||
enablePullDownRefresh: true,
|
||||
backgroundColor: "#f5f5f5",
|
||||
})
|
||||
|
||||
// 下拉刷新
|
||||
defineExpose({
|
||||
onPullDownRefresh() {
|
||||
getVisitorList(true).then(() => {
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
},
|
||||
onReachBottom() {
|
||||
getVisitorList()
|
||||
}
|
||||
onPullDownRefresh() {
|
||||
getVisitorList(true).then(() => {
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
},
|
||||
onReachBottom() {
|
||||
getVisitorList()
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-container {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
padding-bottom: 120rpx; // 为底部导航留出空间
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
padding-bottom: 120rpx; // 为底部导航留出空间
|
||||
}
|
||||
|
||||
.status-tabs {
|
||||
display: flex;
|
||||
background-color: #fff;
|
||||
padding: 20rpx 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
display: flex;
|
||||
background-color: #fff;
|
||||
padding: 20rpx 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
position: relative;
|
||||
padding: 20rpx 0;
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
position: relative;
|
||||
padding: 20rpx 0;
|
||||
|
||||
&.active {
|
||||
color: #1777FF;
|
||||
font-weight: 500;
|
||||
&.active {
|
||||
color: #1777ff;
|
||||
font-weight: 500;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 40rpx;
|
||||
height: 4rpx;
|
||||
background-color: #1777FF;
|
||||
border-radius: 2rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 40rpx;
|
||||
height: 4rpx;
|
||||
background-color: #1777ff;
|
||||
border-radius: 2rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.visitor-list {
|
||||
padding: 0 20rpx;
|
||||
padding-bottom: 20rpx; // 为底部添加一些间距
|
||||
padding: 0 20rpx;
|
||||
padding-bottom: 20rpx; // 为底部添加一些间距
|
||||
|
||||
.visitor-item {
|
||||
background-color: #fff;
|
||||
border-radius: 12rpx;
|
||||
margin-bottom: 20rpx;
|
||||
padding: 24rpx;
|
||||
.visitor-item {
|
||||
background-color: #fff;
|
||||
border-radius: 12rpx;
|
||||
margin-bottom: 20rpx;
|
||||
padding: 24rpx;
|
||||
|
||||
.visitor-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
.visitor-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.visit-time {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
.visit-time {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.status-tag {
|
||||
padding: 4rpx 16rpx;
|
||||
border-radius: 4rpx;
|
||||
font-size: 24rpx;
|
||||
.status-tag {
|
||||
padding: 4rpx 16rpx;
|
||||
border-radius: 4rpx;
|
||||
font-size: 24rpx;
|
||||
|
||||
&.status-pending {
|
||||
background-color: #fff7e6;
|
||||
color: #ffa940;
|
||||
}
|
||||
&.status-pending {
|
||||
background-color: #fff7e6;
|
||||
color: #ffa940;
|
||||
}
|
||||
|
||||
&.status-waiting {
|
||||
background-color: #e6f7ff;
|
||||
color: #1890ff;
|
||||
}
|
||||
&.status-waiting {
|
||||
background-color: #e6f7ff;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
&.status-visited {
|
||||
background-color: #f6ffed;
|
||||
color: #52c41a;
|
||||
}
|
||||
&.status-visited {
|
||||
background-color: #f6ffed;
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
&.status-cancelled {
|
||||
background-color: #f5f5f5;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.status-cancelled {
|
||||
background-color: #f5f5f5;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.visitor-content {
|
||||
.info-row {
|
||||
display: flex;
|
||||
margin-bottom: 16rpx;
|
||||
.visitor-content {
|
||||
.info-row {
|
||||
display: flex;
|
||||
margin-bottom: 16rpx;
|
||||
|
||||
.label {
|
||||
width: 160rpx;
|
||||
color: #666;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.label {
|
||||
width: 160rpx;
|
||||
color: #666;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.value {
|
||||
flex: 1;
|
||||
color: #333;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
.value {
|
||||
flex: 1;
|
||||
color: #333;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.visitor-footer {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 20rpx;
|
||||
.visitor-footer {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 20rpx;
|
||||
|
||||
.action-btn {
|
||||
padding: 12rpx 24rpx;
|
||||
border: 1rpx solid #ddd;
|
||||
border-radius: 4rpx;
|
||||
font-size: 26rpx;
|
||||
.action-btn {
|
||||
padding: 12rpx 24rpx;
|
||||
border: 1rpx solid #ddd;
|
||||
border-radius: 4rpx;
|
||||
font-size: 26rpx;
|
||||
|
||||
&:active {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
&:active {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
color: #666;
|
||||
}
|
||||
.cancel-btn {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.reject-btn {
|
||||
color: #ff4d4f;
|
||||
border-color: #ff4d4f;
|
||||
}
|
||||
.reject-btn {
|
||||
color: #ff4d4f;
|
||||
border-color: #ff4d4f;
|
||||
}
|
||||
|
||||
.accept-btn {
|
||||
color: #fff;
|
||||
background-color: #1777FF;
|
||||
border-color: #1777FF;
|
||||
}
|
||||
}
|
||||
}
|
||||
.accept-btn {
|
||||
color: #fff;
|
||||
background-color: #1777ff;
|
||||
border-color: #1777ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.loading-more, .no-more, .empty {
|
||||
text-align: center;
|
||||
padding: 30rpx;
|
||||
color: #999;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.bottom-nav {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 100rpx;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
border-top: 1rpx solid #eee;
|
||||
padding-bottom: env(safe-area-inset-bottom); // 适配iPhone底部安全区
|
||||
|
||||
.nav-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 10rpx 0;
|
||||
|
||||
.nav-icon {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
|
||||
.nav-text {
|
||||
font-size: 20rpx;
|
||||
color: #999;
|
||||
|
||||
&.active {
|
||||
color: #1777FF;
|
||||
}
|
||||
}
|
||||
}
|
||||
.loading-more,
|
||||
.no-more,
|
||||
.empty {
|
||||
text-align: center;
|
||||
padding: 30rpx;
|
||||
color: #999;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<crud-layout bg="/static/page/blue-bg.png">
|
||||
<view class="h-20rpx" />
|
||||
<view class="flex-row items-center">
|
||||
<view class="bg-#F8F8F8 w-full h-screen overflow-hidden">
|
||||
<view class="card p-30rpx mx-4 flex items-center">
|
||||
<image v-if="userInfo?.avatar" class="w-100rpx h-100rpx rounded-full" :src="userInfo.avatarUrl" mode="aspectFill" />
|
||||
<image v-else class="w-100rpx h-100rpx rounded-full" src="/static/icon/default-avatar.png" mode="aspectFill" />
|
||||
<view class="m-l-30rpx" v-if="token">
|
||||
@@ -15,13 +14,13 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="mt-4 rounded-20rpx shadow-main p-30rpx bg-white!">
|
||||
<view class="card p-30rpx m-4 active:bg-#F8F8F8!">
|
||||
<view class="flex items-center justify-between" @tap="onTabMenu">
|
||||
<text class="sub-text-36 m-l-20rpx">核销</text>
|
||||
<view class="iconfont icon-youjiantou" />
|
||||
</view>
|
||||
</view>
|
||||
</crud-layout>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
Reference in new issue
Block a user