|
|
@@ -36,152 +36,74 @@
|
|
|
</el-form>
|
|
|
</ContentWrap>
|
|
|
|
|
|
- <!-- 列表 -->
|
|
|
+ <!-- 列表(卡片) -->
|
|
|
<ContentWrap style="border: 0">
|
|
|
- <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
|
|
- <el-table-column :label="t('monitor.serial')" width="70" align="center">
|
|
|
- <template #default="scope">
|
|
|
- {{ scope.$index + 1 }}
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column label="部门名称" align="center" prop="deptName" />
|
|
|
- <el-table-column label="成套名称" align="center" prop="name" />
|
|
|
- <el-table-column label="成套类型" align="center">
|
|
|
- <template #default="scope">
|
|
|
- <dict-tag :type="DICT_TYPE.DEVICE_GROUP_TYPE" :value="scope.row.type" />
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
-
|
|
|
- <el-table-column label="描述" align="center" prop="remark" />
|
|
|
- <el-table-column label="设备数量" align="center" prop="deviceCount">
|
|
|
- <template #default="scope">
|
|
|
- {{ (scope.row.details && scope.row.details.length) || 0 }}
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column label="主设备" align="center" prop="mainDeviceName">
|
|
|
- <template #default="scope">
|
|
|
- {{
|
|
|
- scope.row.details.filter((item) => item.ifMaster)[0]?.deviceName +
|
|
|
- ' ' +
|
|
|
- scope.row.details.filter((item) => item.ifMaster)[0]?.deviceCode || '无'
|
|
|
- }}
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
-
|
|
|
- <el-table-column :label="t('devicePerson.operation')" align="center" min-width="120px">
|
|
|
- <template #default="scope">
|
|
|
- <el-button link type="primary" @click="handleEdit(scope.row)"> 查看详情 </el-button>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- </el-table>
|
|
|
- <!-- 分页 -->
|
|
|
- <Pagination
|
|
|
- :total="total"
|
|
|
- v-model:page="queryParams.pageNo"
|
|
|
- v-model:limit="queryParams.pageSize"
|
|
|
- @pagination="getList"
|
|
|
- />
|
|
|
+ <div v-loading="loading">
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col
|
|
|
+ v-for="(item, index) in list"
|
|
|
+ :key="item.id || index"
|
|
|
+ :xs="24"
|
|
|
+ :sm="12"
|
|
|
+ :md="8"
|
|
|
+ :lg="6"
|
|
|
+ class="mt-2"
|
|
|
+ >
|
|
|
+ <el-card shadow="hover" class="device-card" style="border: 0">
|
|
|
+ <div class="card-header">
|
|
|
+ <div class="flex justify-between w-full">
|
|
|
+ <div>
|
|
|
+ <div class="card-title">{{ item.name }}</div>
|
|
|
+ <div class="card-dept">{{ item.deptName }}</div>
|
|
|
+ </div>
|
|
|
+ <el-image
|
|
|
+ v-if="item.type === '1'"
|
|
|
+ :src="img1"
|
|
|
+ style="width: 40px; height: 40px"
|
|
|
+ />
|
|
|
+ <el-image v-else :src="img2" style="width: 40px; height: 40px" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="card-body">
|
|
|
+ <div class="card-row">
|
|
|
+ <span class="muted">成套类型:</span>
|
|
|
+ <dict-tag :type="DICT_TYPE.DEVICE_GROUP_TYPE" :value="item.type" />
|
|
|
+ </div>
|
|
|
+ <div class="card-row"
|
|
|
+ ><span class="muted">设备数量:</span>
|
|
|
+ {{ (item.details && item.details.length) || 0 }}</div
|
|
|
+ >
|
|
|
+ <div class="card-row"
|
|
|
+ ><span class="muted">主设备:</span>
|
|
|
+ {{
|
|
|
+ item.details && item.details.filter((d) => d.ifMaster)[0]
|
|
|
+ ? item.details.filter((d) => d.ifMaster)[0].deviceName +
|
|
|
+ ' ' +
|
|
|
+ item.details.filter((d) => d.ifMaster)[0].deviceCode
|
|
|
+ : '无'
|
|
|
+ }}
|
|
|
+ </div>
|
|
|
+ <!-- <div class="card-row"><span class="muted">描述:</span> {{ item.remark }}</div> -->
|
|
|
+ </div>
|
|
|
+ <template #footer>
|
|
|
+ <el-button type="primary" link @click="handleEdit(item)"> 查看详情 </el-button>
|
|
|
+ </template>
|
|
|
+ </el-card>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <div style="margin-top: 16px">
|
|
|
+ <Pagination
|
|
|
+ :total="total"
|
|
|
+ v-model:page="queryParams.pageNo"
|
|
|
+ v-model:limit="queryParams.pageSize"
|
|
|
+ @pagination="getList"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</ContentWrap>
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
-
|
|
|
- <!-- 新增/编辑成套设备对话框 -->
|
|
|
- <el-dialog :title="dialogTitle" v-model="dialogVisible" width="800px" @close="cancel">
|
|
|
- <template #header>
|
|
|
- <div class="my-header" style="padding-bottom: 20px">
|
|
|
- <span>{{ dialogTitle }}</span>
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- <el-form ref="formRef" :model="formData" :rules="formRules" label-width="80px">
|
|
|
- <el-row :gutter="20">
|
|
|
- <el-col :span="12">
|
|
|
- <el-form-item label="成套名称" prop="name">
|
|
|
- <el-input v-model="formData.name" placeholder="请输入成套名称" />
|
|
|
- </el-form-item>
|
|
|
- </el-col>
|
|
|
-
|
|
|
- <el-col :span="12">
|
|
|
- <el-form-item :label="t('iotDevice.dept')" prop="deptId">
|
|
|
- <el-tree-select
|
|
|
- v-model="formData.deptId"
|
|
|
- :data="deptList"
|
|
|
- :props="defaultProps"
|
|
|
- check-strictly
|
|
|
- node-key="id"
|
|
|
- filterable
|
|
|
- placeholder="请选择所在部门"
|
|
|
- @change="handleDeptChange"
|
|
|
- />
|
|
|
- </el-form-item>
|
|
|
- </el-col>
|
|
|
- </el-row>
|
|
|
-
|
|
|
- <el-row :gutter="20">
|
|
|
- <el-col :span="24">
|
|
|
- <el-form-item label="描述" prop="remark">
|
|
|
- <el-input
|
|
|
- v-model="formData.remark"
|
|
|
- type="textarea"
|
|
|
- placeholder="请输入描述"
|
|
|
- :rows="2"
|
|
|
- />
|
|
|
- </el-form-item>
|
|
|
- </el-col>
|
|
|
- </el-row>
|
|
|
-
|
|
|
- <el-row :gutter="20">
|
|
|
- <el-col :span="24">
|
|
|
- <el-form-item label="选择设备" prop="devices">
|
|
|
- <div class="transfer-container">
|
|
|
- <el-transfer
|
|
|
- v-model="selectedDeviceIds"
|
|
|
- :data="deviceOptions"
|
|
|
- :titles="['设备列表', '已选择设备']"
|
|
|
- :button-texts="['移除', '添加']"
|
|
|
- filterable
|
|
|
- :filter-method="filterDeviceMethod"
|
|
|
- filter-placeholder="请输入设备名称"
|
|
|
- @change="rightDeviceChange"
|
|
|
- >
|
|
|
- <template #left-empty>
|
|
|
- <el-empty :image-size="60" :description="isEdit ? '加载中...' : '请选择设备'" />
|
|
|
- </template>
|
|
|
- <template #right-empty>
|
|
|
- <el-empty :image-size="60" :description="isEdit ? '加载中...' : '请选择设备'" />
|
|
|
- </template>
|
|
|
- </el-transfer>
|
|
|
- </div>
|
|
|
- </el-form-item>
|
|
|
- </el-col>
|
|
|
- </el-row>
|
|
|
-
|
|
|
- <el-row :gutter="20" v-if="selectedDevices.length > 0">
|
|
|
- <el-col :span="12">
|
|
|
- <el-form-item label="设置主设备" prop="mainDevice" label-width="100">
|
|
|
- <el-select
|
|
|
- v-model="mainDeviceId"
|
|
|
- placeholder="请选择主设备"
|
|
|
- clearable
|
|
|
- filterable
|
|
|
- @change="setMainDevice"
|
|
|
- >
|
|
|
- <el-option
|
|
|
- v-for="device in selectedDevices"
|
|
|
- :key="device.id"
|
|
|
- :label="device.label"
|
|
|
- :value="device.id"
|
|
|
- />
|
|
|
- </el-select>
|
|
|
- </el-form-item>
|
|
|
- </el-col>
|
|
|
- </el-row>
|
|
|
- </el-form>
|
|
|
-
|
|
|
- <template #footer>
|
|
|
- <el-button @click="cancel">取 消</el-button>
|
|
|
- <el-button type="primary" @click="submit">确 定</el-button>
|
|
|
- </template>
|
|
|
- </el-dialog>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
@@ -190,6 +112,9 @@ import DeptTree from '@/views/system/user/DeptTree.vue'
|
|
|
import { defaultProps, handleTree } from '@/utils/tree'
|
|
|
import * as DeptApi from '@/api/system/dept'
|
|
|
import { DICT_TYPE, getDictLabel, getStrDictOptions } from '@/utils/dict'
|
|
|
+
|
|
|
+import img1 from '../../../assets/imgs/300.png'
|
|
|
+import img2 from '../../../assets/imgs/other.png'
|
|
|
const deptList = ref<Tree[]>([]) // 树形结构
|
|
|
import { useRouter } from 'vue-router'
|
|
|
const router = useRouter()
|
|
|
@@ -498,4 +423,90 @@ onMounted(async () => {
|
|
|
.el-transfer {
|
|
|
--el-transfer-panel-body-height: 500px;
|
|
|
}
|
|
|
+
|
|
|
+.device-card {
|
|
|
+ height: 100%;
|
|
|
+ border-radius: 12px;
|
|
|
+ overflow: hidden;
|
|
|
+ box-shadow: 0 6px 18px rgba(28, 39, 63, 0.06);
|
|
|
+}
|
|
|
+
|
|
|
+/* 移除 el-card 默认内边距,统一由子元素控制 */
|
|
|
+.device-card ::v-deep .el-card__body {
|
|
|
+ padding: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.device-card .card-header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ padding: 18px 16px;
|
|
|
+ background: linear-gradient(90deg, #2dd4bf 0%, #0ea5e9 100%);
|
|
|
+ color: #fff;
|
|
|
+}
|
|
|
+
|
|
|
+.device-card .card-title {
|
|
|
+ font-weight: 700;
|
|
|
+ font-size: 16px;
|
|
|
+ line-height: 1.2;
|
|
|
+}
|
|
|
+
|
|
|
+.device-card .card-dept {
|
|
|
+ font-size: 12px;
|
|
|
+ opacity: 0.9;
|
|
|
+ margin-top: 6px;
|
|
|
+}
|
|
|
+
|
|
|
+.device-card .card-status {
|
|
|
+ background: rgba(255, 255, 255, 0.18);
|
|
|
+ color: #fff;
|
|
|
+ padding: 6px 10px;
|
|
|
+ border-radius: 999px;
|
|
|
+ font-size: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.device-card .card-body {
|
|
|
+ background: #fff;
|
|
|
+ padding: 14px 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.device-card .card-row {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding: 12px 0;
|
|
|
+ border-bottom: 1px solid #f5f7fa;
|
|
|
+}
|
|
|
+
|
|
|
+.device-card .card-row:last-child {
|
|
|
+ border-bottom: none;
|
|
|
+}
|
|
|
+
|
|
|
+.device-card .card-row .muted {
|
|
|
+ color: #97a0b5;
|
|
|
+ width: 86px;
|
|
|
+ flex-shrink: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.device-card .card-row .value {
|
|
|
+ color: #2b3a4a;
|
|
|
+ flex: 1;
|
|
|
+}
|
|
|
+
|
|
|
+.device-card ::v-deep .el-card__footer {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ padding: 12px 16px 16px;
|
|
|
+ background: #fff;
|
|
|
+}
|
|
|
+
|
|
|
+.device-card .detail-link {
|
|
|
+ color: var(--el-color-primary, #409eff);
|
|
|
+ font-weight: 500;
|
|
|
+}
|
|
|
+
|
|
|
+.device-card .id-label {
|
|
|
+ color: #97a0b5;
|
|
|
+ font-size: 12px;
|
|
|
+}
|
|
|
</style>
|