2025-08-27 10:12:34 +00:00
|
|
|
|
<template>
|
|
|
|
|
|
<div class="order-list-page">
|
|
|
|
|
|
<!-- 搜索栏 -->
|
2025-08-28 09:33:10 +00:00
|
|
|
|
<div class="search-container">
|
|
|
|
|
|
<van-search
|
|
|
|
|
|
v-model="searchKeyword"
|
2025-09-26 06:54:37 +00:00
|
|
|
|
:placeholder="currentTab === 'pending' ? '搜索订单编号、客户名称' : '搜索合同名称'"
|
2025-08-28 09:33:10 +00:00
|
|
|
|
@search="handleSearch"
|
|
|
|
|
|
@clear="handleClear"
|
|
|
|
|
|
class="custom-search"
|
|
|
|
|
|
>
|
|
|
|
|
|
<template #left-icon>
|
|
|
|
|
|
<svg class="search-icon" viewBox="0 0 24 24" fill="none">
|
|
|
|
|
|
<circle cx="11" cy="11" r="8" stroke="currentColor" stroke-width="2"/>
|
|
|
|
|
|
<path d="M21 21L16.65 16.65" stroke="currentColor" stroke-width="2"/>
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</van-search>
|
|
|
|
|
|
</div>
|
2025-08-27 10:12:34 +00:00
|
|
|
|
|
2025-09-26 06:54:37 +00:00
|
|
|
|
<!-- Tab切换 -->
|
|
|
|
|
|
<van-tabs v-model:active="currentTab" @change="onTabChange" class="approval-tabs">
|
|
|
|
|
|
<!-- 待审批Tab -->
|
|
|
|
|
|
<van-tab name="pending" title="待审批">
|
|
|
|
|
|
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
|
|
|
|
|
|
<van-list
|
|
|
|
|
|
v-model:loading="loading"
|
|
|
|
|
|
:finished="finished"
|
|
|
|
|
|
finished-text="没有更多了"
|
|
|
|
|
|
@load="onLoad"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div v-for="order in orderList" :key="order.id" class="order-item" @click="goToDetail(order.id)">
|
|
|
|
|
|
<div class="order-header">
|
|
|
|
|
|
<div class="order-code">{{ order.orderCode }}</div>
|
|
|
|
|
|
<div class="status-tag pending">
|
|
|
|
|
|
待审批
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="order-info">
|
|
|
|
|
|
<div class="info-row">
|
|
|
|
|
|
<span class="label">项目名称:</span>
|
|
|
|
|
|
<span class="value">{{ order.projectName }}</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="info-row">
|
|
|
|
|
|
<span class="label">客户名称:</span>
|
|
|
|
|
|
<span class="value">{{ order.customerName }}</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="info-row">
|
|
|
|
|
|
<span class="label">订单金额:</span>
|
|
|
|
|
|
<span class="value amount">{{ formatAmount(order.shipmentAmount) }}</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="info-row">
|
|
|
|
|
|
<span class="label">创建时间:</span>
|
|
|
|
|
|
<span class="value">{{ formatDate(order.createTime, 'YYYY-MM-DD HH:mm') }}</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-08-27 10:12:34 +00:00
|
|
|
|
</div>
|
2025-09-26 06:54:37 +00:00
|
|
|
|
|
|
|
|
|
|
<!-- 空状态 -->
|
|
|
|
|
|
<div v-if="!loading && orderList.length === 0" class="empty-state">
|
|
|
|
|
|
<van-empty description="暂无待审批数据" />
|
2025-08-27 10:12:34 +00:00
|
|
|
|
</div>
|
2025-09-26 06:54:37 +00:00
|
|
|
|
</van-list>
|
|
|
|
|
|
</van-pull-refresh>
|
|
|
|
|
|
</van-tab>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 已审批Tab -->
|
|
|
|
|
|
<van-tab name="completed" title="已审批">
|
|
|
|
|
|
<van-pull-refresh v-model="completedRefreshing" @refresh="onCompletedRefresh">
|
|
|
|
|
|
<van-list
|
|
|
|
|
|
v-model:loading="completedLoading"
|
|
|
|
|
|
:finished="completedFinished"
|
|
|
|
|
|
finished-text="没有更多了"
|
|
|
|
|
|
@load="onCompletedLoad"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div v-for="item in completedList" :key="item.todoId" class="order-item" @click="goToCompletedDetail(item.businessId)">
|
|
|
|
|
|
<div class="order-header">
|
|
|
|
|
|
<div class="order-code">{{ item.businessKey }}</div>
|
|
|
|
|
|
<div class="status-tag" :class="getCompletedStatusClass(item.approveStatus)">
|
|
|
|
|
|
{{ getCompletedStatusText(item.approveStatus) }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="order-info">
|
|
|
|
|
|
<div class="info-row">
|
|
|
|
|
|
<span class="label">合同名称:</span>
|
|
|
|
|
|
<span class="value">{{ item.businessName }}</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="info-row">
|
|
|
|
|
|
<span class="label">流程名称:</span>
|
|
|
|
|
|
<span class="value">{{ item.processName }}</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="info-row">
|
|
|
|
|
|
<span class="label">发起人:</span>
|
|
|
|
|
|
<span class="value">{{ item.applyUserName }}</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="info-row">
|
|
|
|
|
|
<span class="label">审批时间:</span>
|
|
|
|
|
|
<span class="value">{{ item.approveTime }}</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div v-if="item.approveOpinion" class="info-row">
|
|
|
|
|
|
<span class="label">审批意见:</span>
|
|
|
|
|
|
<span class="value">{{ item.approveOpinion }}</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-08-27 10:12:34 +00:00
|
|
|
|
</div>
|
2025-09-26 06:54:37 +00:00
|
|
|
|
|
|
|
|
|
|
<!-- 空状态 -->
|
|
|
|
|
|
<div v-if="!completedLoading && completedList.length === 0" class="empty-state">
|
|
|
|
|
|
<van-empty description="暂无已审批数据" />
|
2025-08-27 10:12:34 +00:00
|
|
|
|
</div>
|
2025-09-26 06:54:37 +00:00
|
|
|
|
</van-list>
|
|
|
|
|
|
</van-pull-refresh>
|
|
|
|
|
|
</van-tab>
|
|
|
|
|
|
</van-tabs>
|
2025-08-27 10:12:34 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
2025-09-26 06:54:37 +00:00
|
|
|
|
import { ref, onMounted, watch } from 'vue'
|
2025-08-27 10:12:34 +00:00
|
|
|
|
import { useRouter } from 'vue-router'
|
|
|
|
|
|
import { storeToRefs } from 'pinia'
|
|
|
|
|
|
import { useOrderStore } from '@/store/order'
|
|
|
|
|
|
import { formatOrderStatus, formatAmount, formatDate } from '@/utils'
|
2025-09-26 06:54:37 +00:00
|
|
|
|
import type { OrderStatus, ApprovalStatus } from '@/types'
|
2025-08-27 10:12:34 +00:00
|
|
|
|
|
|
|
|
|
|
const router = useRouter()
|
|
|
|
|
|
const orderStore = useOrderStore()
|
2025-09-26 06:54:37 +00:00
|
|
|
|
|
|
|
|
|
|
// 待审批列表相关状态
|
2025-08-27 10:12:34 +00:00
|
|
|
|
const { orderList, loading, finished } = storeToRefs(orderStore)
|
|
|
|
|
|
|
2025-09-26 06:54:37 +00:00
|
|
|
|
// 已审批列表相关状态
|
|
|
|
|
|
const { completedList, completedLoading, completedFinished } = storeToRefs(orderStore)
|
|
|
|
|
|
|
|
|
|
|
|
// Tab相关
|
|
|
|
|
|
const currentTab = ref('pending')
|
|
|
|
|
|
|
2025-08-27 10:12:34 +00:00
|
|
|
|
// 搜索相关
|
|
|
|
|
|
const searchKeyword = ref('')
|
|
|
|
|
|
const refreshing = ref(false)
|
2025-09-26 06:54:37 +00:00
|
|
|
|
const completedRefreshing = ref(false)
|
2025-08-27 10:12:34 +00:00
|
|
|
|
|
|
|
|
|
|
// 获取状态样式类
|
|
|
|
|
|
const getStatusClass = (status: OrderStatus) => {
|
|
|
|
|
|
const classMap = {
|
|
|
|
|
|
'0': 'pending',
|
|
|
|
|
|
'1': 'approved',
|
|
|
|
|
|
'2': 'rejected'
|
|
|
|
|
|
}
|
|
|
|
|
|
return classMap[status] || 'pending'
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 加载数据
|
|
|
|
|
|
const onLoad = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
await orderStore.loadOrderList()
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('加载订单列表失败:', error)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 下拉刷新
|
|
|
|
|
|
const onRefresh = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
await orderStore.loadOrderList(true)
|
|
|
|
|
|
refreshing.value = false
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
refreshing.value = false
|
|
|
|
|
|
console.error('刷新失败:', error)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-26 06:54:37 +00:00
|
|
|
|
// Tab切换处理
|
|
|
|
|
|
const onTabChange = (name: string) => {
|
|
|
|
|
|
currentTab.value = name
|
|
|
|
|
|
searchKeyword.value = ''
|
|
|
|
|
|
|
|
|
|
|
|
if (name === 'completed' && completedList.value.length === 0) {
|
|
|
|
|
|
// 首次加载已审批列表
|
|
|
|
|
|
onCompletedLoad()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 已审批列表加载
|
|
|
|
|
|
const onCompletedLoad = async () => {
|
|
|
|
|
|
console.log('=== van-list 触发 onCompletedLoad ===')
|
|
|
|
|
|
console.log('当前状态:', {
|
|
|
|
|
|
loading: completedLoading.value,
|
|
|
|
|
|
finished: completedFinished.value,
|
|
|
|
|
|
listLength: completedList.value.length,
|
|
|
|
|
|
currentPage: orderStore.completedCurrentPage
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
await orderStore.loadCompletedOrderList()
|
|
|
|
|
|
console.log('onCompletedLoad 执行完成')
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('加载已审批列表失败:', error)
|
|
|
|
|
|
// 确保在出错时也能重置loading状态
|
|
|
|
|
|
orderStore.completedLoading = false
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 已审批列表刷新
|
|
|
|
|
|
const onCompletedRefresh = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
await orderStore.loadCompletedOrderList(true)
|
|
|
|
|
|
completedRefreshing.value = false
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
completedRefreshing.value = false
|
|
|
|
|
|
console.error('刷新已审批列表失败:', error)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-27 10:12:34 +00:00
|
|
|
|
// 搜索处理
|
|
|
|
|
|
const handleSearch = async () => {
|
|
|
|
|
|
try {
|
2025-09-26 06:54:37 +00:00
|
|
|
|
const keyword = searchKeyword.value.trim()
|
|
|
|
|
|
if (currentTab.value === 'pending') {
|
|
|
|
|
|
await orderStore.searchOrders(keyword)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
await orderStore.searchCompletedOrders(keyword)
|
|
|
|
|
|
}
|
2025-08-27 10:12:34 +00:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('搜索失败:', error)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 清空搜索
|
|
|
|
|
|
const handleClear = async () => {
|
|
|
|
|
|
searchKeyword.value = ''
|
|
|
|
|
|
try {
|
2025-09-26 06:54:37 +00:00
|
|
|
|
if (currentTab.value === 'pending') {
|
|
|
|
|
|
await orderStore.searchOrders('')
|
|
|
|
|
|
} else {
|
|
|
|
|
|
await orderStore.searchCompletedOrders('')
|
|
|
|
|
|
}
|
2025-08-27 10:12:34 +00:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('清空搜索失败:', error)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-26 06:54:37 +00:00
|
|
|
|
// 已审批状态文本转换
|
|
|
|
|
|
const getCompletedStatusText = (status: ApprovalStatus) => {
|
|
|
|
|
|
const statusMap = {
|
|
|
|
|
|
2: '驳回',
|
|
|
|
|
|
3: '通过'
|
|
|
|
|
|
}
|
|
|
|
|
|
return statusMap[status] || '提交'
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 已审批状态样式类
|
|
|
|
|
|
const getCompletedStatusClass = (status: ApprovalStatus) => {
|
|
|
|
|
|
const classMap = {
|
|
|
|
|
|
2: 'rejected',
|
|
|
|
|
|
3: 'approved'
|
|
|
|
|
|
}
|
|
|
|
|
|
return classMap[status] || 'pending'
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-27 10:12:34 +00:00
|
|
|
|
// 跳转到详情页
|
|
|
|
|
|
const goToDetail = (id: number) => {
|
2025-12-02 06:04:23 +00:00
|
|
|
|
router.push({ path: `/detail/${id}`, query: { from: 'order' } })
|
2025-08-27 10:12:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-26 06:54:37 +00:00
|
|
|
|
// 跳转到已审批详情页(只读模式)
|
|
|
|
|
|
const goToCompletedDetail = (businessId: number) => {
|
|
|
|
|
|
router.push({
|
|
|
|
|
|
path: `/detail/${businessId}`,
|
2025-12-02 06:04:23 +00:00
|
|
|
|
query: { readonly: 'true', from: 'order' }
|
2025-09-26 06:54:37 +00:00
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-27 10:12:34 +00:00
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
// 重置状态并加载数据
|
|
|
|
|
|
orderStore.resetListState()
|
2025-09-26 06:54:37 +00:00
|
|
|
|
orderStore.resetCompletedListState()
|
2025-08-27 10:12:34 +00:00
|
|
|
|
onLoad()
|
|
|
|
|
|
})
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
|
.order-list-page {
|
|
|
|
|
|
min-height: 100vh;
|
2025-09-26 06:54:37 +00:00
|
|
|
|
background-color: var(--van-background-color);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Tab相关样式
|
|
|
|
|
|
.approval-tabs {
|
|
|
|
|
|
:deep(.van-tabs__wrap) {
|
|
|
|
|
|
position: sticky;
|
2025-12-02 06:04:23 +00:00
|
|
|
|
top: 0;
|
2025-09-26 06:54:37 +00:00
|
|
|
|
z-index: 10;
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
}
|
2025-12-02 06:04:23 +00:00
|
|
|
|
|
2025-09-26 06:54:37 +00:00
|
|
|
|
:deep(.van-tabs__content) {
|
|
|
|
|
|
padding: 16px;
|
|
|
|
|
|
background: #f5f5f5;
|
2025-12-02 06:04:23 +00:00
|
|
|
|
min-height: calc(100vh - 56px);
|
2025-09-26 06:54:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.van-tab) {
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.van-tab--active) {
|
|
|
|
|
|
color: var(--van-primary-color);
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
}
|
2025-08-27 10:12:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.order-item {
|
2025-08-28 09:33:10 +00:00
|
|
|
|
background: #ffffff;
|
2025-08-28 07:37:34 +00:00
|
|
|
|
margin-bottom: 16px;
|
2025-08-28 09:33:10 +00:00
|
|
|
|
padding: 16px;
|
2025-08-27 10:12:34 +00:00
|
|
|
|
cursor: pointer;
|
2025-08-28 09:33:10 +00:00
|
|
|
|
transition: all 0.2s ease;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
border: 1px solid #f0f0f0;
|
2025-08-28 07:37:34 +00:00
|
|
|
|
|
2025-08-27 10:12:34 +00:00
|
|
|
|
&:active {
|
2025-08-28 09:33:10 +00:00
|
|
|
|
transform: translateY(1px);
|
|
|
|
|
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
2025-08-27 10:12:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.order-header {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
2025-08-28 07:37:34 +00:00
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
|
padding-bottom: 12px;
|
|
|
|
|
|
border-bottom: 1px solid #f0f0f0;
|
2025-08-27 10:12:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.order-code {
|
|
|
|
|
|
font-size: 16px;
|
2025-08-28 07:37:34 +00:00
|
|
|
|
font-weight: 600;
|
2025-08-28 09:33:10 +00:00
|
|
|
|
color: #333333;
|
2025-08-28 07:37:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.status-tag {
|
|
|
|
|
|
font-size: 12px;
|
2025-08-28 09:33:10 +00:00
|
|
|
|
padding: 4px 12px;
|
|
|
|
|
|
border-radius: 12px;
|
2025-08-27 10:12:34 +00:00
|
|
|
|
font-weight: 500;
|
2025-08-28 07:37:34 +00:00
|
|
|
|
|
|
|
|
|
|
&.pending {
|
2025-08-28 09:33:10 +00:00
|
|
|
|
background: #FFF3E0;
|
|
|
|
|
|
color: #FF9800;
|
|
|
|
|
|
border: 1px solid #FFE0B2;
|
2025-08-28 07:37:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&.approved {
|
2025-08-28 09:33:10 +00:00
|
|
|
|
background: #E8F5E8;
|
|
|
|
|
|
color: #4CAF50;
|
|
|
|
|
|
border: 1px solid #C8E6C9;
|
2025-08-28 07:37:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&.rejected {
|
2025-08-28 09:33:10 +00:00
|
|
|
|
background: #FFEBEE;
|
|
|
|
|
|
color: #F44336;
|
|
|
|
|
|
border: 1px solid #FFCDD2;
|
2025-08-28 07:37:34 +00:00
|
|
|
|
}
|
2025-08-27 10:12:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.order-info {
|
|
|
|
|
|
.info-row {
|
|
|
|
|
|
display: flex;
|
2025-08-28 09:33:10 +00:00
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
|
align-items: center;
|
2025-08-27 10:12:34 +00:00
|
|
|
|
|
|
|
|
|
|
&:last-child {
|
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.label {
|
|
|
|
|
|
width: 80px;
|
2025-08-28 09:33:10 +00:00
|
|
|
|
color: #666666;
|
2025-08-27 10:12:34 +00:00
|
|
|
|
font-size: 14px;
|
2025-08-28 09:33:10 +00:00
|
|
|
|
font-weight: 400;
|
2025-08-27 10:12:34 +00:00
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.value {
|
|
|
|
|
|
flex: 1;
|
2025-08-28 09:33:10 +00:00
|
|
|
|
color: #333333;
|
2025-08-27 10:12:34 +00:00
|
|
|
|
font-size: 14px;
|
2025-08-28 09:33:10 +00:00
|
|
|
|
font-weight: 400;
|
2025-08-27 10:12:34 +00:00
|
|
|
|
word-break: break-all;
|
2025-08-28 09:33:10 +00:00
|
|
|
|
line-height: 1.4;
|
2025-08-27 10:12:34 +00:00
|
|
|
|
|
|
|
|
|
|
&.amount {
|
2025-08-28 09:33:10 +00:00
|
|
|
|
color: #1976D2;
|
2025-08-28 07:37:34 +00:00
|
|
|
|
font-weight: 600;
|
2025-08-27 10:12:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.empty-state {
|
2025-08-28 09:33:10 +00:00
|
|
|
|
padding: 80px 20px;
|
2025-08-28 07:37:34 +00:00
|
|
|
|
text-align: center;
|
2025-08-28 09:33:10 +00:00
|
|
|
|
position: relative;
|
2025-08-28 07:37:34 +00:00
|
|
|
|
|
|
|
|
|
|
:deep(.van-empty) {
|
|
|
|
|
|
.van-empty__image {
|
2025-08-28 09:33:10 +00:00
|
|
|
|
width: 160px;
|
|
|
|
|
|
height: 160px;
|
|
|
|
|
|
filter: drop-shadow(0 8px 32px rgba(102, 126, 234, 0.2));
|
|
|
|
|
|
animation: float 3s ease-in-out infinite;
|
2025-08-28 07:37:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.van-empty__description {
|
2025-08-28 09:33:10 +00:00
|
|
|
|
font-size: 18px;
|
|
|
|
|
|
color: rgba(255, 255, 255, 0.9);
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
margin-top: 24px;
|
|
|
|
|
|
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
2025-08-28 07:37:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-28 09:33:10 +00:00
|
|
|
|
// 搜索栏容器
|
|
|
|
|
|
.search-container {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
z-index: 10;
|
2025-12-01 08:25:32 +00:00
|
|
|
|
margin: 16px 20px 20px 20px;
|
2025-08-28 09:33:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-28 07:37:34 +00:00
|
|
|
|
// 搜索栏样式优化
|
2025-08-28 09:33:10 +00:00
|
|
|
|
:deep(.custom-search) {
|
|
|
|
|
|
border-radius: 16px;
|
2025-08-28 07:37:34 +00:00
|
|
|
|
overflow: hidden;
|
2025-08-28 09:33:10 +00:00
|
|
|
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.08);
|
|
|
|
|
|
backdrop-filter: blur(20px);
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.95);
|
|
|
|
|
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
|
|
|
|
|
|
&:focus-within {
|
|
|
|
|
|
transform: translateY(-2px);
|
|
|
|
|
|
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15), 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
}
|
2025-08-28 07:37:34 +00:00
|
|
|
|
|
|
|
|
|
|
.van-search__content {
|
2025-08-28 09:33:10 +00:00
|
|
|
|
background: transparent;
|
|
|
|
|
|
padding: 12px 16px;
|
|
|
|
|
|
|
|
|
|
|
|
.van-field__control {
|
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
|
|
|
|
|
|
&::placeholder {
|
|
|
|
|
|
color: #999;
|
|
|
|
|
|
font-weight: normal;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-28 07:37:34 +00:00
|
|
|
|
}
|
2025-08-27 10:12:34 +00:00
|
|
|
|
}
|
2025-08-28 09:33:10 +00:00
|
|
|
|
|
|
|
|
|
|
.search-icon {
|
|
|
|
|
|
width: 20px;
|
|
|
|
|
|
height: 20px;
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
margin-right: 8px;
|
|
|
|
|
|
}
|
2025-08-27 10:12:34 +00:00
|
|
|
|
</style>
|