This commit is contained in:
2026-06-02 15:28:25 +08:00
commit b271b84f70
249 changed files with 42240 additions and 0 deletions
+229
View File
@@ -0,0 +1,229 @@
<template>
<view class="page-container">
<view class="filter-bar">
<picker class="filter-input" mode="date" :value="startDate" @change="handleStartDateChange">
<view>{{ startDate || '起始日期' }}</view>
</picker>
<picker class="filter-input" mode="date" :value="endDate" @change="handleEndDateChange">
<view>{{ endDate || '结束日期' }}</view>
</picker>
<button class="btn btn-primary search-btn" @click="handleQuery">查询</button>
</view>
<scroll-view scroll-y="true" class="page-body" :style="{ height: scrollHeight + 'px' }" lower-threshold="150" @scrolltolower="handleLoadMore">
<view class="scroll-content">
<!-- 选择模式提示 -->
<view class="tip-bar tip-bar-info" v-if="isSelectMode">
<text>点击下方数据条目即可选择</text>
</view>
<view class="data-list">
<view
class="data-card"
v-for="(item, index) in dataList"
:key="index"
@click="handleSelectItem(item)"
:class="{ 'selectable': isSelectMode }"
>
<view class="data-card-text">
<!-- <text>{{ item }}</text> -->
<!-- 名称 -->
<text>{{ item.fwmc }}</text>
<!-- 代码 -->
<text>{{ item.fwdm }}</text>
<!-- 重量 单位 -->
<text>{{ item.csl || item.rkl}}{{ item.jldw }}</text>
<!-- 时间 -->
<text>{{ item.cssj }}</text>
</view>
<!-- 选择模式下显示右侧箭头 -->
<view class="select-arrow" v-if="isSelectMode">
<uni-icons type="right" size="16" color="#cccccc"></uni-icons>
</view>
</view>
<view class="no-data" v-if="dataList.length === 0 && !loading">
<text>暂无数据</text>
</view>
</view>
<uni-load-more :contentText="{contentdown: '显示更多'}" v-if="dataList.length > 0" :status="loadMoreStatus" @clickLoadMore="handleLoadMore" />
</view>
</scroll-view>
</view>
</template>
<script>
import { api } from '@/api'
import { mapGetters } from 'vuex'
import { getDate } from '@/utils/common.js'
export default {
computed: {
...mapGetters('user', ['enterpriseInfo']),
loadMoreStatus() {
if (this.loading) return 'loading'
if (this.hasMore) return 'more'
return 'noMore'
}
},
data() {
return {
startDate: '',
endDate: '',
ledgerInfo: null,
dataList: [],
currentPage: 1,
total: 0,
hasMore: true,
loading: false,
scrollHeight: 0,
/*手机高度*/
phoneHeight: 0,
/* 选择模式 */
isSelectMode: false,
}
},
onLoad(options) {
if (options.item) {
this.ledgerInfo = JSON.parse(decodeURIComponent(options.item))
this.startDate = getDate()
this.endDate = getDate()
}
// 选择模式:从库存调整等页面跳转过来,点击数据条目返回选中结果
if (options.mode === 'select') {
this.isSelectMode = true
// 有台账类型时用其别名做标题,否则默认
const title = this.ledgerInfo ? this.ledgerInfo.alias : '选择数据'
uni.setNavigationBarTitle({ title })
if (!options.item) {
this.startDate = getDate()
this.endDate = getDate()
}
} else if (options.item) {
uni.setNavigationBarTitle({ title: this.ledgerInfo.alias })
}
},
mounted() {
this.init()
this.loadData()
},
methods: {
init() {
let _this = this;
uni.getSystemInfo({
success(res) {
_this.phoneHeight = res.windowHeight;
// 计算组件的高度
let view = uni.createSelectorQuery().select('.filter-bar');
view.boundingClientRect(data => {
let h = _this.phoneHeight - data.height;
_this.scrollHeight = h;
}).exec();
}
});
},
handleStartDateChange(e) {
this.startDate = e.detail.value
},
handleEndDateChange(e) {
this.endDate = e.detail.value
},
handleQuery() {
if (!this.startDate && !this.endDate) {
uni.showToast({ title: '请选择日期', icon: 'none' })
return
}
this.currentPage = 1
this.hasMore = true
this.loadData(false)
},
loadData(isLoadMore = false) {
if (this.loading) return
if (isLoadMore && !this.hasMore) return
this.loading = true
api.ledgerList({
lx: this.ledgerInfo ? this.ledgerInfo.lx : '',
qyid: this.enterpriseInfo.enterpriseId,
ksrq: this.startDate,
jsrq: this.endDate,
dqys: this.currentPage
}).then(res => {
console.log(res)
const newList = res.data.list || []
if (isLoadMore) {
this.dataList = [...this.dataList, ...newList]
} else {
this.dataList = newList
}
this.total = res.data.total || 0
this.hasMore = this.dataList.length < this.total
}).finally(() => {
this.loading = false
})
},
handleLoadMore() {
if (this.loading || !this.hasMore) return
this.currentPage += 1
this.loadData(true)
},
/** 选择模式下点击数据条目,将数据回传给上一页 */
handleSelectItem(item) {
if (!this.isSelectMode) return
const pages = getCurrentPages()
const prevPage = pages[pages.length - 2]
if (prevPage) {
// 将选中项存入上一页,由上一页根据需要提取字段
prevPage.$vm.selectedItem = item
prevPage.$vm.isSelected = true
}
uni.navigateBack()
},
handleScan() { uni.showToast({ title: '扫码查询', icon: 'none' }) }
}
}
</script>
<style lang="scss" scoped>
.scroll-content {
// min-height: 100%;
}
.filter-btn {
height: 40px;
background: $primary-color;
color: #ffffff;
border: none;
border-radius: $border-radius-sm;
font-size: $font-size-sm;
}
.search-btn{
width: 60px;
height: 36px;
}
/* 选择模式下的卡片样式 */
.data-card {
&.selectable {
position: relative;
transition: all 0.2s;
&:active {
background: $bg-primary;
transform: scale(0.98);
}
}
}
.data-card-text{
justify-content: space-between;
display: flex;
}
/* 选择模式右侧箭头 */
.select-arrow {
position: absolute;
right: $spacing-md;
top: 50%;
transform: translateY(-50%);
}
.no-data{
text-align: center;
padding: $spacing-md 0;
}
</style>
+54
View File
@@ -0,0 +1,54 @@
<template>
<view class="page-container">
<scroll-view class="page-body" scroll-y>
<view class="search-bar">
<input class="search-input" v-model="searchKey" placeholder="输入编号/名称查询" />
</view>
<view style="padding: 4px 16px;">
<button class="filter-btn" @click="handleScan">📷 扫码查询</button>
</view>
<view class="data-list">
<view class="data-card" v-for="(item, index) in dataList" :key="index">
<view class="data-card-header">
<text class="data-card-title">{{ item.name }}</text>
<text class="data-card-tag green">已处置</text>
</view>
<view class="data-card-row"><text>处置编号</text><text class="val">{{ item.code }}</text></view>
<view class="data-card-row"><text>处置方式</text><text class="val">{{ item.method }}</text></view>
<view class="data-card-row"><text>处置净重</text><text class="val">{{ item.weight }}</text></view>
<view class="data-card-row"><text>处置时间</text><text class="val">{{ item.time }}</text></view>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
import { api } from '@/api/index'
export default {
data() {
return {
searchKey: '',
dataList: [
{ name: '感染性废物', code: 'CZ20260512001', method: '高压灭菌', weight: '4.20 KG', time: '05-12 15:30' },
{ name: '损伤性废物', code: 'CZ20260511001', method: '焚烧处置', weight: '3.10 KG', time: '05-11 16:00' }
]
}
},
methods: {
handleScan() { uni.showToast({ title: '扫码查询', icon: 'none' }) }
}
}
</script>
<style lang="scss" scoped>
.filter-btn {
height: 32px;
background: $primary-color;
color: #ffffff;
border: none;
border-radius: $border-radius-sm;
font-size: $font-size-sm;
}
</style>
+84
View File
@@ -0,0 +1,84 @@
<template>
<view class="page-container">
<scroll-view class="page-body" scroll-y>
<view class="ledger-menu">
<view
class="ledger-item"
v-for="item in ledgerList"
:key="item.id"
@click="navigateTo(item)"
>
<view class="ledger-text">
<text class="title">{{ item.alias }}</text>
<!-- <text class="desc">{{ item.lx }}</text> -->
</view>
<uni-icons type="right" size="14" color="#cccccc"></uni-icons>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
import { api } from '@/api'
export default {
data() {
return {
ledgerList: []
}
},
onLoad() {
this.loadData()
},
methods: {
navigateTo(item) {
uni.navigateTo({
url: '/pages/ledger/detail?item=' + encodeURIComponent(JSON.stringify(item))
})
},
async loadData() {
const res = await api.ledgetType()
if (res.code === 1000) {
// 按 sort_order 排序
this.ledgerList = res.data.sort((a, b) => a.sort_order - b.sort_order)
}
}
}
}
</script>
<style lang="scss" scoped>
.ledger-menu {
padding: $spacing-md;
}
.ledger-item {
background: #ffffff;
border-radius: $border-radius-md;
padding: $spacing-md;
margin-bottom: $spacing-base;
display: flex;
align-items: center;
gap: $spacing-sm;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}
.ledger-text {
flex: 1;
.title {
display: block;
font-size: $font-size-md;
color: $text-primary;
margin-bottom: 2px;
}
.desc {
display: block;
font-size: $font-size-sm;
color: $text-placeholder;
}
}
</style>
+52
View File
@@ -0,0 +1,52 @@
<template>
<view class="page-container">
<scroll-view class="page-body" scroll-y>
<view class="filter-bar">
<input class="filter-input" v-model="startDate" placeholder="起始日期" />
<input class="filter-input" v-model="endDate" placeholder="结束日期" />
<button class="filter-btn" @click="handleQuery">查询</button>
</view>
<view class="data-list">
<view class="data-card" v-for="(item, index) in dataList" :key="index">
<view class="data-card-header">
<text class="data-card-title">{{ item.name }}</text>
<text class="data-card-tag green">已入库</text>
</view>
<view class="data-card-row"><text>入库编号</text><text class="val">{{ item.code }}</text></view>
<view class="data-card-row"><text>净重</text><text class="val">{{ item.weight }}</text></view>
<view class="data-card-row"><text>仓库/仓位</text><text class="val">{{ item.location }}</text></view>
<view class="data-card-row"><text>入库时间</text><text class="val">{{ item.time }}</text></view>
</view>
</view>
<view style="padding: 8px 16px;">
<button class="btn btn-outline" style="width:100%;height:36px;font-size:12px;" @click="handleReset">重置筛选</button>
</view>
</scroll-view>
</view>
</template>
<script>
import { api } from '@/api/index'
import { getMonthStartDate, getDate } from '@/utils/common.js'
export default {
data() {
return {
startDate: getMonthStartDate(),
endDate: getDate(),
dataList: [
{ name: '感染性废物', code: 'RK20260514001', weight: '2.35 KG', location: '1号暂存间/A区', time: '05-14 09:30' },
{ name: '损伤性废物', code: 'RK20260514002', weight: '1.50 KG', location: '1号暂存间/B区', time: '05-14 10:15' }
]
}
},
methods: {
handleQuery() { uni.showToast({ title: '查询中...', icon: 'none' }) },
handleReset() {
this.startDate = ''
this.endDate = ''
uni.showToast({ title: '已重置', icon: 'none' })
}
}
}
</script>
+45
View File
@@ -0,0 +1,45 @@
<template>
<view class="page-container">
<scroll-view class="page-body" scroll-y>
<view class="filter-bar">
<input class="filter-input" v-model="startDate" placeholder="起始日期" />
<input class="filter-input" v-model="endDate" placeholder="结束日期" />
<button class="filter-btn" @click="handleQuery">查询</button>
</view>
<view class="tip-bar tip-bar-warning">📌 出库台账仅查询展示不可编辑</view>
<view class="data-list">
<view class="data-card" v-for="(item, index) in dataList" :key="index">
<view class="data-card-header">
<text class="data-card-title">{{ item.name }}</text>
<text class="data-card-tag orange">已出库</text>
</view>
<view class="data-card-row"><text>出库编号</text><text class="val">{{ item.code }}</text></view>
<view class="data-card-row"><text>净重</text><text class="val">{{ item.weight }}</text></view>
<view class="data-card-row"><text>出库时间</text><text class="val">{{ item.time }}</text></view>
<view class="data-card-row"><text>去向</text><text class="val">{{ item.destination }}</text></view>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
import { api } from '@/api/index'
import { getMonthStartDate, getDate } from '@/utils/common.js'
export default {
data() {
return {
startDate: getMonthStartDate(),
endDate: getDate(),
dataList: [
{ name: '感染性废物', code: 'CK20260513001', weight: '5.60 KG', time: '05-13 16:30', destination: '外运处置' },
{ name: '损伤性废物', code: 'CK20260513002', weight: '3.10 KG', time: '05-13 16:45', destination: '自行处置' }
]
}
},
methods: {
handleQuery() { uni.showToast({ title: '查询中...', icon: 'none' }) }
}
}
</script>
+56
View File
@@ -0,0 +1,56 @@
<template>
<view class="page-container">
<scroll-view class="page-body" scroll-y>
<view class="filter-bar">
<picker mode="date" :value="date" :start="startDate" :end="endDate" @change="startDateChange">
<view class="filter-input">{{startDateVal}}</view>
</picker>
<picker mode="date" :value="date" :start="startDate" :end="endDate" @change="startDateChange">
<view class="filter-input">{{endDateVal}}</view>
</picker>
<button class="btn filter-btn" @click="handleQuery">查询</button>
</view>
<view class="data-list">
<view class="data-card" v-for="(item, index) in dataList" :key="index">
<view class="data-card-header">
<text class="data-card-title">{{ item.name }}</text>
<text class="data-card-tag blue">产生记录</text>
</view>
<view class="data-card-row"><text>产生科室</text><text class="val">{{ item.department }}</text></view>
<view class="data-card-row"><text>净重</text><text class="val">{{ item.weight }}</text></view>
<view class="data-card-row"><text>经办人</text><text class="val">{{ item.operator }}</text></view>
<view class="data-card-row"><text>产生时间</text><text class="val">{{ item.time }}</text></view>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
import { api } from '@/api/index'
import { getMonthStartDate, getDate } from '@/utils/common.js'
export default {
data() {
return {
startDate: getMonthStartDate(),
endDate: getDate(),
startDateVal: getMonthStartDate(),
endDateVal: getDate(),
dataList: [
{ name: '感染性废物', department: '内科门诊', weight: '2.35 KG', operator: '李伟', time: '05-14 09:30' },
{ name: '损伤性废物', department: '外科病房', weight: '1.50 KG', operator: '张明', time: '05-14 10:15' }
]
}
},
methods: {
handleQuery() { uni.showToast({ title: '查询中...', icon: 'none' }) },
startDateChange() {
console.log('startDateChange', this.startDate)
}
}
}
</script>
<style lang="scss" scoped>
</style>
+148
View File
@@ -0,0 +1,148 @@
<template>
<view class="page-container">
<scroll-view class="page-body" scroll-y>
<view class="filter-bar">
<input class="filter-input" v-model="startDate" placeholder="起始日期" />
<input class="filter-input" v-model="endDate" placeholder="结束日期" />
<button class="filter-btn" @click="handleQuery">查询</button>
</view>
<view class="stat-cards">
<view class="stat-card">
<text class="stat-label">入库总重量</text>
<view class="stat-number">38.5 <text class="stat-unit">KG</text></view>
</view>
<view class="stat-card">
<text class="stat-label">入库总数量</text>
<view class="stat-number">26 <text class="stat-unit"></text></view>
</view>
<view class="stat-card">
<text class="stat-label">贮存地点</text>
<view class="stat-number">2 <text class="stat-unit"></text></view>
</view>
<view class="stat-card">
<text class="stat-label">危废种类</text>
<view class="stat-number">4 <text class="stat-unit"></text></view>
</view>
</view>
<view class="chart-title">各类危废重量分布</view>
<view class="bar-chart">
<view class="bar-row">
<text class="bar-label">感染性</text>
<view class="bar-track"><view class="bar-fill red" style="width:75%;">18.5 KG</view></view>
</view>
<view class="bar-row">
<text class="bar-label">损伤性</text>
<view class="bar-track"><view class="bar-fill orange" style="width:45%;">10.2 KG</view></view>
</view>
<view class="bar-row">
<text class="bar-label">病理性</text>
<view class="bar-track"><view class="bar-fill blue" style="width:20%;">5.3 KG</view></view>
</view>
<view class="bar-row">
<text class="bar-label">药物性</text>
<view class="bar-track"><view class="bar-fill green" style="width:18%;">4.5 KG</view></view>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
import { api } from '@/api/index'
import { getMonthStartDate, getDate } from '@/utils/common.js'
export default {
data() {
return {
startDate: getMonthStartDate(),
endDate: getDate()
}
},
methods: {
handleQuery() { uni.showToast({ title: '查询中...', icon: 'none' }) }
}
}
</script>
<style lang="scss" scoped>
.stat-cards {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: $spacing-base;
padding: $spacing-md;
}
.stat-card {
background: #ffffff;
border-radius: $border-radius-md;
padding: $spacing-base;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
.stat-label {
font-size: $font-size-sm;
color: $text-placeholder;
}
.stat-number {
font-size: $font-size-xxl;
font-weight: 700;
color: $text-primary;
margin-top: $spacing-xs;
.stat-unit {
font-size: $font-size-base;
color: $text-placeholder;
font-weight: 400;
}
}
}
.chart-title {
padding: 0 $spacing-md $spacing-sm;
font-size: $font-size-base;
font-weight: 600;
color: $text-primary;
}
.bar-chart {
padding: 0 $spacing-md;
}
.bar-row {
display: flex;
align-items: center;
gap: $spacing-sm;
margin-bottom: $spacing-sm;
}
.bar-label {
width: 50px;
font-size: $font-size-sm;
color: $text-secondary;
text-align: right;
flex-shrink: 0;
}
.bar-track {
flex: 1;
height: 20px;
background: #f0f0f0;
border-radius: 4px;
overflow: hidden;
}
.bar-fill {
height: 100%;
border-radius: 4px;
display: flex;
align-items: center;
padding-left: 6px;
font-size: $font-size-xs;
color: #ffffff;
&.red { background: $danger-color; }
&.orange { background: $warning-color; }
&.blue { background: $primary-color; }
&.green { background: $success-color; }
}
</style>
+47
View File
@@ -0,0 +1,47 @@
<template>
<view class="page-container">
<scroll-view class="page-body" scroll-y>
<view class="tabs">
<view class="tab" :class="{ active: currentTab === 0 }" @click="currentTab = 0">待提交</view>
<view class="tab" :class="{ active: currentTab === 1 }" @click="currentTab = 1">已提交</view>
<view class="tab" :class="{ active: currentTab === 2 }" @click="currentTab = 2">已完成</view>
</view>
<view class="data-list">
<view class="data-card" v-for="(item, index) in filteredList" :key="index">
<view class="data-card-header">
<text class="data-card-title">{{ item.code }}</text>
<text class="data-card-tag" :class="item.statusClass">{{ item.status }}</text>
</view>
<view class="data-card-row"><text>危废名称</text><text class="val">{{ item.name }}</text></view>
<view class="data-card-row"><text>转移重量</text><text class="val">{{ item.weight }}</text></view>
<view class="data-card-row" v-if="item.receiver"><text>接收单位</text><text class="val">{{ item.receiver }}</text></view>
<view class="data-card-row"><text>{{ item.timeLabel }}</text><text class="val">{{ item.time }}</text></view>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
import { api } from '@/api/index'
export default {
data() {
return {
currentTab: 0,
dataList: [
{ code: 'LD20260514001', name: '感染性废物', weight: '5.60 KG', receiver: '上海XX环保处置公司', status: '待提交', statusClass: 'orange', timeLabel: '创建时间', time: '05-14 14:30' },
{ code: 'LD20260513001', name: '损伤性废物', weight: '3.10 KG', receiver: '', status: '已提交', statusClass: 'blue', timeLabel: '提交时间', time: '05-13 16:50' }
]
}
},
computed: {
filteredList() {
const statusMap = ['待提交', '已提交', '已完成']
return this.dataList.filter(item => item.status === statusMap[this.currentTab])
}
},
methods: {
}
}
</script>