|
|
@@ -1,46 +1,43 @@
|
|
|
|
|
|
<template>
|
|
|
<view class="app-container pb-24">
|
|
|
- <TopBar title="项目库" show-back>
|
|
|
- <template #right>
|
|
|
- <view class="px-2 py-1 flex items-center" @click="goToAdd">
|
|
|
- <text class="uni-icons uniui-plusempty text-primary text-xl"></text>
|
|
|
- <text class="text-primary text-sm ml-1">新增</text>
|
|
|
- </view>
|
|
|
- </template>
|
|
|
- </TopBar>
|
|
|
-
|
|
|
+ <TopBar title="项目库" show-back />
|
|
|
+
|
|
|
<!-- 顶部搜索栏 -->
|
|
|
<view class="bg-white px-4 py-3 sticky top-0 z-40">
|
|
|
<view class="flex items-center bg-gray-100 rounded-2xl px-4 py-2">
|
|
|
<text class="uni-icons uniui-search text-gray-400 mr-2 text-base"></text>
|
|
|
- <input
|
|
|
- class="flex-1 bg-transparent text-sm text-gray-700"
|
|
|
- placeholder="搜索项目名称"
|
|
|
+ <input
|
|
|
+ class="flex-1 bg-transparent text-sm text-gray-700"
|
|
|
+ placeholder="搜索项目名称"
|
|
|
v-model="searchKeyword"
|
|
|
/>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
- <!-- 顶部筛选标签 - 使用 uni-segmented-control -->
|
|
|
- <uni-segmented-control
|
|
|
- :current="currentFilterIndex"
|
|
|
- :values="filterLabels"
|
|
|
- style-type="text"
|
|
|
- active-color="#4f8ef7"
|
|
|
- @clickItem="onFilterChange"
|
|
|
- />
|
|
|
+ <!-- 顶部筛选标签:药丸式分段控件 -->
|
|
|
+ <view class="filter-tabs">
|
|
|
+ <view
|
|
|
+ v-for="(label, index) in filterLabels"
|
|
|
+ :key="index"
|
|
|
+ class="filter-tab"
|
|
|
+ :class="{ 'filter-tab-active': currentFilterIndex === index }"
|
|
|
+ @click="onFilterChange(index)"
|
|
|
+ >
|
|
|
+ {{ label }}
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
|
|
|
<!-- 项目列表 - 使用 uni-list + uni-card + uni-swipe-action -->
|
|
|
<view class="mt-2">
|
|
|
<view v-if="projectStore.loading" class="py-16 text-center">
|
|
|
<text class="text-gray-400">加载中...</text>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<view v-else-if="filteredProjects.length === 0">
|
|
|
<EmptyState message="暂无项目" />
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<uni-list v-else border>
|
|
|
<uni-swipe-action
|
|
|
v-for="project in filteredProjects"
|
|
|
@@ -48,7 +45,7 @@
|
|
|
:actions="swipeActions"
|
|
|
@click="onSwipeAction(project.id, $event)"
|
|
|
>
|
|
|
- <uni-list-item
|
|
|
+ <uni-list-item
|
|
|
:title="project.name"
|
|
|
:note="project.address + ' | ' + project.customerName"
|
|
|
:right-text="project.type"
|
|
|
@@ -65,10 +62,16 @@
|
|
|
</uni-list>
|
|
|
</view>
|
|
|
|
|
|
+ <!-- 新增悬浮按钮:避开胶囊按钮 -->
|
|
|
+ <view class="fab" @click="goToAdd">
|
|
|
+ <text class="uni-icons uniui-plusempty fab-icon"></text>
|
|
|
+ <text class="fab-text">新增</text>
|
|
|
+ </view>
|
|
|
+
|
|
|
<!-- 加载更多 -->
|
|
|
<view v-if="filteredProjects.length > 0" class="px-4 mt-4 mb-4">
|
|
|
<view v-if="projectStore.hasMore" class="text-center py-4">
|
|
|
- <text
|
|
|
+ <text
|
|
|
class="text-sm text-blue-500 font-medium"
|
|
|
@click="loadMore"
|
|
|
>
|
|
|
@@ -91,7 +94,6 @@ import TopBar from '../../components/common/TopBar.vue'
|
|
|
import UniList from '../../components/uni-list/uni-list.vue'
|
|
|
import UniListItem from '../../components/uni-list/uni-list-item.vue'
|
|
|
import UniSwipeAction from '../../components/uni-swipe-action/uni-swipe-action.vue'
|
|
|
-import UniSegmentedControl from '../../components/uni-segmented-control/uni-segmented-control.vue'
|
|
|
|
|
|
const projectStore = useProjectStore()
|
|
|
const searchKeyword = ref('')
|
|
|
@@ -110,15 +112,15 @@ const filterLabels = filterTypes.map(t => t.label)
|
|
|
const filteredProjects = computed(() => {
|
|
|
let list = projectStore.projects
|
|
|
const filterValue = filterTypes[currentFilterIndex.value].value
|
|
|
-
|
|
|
+
|
|
|
if (filterValue !== 'all') {
|
|
|
list = list.filter(p => p.type === filterValue)
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
if (searchKeyword.value) {
|
|
|
list = list.filter(p => p.name.includes(searchKeyword.value))
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
return list
|
|
|
})
|
|
|
|
|
|
@@ -177,3 +179,67 @@ onPullDownRefresh(() => {
|
|
|
refreshData()
|
|
|
})
|
|
|
</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+/* ==================== 筛选标签:药丸式分段控件 ==================== */
|
|
|
+.filter-tabs {
|
|
|
+ display: flex;
|
|
|
+ gap: 8px;
|
|
|
+ padding: 10px 16px;
|
|
|
+ background-color: #ffffff;
|
|
|
+ overflow-x: auto;
|
|
|
+ white-space: nowrap;
|
|
|
+}
|
|
|
+
|
|
|
+.filter-tab {
|
|
|
+ flex-shrink: 0;
|
|
|
+ padding: 6px 16px;
|
|
|
+ border-radius: 999px;
|
|
|
+ font-size: 13px;
|
|
|
+ color: #709484; /* 晨雾灰绿 */
|
|
|
+ background-color: #f6fbf9; /* 云雾白 */
|
|
|
+ border: 1px solid rgba(164, 216, 152, 0.4);
|
|
|
+ transition: all 0.18s ease;
|
|
|
+}
|
|
|
+
|
|
|
+.filter-tab-active {
|
|
|
+ color: #ffffff;
|
|
|
+ background: linear-gradient(135deg, #368f6f 0%, #5ab8d0 100%); /* 青山绿 → 流水青 */
|
|
|
+ border-color: transparent;
|
|
|
+ box-shadow: 0 6px 14px -6px rgba(54, 143, 111, 0.6);
|
|
|
+}
|
|
|
+
|
|
|
+/* ==================== 新增悬浮按钮 ==================== */
|
|
|
+.fab {
|
|
|
+ position: fixed;
|
|
|
+ right: 20px;
|
|
|
+ bottom: calc(28px + env(safe-area-inset-bottom));
|
|
|
+ z-index: 99;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 4px;
|
|
|
+ height: 50px;
|
|
|
+ padding: 0 22px;
|
|
|
+ border-radius: 999px;
|
|
|
+ background: linear-gradient(135deg, #368f6f 0%, #5ab8d0 100%);
|
|
|
+ box-shadow: 0 10px 22px -8px rgba(54, 143, 111, 0.65);
|
|
|
+}
|
|
|
+
|
|
|
+.fab:active {
|
|
|
+ transform: scale(0.95);
|
|
|
+ opacity: 0.9;
|
|
|
+}
|
|
|
+
|
|
|
+.fab-icon {
|
|
|
+ color: #ffffff;
|
|
|
+ font-size: 18px;
|
|
|
+}
|
|
|
+
|
|
|
+.fab-text {
|
|
|
+ color: #ffffff;
|
|
|
+ font-size: 15px;
|
|
|
+ font-weight: 600;
|
|
|
+ letter-spacing: 1px;
|
|
|
+}
|
|
|
+</style>
|
|
|
+
|