Files
im-uniapp/components/hrm/DateTimePicker.vue
2026-04-17 12:09:43 +08:00

70 lines
3.0 KiB
Vue

<template>
<view v-if="visible" class="mask" @tap="close">
<view class="sheet" @tap.stop>
<view class="sheet-header">
<text class="sheet-title">选择时间</text>
<text class="sheet-close" @tap="close">关闭</text>
</view>
<picker-view ref="picker" class="wheel" @change="onChange">
<picker-view-column>
<view v-for="(d, i) in dateOptions" :key="d" class="wheel-item"><text>{{ d }}</text></view>
</picker-view-column>
<picker-view-column>
<view v-for="(h, i) in hourOptions" :key="h" class="wheel-item"><text>{{ h }}</text></view>
</picker-view-column>
</picker-view>
<view class="footer">
<button class="btn ghost" @tap="close">取消</button>
<button class="btn primary" @tap="confirm">确定</button>
</view>
</view>
</view>
</template>
<script>
export default {
props: { visible: Boolean, value: String },
emits: ['update:visible', 'change'],
data() { return { pickerValue: [0, 0], days: 30 } },
computed: {
dateOptions() { const res = []; const base = new Date(); base.setHours(0,0,0,0); for (let i = 0; i < this.days; i++) { const d = new Date(base); d.setDate(d.getDate() + i); res.push(this.formatYMD(d)) } return res },
hourOptions() { return Array.from({ length: 24 }, (_, i) => `${i < 10 ? '0' : ''}${i}`) }
},
watch: {
visible(v) { if (v) setTimeout(() => this.initValue(), 100) }
},
methods: {
initValue() {
if (this.value) {
const v = String(this.value).replace('T', ' ')
const parts = v.split(' ')
const ymd = parts[0].split('-')
const hm = parts[1]?.split(':') || [0, 0]
const hour = parseInt(hm[0]) || 0
const dateIndex = this.dateOptions.indexOf(ymd.join('-'))
this.pickerValue = [dateIndex >= 0 ? dateIndex : 0, hour]
} else {
this.pickerValue = [0, 0]
}
this.$nextTick(() => {
const pv = this.$refs.picker
if (pv) pv.setValue(this.pickerValue)
})
},
onChange(e) { this.pickerValue = e.detail.value },
confirm() {
const date = this.dateOptions[this.pickerValue[0]] || this.dateOptions[0]
let hour = this.pickerValue[1] || 0
if (hour >= 24) hour = 23
this.$emit('change', `${date}T${hour < 10 ? '0' : ''}${hour}:00:00.000+08:00`)
this.close()
},
close() { this.$emit('update:visible', false) },
formatYMD(d) { const p = n => (n < 10 ? `0${n}` : n); return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}` }
}
}
</script>
<style scoped>
.mask{position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:1000;display:flex;align-items:flex-end}.sheet{width:100%;background:#fff;border-radius:24rpx 24rpx 0 0;padding:20rpx;box-sizing:border-box}.sheet-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:16rpx}.sheet-title{font-size:30rpx;font-weight:800}.sheet-close{font-size:26rpx;color:#1677ff}.wheel{height:520rpx}.wheel-item{display:flex;align-items:center;justify-content:center;height:88rpx}.footer{display:flex;gap:12rpx;margin-top:16rpx}.btn{flex:1;border-radius:16rpx}.btn.ghost{background:#f3f4f6;color:#334155}.btn.primary{background:#1677ff;color:#fff}
</style>