09Java之若依实战篇--帝可得后台管理系统03(设备管理、策略管理)

1、设备管理

1.1、需求说明

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

  1. 新增设备类型: 允许管理员定义新的售货机型号,包括其规格和容量。

  2. 新增设备: 在新的设备类型定义后,系统应允许添加新的售货机实例,并将它们分配到特定的点位。

  3. 新增货道: 对于每个新添加的设备,系统应支持定义新的货道,后期用于关联相应的商品SKU。


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

  • 关系字段:vm_type_id、node_id、vm_id

  • 数据字典:vm_status(0未投放、1运营、3撤机)

  • 冗余字段:addr、business_type、region_id、partner_id(简化查询接口、提高查询效率)

id,inner_code都可以做唯一标识,想把唯一标识暴露但是不想让它和主键一样有规律暴露多少台设备

1.2、生成基础代码

1.2.1、需求

使用若依代码生成器,生成设备类型、设备、货道前后端基础代码,并导入到项目中:

1.2.2、步骤

①创建目录菜单

创建设备管理目录菜单

②添加数据字典

先创建设备状态的字典类型

再创建设备状态的字典数据

③配置代码生成信息

导入三张表

配置设备类型表(参考原型)

配置设备表(参考原型)

配置货道表(无原型)

④下载代码并导入项目

选中三张表生成下载

解压ruoyi.zip得到前后端代码和动态菜单sql

注意:货道动态菜单sql和前端不需要导入

代码导入

调整二级菜单显示顺序(设备状态稍后完成)

1.3、设备类型改造

1.3.1、基础页面

1.3.1.1、需求

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

1.3.1.2、代码实现

在vmType/index.vue视图组件中修改

<!-- 查询条件 -->
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
    <el-form-item label="型号名称" prop="name">
        <el-input  v-model="queryParams.name" placeholder="请输入型号名称" clearable  @keyup.enter="handleQuery"/>
    </el-form-item>
    <el-form-item>
        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
    </el-form-item>
</el-form>

<!-- 列表展示 -->
<el-table v-loading="loading" :data="vmTypeList" @selection-change="handleSelectionChange">
    <el-table-column type="selection" width="55" align="center" />
    <el-table-column label="型号名称" align="center" prop="name" />
    <el-table-column label="型号编码" align="center" prop="model" />
    <el-table-column label="设备图片" align="center" prop="image" width="100">
        <template #default="scope">
<image-preview :src="scope.row.image" :width="50" :height="50"/>
        </template>
    </el-table-column>
    <el-table-column label="货道行" align="center" prop="vmRow" />
    <el-table-column label="货道列" align="center" prop="vmCol" />
    <el-table-column label="设备容量" align="center" prop="channelMaxCapacity" />
    <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template #default="scope">
		<el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['manage:vmType:edit']">修改</el-button>
		<el-button link type="primary" @click="handleDelete(scope.row)" v-hasPermi="['manage:vmType:remove']">删除</el-button>
        </template>
    </el-table-column>
</el-table>

<!-- 添加或修改设备类型管理对话框 -->
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
    <el-form ref="vmTypeRef" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="型号名称" prop="name">
            <el-input v-model="form.name" placeholder="请输入型号名称" />
        </el-form-item>
        <el-form-item label="型号编码" prop="model">
            <el-input v-model="form.model" placeholder="请输入型号编码" />
        </el-form-item>
        <el-form-item label="货道数" prop="vmRow">
            <el-input-number v-model="form.vmRow" placeholder="请输入"  :min="1" :max="10"/>行&nbsp;&nbsp;
            <el-input-number v-model="form.vmCol" placeholder="请输入"  :min="1" :max="10"/>列
        </el-form-item>
        <el-form-item label="货道容量" prop="channelMaxCapacity">
            <el-input-number v-model="form.channelMaxCapacity" placeholder="请输入"  :min="1" :max="10"/>个
        </el-form-item>
        <el-form-item label="设备图片" prop="image">
            <image-upload v-model="form.image"/>
        </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>

1.4、设备管理改造

1.4.1、基础页面

1.4.1.1、需求

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

1.4.1.2、代码实现

刷新设备表数据

update tb_vending_machine set partner_id=2 where id=80;
update tb_vending_machine set addr=(select address from tb_node where id = 1) where node_id=1;
update tb_vending_machine set addr=(select address from tb_node where id = 2) where node_id=2;

Input Number 数字输入框 | Element Plus

1、将设备容量由文本框改为数字框

2、 

改为一行内展示,数字框

 

3、测试

