字典类型管理+字典数据管理
This commit is contained in:
@@ -201,6 +201,55 @@
|
||||
</template>
|
||||
</el-drawer>
|
||||
|
||||
<!-- 下拉框选项配置对话框 -->
|
||||
<el-dialog
|
||||
v-model="selectOptionsDialogVisible"
|
||||
:title="`[${currentSelectParam?.paramName || ''}]下拉框选项列表配置`"
|
||||
width="600px"
|
||||
:before-close="handleSelectOptionsDialogClose"
|
||||
>
|
||||
<div class="select-options-container">
|
||||
<!-- 输入区域 -->
|
||||
<div class="select-options-input-area">
|
||||
<span class="input-label">选项数据:</span>
|
||||
<el-input
|
||||
v-model="selectOptionInput"
|
||||
placeholder="请输入选项数据"
|
||||
clearable
|
||||
style="flex: 1; margin-right: 8px"
|
||||
@keyup.enter="handleAddSelectOption"
|
||||
/>
|
||||
<el-button type="primary" @click="handleAddSelectOption">添加</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 选项卡片列表 -->
|
||||
<div class="select-options-cards">
|
||||
<div
|
||||
v-for="option in selectOptionsList"
|
||||
:key="option.id"
|
||||
class="select-option-card"
|
||||
>
|
||||
<span class="option-text">{{ option.dicValue }}</span>
|
||||
<el-icon
|
||||
class="option-delete-icon"
|
||||
@click="handleDeleteSelectOption(option)"
|
||||
>
|
||||
<Close />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div v-if="selectOptionsList.length === 0" class="empty-tip">
|
||||
暂无选项数据,请添加
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="handleSelectOptionsDialogClose">取消</el-button>
|
||||
<el-button type="primary" @click="handleSaveSelectOptions">保存</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 参数配置对话框 -->
|
||||
<el-dialog
|
||||
v-model="paramDialogVisible"
|
||||
@@ -276,7 +325,7 @@
|
||||
</el-table-column>
|
||||
|
||||
<!-- 表单控件 -->
|
||||
<el-table-column label="表单控件" min-width="120">
|
||||
<el-table-column label="表单控件" min-width="120" align="left">
|
||||
<template #default="{ row }">
|
||||
<el-select
|
||||
v-if="row.isEditing"
|
||||
@@ -292,7 +341,17 @@
|
||||
:value="form.value"
|
||||
/>
|
||||
</el-select>
|
||||
<span v-else>{{ row.formType || '暂无' }}</span>
|
||||
<el-button
|
||||
v-else-if="row.formType === 'select'"
|
||||
type="success"
|
||||
size="small"
|
||||
link
|
||||
class="form-type-select-btn"
|
||||
@click="handleConfigSelectOptions(row)"
|
||||
>
|
||||
下拉框
|
||||
</el-button>
|
||||
<span v-else>{{ getFormTypeLabel(row.formType) || '暂无' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
@@ -353,7 +412,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { Plus, Edit, Delete, Setting, Check } from '@element-plus/icons-vue'
|
||||
import { Plus, Edit, Delete, Setting, Check, Close } from '@element-plus/icons-vue'
|
||||
import {
|
||||
devInfoadd,
|
||||
devInfodel,
|
||||
@@ -369,6 +428,8 @@ import {
|
||||
devparamlist,
|
||||
devparambyid,
|
||||
} from '@/api/tb/devparam'
|
||||
import { dictypeadd, dictypelist } from '@/api/system/dictype'
|
||||
import { dicdataadd, dicdatadel, dicdatabydicid } from '@/api/system/dicdata'
|
||||
|
||||
// 加载状态
|
||||
const loading = ref(false)
|
||||
@@ -769,6 +830,12 @@ const getParamIndex = (index: number) => {
|
||||
return (paramPagination.pageNum - 1) * paramPagination.pageSize + index + 1
|
||||
}
|
||||
|
||||
// 获取表单控件标签
|
||||
const getFormTypeLabel = (formType: string) => {
|
||||
const option = formTypeOptions.find((item) => item.value === formType)
|
||||
return option ? option.label : formType
|
||||
}
|
||||
|
||||
// 打开参数配置对话框
|
||||
const handleConfigParams = async (row: any) => {
|
||||
currentDevice.value = row
|
||||
@@ -935,6 +1002,37 @@ const handleSaveParam = async (row: any) => {
|
||||
if (wasNew) {
|
||||
await getParamList()
|
||||
}
|
||||
|
||||
// 如果表单控件是下拉框,检查是否已配置过选项,只有未配置时才弹出配置对话框
|
||||
if (row.formType === 'select') {
|
||||
// 查找对应的字典类型
|
||||
const dicTypeListRes: any = await dictypelist({
|
||||
pageNum: 1,
|
||||
pageSize: 1000,
|
||||
})
|
||||
|
||||
const dicTypeData = dicTypeListRes?.data ?? dicTypeListRes ?? {}
|
||||
const dicTypeRecords = dicTypeData.records || dicTypeData.list || dicTypeData.rows || []
|
||||
|
||||
const dicType = dicTypeRecords.find(
|
||||
(item: any) => item.dicName === row.paramName
|
||||
)
|
||||
|
||||
if (dicType) {
|
||||
// 检查是否已有选项数据
|
||||
const optionsRes: any = await dicdatabydicid(dicType.id)
|
||||
const optionsData = optionsRes?.data ?? optionsRes ?? {}
|
||||
const optionsRecords = Array.isArray(optionsData) ? optionsData : (optionsData.records || optionsData.list || optionsData.rows || [])
|
||||
|
||||
// 只有没有选项数据时才弹出配置对话框
|
||||
if (optionsRecords.length === 0) {
|
||||
await handleCreateDicTypeAndShowConfig(row)
|
||||
}
|
||||
} else {
|
||||
// 如果字典类型不存在,创建并弹出配置对话框
|
||||
await handleCreateDicTypeAndShowConfig(row)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ElMessage.error(res?.message || res?.msg || (row.isNew ? '新增失败' : '更新失败'))
|
||||
}
|
||||
@@ -946,6 +1044,87 @@ const handleSaveParam = async (row: any) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 创建字典类型并显示配置对话框
|
||||
const handleCreateDicTypeAndShowConfig = async (row: any) => {
|
||||
try {
|
||||
// 检查是否已存在该字典类型
|
||||
const dicTypeListRes: any = await dictypelist({
|
||||
pageNum: 1,
|
||||
pageSize: 1000,
|
||||
})
|
||||
|
||||
const dicTypeData = dicTypeListRes?.data ?? dicTypeListRes ?? {}
|
||||
const dicTypeRecords = dicTypeData.records || dicTypeData.list || dicTypeData.rows || []
|
||||
|
||||
// 查找是否已存在相同名称的字典类型
|
||||
const existingDicType = dicTypeRecords.find(
|
||||
(item: any) => item.dicName === row.paramName
|
||||
)
|
||||
|
||||
let dicTypeId: number | undefined
|
||||
|
||||
if (existingDicType) {
|
||||
// 如果已存在,使用现有的ID
|
||||
dicTypeId = existingDicType.id
|
||||
} else {
|
||||
// 如果不存在,创建新的字典类型
|
||||
const dicTypeRes: any = await dictypeadd({
|
||||
dicName: row.paramName,
|
||||
})
|
||||
|
||||
if (dicTypeRes?.code === '0' || dicTypeRes?.code === 0 || dicTypeRes?.success) {
|
||||
// 获取新创建的字典类型ID
|
||||
const newDicTypeData = dicTypeRes?.data ?? dicTypeRes ?? {}
|
||||
dicTypeId = newDicTypeData.id
|
||||
|
||||
// 如果返回的数据中没有ID,重新查询
|
||||
if (!dicTypeId) {
|
||||
const refreshListRes: any = await dictypelist({
|
||||
pageNum: 1,
|
||||
pageSize: 1000,
|
||||
})
|
||||
const refreshData = refreshListRes?.data ?? refreshListRes ?? {}
|
||||
const refreshRecords = refreshData.records || refreshData.list || refreshData.rows || []
|
||||
const newDicType = refreshRecords.find(
|
||||
(item: any) => item.dicName === row.paramName
|
||||
)
|
||||
dicTypeId = newDicType?.id
|
||||
}
|
||||
} else {
|
||||
ElMessage.error('创建字典类型失败')
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 打开配置对话框
|
||||
if (dicTypeId) {
|
||||
// 先加载选项列表,检查是否已有选项数据
|
||||
await loadSelectOptions(dicTypeId)
|
||||
|
||||
// 如果还没有选项数据,才弹出提示
|
||||
if (selectOptionsList.value.length === 0) {
|
||||
await ElMessageBox.alert('请编辑下拉框选项列表内容', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
type: 'info',
|
||||
})
|
||||
}
|
||||
|
||||
currentSelectParam.value = {
|
||||
...row,
|
||||
dicTypeId: dicTypeId,
|
||||
}
|
||||
selectOptionsDialogVisible.value = true
|
||||
} else {
|
||||
ElMessage.error('无法获取字典类型ID')
|
||||
}
|
||||
} catch (error: any) {
|
||||
if (error !== 'cancel') {
|
||||
console.error('创建字典类型失败:', error)
|
||||
ElMessage.error('创建字典类型失败')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 删除参数
|
||||
const handleDeleteParam = async (row: any) => {
|
||||
try {
|
||||
@@ -1001,6 +1180,156 @@ const handleParamDialogClose = () => {
|
||||
currentDevice.value = null
|
||||
}
|
||||
|
||||
// 下拉框选项配置相关
|
||||
const selectOptionsDialogVisible = ref(false)
|
||||
const currentSelectParam = ref<any>(null)
|
||||
const selectOptionInput = ref('')
|
||||
const selectOptionsList = ref<any[]>([])
|
||||
|
||||
// 打开下拉框选项配置对话框
|
||||
const handleConfigSelectOptions = async (row: any) => {
|
||||
try {
|
||||
// 查找对应的字典类型
|
||||
const dicTypeListRes: any = await dictypelist({
|
||||
pageNum: 1,
|
||||
pageSize: 1000,
|
||||
})
|
||||
|
||||
const dicTypeData = dicTypeListRes?.data ?? dicTypeListRes ?? {}
|
||||
const dicTypeRecords = dicTypeData.records || dicTypeData.list || dicTypeData.rows || []
|
||||
|
||||
const dicType = dicTypeRecords.find(
|
||||
(item: any) => item.dicName === row.paramName
|
||||
)
|
||||
|
||||
if (!dicType) {
|
||||
ElMessage.warning('未找到对应的字典类型,请先保存参数')
|
||||
return
|
||||
}
|
||||
|
||||
currentSelectParam.value = {
|
||||
...row,
|
||||
dicTypeId: dicType.id,
|
||||
}
|
||||
selectOptionsDialogVisible.value = true
|
||||
await loadSelectOptions(dicType.id)
|
||||
} catch (error) {
|
||||
console.error('打开下拉框配置失败:', error)
|
||||
ElMessage.error('打开下拉框配置失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 加载下拉框选项列表
|
||||
const loadSelectOptions = async (dicId: number) => {
|
||||
try {
|
||||
const res: any = await dicdatabydicid(dicId)
|
||||
|
||||
const data = res?.data ?? res ?? {}
|
||||
const records = Array.isArray(data) ? data : (data.records || data.list || data.rows || [])
|
||||
|
||||
selectOptionsList.value = records
|
||||
} catch (error) {
|
||||
console.error('加载下拉框选项失败:', error)
|
||||
ElMessage.error('加载下拉框选项失败')
|
||||
selectOptionsList.value = []
|
||||
}
|
||||
}
|
||||
|
||||
// 添加下拉框选项
|
||||
const handleAddSelectOption = async () => {
|
||||
if (!selectOptionInput.value || selectOptionInput.value.trim() === '') {
|
||||
ElMessage.warning('请输入选项数据')
|
||||
return
|
||||
}
|
||||
|
||||
if (!currentSelectParam.value?.dicTypeId) {
|
||||
ElMessage.error('字典类型ID不存在')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const res: any = await dicdataadd({
|
||||
dicId: currentSelectParam.value.dicTypeId,
|
||||
dicLabel: currentSelectParam.value.paramType || '',
|
||||
dicValue: selectOptionInput.value.trim(),
|
||||
})
|
||||
|
||||
if (res?.code === '0' || res?.code === 0 || res?.success) {
|
||||
ElMessage.success('添加成功')
|
||||
selectOptionInput.value = ''
|
||||
// 重新加载选项列表
|
||||
await loadSelectOptions(currentSelectParam.value.dicTypeId)
|
||||
} else {
|
||||
ElMessage.error(res?.message || res?.msg || '添加失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('添加下拉框选项失败:', error)
|
||||
ElMessage.error('添加下拉框选项失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 删除下拉框选项
|
||||
const handleDeleteSelectOption = async (option: any) => {
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
`确定要删除"${option.dicValue || '该选项'}"吗?`,
|
||||
'提示',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}
|
||||
)
|
||||
|
||||
const res: any = await dicdatadel(option.id)
|
||||
|
||||
if (res?.code === '0' || res?.code === 0 || res?.success) {
|
||||
ElMessage.success('删除成功')
|
||||
// 重新加载选项列表
|
||||
if (currentSelectParam.value?.dicTypeId) {
|
||||
await loadSelectOptions(currentSelectParam.value.dicTypeId)
|
||||
}
|
||||
} else {
|
||||
ElMessage.error(res?.message || res?.msg || '删除失败')
|
||||
}
|
||||
} catch (error: any) {
|
||||
if (error !== 'cancel') {
|
||||
console.error('删除下拉框选项失败:', error)
|
||||
ElMessage.error('删除下拉框选项失败')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 保存下拉框选项配置
|
||||
const handleSaveSelectOptions = async () => {
|
||||
if (!currentSelectParam.value) {
|
||||
return
|
||||
}
|
||||
|
||||
if (selectOptionsList.value.length === 0) {
|
||||
await ElMessageBox.alert(
|
||||
`${currentSelectParam.value.paramName}的下拉框选项列表还未配置,请先完成配置`,
|
||||
'提示',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
type: 'warning',
|
||||
}
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
selectOptionsDialogVisible.value = false
|
||||
ElMessage.success(`${currentSelectParam.value.paramName}下拉框选项列表保存成功!`)
|
||||
}
|
||||
|
||||
// 关闭下拉框选项配置对话框
|
||||
const handleSelectOptionsDialogClose = () => {
|
||||
selectOptionsDialogVisible.value = false
|
||||
selectOptionInput.value = ''
|
||||
selectOptionsList.value = []
|
||||
currentSelectParam.value = null
|
||||
}
|
||||
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
getIslandList().then(() => {
|
||||
@@ -1063,5 +1392,97 @@ onMounted(() => {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.select-options-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.select-options-input-area {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.input-label {
|
||||
min-width: 80px;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.select-options-cards {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20px;
|
||||
min-height: 100px;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
padding: 20px;
|
||||
background: linear-gradient(135deg, #e3f2fd 0%, #f0f2f5 100%);
|
||||
border-radius: 4px;
|
||||
background-image:
|
||||
linear-gradient(rgba(64, 158, 255, 0.03) 1px, transparent 1px),
|
||||
linear-gradient(90deg, rgba(64, 158, 255, 0.03) 1px, transparent 1px);
|
||||
background-size: 20px 20px;
|
||||
}
|
||||
|
||||
.select-option-card {
|
||||
position: relative;
|
||||
padding: 16px 20px;
|
||||
background-color: #fff;
|
||||
border: 1px solid rgba(64, 158, 255, 0.1);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
cursor: default;
|
||||
transition: all 0.3s;
|
||||
min-width: 120px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.select-option-card:hover {
|
||||
box-shadow: 0 4px 16px rgba(64, 158, 255, 0.2);
|
||||
transform: translateY(-4px);
|
||||
border-color: rgba(64, 158, 255, 0.3);
|
||||
}
|
||||
|
||||
.option-text {
|
||||
font-size: 1.2em;
|
||||
color: #303133;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.option-delete-icon {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
font-size: 16px;
|
||||
color: #909399;
|
||||
cursor: pointer;
|
||||
transition: color 0.3s;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.option-delete-icon:hover {
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.empty-tip {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
color: #909399;
|
||||
font-size: 16px;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.form-type-select-btn {
|
||||
font-size: inherit;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user