feat: 移动端列表页支持搜索+分页(25条/页);历史移至请假后

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-07-13 00:49:43 +08:00
parent 3059f0e7e4
commit 72d869bafb
6 changed files with 104 additions and 11 deletions
+21 -2
View File
@@ -6,17 +6,28 @@ import { keyVisitsApi } from '@/api/keyVisits'
const router = useRouter()
const loading = ref(false)
const searchText = ref('')
const page = ref(1)
const pageSize = ref(25)
const total = ref(0)
const items = ref<any[]>([])
onMounted(loadItems)
async function loadItems() {
loading.value = true
try { const res = await keyVisitsApi.list(); items.value = Array.isArray(res.data) ? res.data : (res.data.items || []) }
catch (_) {}
try {
const params: any = { page: page.value, page_size: pageSize.value }
if (searchText.value) params.search = searchText.value
const res = await keyVisitsApi.list()
const raw = Array.isArray(res.data) ? res.data : (res.data.items || [])
items.value = raw; total.value = res.data.total || raw.length
} catch (_) {}
finally { loading.value = false }
}
function onSearch() { page.value = 1; loadItems() }
const urgencyColors: Record<string, string> = { '一般': '#5B7FA5', '重要': '#C4934A', '紧急': '#B8472E' }
async function handleDelete(id: string) {
@@ -41,6 +52,11 @@ async function handleDelete(id: string) {
<button class="new-btn" @click="router.push('/m/key-visit/new')">+ 新建要客</button>
<div style="margin-bottom:12px;display:flex;gap:8px">
<el-input v-model="searchText" placeholder="搜索..." size="small" clearable @keyup.enter="onSearch" @clear="onSearch" />
<el-button size="small" @click="onSearch">搜索</el-button>
</div>
<div class="cards">
<div v-if="items.length === 0 && !loading" class="empty-state"><div class="empty-glyph">—</div><p class="empty-text">暂不要客记录</p></div>
<article v-for="item in items" :key="item.id" class="card" @click="router.push(`/m/key-visit/${item.id}/edit`)">
@@ -56,7 +72,10 @@ async function handleDelete(id: string) {
</div>
</div>
</article>
<div v-if="total > pageSize" style="display:flex;justify-content:center;margin-top:14px">
<el-pagination v-model:current-page="page" :page-size="pageSize" :total="total" layout="prev, pager, next" small @current-change="loadItems" />
</div>
</div>
</div>
</template>
+17 -1
View File
@@ -6,6 +6,10 @@ import { miniBusinessApi } from '@/api/miniBusiness'
const router = useRouter()
const loading = ref(false)
const searchText = ref('')
const page = ref(1)
const pageSize = ref(25)
const total = ref(0)
const items = ref<any[]>([])
const statusOrder: Record<string, number> = { '跟进中': 0, '已签约': 1, '已流失': 2 }
@@ -14,13 +18,17 @@ onMounted(loadItems)
async function loadItems() {
loading.value = true
try {
const params: any = { page: page.value, page_size: pageSize.value }
if (searchText.value) params.search = searchText.value
const res = await miniBusinessApi.list()
const raw = Array.isArray(res.data) ? res.data : (res.data.items || [])
items.value = raw.sort((a: any, b: any) => (statusOrder[a.status] ?? 9) - (statusOrder[b.status] ?? 9))
items.value = raw; total.value = res.data.total || raw.length
} catch (_) {}
finally { loading.value = false }
}
function onSearch() { page.value = 1; loadItems() }
const statusColors: Record<string, string> = { '跟进中': '#C4934A', '已签约': '#4A6741', '已流失': '#B8472E' }
async function handleDelete(id: string) {
@@ -45,6 +53,11 @@ async function handleDelete(id: string) {
<button class="new-btn" @click="router.push('/m/mini-biz/new')">+ 新建商机</button>
<div style="margin-bottom:12px;display:flex;gap:8px">
<el-input v-model="searchText" placeholder="搜索..." size="small" clearable @keyup.enter="onSearch" @clear="onSearch" />
<el-button size="small" @click="onSearch">搜索</el-button>
</div>
<div class="cards">
<div v-if="items.length === 0 && !loading" class="empty-state"><div class="empty-glyph">—</div><p class="empty-text">暂无商机记录</p></div>
<article v-for="item in items" :key="item.id" class="card" @click="router.push(`/m/mini-biz/${item.id}/edit`)">
@@ -60,7 +73,10 @@ async function handleDelete(id: string) {
</div>
</div>
</article>
<div v-if="total > pageSize" style="display:flex;justify-content:center;margin-top:14px">
<el-pagination v-model:current-page="page" :page-size="pageSize" :total="total" layout="prev, pager, next" small @current-change="loadItems" />
</div>
</div>
</div>
</template>
+21 -2
View File
@@ -5,6 +5,10 @@ import api from '@/api/index'
const router = useRouter()
const loading = ref(false)
const searchText = ref('')
const page = ref(1)
const pageSize = ref(25)
const total = ref(0)
const items = ref<any[]>([])
onMounted(loadItems)
@@ -16,10 +20,17 @@ const catColors: Record<string, string> = {
async function loadItems() {
loading.value = true
try { const res = await api.get('/daily-notes/'); items.value = Array.isArray(res.data) ? res.data : (res.data.items || []) }
catch (_) {}
try {
const params: any = { page: page.value, page_size: pageSize.value }
if (searchText.value) params.search = searchText.value
const res = await api.get('/daily-notes/', { params })
const raw = Array.isArray(res.data) ? res.data : (res.data.items || [])
items.value = raw; total.value = res.data.total || raw.length
} catch (_) {}
finally { loading.value = false }
}
function onSearch() { page.value = 1; loadItems() }
</script>
<template>
@@ -32,6 +43,11 @@ async function loadItems() {
<div class="form-rule"></div>
</header>
<div style="margin-bottom:12px;display:flex;gap:8px">
<el-input v-model="searchText" placeholder="搜索..." size="small" clearable @keyup.enter="onSearch" @clear="onSearch" />
<el-button size="small" @click="onSearch">搜索</el-button>
</div>
<div v-loading="loading" class="cards">
<div v-if="items.length === 0 && !loading" class="empty-state"><div class="empty-glyph">—</div><p class="empty-text">暂无纪要记录</p></div>
<article v-for="item in items" :key="item.id" class="card" @click="router.push(`/m/note/${item.id}/edit`)">
@@ -47,7 +63,10 @@ async function loadItems() {
</div>
</div>
</article>
<div v-if="total > pageSize" style="display:flex;justify-content:center;margin-top:14px">
<el-pagination v-model:current-page="page" :page-size="pageSize" :total="total" layout="prev, pager, next" small @current-change="loadItems" />
</div>
</div>
</div>
</template>
+21 -2
View File
@@ -6,17 +6,28 @@ import api from '@/api/index'
const router = useRouter()
const loading = ref(false)
const searchText = ref('')
const page = ref(1)
const pageSize = ref(25)
const total = ref(0)
const items = ref<any[]>([])
onMounted(loadItems)
async function loadItems() {
loading.value = true
try { const res = await api.get('/work-plans/'); items.value = Array.isArray(res.data) ? res.data : (res.data.items || []) }
catch (_) {}
try {
const params: any = { page: page.value, page_size: pageSize.value }
if (searchText.value) params.search = searchText.value
const res = await api.get('/work-plans/', { params })
const raw = Array.isArray(res.data) ? res.data : (res.data.items || [])
items.value = raw; total.value = res.data.total || raw.length
} catch (_) {}
finally { loading.value = false }
}
function onSearch() { page.value = 1; loadItems() }
async function handleDelete(id: string) {
try {
await ElMessageBox.confirm('确定删除?', '确认', { type: 'warning' })
@@ -39,6 +50,11 @@ async function handleDelete(id: string) {
<button class="new-btn" @click="router.push('/m/work-plan/new')">+ 新建计划</button>
<div style="margin-bottom:12px;display:flex;gap:8px">
<el-input v-model="searchText" placeholder="搜索..." size="small" clearable @keyup.enter="onSearch" @clear="onSearch" />
<el-button size="small" @click="onSearch">搜索</el-button>
</div>
<div class="cards">
<div v-if="items.length === 0 && !loading" class="empty-state"><div class="empty-glyph">—</div><p class="empty-text">暂无工作计划</p></div>
<article v-for="item in items" :key="item.id" class="card" @click="router.push(`/m/work-plan/${item.id}/edit`)">
@@ -54,7 +70,10 @@ async function handleDelete(id: string) {
</div>
</div>
</article>
<div v-if="total > pageSize" style="display:flex;justify-content:center;margin-top:14px">
<el-pagination v-model:current-page="page" :page-size="pageSize" :total="total" layout="prev, pager, next" small @current-change="loadItems" />
</div>
</div>
</div>
</template>
+22 -2
View File
@@ -5,17 +5,29 @@ import api from '@/api/index'
const router = useRouter()
const loading = ref(false)
const searchText = ref('')
const page = ref(1)
const pageSize = ref(25)
const total = ref(0)
const items = ref<any[]>([])
onMounted(loadItems)
async function loadItems() {
loading.value = true
try { const res = await api.get('/visits/'); items.value = Array.isArray(res.data) ? res.data : (res.data.items || []) }
catch (_) {}
try {
const params: any = { page: page.value, page_size: pageSize.value }
if (searchText.value) params.search = searchText.value
const res = await api.get('/visits/', { params })
const raw = Array.isArray(res.data) ? res.data : (res.data.items || [])
items.value = raw; total.value = res.data.total || raw.length
} catch (_) {}
finally { loading.value = false }
}
function onSearch() { page.value = 1; loadItems() }
const methodColors: Record<string, string> = { '上门': '#4A6741', '电话': '#5B7FA5', '微信': '#22c55e', '出差': '#C4934A' }
</script>
@@ -29,6 +41,11 @@ const methodColors: Record<string, string> = { '上门': '#4A6741', '电话': '#
<div class="form-rule"></div>
</header>
<div style="margin-bottom:12px;display:flex;gap:8px">
<el-input v-model="searchText" placeholder="搜索..." size="small" clearable @keyup.enter="onSearch" @clear="onSearch" />
<el-button size="small" @click="onSearch">搜索</el-button>
</div>
<div v-loading="loading" class="cards">
<div v-if="items.length === 0 && !loading" class="empty-state"><div class="empty-glyph">—</div><p class="empty-text">暂无拜访记录</p></div>
<article v-for="item in items" :key="item.id" class="card" @click="router.push(`/m/visit/${item.id}/edit`)">
@@ -44,7 +61,10 @@ const methodColors: Record<string, string> = { '上门': '#4A6741', '电话': '#
</div>
</div>
</article>
<div v-if="total > pageSize" style="display:flex;justify-content:center;margin-top:14px">
<el-pagination v-model:current-page="page" :page-size="pageSize" :total="total" layout="prev, pager, next" small @current-change="loadItems" />
</div>
</div>
</div>
</template>
+2 -2
View File
@@ -26,12 +26,12 @@ onMounted(async () => {
})
const modules = [
{ path: '/m/visits', label: '历史拜访', icon: '📋', count: () => counts.value.visits, color: '#4A6741' },
{ path: '/m/notes', label: '历史纪要', icon: '📝', count: () => counts.value.notes, color: '#1C3738' },
{ path: '/m/plans', label: '工作计划', icon: '📅', count: () => counts.value.plans, color: '#4A6741' },
{ path: '/m/mini-biz', label: '商机跟单', icon: '💰', count: () => counts.value.miniBiz, color: '#C4934A' },
{ path: '/m/key-visits', label: '要客拜访', icon: '⭐', count: () => counts.value.keyVisits, color: '#5B7FA5' },
{ path: '/m/leaves', label: '请假管理', icon: '📋', count: () => counts.value.leaves, color: '#9CA3AF' },
{ path: '/m/visits', label: '历史拜访', icon: '🕐', count: () => counts.value.visits, color: '#4A6741' },
{ path: '/m/notes', label: '历史纪要', icon: '📝', count: () => counts.value.notes, color: '#1C3738' },
]
</script>