4、模拟数据字典的方式(之前用的多表查询)来展示合作商设备型号

 

 1、数据字典首先做了预加载的操作,预加载设备状态的所有列表信息

2、然后在展示区域自定义列表标签

3、首先使用v-for来遍历我们的字典选项、然后进行一个条件判断、当我们数据库返回的值和字典的值一样,就在页面中去显示对应的名称。

4、当然设备型号和合作商是作为数据库的外键字段,并不是字典。不能直接用数据字典的相关标签,而是通过前端代码做一个模拟操作。

预加载设备型号列表信息和合作商列表信息

1、引入js文件 

2、 方法

3、测试

 

4、接下来使用v-for的指令来遍历,将原有的外键id显示对应的名称 

 

 

 数据库只是做了一个单表查询操作

新增设备管理改造

 

文本框改为下拉框(选择型号:我们在列表展示期间已经预加载了所有型号信息) 

 

选择点位:(之前没有查询过,所以要重新查询一遍,先导入js,然后进行查询)

导入js

方法

 改为下拉框

 测试

修改设备改造 

 这里设备类型v-if判断需要用form.vmTypeId(表单中id),不是之前scope.row.vmTypeId(行对象id

 

 

 

在vm/index.vue视图组件中修改

<!-- 查询条件 -->
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
    <el-form-item label="设备编号" prop="innerCode">
        <el-input v-model="queryParams.innerCode" placeholder="请输入设备编号" clearable @keyup.enter="handleQuery" />
    </el-form-item>
    <el-form-item>
        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
    </el-form-item>
</el-form>

<!-- 列表展示 -->
<el-table v-loading="loading" :data="vmList" @selection-change="handleSelectionChange">
  <el-table-column type="selection" width="55" align="center" />
  <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="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>
  <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" class-name="small-padding fixed-width">
    <template #default="scope">
      <el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['manage:vm:edit']">修改</el-button>
    </template>
  </el-table-column>
</el-table>

<!-- 添加或修改设备管理对话框 -->
<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="设备编号">
      <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="设备类型" v-if="form.innerCode != null">
      <div v-for="item in vmTypeList" :key="item.id">
        <span v-if="form.vmTypeId == item.id">{{ item.name }}</span>
      </div>
    </el-form-item>
    <el-form-item label="设备容量" v-if="form.innerCode != null">
      <span>{{ form.channelMaxCapacity }}</span>
    </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="请选择设备型号" style="width: 100%">
        <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="nodeId">
      <!-- <el-input v-model="form.nodeId" placeholder="请输入点位Id" /> -->
      <el-select v-model="form.nodeId" placeholder="请选择点位" style="width: 100%">
        <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="合作商" v-if="form.innerCode != null">
      <div v-for="item in partnerList" :key="item.id">
        <span v-if="form.partnerId == item.id">{{ item.partnerName }}</span>
      </div>
    </el-form-item>
    <el-form-item label="所属区域" v-if="form.innerCode != null">
      <div v-for="item in regionList" :key="item.id">
        <span v-if="form.regionId == item.id">{{ item.regionName }}</span>
      </div>
    </el-form-item>
    <el-form-item label="设备地址" 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>

<script setup name="Vm">
import { listVmType } from "@/api/manage/vmType";
import { listPartner } from "@/api/manage/partner";
import { loadAllParams } from '@/api/page';
import { listNode } from '@/api/manage/node';
import { listRegion } from "@/api/manage/region";
    
/* 查询设备类型列表 */
const vmTypeList = ref([]);
function getVmTypeList() {
  listVmType(loadAllParams).then((response) => {
    vmTypeList.value = response.rows;
  });
}
/* 查询合作商列表 */
const partnerList = ref([]);
function getPartnerList() {
  listPartner(loadAllParams).then((response) => {
    partnerList.value = response.rows;
  });
}
/* 查询点位列表 */
const nodeList = ref([]);
function getNodeList() {
  listNode(loadAllParams).then((response) => {
    nodeList.value = response.rows;
  });
}
/* 查询区域列表 */
const regionList = ref([]);
function getRegionList() {
  listRegion(loadAllParams).then((response) => {
    regionList.value = response.rows;
  });
}
getRegionList();
getPartnerList();
getNodeList();
getVmTypeList();
</script>

1.4.2、新增设备

1.4.2.1、需求

新增设备时,补充设备表其他字段信息,还需要根据售货机类型创建所属货道

我们了解到在新增设备时,添加设备和货道表,还包含点位和设备类型的查询,共涉及到四张表的操作

这个过程需要我们仔细处理每个字段,确保数据的一致性和完整性

本次修改只涉及到后端部分

新增时,只有点位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位编号,补充货道编号
    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());
    BeanUtil.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;
}

