帝可得-设备管理

发布于:2024-12-06 ⋅ 阅读:(40) ⋅ 点赞:(0)

设备管理

需求说明

在这里插入图片描述

点位管理主要涉及到三个功能模块,业务流程如下:

  1. 新增设备类型: 允许管理员定义新的售货机型号,包括其规格和容量。
  2. 新增设备: 在新的设备类型定义后,系统应允许添加新的售货机实例,并将它们分配到特定的点位。
  3. 新增货道: 对于每个新添加的设备,系统应支持定义新的货道,后期用于关联相应的商品SKU。
登录系统
新增设备类型
新增设备
新增货道

对于设备和其他管理数据,下面是示意图:

  • 关系字段:vm_type_id、node_id、vm_id
  • 数据字典:vm_status(0未投放、1运营、3撤机)
  • 冗余字段:addr、business_type、region_id、partner_id(简化查询接口、提高查询效率)
  • 在这里插入图片描述

生成基础代码

需求

使用若依代码生成器,生成设备类型、设备、货道前后端基础代码,并导入到项目中:
在这里插入图片描述

步骤

①创建目录菜单

创建设备管理目录菜单
在这里插入图片描述
在这里插入图片描述
②添加数据字典
先创建设备状态的字典类型
在这里插入图片描述
在这里插入图片描述
再创建设备状态的字典数据
在这里插入图片描述
在这里插入图片描述
③配置代码生成信息
导入三张表
在这里插入图片描述
配置设备类型表(参考原型)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
配置设备表(参考原型)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
配置货道表(无原型)
在这里插入图片描述
在这里插入图片描述
④下载代码并导入项目
选中三张表生成下载
在这里插入图片描述
解压ruoyi.zip得到前后端代码和动态菜单sql

注意:货道动态菜单sql和前端不需要导入
在这里插入图片描述
代码导入
在这里插入图片描述
在这里插入图片描述

调整二级菜单显示顺序(设备状态稍后完成)
在这里插入图片描述
页面展示:
在这里插入图片描述
在这里插入图片描述

设备类型改造

基础页面

需求
参考页面原型,完成基础布局展示改造
在这里插入图片描述

页面改造

搜索区域改造
在这里插入图片描述
在这里插入图片描述
列表展示区域

