You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

210 lines
5.5 KiB

1 month ago
<template>
<!-- 功能与 4T 一致透明遮罩可拖动记录位置不阻挡地图风格保持原样 -->
<div v-if="value" class="k-time-set-dialog">
<div class="panel-container" :style="panelStyle">
<div class="dialog-header" @mousedown="onDragStart">
<h3>设定 / 修改 K </h3>
<div class="close-btn" @mousedown.stop @click="closeDialog">×</div>
</div>
<div class="dialog-body">
<el-form label-width="90px">
<el-form-item label="K 时(基准)">
<el-date-picker
:value="dateTime"
@input="$emit('update:dateTime', $event)"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="选择日期和时间"
style="width: 100%"
/>
</el-form-item>
</el-form>
<div class="dialog-footer">
<el-button @click="closeDialog"> </el-button>
<el-button type="primary" @click="handleSave"> </el-button>
</div>
</div>
</div>
</div>
</template>
<script>
const STORAGE_KEY_PREFIX = 'kTimeSetPanel_'
export default {
name: 'KTimeSetDialog',
props: {
value: { type: Boolean, default: false },
dateTime: { type: String, default: null },
roomId: { type: [String, Number], default: null }
},
data() {
return {
panelLeft: null,
panelTop: null,
panelWidth: 420,
panelHeight: 250,
isDragging: false,
dragStartX: 0,
dragStartY: 0
}
},
computed: {
panelStyle() {
const left = this.panelLeft != null ? this.panelLeft : (window.innerWidth - this.panelWidth) / 2 - 20
const top = this.panelTop != null ? this.panelTop : (window.innerHeight - this.panelHeight) / 2 - 40
return {
left: `${left}px`,
top: `${top}px`,
width: `${this.panelWidth}px`,
height: `${this.panelHeight}px`
}
}
},
watch: {
value(val) {
if (val) this.loadPosition()
}
},
methods: {
closeDialog() {
this.$emit('input', false)
},
handleSave() {
this.$emit('save')
},
getStorageKey() {
return STORAGE_KEY_PREFIX + (this.roomId || 'default')
},
loadPosition() {
try {
const raw = localStorage.getItem(this.getStorageKey())
if (raw) {
const d = JSON.parse(raw)
if (d.panelPosition) {
const left = Number(d.panelPosition.left)
const top = Number(d.panelPosition.top)
if (!isNaN(left) && left >= 0) this.panelLeft = Math.min(left, window.innerWidth - this.panelWidth)
if (!isNaN(top) && top >= 0) this.panelTop = Math.min(top, window.innerHeight - this.panelHeight)
}
}
} catch (e) {
console.warn('加载 K 时弹窗位置失败:', e)
}
},
savePosition() {
try {
const payload = {}
if (this.panelLeft != null && this.panelTop != null) {
payload.panelPosition = { left: this.panelLeft, top: this.panelTop }
}
localStorage.setItem(this.getStorageKey(), JSON.stringify(payload))
} catch (e) {
console.warn('保存 K 时弹窗位置失败:', e)
}
},
onDragStart(e) {
e.preventDefault()
this.isDragging = true
const currentLeft = this.panelLeft != null ? this.panelLeft : (window.innerWidth - this.panelWidth) / 2 - 20
const currentTop = this.panelTop != null ? this.panelTop : (window.innerHeight - this.panelHeight) / 2 - 40
this.dragStartX = e.clientX - currentLeft
this.dragStartY = e.clientY - currentTop
document.addEventListener('mousemove', this.onDragMove)
document.addEventListener('mouseup', this.onDragEnd)
},
onDragMove(e) {
if (!this.isDragging) return
e.preventDefault()
let left = e.clientX - this.dragStartX
let top = e.clientY - this.dragStartY
left = Math.max(0, Math.min(window.innerWidth - this.panelWidth, left))
top = Math.max(0, Math.min(window.innerHeight - this.panelHeight, top))
this.panelLeft = left
this.panelTop = top
},
onDragEnd() {
this.isDragging = false
document.removeEventListener('mousemove', this.onDragMove)
document.removeEventListener('mouseup', this.onDragEnd)
this.savePosition()
}
}
}
</script>
<style scoped>
/* 透明遮罩、不阻挡地图 */
.k-time-set-dialog {
position: fixed;
inset: 0;
z-index: 1000;
background: transparent;
pointer-events: none;
}
/* 原 el-dialog 风格 */
.panel-container {
position: fixed;
background: white;
border-radius: 8px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
overflow: hidden;
z-index: 1001;
pointer-events: auto;
display: flex;
flex-direction: column;
}
.dialog-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 20px;
background-color: #f5f7fa;
border-bottom: 1px solid #ebeef5;
cursor: move;
}
.dialog-header h3 {
margin: 0;
font-size: 16px;
font-weight: 600;
color: #303133;
}
.close-btn {
font-size: 20px;
color: #909399;
cursor: pointer;
transition: color 0.3s;
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
}
.close-btn:hover {
color: #606266;
background: #f5f5f5;
border-radius: 50%;
}
.dialog-body {
padding: 20px 25px;
flex: 1;
overflow: hidden;
}
.dialog-footer {
display: flex;
justify-content: flex-end;
gap: 12px;
padding: 10px 0 0 0;
margin-top: 10px;
border-top: 1px solid #ebeef5;
}
</style>