如果循环30次,每次都存到数据库当中,底层都需要跟数据库建立连接操作。

所以改为批量保存

【若依的代码中没有提供批量新增的操作,需要自己动手改造】

批量新增不需要动态sql,传哪个值,修改哪个值即可

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);
}

测试

 

有小bug,下面商品id,为0代表没有关联商品,但是这里为null,可能会出现空指针异常

【mapper.xml中不传入数据即可,数据库设置默认为0】

 

1.4.3、修改设备

1.4.3.1、需求

修改设备时,根据点位同步更新冗余字段信息

根据前端提交的点位ID,后端需要查询点位表,来获取点位的详细信息,包括详细地址、商圈类型、区域ID和合作商ID,获取到点位信息后,我们需要更新设备表中的相关冗余字段。

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

改一下

 

1.5、设备状态改造

因为设备状态和设备管理是同一套后端代码,导致若依没有生成这部分的前端代码

1.5.1、创建视图组件

创建vmStatus/index.vue视图组件

1.5.2、创建二级菜单

1、组件路径需要和下面映射上

2、路由地址就是网页显示的地址(需要和组件映射上,然后产生页面的跳转)

区别:没有其它的权限(与生成代码导入数据库相比)

 

其实就是数据库多了一些数据

 

1.5.3、改造视图组件

1、

 2、查看详情

 

 

<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
      <el-form-item label="设备编号" prop="innerCode">
        <el-input
          v-model="queryParams.innerCode"
          placeholder="请输入设备编号"
          clearable
          @keyup.enter="handleQuery"
        />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

  
	<!-- 列表展示 -->
    <el-table v-loading="loading" :data="vmList" @selection-change="handleSelectionChange">
      <el-table-column label="序号" type="index" width="55" align="center" />
      <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="left" prop="addr" show-overflow-tooltip="true"/>
      <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">
         {{ scope.row.runningStatus!=null? JSON.parse(scope.row.runningStatus).status==true?'正常':'异常' :'异常'}}
        </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>
      </el-table-column>
    </el-table>
    
    <pagination
      v-show="total>0"
      :total="total"
      v-model:page="queryParams.pageNum"
      v-model:limit="queryParams.pageSize"
      @pagination="getList"
    />

    <!-- 添加或修改设备管理对话框 -->
    <el-dialog :title="title" v-model="open" width="500px" append-to-body>
    </el-dialog>
  </div>
</template>

<script setup name="Vm">
import { listVm, getVm, delVm, addVm, updateVm } from "@/api/manage/vm";
import{listVmType} from "@/api/manage/vmType";
import{listPartner} from "@/api/manage/partner";
import{loadAllParams} from "@/api/page";
import{listNode} from "@/api/manage/node";
import{listRegion} from "@/api/manage/region";
import { ref } from "vue";

const { proxy } = getCurrentInstance();
const { vm_status } = proxy.useDict('vm_status');

const vmList = ref([]);
const open = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const title = ref("");

const data = reactive({
  form: {},
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    innerCode: null,
    nodeId: null,
    businessType: null,
    regionId: null,
    partnerId: null,
    vmTypeId: null,
    vmStatus: null,
    runningStatus: null,
    policyId: null,
  },
  rules: {
    nodeId: [
      { required: true, message: "点位Id不能为空", trigger: "blur" }
    ],
    vmTypeId: [
      { required: true, message: "设备型号不能为空", trigger: "blur" }
    ],
  }
});

const { queryParams, form, rules } = toRefs(data);

/** 查询设备管理列表 */
function getList() {
  loading.value = true;
  listVm(queryParams.value).then(response => {
    vmList.value = response.rows;
    total.value = response.total;
    loading.value = false;
  });
}

// 取消按钮
function cancel() {
  open.value = false;
  reset();
}

// 表单重置
function reset() {
  form.value = {
    id: null,
    innerCode: null,
    channelMaxCapacity: null,
    nodeId: null,
    addr: null,
    lastSupplyTime: null,
    businessType: null,
    regionId: null,
    partnerId: null,
    vmTypeId: null,
    vmStatus: null,
    runningStatus: null,
    longitudes: null,
    latitude: null,
    clientId: null,
    policyId: null,
    createTime: null,
    updateTime: null
  };
  proxy.resetForm("vmRef");
}

/** 搜索按钮操作 */
function handleQuery() {
  queryParams.value.pageNum = 1;
  getList();
}

/** 重置按钮操作 */
function resetQuery() {
  proxy.resetForm("queryRef");
  handleQuery();
}

