Browse Source
# Conflicts: # ruoyi-ui/src/views/cesiumMap/index.vue # ruoyi-ui/src/views/childRoom/index.vuemaster
8 changed files with 1033 additions and 118 deletions
@ -0,0 +1,172 @@ |
|||
<template> |
|||
<el-dialog |
|||
title="选择图标" |
|||
:visible.sync="dialogVisible" |
|||
width="600px" |
|||
:modal="true" |
|||
:close-on-click-modal="false" |
|||
:close-on-press-escape="false" |
|||
class="icon-select-dialog" |
|||
> |
|||
<div class="icon-grid"> |
|||
<div |
|||
v-for="item in availableIcons" |
|||
:key="item.id" |
|||
class="icon-item" |
|||
:class="{ selected: selectedIcons.includes(item.id) }" |
|||
@click="toggleIcon(item)" |
|||
> |
|||
<i :class="item.icon"></i> |
|||
<span class="icon-name">{{ item.name }}</span> |
|||
<div v-if="selectedIcons.includes(item.id)" class="check-icon"> |
|||
<i class="el-icon-check"></i> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<span slot="footer" class="dialog-footer"> |
|||
<el-button @click="dialogVisible = false" size="small">取消</el-button> |
|||
<el-button type="primary" @click="confirmAdd" size="small">确定</el-button> |
|||
</span> |
|||
</el-dialog> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'IconSelectDialog', |
|||
props: { |
|||
visible: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
availableIcons: { |
|||
type: Array, |
|||
default: () => [] |
|||
}, |
|||
existingIcons: { |
|||
type: Array, |
|||
default: () => [] |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
selectedIcons: [] |
|||
} |
|||
}, |
|||
computed: { |
|||
dialogVisible: { |
|||
get() { |
|||
return this.visible |
|||
}, |
|||
set(val) { |
|||
this.$emit('update:visible', val) |
|||
} |
|||
} |
|||
}, |
|||
watch: { |
|||
visible(newVal) { |
|||
if (newVal) { |
|||
this.selectedIcons = [] |
|||
} |
|||
} |
|||
}, |
|||
methods: { |
|||
toggleIcon(item) { |
|||
const index = this.selectedIcons.indexOf(item.id) |
|||
if (index > -1) { |
|||
this.selectedIcons.splice(index, 1) |
|||
} else { |
|||
this.selectedIcons.push(item.id) |
|||
} |
|||
}, |
|||
|
|||
confirmAdd() { |
|||
const selectedItems = this.availableIcons.filter(item => |
|||
this.selectedIcons.includes(item.id) |
|||
) |
|||
this.$emit('confirm', selectedItems) |
|||
this.dialogVisible = false |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.icon-select-dialog >>> .el-dialog__body { |
|||
padding: 20px; |
|||
} |
|||
|
|||
.icon-grid { |
|||
display: grid; |
|||
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); |
|||
gap: 15px; |
|||
max-height: 400px; |
|||
overflow-y: auto; |
|||
} |
|||
|
|||
.icon-item { |
|||
display: flex; |
|||
flex-direction: column; |
|||
align-items: center; |
|||
justify-content: center; |
|||
padding: 15px 10px; |
|||
border: 2px solid #E4E7ED; |
|||
border-radius: 8px; |
|||
cursor: pointer; |
|||
transition: all 0.3s; |
|||
position: relative; |
|||
background: white; |
|||
} |
|||
|
|||
.icon-item:hover { |
|||
border-color: #008aff; |
|||
background: rgba(0, 138, 255, 0.05); |
|||
transform: translateY(-2px); |
|||
box-shadow: 0 4px 12px rgba(0, 138, 255, 0.15); |
|||
} |
|||
|
|||
.icon-item.selected { |
|||
border-color: #008aff; |
|||
background: rgba(0, 138, 255, 0.1); |
|||
} |
|||
|
|||
.icon-item i { |
|||
font-size: 28px; |
|||
color: #555; |
|||
margin-bottom: 8px; |
|||
transition: color 0.3s; |
|||
} |
|||
|
|||
.icon-item:hover i, |
|||
.icon-item.selected i { |
|||
color: #008aff; |
|||
} |
|||
|
|||
.icon-name { |
|||
font-size: 12px; |
|||
color: #606266; |
|||
text-align: center; |
|||
word-break: break-all; |
|||
} |
|||
|
|||
.check-icon { |
|||
position: absolute; |
|||
top: 5px; |
|||
right: 5px; |
|||
width: 20px; |
|||
height: 20px; |
|||
border: 2px solid #008aff; |
|||
border-radius: 50%; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
color: #008aff; |
|||
font-size: 12px; |
|||
} |
|||
|
|||
.dialog-footer { |
|||
display: flex; |
|||
justify-content: flex-end; |
|||
gap: 10px; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,197 @@ |
|||
<template> |
|||
<div v-if="value" class="page-layout-dialog"> |
|||
<div class="dialog-content"> |
|||
<div class="dialog-header"> |
|||
<h3>页面布局</h3> |
|||
<div class="close-btn" @click="closeDialog">×</div> |
|||
</div> |
|||
|
|||
<div class="dialog-body"> |
|||
<div class="position-options"> |
|||
<div |
|||
v-for="option in positionOptions" |
|||
:key="option.value" |
|||
class="position-option" |
|||
:class="{ active: selectedPosition === option.value }" |
|||
@click="selectPosition(option.value)" |
|||
> |
|||
<i :class="option.icon"></i> |
|||
<span>{{ option.label }}</span> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="dialog-footer"> |
|||
<el-button @click="closeDialog" size="small">取消</el-button> |
|||
<el-button type="primary" @click="saveLayout" size="small">确定</el-button> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'PageLayoutDialog', |
|||
props: { |
|||
value: { |
|||
type: Boolean, |
|||
default: false |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
selectedPosition: 'left', |
|||
positionOptions: [ |
|||
{ value: 'top', label: '顶部', icon: 'el-icon-top' }, |
|||
{ value: 'bottom', label: '底部', icon: 'el-icon-bottom' }, |
|||
{ value: 'left', label: '左侧', icon: 'el-icon-back' }, |
|||
{ value: 'right', label: '右侧', icon: 'el-icon-right' } |
|||
] |
|||
}; |
|||
}, |
|||
watch: { |
|||
value(newVal) { |
|||
if (newVal) { |
|||
this.selectedPosition = this.$parent.menuPosition || 'left'; |
|||
} |
|||
} |
|||
}, |
|||
methods: { |
|||
selectPosition(position) { |
|||
this.selectedPosition = position; |
|||
}, |
|||
closeDialog() { |
|||
this.$emit('input', false); |
|||
}, |
|||
saveLayout() { |
|||
this.$emit('save', this.selectedPosition); |
|||
this.closeDialog(); |
|||
} |
|||
} |
|||
}; |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.page-layout-dialog { |
|||
position: fixed; |
|||
top: 0; |
|||
left: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
z-index: 1000; |
|||
display: flex; |
|||
align-items: flex-start; |
|||
justify-content: center; |
|||
padding-top: 100px; |
|||
pointer-events: none; |
|||
} |
|||
|
|||
.dialog-content { |
|||
position: relative; |
|||
background: white; |
|||
border-radius: 8px; |
|||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); |
|||
width: 300px; |
|||
animation: dialog-fade-in 0.3s ease; |
|||
pointer-events: auto; |
|||
} |
|||
|
|||
@keyframes dialog-fade-in { |
|||
from { |
|||
opacity: 0; |
|||
transform: translateY(-20px); |
|||
} |
|||
to { |
|||
opacity: 1; |
|||
transform: translateY(0); |
|||
} |
|||
} |
|||
|
|||
.dialog-header { |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: space-between; |
|||
padding: 12px 16px; |
|||
border-bottom: 1px solid #e8e8e8; |
|||
} |
|||
|
|||
.dialog-header h3 { |
|||
margin: 0; |
|||
font-size: 14px; |
|||
font-weight: 600; |
|||
color: #333; |
|||
} |
|||
|
|||
.close-btn { |
|||
font-size: 18px; |
|||
color: #999; |
|||
cursor: pointer; |
|||
transition: color 0.3s; |
|||
line-height: 1; |
|||
} |
|||
|
|||
.close-btn:hover { |
|||
color: #666; |
|||
} |
|||
|
|||
.dialog-body { |
|||
padding: 16px; |
|||
} |
|||
|
|||
.position-options { |
|||
display: grid; |
|||
grid-template-columns: repeat(2, 1fr); |
|||
gap: 10px; |
|||
} |
|||
|
|||
.position-option { |
|||
display: flex; |
|||
flex-direction: column; |
|||
align-items: center; |
|||
justify-content: center; |
|||
padding: 15px 10px; |
|||
border: 1px solid #e8e8e8; |
|||
border-radius: 6px; |
|||
cursor: pointer; |
|||
transition: all 0.3s; |
|||
background: white; |
|||
} |
|||
|
|||
.position-option:hover { |
|||
border-color: #008aff; |
|||
background: rgba(0, 138, 255, 0.05); |
|||
transform: translateY(-2px); |
|||
box-shadow: 0 2px 8px rgba(0, 138, 255, 0.15); |
|||
} |
|||
|
|||
.position-option.active { |
|||
border-color: #008aff; |
|||
background: rgba(0, 138, 255, 0.1); |
|||
} |
|||
|
|||
.position-option i { |
|||
font-size: 24px; |
|||
color: #555; |
|||
margin-bottom: 6px; |
|||
transition: color 0.3s; |
|||
} |
|||
|
|||
.position-option:hover i, |
|||
.position-option.active i { |
|||
color: #008aff; |
|||
} |
|||
|
|||
.position-option span { |
|||
font-size: 13px; |
|||
color: #606266; |
|||
} |
|||
|
|||
.dialog-footer { |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: flex-end; |
|||
padding: 12px 16px; |
|||
border-top: 1px solid #e8e8e8; |
|||
gap: 8px; |
|||
} |
|||
</style> |
|||
Loading…
Reference in new issue