Files
energy_storage/web/src/components/DetailInfo.vue

716 lines
22 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- item.type:xxxx-unshow:表示不显示 items.displayFlag为false表示不展示卡片 -->
<template>
<div class="card-content">
<a-card style="margin: 0 0 15px 0; text-align: left">
<div :class="['info-title', items.title ? '' : 'title-none']">
<div class="box">
<div>
{{ items.title ? items.title : '基础信息' }}
</div>
<a-tooltip
placement="bottomLeft"
trigger="['hover','click']"
:overlay-style="{ color: '#ccc' }"
v-if="items.tooltip && items.tooltip !== ''"
>
<template #title>
<!-- -->
<span v-html="items.tooltip"></span>
</template>
<ExclamationCircleOutlined
:style="{
fontSize: '18px',
color: 'var(--theme-text3)',
cursor: 'pointer',
position: 'relative',
top: '0',
left: '15px'
}"
/>
</a-tooltip>
</div>
</div>
<div class="info-content">
<a-form
layout="horizontal"
:wrap="true"
ref="formRef"
:rules="props.formRules"
name="info-form"
class="info-form"
label-align="left"
:model="propsInfo.ruleForm.value"
@submit="handleSubmit"
@onFieldsChange="onFieldsChange"
>
<template v-for="item in items.list">
<div
v-if="item.type !== 'unshow'"
:key="item.key"
:class="item.className ? [item.className, 'item-div'] : 'item-div'"
>
<a-form-item
:label="item.label"
:name="item.key"
:class="[item.colStatus || item.type === 'table' ? 'item-width' : 'form-item']"
:tooltip="item.tooltip ? item.tooltip : ''"
>
<a-input-password
v-if="item.type === 'input-password'"
v-model:value="propsInfo.ruleForm.value[item.key]"
:placeholder="'请输入' + item.label"
:disabled="!props.disabled && type ? !!item.disabled : props.disabled"
/>
<a-input
v-if="item.type === 'input'"
v-model:value="propsInfo.ruleForm.value[item.key]"
:type="item.inputType"
:placeholder="'请输入' + item.label"
:disabled="!props.disabled && type ? !!item.disabled : props.disabled"
/>
<a-input-number
v-if="item.type == 'input-number'"
id="inputNumber"
v-model:value="propsInfo.ruleForm.value[item.key]"
:min="item.min || 0"
:max="item.max || 10000000"
:formatter="item.formatter || null"
:addon-before="item.addonBefore"
:disabled="props.disabled"
/>
<a-date-picker
v-if="item.type === 'date-picker'"
v-model:value="propsInfo.ruleForm.value[item.key]"
:placeholder="'请输入' + item.label"
:disabled="props.disabled"
value-format="YYYY-MM-DD"
/>
<a-date-picker
show-time
v-if="item.type === 'time'"
value-format="YYYY-MM-DD HH:mm:ss"
:disabled="props.disabled"
v-model:value="propsInfo.ruleForm.value[item.key]"
:placeholder="'请输入' + item.label"
/>
<a-range-picker
v-if="item.type === 'date-time'"
v-model:value="propsInfo.ruleForm.value[item.key]"
value-format="YYYY-MM-DD HH:mm:ss"
:disabled="props.disabled"
show-time
/>
<a-time-range-picker
v-if="item.type === 'timeRangePicker'"
v-model:value="propsInfo.ruleForm.value[item.key]"
value-format="HH:mm"
format="HH:mm"
:disabled="props.disabled"
/>
<a-time-picker
v-if="item.type === 'timePicker'"
v-model:value="propsInfo.ruleForm.value[item.key]"
value-format="HH:mm"
format="HH:mm"
:disabled="props.disabled"
/>
<a-textarea
v-if="item.type === 'textarea'"
v-model:value="propsInfo.ruleForm.value[item.key]"
:placeholder="'请输入' + item.label"
allow-clear
:disabled="!props.disabled && type ? !!item.disabled : props.disabled"
:auto-size="item.autoSize ? item.autoSize : { minRows: 3, maxRows: 10 }"
/>
<a-select
:dropdown-match-select-width="false"
v-if="item.type === 'select'"
v-model:value="propsInfo.ruleForm.value[item.key]"
:placeholder="'请选择' + item.label"
:disabled="!props.disabled && type ? !!item.disabled : props.disabled"
allow-clear
>
<template v-if="item.options">
<a-select-option
:value="selectItem[item.options.value]"
v-for="selectItem in item.list"
:key="selectItem[item.options.value]"
>
{{ selectItem[item.options.label] }}
</a-select-option>
</template>
<template v-else>
<a-select-option
:value="selectItem.value"
v-for="selectItem in item.list"
:key="selectItem.value"
>
{{ selectItem.label }}
</a-select-option>
</template>
</a-select>
<!-- 下拉多选 -->
<a-select
:dropdown-match-select-width="false"
v-if="item.type === 'selectMultiple'"
mode="multiple"
v-model:value="propsInfo.ruleForm.value[item.key]"
:placeholder="'请选择' + item.label"
:disabled="!props.disabled && type ? !!item.disabled : props.disabled"
allow-clear
>
<a-select-option
:value="selectItem.value"
v-for="selectItem in item.list"
:key="selectItem.value"
>
{{ selectItem.label }}
</a-select-option>
</a-select>
<!-- 新增时disabled -->
<a-select
:dropdown-match-select-width="false"
v-if="item.type === 'select-disabled'"
v-model:value="propsInfo.ruleForm.value[item.key]"
:placeholder="'请选择' + item.label"
:disabled="!props.disabled ? item.disabled : props.disabled"
allow-clear
>
<a-select-option
:value="selectItem.value"
v-for="selectItem in item.list"
:key="selectItem.value"
>
{{ selectItem.label }}
</a-select-option>
</a-select>
<!-- 下拉展示icon -->
<a-select
v-if="item.type === 'icon-select'"
:get-popup-container="(triggerNode) => triggerNode.parentNode"
v-model:value="propsInfo.ruleForm.value[item.key]"
allow-clear
option-label-prop="children"
>
<a-select-option
v-for="icon in iconList"
:key="icon.icon_id"
:value="`icon-${icon.font_class}`"
>
<i
class="iconfont"
:class="`icon-${icon.font_class}`"
style="margin-right: 8px"
></i>
<span> {{ icon.name }} </span>
</a-select-option>
</a-select>
<a-switch
v-if="item.type === 'switch'"
v-model:checked="propsInfo.ruleForm.value[item.key]"
style="margin-bottom: 5px"
:disabled="!props.disabled && type ? !!item.disabled : props.disabled"
/>
<a-radio-group
name="radioGroup"
v-model:value="propsInfo.ruleForm.value[item.key]"
v-if="item.type === 'radio'"
:disabled="props.disabled"
>
<a-radio
:value="radioItem.value"
v-for="radioItem in item.list"
:key="radioItem.value"
>
{{ radioItem.label }}
</a-radio>
</a-radio-group>
<a-tree-select
:disabled="props.disabled"
v-model:value="propsInfo.ruleForm.value[item.key]"
v-if="item.type === 'tree-radio'"
style="width: 100%"
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
:tree-data="item.list"
:placeholder="'请选择' + item.label"
:field-names="
item.replaceFields
? item.replaceFields
: {
children: 'children',
title: 'title',
key: 'key',
value: 'value'
}
"
/>
<a-tree-select
:allow-clear="true"
:disabled="props.disabled"
v-if="item.type === 'tree-check'"
v-model:value="propsInfo.ruleForm.value[item.key]"
style="width: 100%"
:tree-data="item.list"
:tree-checkable="true"
:show-checked-strategy="SHOW_PARENT"
:placeholder="'请选择' + item.label"
:field-names="
item.replaceFields
? item.replaceFields
: {
children: 'children',
title: 'title',
key: 'key',
value: 'value'
}
"
:check="checkTree"
/>
<a-tree-select
:disabled="props.disabled"
v-if="item.type === 'tree-check-org'"
v-model:value="propsInfo.ruleForm.value[item.key]"
style="width: 100%"
:tree-data="item.list"
allow-clear
multiple
tree-default-expand-all
:placeholder="'请选择' + item.label"
:field-names="
item.replaceFields
? item.replaceFields
: {
children: 'children',
title: 'title',
key: 'key',
value: 'value'
}
"
:check="checkTree"
/>
<a-cascader
:disabled="props.disabled"
v-if="item.type === 'cascader'"
:options="item.list"
:field-names="
item.fieldNames
? item.fieldNames
: { label: 'label', value: 'value', children: 'children' }
"
:show-search="{ filter }"
:placeholder="'请选择' + item.label"
v-model:value="propsInfo.ruleForm.value[item.key]"
change-on-select
>
</a-cascader>
<a-checkbox
v-if="item.type === 'checkbox'"
v-model:checked="propsInfo.ruleForm.value[item.key]"
>
</a-checkbox>
<div v-if="item.type === 'tag'" class="table-css">
<a-tag :color="propsInfo.ruleForm.value[item.key] ? 'green' : 'red'">
{{ item.list[propsInfo.ruleForm.value[item.key]] }}
</a-tag>
</div>
<!-- </a-col>-->
<!-- <a-button v-if="item.type === 'btn'" @click="btnClick(item)">{{ item.title }}</a-button> -->
<div v-if="item.type === 'table'" class="table-css">
<slot :name="item.type" v-bind="item"></slot>
</div>
<div v-if="item.type === 'treetable'" class="table-css">
<slot :name="item.type" v-bind="item"></slot>
</div>
<div v-if="item.type === 'slot'">
<slot
:name="item.slotName"
v-bind="{ ...item, ...propsInfo.ruleForm.value }"
></slot>
</div>
</a-form-item>
</div>
</template>
<!-- <a-form-item
v-for="item in items.list"
:key="item.key"
:label="item.label"
:name="item.key"
:class="[item.colStatus ? 'item-width' : 'form-item']"
> -->
</a-form>
</div>
</a-card>
</div>
</template>
<script setup>
import { UserOutlined, InfoCircleOutlined, ExclamationCircleOutlined } from '@ant-design/icons-vue'
import {
ref,
reactive,
defineProps,
defineEmits,
watch,
toRefs,
onMounted,
defineExpose
} from 'vue'
import iconfonts from '../assets/iconfont/iconfont.json'
import validateRulesObj from '../utils/decorator'
const iconList = iconfonts.glyphs
const formRef = ref()
const props = defineProps({
items: {
type: Object,
required: () => []
},
formRules: {
type: Object
},
ruleForm: {
type: Object
},
disabled: {
type: Boolean
},
type: {
type: Boolean,
default: false
}
})
const propsInfo = toRefs(props)
const exposeRuleForm = propsInfo.ruleForm.value
onMounted(() => {})
const emit = defineEmits(['handlerClick'])
const data = reactive({
validateRulesObj,
newRuleForm: {},
// : {},
key: 0,
tableIndex: null,
tableInfo: [],
// tableIndex: 0,
mockData: [{}],
targetKeys: [],
// 单选-树节点
treeRadioValue: null,
treeData: [
{ id: 1, pId: 0, value: '1', title: 'Expand to load' },
{ id: 2, pId: 0, value: '2', title: 'Expand to load' },
{ id: 3, pId: 0, value: '3', title: 'Tree Node', isLeaf: true }
],
treeCheckValue: null,
// SHOW_PARENT: TreeSelect.SHOW_PARENT,
loading: false,
imageUrl: ''
})
const extraInformation = ref(
'Cron表达式由6个(或7个)字段组成,分别表示秒、分、小时、月中的日期、月份、星期中的日期(以及可选的年份)。每个字段可以包含以下字符:·星号(*):表示该字段可以接受任何值、·问号(?):通常用于""星期”字段,表示不指定值,即表示“无特定值”。·连字符(-):用于指定范围,如"10-12表示101112·逗号():用于指定多个值MON,WED,FRI表示星期一星期三和星期五·斜杠(/):0/15015·L:""()W:()15W15#:6#3Cron:"0012**?12'
)
watch(
() => props.formRules,
(nVal, o) => {
for (const key in nVal) {
nVal[key].forEach((item) => {
if (item.validatorType) {
item.validator = data.validateRulesObj[item.validatorType]?.rules[0].validator
}
})
}
},
{ deep: true, immediate: true }
)
function checkTree(checkedKeys, e) {}
// 按钮的点击事件
function btnClick(item) {
emit('handlerClick', item)
}
function confirm() {
return new Promise((resolve, reject) => {
if (formRef.value) {
formRef.value
.validate()
.then(() => {
resolve(true)
})
.catch((error) => {
resolve(false)
})
}
})
}
function handleReset() {
if (formRef.value) {
formRef.value.resetFields()
}
}
function switchChange(checked, switchItem) {
propsInfo.ruleForm.value[switchItem.key] = checked
}
function RadioChange(e, radioItem) {
const { value } = e.target
propsInfo.ruleForm.value[radioItem.key] = value
}
function transferChange(targetKeys, transferItem) {
data.targetKeys = targetKeys
propsInfo.ruleForm.value[transferItem.key] = data.targetKeys
}
function transferSearch(dir, value) {}
// 单选-树节点
function genTreeNode(parentId, isLeaf = false) {
const random = Math.random().toString(36).substring(2, 6)
return {
id: random,
pId: parentId,
value: random,
title: isLeaf ? 'Tree Node' : 'Expand to load',
isLeaf
}
}
function onLoadTree(treeNode) {
return new Promise((resolve) => {
const { id } = treeNode.dataRef
setTimeout(() => {
data.treeData = data.treeData.concat([
data.genTreeNode(id, false),
data.genTreeNode(id, true)
])
resolve()
}, 300)
})
}
function treeChange(key, value, node, extra) {
propsInfo.ruleForm.value[key] = value
}
// 级联选择器
function cascaderChange(value, cascaderItem) {
propsInfo.ruleForm.value[cascaderItem.key] = value
}
function filter(inputValue, path) {
return path.some((option) => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1)
}
function getBase64(img, callback) {
const reader = new FileReader()
reader.addEventListener('load', () => callback(reader.result))
reader.readAsDataURL(img)
}
function avatarUploadChange(info) {
if (info.file.status === 'uploading') {
data.loading = true
return
}
if (info.file.status === 'done') {
getBase64(info.file.originFileObj, (imageUrl) => {
data.imageUrl = imageUrl
data.loading = false
})
}
}
function onFieldsChange() {}
function handleSubmit() {}
// 主动暴露方法
defineExpose({
confirm,
handleReset,
ruleForm: exposeRuleForm
})
</script>
<style lang="scss" scoped>
.allHeight {
height: 100%;
}
.card-content:first-child {
margin-top: 0px;
}
.card-content {
margin-top: 15px;
}
:deep(.ant-timeline) {
color: var(--theme-text-default) !important;
.ant-timeline-item-tail {
border-inline-start: 2px solid var(--theme-text-default) !important;
}
}
:deep(.ant-form-item .ant-form-item-label > label) {
color: var(--theme-text-default) !important;
}
.info-title {
font-size: 18px;
font-weight: 530;
color: var(--theme-text-default);
text-align: left;
border-bottom: 1.5px solid var(--theme-bg);
margin-bottom: 20px;
.box {
color: #fff;
width: 230px;
display: flex;
align-items: center;
margin-bottom: 10px;
border-bottom: 5px solid transparent;
border-image: url('../assets/boxBottom.png') 0 0 100% 0 stretch;
div:last-child {
height: 25px;
line-height: 25px;
}
}
:deep(.a-tooltip) {
color: var(--theme-text3);
}
:deep(.ant-divider) {
color: var(--theme-bg);
}
}
// :deep(.ant-table-wrapper) {
// :deep(.ant-input) {
// background: red !important;
// }
// }
.title-none {
display: none;
}
:deep(.ant-card) {
background-color: transparent;
}
:deep(.ant-card-body) {
padding: 15px;
height: 100%;
border-radius: 8px;
.ant-form {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
height: 100%;
.item-l,
.item-div {
height: 100%;
}
}
}
.ant-card-bordered {
border: none;
}
.info-content {
height: calc(100% - 30px);
.info-form {
.item-div {
width: 45%;
display: inline-block;
}
.item-l {
width: 100%;
}
.form-item {
// width: 320px !important;
}
}
}
:deep(.ant-form-item-label) {
color: #fff;
font-size: 16px !important;
width: 100px;
}
:deep(.ant-form-item-control-wrapper) {
flex: 1;
}
.editable-row-operations a {
margin-right: 8px;
}
// 表格中的按钮
:deep(.ant-table-cell) {
.ant-btn {
height: 24px !important;
color: #fff;
}
.ant-btn-dangerous {
background: var(--theme-btn2) !important;
}
.btn-del {
background: var(--theme-btn2);
}
.btn-add {
background: var(--theme-btn3);
}
.btn-upload,
.btn-downTemplate {
background: var(--theme-btn1);
}
}
:deep(.ant-calendar-picker) {
width: 100% !important;
}
:deep(.ant-picker) {
width: 100% !important;
}
:deep(.ant-input-number) {
width: 100% !important;
}
:deep(.ant-form-item.form-item) {
padding: 0px !important;
padding-right: 20px !important;
}
:deep(.ant-checkbox-disabled + span) {
color: var(--theme-text-default) !important;
}
:deep(textarea.ant-input) {
background-color: var(--theme-bg) !important;
border: none !important;
color: var(--theme-text-default) !important;
}
:deep(.ant-input-clear-icon){
color: #fff;
}
:deep(.ant-select .ant-select-clear,.ant-select-clear:hover){
color: #fff;
background: none !important;
}
:deep(.ant-checkbox-wrapper) {
color: var(--theme-text-default);
}
</style>