// 多选框选中数据
function handleSelectionChange(selection) {
  ids.value = selection.map(item => item.id);
  single.value = selection.length != 1;
  multiple.value = !selection.length;
}

/** 新增按钮操作 */
function handleAdd() {
  reset();
  open.value = true;
  title.value = "添加设备管理";
}

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

/** 提交按钮 */
function submitForm() {
  proxy.$refs["vmRef"].validate(valid => {
    if (valid) {
      if (form.value.id != null) {
        updateVm(form.value).then(response => {
          proxy.$modal.msgSuccess("修改成功");
          open.value = false;
          getList();
        });
      } else {
        addVm(form.value).then(response => {
          proxy.$modal.msgSuccess("新增成功");
          open.value = false;
          getList();
        });
      }
    }
  });
}

/** 删除按钮操作 */
function handleDelete(row) {
  const _ids = row.id || ids.value;
  proxy.$modal.confirm('是否确认删除设备管理编号为"' + _ids + '"的数据项?').then(function() {
    return delVm(_ids);
  }).then(() => {
    getList();
    proxy.$modal.msgSuccess("删除成功");
  }).catch(() => {});
}

/** 导出按钮操作 */
function handleExport() {
  proxy.download('manage/vm/export', {
    ...queryParams.value
  }, `vm_${new Date().getTime()}.xlsx`)
}

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

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

/* 查询点位列表 */
const nodeList=ref([]);
function getNodeList() {
  listNode(loadAllParams).then(response => {
    nodeList.value = response.rows;
  });
}

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

getRegionList();
getNodeList();
getPartnerList();
getVmTypeList();
getList();
</script>

1.6、点位查看详情

目前还没有查看详情:

1、查看详情按钮 

2、引入js 