初始的表没有创建日期和更新日期的字段,可以手动加上,然后再在后端的查询中返回create_time字段。前端则需要添加显示当前日期的组件。

      <el-table-column label="创建日期" align="center" prop="createTime">
        <template #default="scope">
          {{ new Date(scope.row.createTime).toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' }).replace(/\//g, '-') }}
        </template>
      </el-table-column>

在这里插入图片描述

新增对话框改造

将行和列以及货道容量改为数字输入框

        <el-form-item label="货道数:" prop="row">
          <el-input-number :min="1" :max="10" v-model="form.vmRow" placeholder="请输入行" /> 行 &nbsp;&nbsp;
          <el-input-number :min="1" :max="10" v-model="form.vmCol" placeholder="请输入列" /> 列
        </el-form-item>
        <el-form-item label="货道容量:" prop="capacity" >
          <!-- <el-input v-model="form.channelMaxCapacity" style="width: 80px" /> -->
          <el-input-number
            v-model="form.channelMaxCapacity"
            :min="1"
            :max="10"
            placeholder="请输入"
          />
        </el-form-item>

在这里插入图片描述

在这里插入图片描述

设备管理改造

基础页面

需求

参考页面原型,完成基础布局展示改造

在这里插入图片描述

页面改造

搜索区域改造

在这里插入图片描述

列表展示区域改造

设备型号显示:

<el-table-column label="设备型号" align="center" prop="vmTypeId" >
    <template #default="scope">
      <div v-for="item in vmTypeList" :key="item.id">
        <span v-if="item.id==scope.row.vmTypeId">{{ item.name }}</span>
      </div>
    </template>
  </el-table-column>
  
import { listVmType } from "@/api/manage/vmType";
import { loadAllParams } from '@/api/page';

/* 查询设备类型列表 */
const vmTypeList = ref([]);
function getVmTypeList() {
  listVmType(loadAllParams).then((response) => {
    vmTypeList.value = response.rows;
  });
}

getVmTypeList();

在这里插入图片描述

合作商名称显示:

使用cursor中进行修改的语句模板:

在列表展示的合作商部分显示合作商名称,需要导入partner.js中的listPartner方法,传递的参数为loadAllParams,需要将返回的数据存储在partnerList集合中。在展示的合作商标签部分使用循环进行遍历合作商id,展示对应id的name。

代码:

import { listPartner } from "@/api/manage/partner"; // 添加导入

// 查询合作商列表
const partnerList = ref([]);
function getPartnerList() {
  listPartner(loadAllParams).then((response) => {
    partnerList.value = response.rows;
  });
}

getPartnerList();

<el-table-column label="合作商" align="center" prop="partnerId">
        <template #default="scope">
          <div v-for="item in partnerList" :key="item.id">
            <span v-if="item.id == scope.row.partnerId">{{
              item.partnerName
            }}</span>
          </div>
        </template>
      </el-table-column>

查看后端返回数据,合作商名为partnerName需要将name修改为partnerName。

在这里插入图片描述

对话框改造

设备型号改为下拉框:

语句模板:

将添加或修改对话框中的设备型号字段改为下拉框,需要根据设备型号显示设备的名称。

代码:

<el-form-item label="设备型号" prop="vmTypeId">
          <!-- <el-input v-model="form.vmTypeId" placeholder="请输入设备型号" /> -->
          <el-select v-model="form.vmTypeId" placeholder="请选择设备型号">
            <el-option
              v-for="item in vmTypeList"
              :key="item.id"
              :label="item.name"
              :value="item.id"
            />
          </el-select>
        </el-form-item>

在这里插入图片描述

点位改为下拉框:

语句模板:

将添加或修改对话框中的点位字段改为下拉框,需要根据点位Id显示对应的点位名。
需要调用node.js中的listNode方法,传入的参数为loadAllParams,将返回的数据封装到nodeList集合中,在下拉框区域进行遍历。

代码:

import { listNode } from "@/api/manage/node"; // 添加导入

// 添加获取点位列表的方法
const nodeList = ref([]);
function getNodeList() {
  listNode(loadAllParams).then((response) => {
    nodeList.value = response.rows;
  });
}
getNodeList();


<el-form-item label="点位" prop="nodeId">
          <!-- <el-input v-model="form.nodeId" placeholder="请输入点位Id" /> -->
          <el-select v-model="form.nodeId" placeholder="请选择点位">
            <el-option
              v-for="item in nodeList"
              :key="item.id"
              :label="item.nodeName"
              :value="item.id"
            />
          </el-select>
        </el-form-item>

在这里插入图片描述

自动生成系统编号:

在新增时要显示系统自动生成,修改对话框要显示具体的编号。

<el-form-item label="设备编号" prop="innerCode">
          <!-- <el-input v-model="form.innerCode" placeholder="请输入设备编号" /> -->
           <span> {{ form.innerCode == null? '系统自动生成':form.innerCode }} </span>
        </el-form-item>

在这里插入图片描述

在这里插入图片描述

修改对话框补全:

 <!-- 添加或修改设备管理对话框 -->
    <el-dialog :title="title" v-model="open" width="500px" append-to-body>
      <el-form ref="vmRef" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="设备编号:" prop="innerCode">
          <!-- <el-input v-model="form.innerCode" placeholder="请输入设备编号" /> -->
           <span> {{ form.innerCode == null? '系统自动生成':form.innerCode }} </span>
        </el-form-item>
        <el-form-item label="供货时间:" v-if="form.innerCode != null">
          <span>{{ parseTime(form.lastSupplyTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
        </el-form-item>
        <!-- 回显设备类型 -->
        <el-form-item label="设备类型:" prop="vmTypeId" v-if="form.innerCode != null">
            <div v-for="item in vmTypeList" :key="item.id">
              <span v-if="item.id == form.vmTypeId">{{ item.name }}</span>
            </div>
        </el-form-item>
        <!-- 显示设备容量 -->
         <el-form-item label="设备容量:" prop="channelMaxCapacity" v-if="form.innerCode != null">
          <span>{{ form.channelMaxCapacity }}</span>
        </el-form-item>
        <el-form-item label="设备点位:" prop="nodeId">
          <!-- <el-input v-model="form.nodeId" placeholder="请输入点位Id" /> -->
          <el-select v-model="form.nodeId" placeholder="请选择点位">
            <el-option
              v-for="item in nodeList"
              :key="item.id"
              :label="item.nodeName"
              :value="item.id"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="设备型号:" prop="vmTypeId" v-if="form.innerCode == null">
          <!-- <el-input v-model="form.vmTypeId" placeholder="请输入设备型号" /> -->
          <el-select v-model="form.vmTypeId" placeholder="请选择设备型号">
            <el-option
              v-for="item in vmTypeList"
              :key="item.id"
              :label="item.name"
              :value="item.id"
            />
          </el-select>
        </el-form-item>
        <!-- 回显合作商名 -->
        <el-form-item label="合作商:" prop="partnerId" v-if="form.innerCode != null">
            <div v-for="item in partnerList" :key="item.id">
              <span v-if="item.id == form.partnerId">{{
                item.partnerName
              }}</span>
            </div>
        </el-form-item>
        <!-- 回显所属区域 -->
        <el-form-item label="所属区域:" prop="regionId" v-if="form.innerCode != null">
          <div v-for="item in regionList" :key="item.id">
            <span v-if="item.id == form.regionId">{{ item.regionName }}</span>
          </div>
        </el-form-item>
        <!-- 回显设备地址 -->
        <el-form-item label="设备地址:" prop="addr" v-if="form.innerCode != null">
          <span>{{ form.addr }}</span>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确 定</el-button>
          <el-button @click="cancel">取 消</el-button>
        </div>
      </template>
    </el-dialog>


// ------------------------------
import { listRegion } from "@/api/manage/region"; // 添加导入

// 查询区域列表
const regionList = ref([]);
function getRegionList() {
  listRegion(loadAllParams).then((response) => {
    regionList.value = response.rows;
  });
}

getList();

在这里插入图片描述

新增设备改造

需求

在这里插入图片描述

在新增设备的对话框中前端提交两个参数,分别是设备型号id和点位id。但是在保存数据库时,需要补充设备表的其他字段信息,还需要根据售货机类型创建所属货道。

在这里插入图片描述

高亮部分为需要补充的字段,其他有些参数等设备运行之后才提交。

代码实现

VendingMachineServiceImpl:

@Autowired
private INodeService nodeService;
@Autowired
private IVmTypeService vmTypeService;
@Autowired
private IChannelService channelService;

/**
 * 新增设备管理
 *
 * @param vendingMachine 设备管理
 * @return 结果
 */
@Transactional
@Override
public int insertVendingMachine(VendingMachine vendingMachine) {
    //1. 新增设备表
    //1-1 生成8位编号,补充货道编号。在common包下提供了UUID工具类
    String innerCode = UUIDUtils.getUUID();
    vendingMachine.setInnerCode(innerCode); // 售货机编号
    //1-2 查询售货机类型表,补充设备容量
    VmType vmType = vmTypeService.selectVmTypeById(vendingMachine.getVmTypeId());
    vendingMachine.setChannelMaxCapacity(vmType.getChannelMaxCapacity());
    //1-3 查询点位表,补充 区域、点位、合作商等信息
    Node node = nodeService.selectNodeById(vendingMachine.getNodeId());
    BeanUtils.copyProperties(node, vendingMachine, "id");
    vendingMachine.setAddr(node.getAddress());
    //1-4 设备状态
    vendingMachine.setVmStatus(DkdContants.VM_STATUS_NODEPLOY);// 0-未投放(数据库有默认值,这个不写也不影响)
    vendingMachine.setCreateTime(DateUtils.getNowDate());// 创建时间
    vendingMachine.setUpdateTime(DateUtils.getNowDate());// 更新时间
    //1-5 保存
    int result = vendingMachineMapper.insertVendingMachine(vendingMachine);
    //2. 新增售货机的货道表
    //2-1 声明货道集合
    List<Channel> channelList = new ArrayList<>();
    //2-2 双层for循环
    for (int i = 1; i <= vmType.getVmRow(); i++) { // 外层行
        for (int j = 1; j <= vmType.getVmCol(); j++) {// 内层列
            //2-3 封装channel
            Channel channel = new Channel();
            channel.setChannelCode(i + "-" + j);// 货道编号
            channel.setVmId(vendingMachine.getId());// 售货机id
            channel.setInnerCode(vendingMachine.getInnerCode());// 售货机编号
            channel.setMaxCapacity(vmType.getChannelMaxCapacity());// 货道最大容量
            channel.setCreateTime(DateUtils.getNowDate());// 创建时间
            channel.setUpdateTime(DateUtils.getNowDate());// 更新时间
             channelList.add(channel);
        }
    }
    //2-4 批量新增
    channelService.batchInsertChannel(channelList);
    return result;
}
实现批量插入

ChannelMapper接口和xml:

/**
 * 批量新增售货机货道
 * @param channelList
 * @return 结果
 */
public int batchInsertChannel(List<Channel> channelList);
<insert id="batchInsertChannel" parameterType="java.util.List">
    INSERT INTO tb_channel (
    channel_code, vm_id, inner_code, max_capacity, last_supply_time, create_time, update_time
    ) VALUES
    <foreach collection="list" item="channel" separator=",">
        (
        #{channel.channelCode},
        #{channel.vmId},
        #{channel.innerCode},
        #{channel.maxCapacity},
        #{channel.lastSupplyTime},
        #{channel.createTime},
        #{channel.updateTime}
        )
    </foreach>
</insert>

IChannelService:

/**
 * 批量新增售货机货道
 * @param channelList
 * @return 结果
 */
public int batchInsertChannel(List<Channel> channelList);

ChannelServiceImpl:

/**
 * 批量新增售货机货道
 * @param channelList
 * @return 结果
 */
@Override
public int batchInsertChannel(List<Channel> channelList) {
    return channelMapper.batchInsertChannel(channelList);
}

在这里插入图片描述

在这里插入图片描述

型号对应的货道信息:

在这里插入图片描述

售货机表:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

货道表:

在这里插入图片描述

修改设备

需求

修改设备时,根据点位同步更新冗余字段信息。后端会接收前端提供的node_id,根据node_id查询点位表获取相关信息,获取到点位信息之后需要更新到设备表的冗余字段。

在这里插入图片描述

代码实现

VendingMachineServiceImpl:

/**
 * 修改设备管理
 *
 * @param vendingMachine 设备管理
 * @return 结果
 */
@Override
public int updateVendingMachine(VendingMachine vendingMachine) {
    //查询点位表,补充 区域、点位、合作商等信息
    Node node = nodeService.selectNodeById(vendingMachine.getNodeId());
    BeanUtils.copyProperties(node, vendingMachine, "id");// 商圈类型、区域、合作商
    vendingMachine.setAddr(node.getAddress());// 设备地址
    vendingMachine.setUpdateTime(DateUtils.getNowDate());// 更新时间
    return vendingMachineMapper.updateVendingMachine(vendingMachine);
}

设备状态改造

页面原型

在这里插入图片描述

创建视图组件

设备管理和设备状态共用的是同一套后端代码,导致若依并没有生成这部分的前端页面。

参考设备管理,创建vmStatus/index.vue视图组件

在这里插入图片描述

创建二级菜单

在这里插入图片描述
在这里插入图片描述

列表展示改造

<el-table-column label="序号" align="center" prop="id" />
      <el-table-column label="设备编号" align="center" prop="innerCode" />
      <el-table-column label="设备型号" align="center" prop="vmTypeId">
        <template #default="scope">
          <div v-for="item in vmTypeList" :key="item.id">
            <span v-if="item.id == scope.row.vmTypeId">{{ item.name }}</span>
          </div>
        </template>
      </el-table-column>
      <el-table-column label="详细地址" align="center" prop="addr" />
      <el-table-column label="运营状态" align="center" prop="vmStatus">
        <template #default="scope">
          <dict-tag :options="vm_status" :value="scope.row.vmStatus" />
        </template>
      </el-table-column>
      <el-table-column label="设备状态" align="center" prop="vmStatus">
        <template #default="scope">
         <span v-if="scope.row.runningStatus!=null">{{ JSON.parse(scope.row.runningStatus).status==true?'正常':'异常' }}</span>
          <span v-else>异常</span>
        </template>
      </el-table-column>
      <el-table-column
        label="操作"
        align="center"
        class-name="small-padding fixed-width"
      >
        <template #default="scope">
          <el-button
            link
            type="primary"
            @click="getVmInfo(scope.row)"
            v-hasPermi="['manage:vm:query']"
            >查看详情</el-button
          >
        </template>

在这里插入图片描述

点位查看详情

在node/index.vue视图组件中修改,,将修改方法改造为查看详情方法,详细信息等设备运行之后才能展示。

<el-button link type="primary" @click="getNodeInfo(scope.row)" v-hasPermi="['manage:vm:list']">查看详情</el-button>

 <!-- 查看详情对话框 -->
 <el-dialog :title="title" v-model="open" width="500px" append-to-body>
 </el-dialog>

    
/** 查看详情按钮操作 */
function  getVmInfo(row) {
  reset();
  const _id = row.id || ids.value;
  getVm(_id).then((response) => {
    form.value = response.data;
    open.value = true;
    title.value = "设备详情";
  });
}
</script>

在这里插入图片描述