9.18王德鹏/1

This commit is contained in:
2025-09-18 14:22:04 +08:00
parent a8dcee7296
commit 335e21347b
90 changed files with 1618 additions and 1346 deletions

View File

@@ -0,0 +1,162 @@
<template>
<view class="page">
<!-- 顶部时间维度筛选 -->
<view class="seg">
<view :class="['seg-item', range==='custom' && 'active']" @click="switchRange('custom')">自定义</view>
<view :class="['seg-item', range==='week' && 'active']" @click="switchRange('week')">本周</view>
<view :class="['seg-item', range==='today' && 'active']" @click="switchRange('today')">今日</view>
<view :class="['seg-item', range==='month' && 'active']" @click="switchRange('month')">本月</view>
<view :class="['seg-item', range==='year' && 'active']" @click="switchRange('year')">本年</view>
</view>
<!-- 业务类型侧边切换销售/进货/收款/资金/盘点 -->
<view class="content">
<view class="biz-tabs">
<view v-for="b in bizList" :key="b.key" :class="['biz', biz===b.key && 'active']" @click="switchBiz(b.key)">{{ b.name }}</view>
</view>
<view class="panel">
<!-- 搜索框与期间显示总额 -->
<view class="toolbar">
<view class="search">
<input class="search-input" v-model.trim="query.kw" :placeholder="placeholder" @confirm="reload" />
</view>
<view class="period">{{ periodLabel }}</view>
<button size="mini" @click="reload">查询</button>
</view>
<view class="total">合计¥{{ totalAmount.toFixed(2) }}</view>
<!-- 列表 -->
<scroll-view scroll-y class="list" @scrolltolower="loadMore">
<block v-if="items.length">
<view class="item" v-for="it in items" :key="it.id" @click="openDetail(it)">
<view class="item-left">
<view class="date">{{ formatDate(it.orderTime || it.txTime || it.createdAt) }}</view>
<view class="name">{{ it.customerName || it.supplierName || it.accountName || it.remark || '-' }}</view>
<view class="no">{{ it.orderNo || it.code || it.id }}</view>
</view>
<view class="amount">¥ {{ (it.amount || 0).toFixed(2) }}</view>
<view class="arrow"></view>
</view>
</block>
<view v-else class="empty">暂无数据</view>
</scroll-view>
<!-- 右下角新增按钮根据业务类型跳转对应开单页或创建页 -->
<view class="fab" @click="onCreate"></view>
</view>
</view>
</view>
</template>
<script>
import { get } from '../../common/http.js'
const API_OF = {
sale: '/api/orders',
purchase: '/api/purchase-orders',
collect: '/api/payments',
fund: '/api/other-transactions',
stock: '/api/inventories/logs'
}
export default {
data() {
return {
biz: 'sale',
bizList: [
{ key: 'sale', name: '出货' },
{ key: 'purchase', name: '进货' },
{ key: 'collect', name: '收款' },
{ key: 'fund', name: '资金' },
{ key: 'stock', name: '盘点' }
],
range: 'month',
query: { kw: '' },
items: [],
page: 1,
size: 20,
finished: false,
loading: false,
startDate: '',
endDate: ''
}
},
computed: {
placeholder() { return '单据号/客户名称/品名规格/备注' },
periodLabel() { return this.startDate && this.endDate ? `${this.startDate}~${this.endDate}` : '' },
totalAmount() { return this.items.reduce((s, it) => s + Number(it.amount || 0), 0) }
},
onLoad() {
try { console.log('[detail] onLoad route = pages/detail/index') } catch(e){}
this.computeRange()
this.reload()
},
methods: {
switchBiz(k) { if (this.biz === k) return; this.biz = k; this.reload() },
switchRange(r) { this.range = r; this.computeRange(); this.reload() },
computeRange() {
const now = new Date()
const pad = n => String(n).padStart(2, '0')
const fmt = d => `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}`
let start = now, end = now
if (this.range === 'today') { start = end = now }
else if (this.range === 'week') { const day = now.getDay() || 7; start = new Date(now.getFullYear(), now.getMonth(), now.getDate() - day + 1); end = now }
else if (this.range === 'month') { start = new Date(now.getFullYear(), now.getMonth(), 1); end = new Date(now.getFullYear(), now.getMonth() + 1, 0) }
else if (this.range === 'year') { start = new Date(now.getFullYear(), 0, 1); end = new Date(now.getFullYear(), 11, 31) }
else { start = new Date(now.getFullYear(), now.getMonth(), 1); end = new Date(now.getFullYear(), now.getMonth() + 1, 0) }
this.startDate = fmt(start); this.endDate = fmt(end)
},
reload() { this.items = []; this.page = 1; this.finished = false; this.loadMore() },
async loadMore() {
if (this.loading || this.finished) return
this.loading = true
try {
const path = API_OF[this.biz] || '/api/orders'
const params = { kw: this.query.kw, page: this.page, size: this.size, startDate: this.startDate, endDate: this.endDate, biz: this.biz }
if (this.biz === 'sale') params.type = 'out'
const res = await get(path, params)
const list = Array.isArray(res?.list) ? res.list : (Array.isArray(res) ? res : [])
this.items = this.items.concat(list)
if (list.length < this.size) this.finished = true
this.page += 1
} catch (e) {
uni.showToast({ title: '加载失败', icon: 'none' })
} finally { this.loading = false }
},
formatDate(s) { if (!s) return ''; try { const d = new Date(s); const pad = n => String(n).padStart(2, '0'); return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}` } catch (_) { return String(s).slice(0,10) } },
onCreate() { if (this.biz === 'sale') { uni.navigateTo({ url: '/pages/order/create' }); return } uni.showToast({ title: '该类型创建页待实现', icon: 'none' }) },
openDetail(it) { uni.showToast({ title: '详情开发中', icon: 'none' }) }
}
}
</script>
<style>
.page { display:flex; flex-direction: column; height: 100vh; }
.seg { display:flex; background:#fff; }
.seg-item { flex:1; padding: 22rpx 0; text-align:center; color:#666; }
.seg-item.active { color:#18b566; font-weight: 600; }
.content { display:flex; flex:1; min-height: 0; }
.biz-tabs { width: 120rpx; background:#eef6ff; display:flex; flex-direction: column; }
.biz { flex:0 0 120rpx; display:flex; align-items:center; justify-content:center; color:#4aa3d6; }
.biz.active { background:#3ac1c9; color:#fff; border-radius: 0 16rpx 16rpx 0; }
.panel { flex:1; display:flex; flex-direction: column; background:#fff; margin: 16rpx; border-radius: 16rpx; padding: 12rpx; }
.toolbar { display:flex; align-items: center; gap: 12rpx; padding: 8rpx 6rpx; }
.search { flex:1; }
.search-input { width:100%; background:#f6f6f6; border-radius: 12rpx; padding: 12rpx; }
.period { color:#999; font-size: 24rpx; padding: 0 6rpx; }
.total { color:#18b566; font-weight: 700; padding: 6rpx 6rpx 12rpx; }
.list { flex:1; }
.item { display:flex; align-items:center; padding: 20rpx 10rpx; border-bottom: 1rpx solid #f1f1f1; }
.item-left { flex:1; }
.date { color:#999; font-size: 24rpx; }
.name { color:#333; margin: 4rpx 0; font-weight: 600; }
.no { color:#bbb; font-size: 22rpx; }
.amount { color:#333; font-weight: 700; }
.arrow { color:#ccc; font-size: 40rpx; margin-left: 8rpx; }
.empty { height: 50vh; display:flex; align-items:center; justify-content:center; color:#999; }
.fab { position: fixed; right: 30rpx; bottom: 120rpx; width: 100rpx; height: 100rpx; background:#18b566; color:#fff; border-radius: 50rpx; text-align:center; line-height: 100rpx; font-size: 48rpx; box-shadow: 0 8rpx 20rpx rgba(0,0,0,0.15); }
</style>