3、方法(nodeOpen是来控制对话框显示隐藏 

4、对话框(可以复制之前的设备状态进行修改)

 这里设备状态用到数据字典(需要预加载)

这里没有生成预加载

所以

 5、引入数据字典状态信息

 

6、测试

 

在node/index.vue视图组件中修改

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

<!-- 点位详情对话框 -->
<el-dialog title="点位详情" v-model="nodeOpen" width="600px" append-to-body>
  <el-table :data="vmList">
    <el-table-column label="序号" type="index" width="80" align="center" prop="id" />
    <el-table-column label="设备编号" align="center" prop="innerCode" />
    <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="lastSupplyTime" width="180">
      <template #default="scope">
        <span>{{ parseTime(scope.row.lastSupplyTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
      </template>
    </el-table-column>
  </el-table>
</el-dialog>


<script setup name="Node">
import { listVm } from "@/api/manage/vm";
/* 引入设备状态数据字典 */
const { vm_status } = proxy.useDict('vm_status');
    
/* 查看详情 */
const nodeOpen = ref(false);
const vmList = ref([]);
function getNodeInfo(row) {
  // 根据点位id,查询设备列表
  loadAllParams.nodeId = row.id;
  listVm(loadAllParams).then(response => {
    vmList.value = response.rows;
    nodeOpen.value = true;
  });
}
</script>

2、策略管理

2.1、需求说明

策略管理主要涉及到二个功能模块,业务流程如下:

  1. 新增策略: 允许管理员定义新的策略,包括策略的具体内容和参数(如折扣率)

  2. 策略分配: 将策略分配给一个或多个售货机。


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

  • 关系字段:policy_id

2.2、生成基础代码

2.2.1、需求

使用若依代码生成器,生成策略管理前后端基础代码,并导入到项目中:

2.2.2、步骤

①创建目录菜单

创建策略管理目录菜单

②配置代码生成信息

导入策略表

配置策略表(参考原型)

③下载代码并导入项目

选中策略表生成下载

解压ruoyi.zip得到前后端代码和动态菜单sql

导入动态菜单

 

代码导入

重启

2.3、策略管理改造

2.3.1、基础页面

2.3.1.1、需求

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

2.3.1.2、代码实现

在policy/index.vue视图组件中修改

改造完毕:

1、添加策略管理

 不支持小数

<!-- 列表展示 -->
<el-table v-loading="loading" :data="policyList" @selection-change="handleSelectionChange">
  <el-table-column type="selection" width="55" align="center" />
  <el-table-column label="序号" type="index" width="50" align="center" prop="policyId" />
  <el-table-column label="策略名称" align="center" prop="policyName" />
  <el-table-column label="策略方案" align="center" prop="discount" />
  <el-table-column label="创建时间" align="center" prop="createTime" width="180">
    <template #default="scope">
      <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</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="handleUpdate(scope.row)" v-hasPermi="['manage:policy:edit']">修改</el-button>
      <el-button link type="primary"  @click="handleDelete(scope.row)" v-hasPermi="['manage:policy:remove']">删除</el-button>
    </template>
  </el-table-column>
</el-table>


<!-- 添加或修改策略管理对话框 -->
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
  <el-form ref="policyRef" :model="form" :rules="rules" label-width="80px">
    <el-form-item label="策略名称" prop="policyName">
      <el-input v-model="form.policyName" placeholder="请输入策略名称" />
    </el-form-item>
    <el-form-item label="策略方案" prop="discount">
     <el-input-number :min="1" :max="100" :precision="0" v-model="form.discount" placeholder="请输入策略" />
    </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>

2.3.2、查看详情

2.3.2.1、需求

点击查看详情,展示策略名称和该策略下的设备列表

2.3.2.2、代码实现

之前做过很多次了

1、添加查看详情按钮,绑定一个点击事件,点击事件时促发相应的方法

2、 方法

 

3、查看详情框

 

在policy/index.vue视图组件中修改

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

<!-- 策略详情对话框 -->
<el-dialog v-model="policyOpen" title="策略详情" width="500px">
  <el-form-item label="策略名称" prop="policyName">
    <el-input v-model="form.policyName" placeholder="请输入策略名称" disabled />
  </el-form-item>
  <label>包含设备:</label>
  <el-table :data="vmList">
    <el-table-column label="序号" type="index" width="80" align="center" prop="id" />
    <el-table-column label="点位地址" align="left" prop="addr" show-overflow-tooltip />
    <el-table-column label="设备编号" align="center" prop="innerCode" />
  </el-table>
</el-dialog>

<script setup name="Policy">
import { listVm } from "@/api/manage/vm";
import { loadAllParams } from "@/api/page";
    
/* 查看策略详情 */
const policyOpen = ref(false);
const vmList = ref([]);
function getPolicyInfo(row) {
  //1. 获取策略信息
  form.value = row;
  //2. 根据策略id,查询设备列表
  loadAllParams.policyId = row.policyId;
  listVm(loadAllParams).then(response => {
    vmList.value = response.rows;
    policyOpen.value = true;
  });
}
</script>

2.4、设备策略分配

2.4.1、需求

设备管理页面中点击策略,对设备设置一个固定折扣,用于营销作用

2.4.2、代码实现

1、

2、

 

3、 

点击策略的时候会弹窗 【查询所有策略列表,同时在前端部分把当前行的id和策略id(红框)封装给表单对象了(策略管理)】

这个确定和取消可以和修改设备共用

 

 

点击确认:(以设备id为条件去更新当前设备的策略id

 

是因为这里点位id为空,所以查询的就是null

 

在vm/index.vue视图组件中修改

<el-button link type="primary" @click="handleUpdatePolicy(scope.row)" v-hasPermi="['manage:vm:edit']">策略</el-button>

<!-- 策略管理对话框 -->
<el-dialog title="策略管理" v-model="policyOpen" width="500px" append-to-body>
  <el-form ref="vmRef" :model="form" label-width="80px">
    <el-form-item label="策略" prop="policyId">
      <el-select v-model="form.policyId" placeholder="请选择策略">
        <el-option v-for="item in policyList" :key="item.policyId" :label="item.policyName"
          :value="item.policyId"></el-option>
      </el-select>
    </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>

<script setup name="Vm">
import { listPolicy } from '@/api/manage/policy';
    
// 取消按钮
function cancel() {
  open.value = false;
  policyOpen.value=false; // 关闭策略对话框
  reset();
}
    
/** 提交按钮 */
function submitForm() {
  proxy.$refs["vmRef"].validate(valid => {
    if (valid) {
      if (form.value.id != null) {
        updateVm(form.value).then(response => {
          proxy.$modal.msgSuccess("修改成功");
          open.value = false;
           
          getList();
        });
      } else {
        addVm(form.value).then(response => {
          proxy.$modal.msgSuccess("新增成功");
          open.value = false;
          getList();
        });
      }
    }
  });
}
    
/* 设备策略分配 */
const policyList = ref([]);
const policyOpen = ref(false);
function handleUpdatePolicy(row) {
  //1. 为表单赋值设备id和策略id
  form.value.id = row.id;
  form.value.policyId = row.policyId;
  //2. 查询策略列表
  listPolicy(loadAllParams).then((response) => {
    policyList.value = response.rows;
    policyOpen.value = true;
  });
}
</script>

确保确认对话框取消

在VendingMachineServiceImpl中修改

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值