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.
 
 
 

302 lines
8.2 KiB

<script setup lang="ts">
import { computed, reactive } from "vue";
import { ElButton, ElDivider, ElFormItem, ElIcon, ElInputNumber, useFormItem } from "element-plus";
import { CopyDocument, Delete } from "@element-plus/icons-vue";
import { Typeof } from "@ease-forge/shared";
defineOptions({
name: 'BayEditor',
});
interface DtBay {
/** 列的宽度 */
bayWidth: number;
/** 列偏移 */
offset: number;
/** 每层的高度 */
levelHeight: Array<number>;
}
type DtBays = Array<DtBay>;
// 组件事件定义
const emit = defineEmits<{
/** 更新内联表格数据 */
"update:modelValue": [value: DtBays];
}>();
// 定义 Props 类型
interface BayEditorProps {
modelValue: DtBays;
}
// 读取组件 props 属性
const props = withDefaults(defineProps<BayEditorProps>(), {});
// 定义 State 类型
interface BayEditorState {
numberOfBays: number;
numberOfLevels: number;
widthOfBays: number;
heightOfLevels: number;
selectIdx?: number;
}
// state 属性
const state = reactive<BayEditorState>({
numberOfBays: props.modelValue?.length ?? 1,
numberOfLevels: props.modelValue?.[0]?.levelHeight?.length ?? 1,
widthOfBays: props.modelValue?.[0]?.bayWidth ?? 1,
heightOfLevels: props.modelValue?.[0]?.levelHeight?.length ?? 1,
});
// 定义 Data 类型
interface BayEditorData {
labelWidth: number;
}
// 内部数据
const data: BayEditorData = {
labelWidth: 110,
};
const { formItem } = useFormItem();
const list = computed(() => props.modelValue ?? []);
const selectDay = computed(() => {
if (Typeof.noValue(state.selectIdx)) return;
return props.modelValue?.[state.selectIdx];
});
function setSelectIdx(idx: number) {
state.selectIdx = idx;
}
function applyBasicSettings() {
}
function deleteBay() {
}
function copyBay() {
}
interface BayEditorExpose {
state: BayEditorState;
data: BayEditorData;
}
const expose: BayEditorExpose = {
state,
data,
};
// 定义组件公开内容
defineExpose(expose);
export type {
BayEditorProps,
BayEditorState,
}
</script>
<template>
<div class="bay-editor">
<ElDivider class="bay-editor-title" contentPosition="left">Basic</ElDivider>
<div class="flex-column-container bay-editor-basic" style="gap: 8px;">
<div class="flex-row-container">
<ElFormItem label="Number of Bays" :labelWidth="data.labelWidth">
<ElInputNumber :controls="false" v-model="state.numberOfBays"/>
</ElFormItem>
<ElFormItem label="Number of Levels" :labelWidth="data.labelWidth">
<ElInputNumber :controls="false" v-model="state.numberOfLevels"/>
</ElFormItem>
</div>
<div class="flex-row-container">
<ElFormItem label="Width of Bays" :labelWidth="data.labelWidth">
<ElInputNumber :controls="false" v-model="state.widthOfBays"/>
</ElFormItem>
<ElFormItem label="Height of Levels" :labelWidth="data.labelWidth">
<ElInputNumber :controls="false" v-model="state.heightOfLevels"/>
</ElFormItem>
</div>
<div class="flex-row-container">
<div style="width: 248px;"/>
<ElButton size="small" @click="applyBasicSettings">Apply Basic Settings</ElButton>
</div>
</div>
<ElDivider class="bay-editor-title" contentPosition="left">Advanced</ElDivider>
<div class="flex-row-container bay-editor-advanced">
<div class="flex-item-fixed flex-column-container bay-editor-bay-list">
<div class="flex-item-fixed tools-button-container">
<ElIcon :class="['tools-button-icon', { 'tools-button-disabled': false }]" @click="copyBay">
<CopyDocument/>
</ElIcon>
<ElIcon :class="['tools-button-icon', { 'tools-button-disabled': false }]" @click="deleteBay">
<Delete/>
</ElIcon>
</div>
<div class="flex-item-fill bay-editor-bay-list-name">
<div
v-for="(item, idx) in list"
:class="[
'list-item',
{
'list-item-select': state.selectIdx === idx,
},
]"
@click="setSelectIdx(idx)"
>
{{ `Bay ${idx + 1}` }}
</div>
</div>
</div>
<div class="flex-item-fill flex-column-container bay-editor-bay-info">
<template v-if="selectDay">
<div class="flex-item-fixed">
<ElFormItem label="Bay Width" :labelWidth="80">
<ElInputNumber :controls="false" :modelValue="selectDay.bayWidth"/>
</ElFormItem>
<div style="height: 8px;"/>
<ElFormItem label="Bay Offset" :labelWidth="80">
<ElInputNumber :controls="false" :modelValue="selectDay.offset"/>
</ElFormItem>
</div>
<div>Level Heights</div>
<div class="flex-item-fill bay-editor-bay-info-level-height">
<ElFormItem
v-for="(levelHeight, idx) in selectDay.levelHeight"
:label="`Level ${idx+1}`"
:labelWidth="64"
>
<ElInputNumber :controls="false" :modelValue="levelHeight"/>
</ElFormItem>
</div>
</template>
</div>
</div>
</div>
</template>
<style scoped>
.bay-editor {
width: 100%;
}
.bay-editor-title {
height: 12px;
user-select: none;
}
.bay-editor-basic :deep(.el-input-number) {
width: 80px;
}
.bay-editor-advanced {
height: 256px;
}
.bay-editor-bay-list {
width: 72px;
}
.bay-editor-bay-list-name {
border: 1px solid #dddddd;
}
.tools-button-container {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
justify-content: center;
gap: 4px;
cursor: pointer;
width: 100%;
}
.tools-button-container > .tools-button-icon {
color: #8c8c8c;
padding: 4px;
font-size: 22px;
border-radius: 2px;
}
.tools-button-container > .tools-button-icon:hover {
color: #595959;
background-color: #d9d9d9;
}
.tools-button-container > .tools-button-icon:active {
color: #434343;
background-color: #bfbfbf;
}
.tools-button-container > .tools-button-disabled {
cursor: not-allowed;
}
.tools-button-container > .tools-button-disabled.tools-button-icon,
.tools-button-container > .tools-button-disabled.tools-button-icon:hover,
.tools-button-container > .tools-button-disabled.tools-button-icon:active {
color: #d9d9d9;
background-color: unset;
pointer-events: none;
}
.list-item {
padding: 4px 0 4px 2px;
cursor: pointer;
border-bottom: 1px solid #f0f0f0;
user-select: none;
color: #262626;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.list-item:hover {
background-color: #f0f0f0;
}
.list-item:active {
background-color: #dddddd;
}
.list-item.list-item-select,
.list-item.list-item-select:hover,
.list-item.list-item-select:active {
background-color: #d9d9d9;
}
.bay-editor-bay-info {
padding-left: 6px;
}
.bay-editor-bay-info-level-height {
border: 1px solid #dddddd;
}
.bay-editor-bay-info-level-height :deep(.el-input__wrapper) {
border: none;
outline: none;
box-shadow: none;
}
.bay-editor-bay-info-level-height :deep(.el-form-item) {
border-bottom: 1px solid #dddddd;
}
.bay-editor-bay-info-level-height :deep(.el-form-item > .el-form-item__label) {
border-right: 1px solid #dddddd;
}
.bay-editor-bay-info-level-height :deep(.el-input-number) {
width: 100%;
}
.bay-editor-bay-info-level-height :deep(input[type=number].el-input__inner) {
text-align: left;
}
</style>