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.
209 lines
5.5 KiB
209 lines
5.5 KiB
<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>
|
|
|