202 lines
5.2 KiB
Vue
202 lines
5.2 KiB
Vue
<template>
|
||
<view>
|
||
<view class="month-picker">
|
||
<picker
|
||
mode="date"
|
||
fields="month"
|
||
:value="selectedMonth"
|
||
:start="startDate"
|
||
:end="endDate"
|
||
@change="handleMonthChange"
|
||
>
|
||
<view class="picker-content">
|
||
<!-- 左箭头 -->
|
||
<view
|
||
class="arrow"
|
||
@click.stop="changeMonth(-1)"
|
||
:class="{ disabled: isMinMonth }"
|
||
>
|
||
◀
|
||
</view>
|
||
|
||
<view class="month-display">
|
||
<text class="label">选择月份:</text>
|
||
<text class="month-text">{{ formattedMonth }}</text>
|
||
</view>
|
||
|
||
<!-- 右箭头 -->
|
||
<view
|
||
class="arrow"
|
||
@click.stop="changeMonth(1)"
|
||
:class="{ disabled: isMaxMonth }"
|
||
>
|
||
▶
|
||
</view>
|
||
|
||
<text class="icon">▼</text>
|
||
</view>
|
||
</picker>
|
||
</view>
|
||
|
||
<view>
|
||
<k-table :columns="columns" :data="tableData"></k-table>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
// 1. 导入组件(路径需根据实际项目结构调整)
|
||
import klpTable from "../klp-ui/k-table/k-table.vue";
|
||
|
||
// 2. 独立工具函数(避免data初始化时调用this.methods的问题)
|
||
function getCurrentMonth() {
|
||
const date = new Date();
|
||
const year = date.getFullYear();
|
||
const month = (date.getMonth() + 1).toString().padStart(2, "0");
|
||
return `${year}-${month}`;
|
||
}
|
||
|
||
function getDefaultMonth() {
|
||
return getCurrentMonth();
|
||
}
|
||
|
||
export default {
|
||
// 3. 显式注册局部组件(Vue 2 必需)
|
||
components: {
|
||
klpTable
|
||
},
|
||
// 4. 响应式数据(替代 Vue 3 的 ref)
|
||
data() {
|
||
return {
|
||
// 默认选中当前月份
|
||
selectedMonth: getDefaultMonth(),
|
||
// 可选月份范围:2020年1月 - 当前月
|
||
startDate: "2020-01",
|
||
endDate: getCurrentMonth(),
|
||
// 表格列配置
|
||
columns: [
|
||
{ title: '班组', key: 'team' },
|
||
{ title: '作业次数', key: 'workCount' },
|
||
{ title: '原始产量', key: 'originalOutput' },
|
||
{ title: '成材率', key: 'yieldRate' },
|
||
{ title: '厚度合格率', key: 'thicknessPassRate' }
|
||
],
|
||
// 表格数据
|
||
tableData: [
|
||
{ team: '班组1', workCount: 100, originalOutput: 1000, yieldRate: '95%', thicknessPassRate: '90%' },
|
||
{ team: '班组2', workCount: 120, originalOutput: 1200, yieldRate: '92%', thicknessPassRate: '88%' },
|
||
{ team: '班组3', workCount: 90, originalOutput: 900, yieldRate: '93%', thicknessPassRate: '91%' },
|
||
{ team: '班组4', workCount: 110, originalOutput: 1100, yieldRate: '94%', thicknessPassRate: '89%' }
|
||
]
|
||
};
|
||
},
|
||
// 5. 计算属性(替代 Vue 3 的 computed 函数)
|
||
computed: {
|
||
// 是否为最小可选月份(2020-01)
|
||
isMinMonth() {
|
||
return this.selectedMonth === this.startDate;
|
||
},
|
||
// 是否为最大可选月份(当前月)
|
||
isMaxMonth() {
|
||
return this.selectedMonth === this.endDate;
|
||
},
|
||
// 格式化月份显示(如:2024年05月)
|
||
formattedMonth() {
|
||
const [year, month] = this.selectedMonth.split("-");
|
||
return `${year}年${month}月`;
|
||
}
|
||
},
|
||
// 6. 方法定义(所有函数需放在 methods 中)
|
||
methods: {
|
||
// 选择器切换月份(picker组件自带事件)
|
||
handleMonthChange(e) {
|
||
this.selectedMonth = e.detail.value;
|
||
},
|
||
// 箭头切换月份(左减1,右加1)
|
||
changeMonth(step) {
|
||
// 解析当前选中的年月
|
||
const [year, month] = this.selectedMonth.split("-").map(Number);
|
||
// 计算目标月份(month从0开始,需-1后+step)
|
||
const targetDate = new Date(year, month - 1 + step);
|
||
// 格式化目标月份为 YYYY-MM
|
||
const targetMonth = `${targetDate.getFullYear()}-${(targetDate.getMonth() + 1).toString().padStart(2, "0")}`;
|
||
|
||
// 边界校验:不能小于最小月,不能大于最大月
|
||
if (this.compareMonths(targetMonth, this.startDate) < 0) return;
|
||
if (this.compareMonths(targetMonth, this.endDate) > 0) return;
|
||
|
||
// 更新选中月份
|
||
this.selectedMonth = targetMonth;
|
||
},
|
||
// 比较两个月份(a > b 返回1,a = b 返回0,a < b 返回-1)
|
||
compareMonths(a, b) {
|
||
const [aYear, aMonth] = a.split("-").map(Number);
|
||
const [bYear, bMonth] = b.split("-").map(Number);
|
||
|
||
if (aYear !== bYear) return aYear - bYear;
|
||
return aMonth - bMonth;
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style scoped>
|
||
/* 月份选择器 */
|
||
.month-picker {
|
||
padding: 20rpx;
|
||
}
|
||
|
||
.picker-content {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 24rpx 20rpx;
|
||
background: #fff;
|
||
border-radius: 12rpx;
|
||
border: 1rpx solid #e8e8e8;
|
||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
|
||
}
|
||
|
||
.month-display {
|
||
flex: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.arrow {
|
||
padding: 0 24rpx;
|
||
font-size: 32rpx;
|
||
color: #1a73e8;
|
||
cursor: pointer;
|
||
transition: all 0.2s ease;
|
||
font-weight: 600;
|
||
|
||
&:active {
|
||
opacity: 0.7;
|
||
transform: scale(0.9);
|
||
}
|
||
|
||
&.disabled {
|
||
color: #ccc;
|
||
pointer-events: none;
|
||
}
|
||
}
|
||
|
||
.label {
|
||
color: #666;
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.month-text {
|
||
color: #1a73e8;
|
||
font-weight: 600;
|
||
font-size: 30rpx;
|
||
margin: 0 20rpx;
|
||
}
|
||
|
||
.icon {
|
||
color: #999;
|
||
font-size: 24rpx;
|
||
margin-left: 20rpx;
|
||
}
|
||
</style> |