一、设计需求
本系统主要是由RFID自动识别技术,通过无线射频方式对宠物的电子标签进行读取,获取宠物的基本信息和在店内的所有消费,然后将数据通过网络传输至服务器。在应用层开发一个管理系统,对宠物信息、店内消费等各种行为进行管理。同时系统需有登录注册功能,宠物信息管理,店内消费管理等功能。
宠物店管理系统主要分为以下模块:
1.RFID模块:由天线和射频电路组成,通过自动识别电子标签,采集数据,采用RFID封装技术将其封装,并传输给服务器。
2.电子标签模块:接收外部信号和发送信号
3.店铺管理模块:管理员可以对店铺商品进行增删改操作,修改、删除顾客宠物信息以及店内消费行为。
4.登录注册模块:新用户可以进行注册和登录5.用户管理模块:对注册用户进行管理
二、设计需求总结
整个系统的设计:
(1). 宠物店每来一个新的宠物,就在软件端进行注册、注册时填入宠物的名称,宠物的类型,主人的电话号码、选择一张宠物的图片方便后面展示(图片可以预存几张猫、狗即可)、如果宠物后面在店里有消费也会记录包含时间,这些数据都保存在软件端的数据库里。
(2). 开卡: 新宠物注册之后,需要为这个宠物办理一张电子标签卡,这个卡里存放着这个宠物主人的电话号码,后面要查询这个宠物的信息,就读取整个电子标签里的电话号码,到数据库里查询。
(3). 开卡和查询的数据传输: 设备端与软件端采用 TCP网络方式进行通信;设备端当做TCP客户端,软件端当做TCP服务器;当设备端查询宠物的电子标签时,设备端读取电话号码之后,会通过约定的数据格式通过网络传递给软件端。 当软件端开卡注册时,也会用约定好的数据格式传递给设备端,如果设备端收到数据,开发板上的LED会点亮;这时把IC拿到RC522射频模块上刷一下即可;如果成功写入LED灯就会关闭。
(4). 软件端的设计(这个软件是给店家用的,功能都是针对店家这边方向开发):
有注册界面、登录界面;
主界面上显示店内有所有注册过的宠物信息,每个宠物有图片进行显示、宠物图片下面就显示宠物的名称;
商品界面: 展示一些狗粮、猫粮、药剂、一些宠物周边物品。 用于演示消费功能。 可以预定几个商品即可。 用户可以自己动态添加修改。
管理员界面: 可以对店内的商品进行添加、设计价格、修改宠物的信息等。
查询页面: 输入宠物信息可以查询这个宠物在店里的所有详细信息。
设备硬件部分:
这里的硬件刷卡部分采用的使用STM32开发的,更加灵活方便,完成对IC卡读写通过网络与JAVA服务器通信,也可以换成扫码枪之类的其他设备。
1. RC522刷卡模块负责对卡进行读写。
2. ESP8266WIFI初始化工作在STA模式,连接到指定WIFI,与软件所在的电脑处于同一个局域网,方便连接软件端的服务器进行数据通信,每次设备开机将会自动连接到程序里设置好WIFI热点和服务器。
3. 设备端上有一个LED灯,用来显示刷卡的状态—成功与否。
完整资料包下载地址: https://download.csdn.net/download/xiaolong1126626497/20687600
三、硬件设备效果图与部分核心代码
#include "esp8266.h" u8 ESP8266_IP_ADDR[16]; //255.255.255.255 u8 ESP8266_MAC_ADDR[18]; //硬件地址 /* 函数功能: ESP8266命令发送函数 函数返回值:0表示成功 1表示失败 */ u8 ESP8266_SendCmd(char *cmd) { u8 i,j; for(i=0;i<10;i++) //检测的次数--发送指令的次数 { USARTx_StringSend(USART3,cmd); for(j=0;j<100;j++) //等待的时间 { delay_ms(50); if(USART3_RX_FLAG) { USART3_RX_BUFFER[USART3_RX_CNT]='\0'; USART3_RX_FLAG=0; USART3_RX_CNT=0; if(strstr((char*)USART3_RX_BUFFER,"OK")) { return 0; } } } } return 1; } /* 函数功能: ESP8266硬件初始化检测函数 函数返回值:0表示成功 1表示失败 */ u8 ESP8266_Init(void) { //退出透传模式 USARTx_StringSend(USART3,"+++"); delay_ms(50); return ESP8266_SendCmd("AT\r\n"); } /* 函数功能: 一键配置WIFI为AP+TCP服务器模式 函数参数: char *ssid 创建的热点名称 char *pass 创建的热点密码 (最少8位) u16 port 创建的服务器端口号 函数返回值: 0表示成功 其他值表示对应错误值 */ u8 ESP8266_AP_TCP_Server_Mode(char *ssid,char *pass,u16 port) { char *p; u8 i; char ESP8266_SendCMD[100]; //组合发送过程中的命令 /*1. 测试硬件*/ if(ESP8266_SendCmd("AT\r\n"))return 1; /*2. 关闭回显*/ if(ESP8266_SendCmd("ATE0\r\n"))return 2; /*3. 设置WIFI模式*/ if(ESP8266_SendCmd("AT+CWMODE=2\r\n"))return 3; /*4. 复位*/ ESP8266_SendCmd("AT+RST\r\n"); delay_ms(1000); delay_ms(1000); delay_ms(1000); /*5. 关闭回显*/ if(ESP8266_SendCmd("ATE0\r\n"))return 5; /*6. 设置WIFI的AP模式参数*/ sprintf(ESP8266_SendCMD,"AT+CWSAP=\"%s\",\"%s\",1,4\r\n",ssid,pass); if(ESP8266_SendCmd(ESP8266_SendCMD))return 6; /*7. 开启多连接*/ if(ESP8266_SendCmd("AT+CIPMUX=1\r\n"))return 7; /*8. 设置服务器端口号*/ sprintf(ESP8266_SendCMD,"AT+CIPSERVER=1,%d\r\n",port); if(ESP8266_SendCmd(ESP8266_SendCMD))return 8; /*9. 查询本地IP地址*/ if(ESP8266_SendCmd("AT+CIFSR\r\n"))return 9; //提取IP地址 p=strstr((char*)USART3_RX_BUFFER,"APIP"); if(p) { p+=6; for(i=0;*p!='"';i++) { ESP8266_IP_ADDR[i]=*p++; } ESP8266_IP_ADDR[i]='\0'; } //提取MAC地址 p=strstr((char*)USART3_RX_BUFFER,"APMAC"); if(p) { p+=7; for(i=0;*p!='"';i++) { ESP8266_MAC_ADDR[i]=*p++; } ESP8266_MAC_ADDR[i]='\0'; } //打印总体信息 USART1_Printf("当前WIFI模式:AP+TCP服务器\n"); USART1_Printf("当前WIFI热点名称:%s\n",ssid); USART1_Printf("当前WIFI热点密码:%s\n",pass); USART1_Printf("当前TCP服务器端口号:%d\n",port); USART1_Printf("当前TCP服务器IP地址:%s\n",ESP8266_IP_ADDR); USART1_Printf("当前TCP服务器MAC地址:%s\n",ESP8266_MAC_ADDR); return 0; } /* 函数功能: TCP服务器模式下的发送函数 发送指令: */ u8 ESP8266_ServerSendData(u8 id,u8 *data,u16 len) { u8 i,j,n; char ESP8266_SendCMD[100]; //组合发送过程中的命令 for(i=0;i<10;i++) { sprintf(ESP8266_SendCMD,"AT+CIPSEND=%d,%d\r\n",id,len); USARTx_StringSend(USART3,ESP8266_SendCMD); for(j=0;j<10;j++) { delay_ms(50); if(USART3_RX_FLAG) { USART3_RX_BUFFER[USART3_RX_CNT]='\0'; USART3_RX_FLAG=0; USART3_RX_CNT=0; if(strstr((char*)USART3_RX_BUFFER,">")) { //继续发送数据 USARTx_DataSend(USART3,data,len); //等待数据发送成功 for(n=0;n<200;n++) { delay_ms(50); if(USART3_RX_FLAG) { USART3_RX_BUFFER[USART3_RX_CNT]='\0'; USART3_RX_FLAG=0; USART3_RX_CNT=0; if(strstr((char*)USART3_RX_BUFFER,"SEND OK")) { return 0; } } } } } } } return 1; } /* 函数功能: 配置WIFI为STA模式+TCP客户端模式 函数参数: char *ssid 创建的热点名称 char *pass 创建的热点密码 (最少8位) char *p 将要连接的服务器IP地址 u16 port 将要连接的服务器端口号 u8 flag 1表示开启透传模式 0表示关闭透传模式 函数返回值:0表示成功 其他值表示对应的错误 */ u8 ESP8266_STA_TCP_Client_Mode(char *ssid,char *pass,char *ip,u16 port,u8 flag) { char ESP8266_SendCMD[100]; //组合发送过程中的命令 //退出透传模式 //USARTx_StringSend(USART3,"+++"); //delay_ms(50); /*1. 测试硬件*/ if(ESP8266_SendCmd("AT\r\n"))return 1; /*2. 关闭回显*/ if(ESP8266_SendCmd("ATE0\r\n"))return 2; /*3. 设置WIFI模式*/ if(ESP8266_SendCmd("AT+CWMODE=1\r\n"))return 3; /*4. 复位*/ ESP8266_SendCmd("AT+RST\r\n"); delay_ms(1000); delay_ms(1000); delay_ms(1000); /*5. 关闭回显*/ if(ESP8266_SendCmd("ATE0\r\n"))return 5; /*6. 配置将要连接的WIFI热点信息*/ sprintf(ESP8266_SendCMD,"AT+CWJAP=\"%s\",\"%s\"\r\n",ssid,pass); if(ESP8266_SendCmd(ESP8266_SendCMD))return 6; /*7. 设置单连接*/ if(ESP8266_SendCmd("AT+CIPMUX=0\r\n"))return 7; /*8. 配置要连接的TCP服务器信息*/ sprintf(ESP8266_SendCMD,"AT+CIPSTART=\"TCP\",\"%s\",%d\r\n",ip,port); if(ESP8266_SendCmd(ESP8266_SendCMD))return 8; /*9. 开启透传模式*/ if(flag) { if(ESP8266_SendCmd("AT+CIPMODE=1\r\n"))return 9; //开启 if(ESP8266_SendCmd("AT+CIPSEND\r\n"))return 10; //开始透传 if(!(strstr((char*)USART3_RX_BUFFER,">"))) { return 11; } //如果想要退出发送: "+++" } //打印总体信息 USART1_Printf("当前WIFI模式:STA+TCP客户端\n"); USART1_Printf("当前连接的WIFI热点名称:%s\n",ssid); USART1_Printf("当前连接的WIFI热点密码:%s\n",pass); USART1_Printf("当前连接的TCP服务器端口号:%d\n",port); USART1_Printf("当前连接的TCP服务器IP地址:%s\n",ip); return 0; } /* 函数功能: TCP客户端模式下的发送函数 发送指令: */ u8 ESP8266_ClientSendData(u8 *data,u16 len) { u8 i,j,n; char ESP8266_SendCMD[100]; //组合发送过程中的命令 for(i=0;i<10;i++) { sprintf(ESP8266_SendCMD,"AT+CIPSEND=%d\r\n",len); USARTx_StringSend(USART3,ESP8266_SendCMD); for(j=0;j<10;j++) { delay_ms(50); if(USART3_RX_FLAG) { USART3_RX_BUFFER[USART3_RX_CNT]='\0'; USART3_RX_FLAG=0; USART3_RX_CNT=0; if(strstr((char*)USART3_RX_BUFFER,">")) { //继续发送数据 USARTx_DataSend(USART3,data,len); //等待数据发送成功 for(n=0;n<200;n++) { delay_ms(50); if(USART3_RX_FLAG) { USART3_RX_BUFFER[USART3_RX_CNT]='\0'; USART3_RX_FLAG=0; USART3_RX_CNT=0; if(strstr((char*)USART3_RX_BUFFER,"SEND OK")) { return 0; } } } } } } } return 1; }
四、JAVA端效果图与部分代码示例
完整资料包下载地址: https://download.csdn.net/download/xiaolong1126626497/20687600
package com.controller; import java.util.List; import java.util.Map; import javax.servlet.http.HttpSession; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.common.bean.MySessionContext; import com.common.bean.ResultData; import com.entity.User; import com.mapper.UserMapper; @RestController() @RequestMapping("/user") public class UserController { @Autowired private UserMapper um; @PostMapping("changepswd.action") ResultData changePswd(String token,@RequestBody Map<String,String> map) { HttpSession ss = MySessionContext.getSession( token ); if( ss == null ) { return ResultData.fail("请先登录!"); } User uu = (User) ss.getAttribute("login_user"); if( uu == null ) return ResultData.fail("请先登录!"); String password = map.get("password"); String newpassword = map.get("password2"); int num = um.updatePassword(uu.getId(), password, newpassword); if( num > 0) return ResultData.success(); return ResultData.fail("原始密码错误"); } @PostMapping("adduser.action") ResultData addUser(String token,@RequestBody User user) { HttpSession ss = MySessionContext.getSession( token ); if( ss == null ) { return ResultData.fail("请先登录!"); } User uu = (User) ss.getAttribute("login_user"); System.out.println( uu ); if( uu == null ) return ResultData.fail("请先登录!"); if( !("admin".equalsIgnoreCase(uu.getRole()) || "root".equals( uu.getRole() ) ) ) { return ResultData.fail("请用管理员账号登录再添加"); } um.addUser(user); return ResultData.success(); } @PostMapping("delete.action") ResultData deleteUser(String token,@RequestBody User user) { System.out.println( user); HttpSession ss = MySessionContext.getSession( token ); if( ss == null ) { return ResultData.fail("请先登录!"); } User uu = (User) ss.getAttribute("login_user"); if( uu == null ) return ResultData.fail("请先登录!"); if("admin".equalsIgnoreCase(user.getRole()) || "root".equals( user.getRole() )) return ResultData.fail("无法删除管理员用户!"); if( !("admin".equalsIgnoreCase(uu.getRole()) || "root".equals( uu.getRole() ) ) ) { return ResultData.fail("请用管理员账号登录再删除"); } um.deleteUser(user); return ResultData.success(); } @PostMapping("getall.action") ResultData getAll(String token) { HttpSession ss = MySessionContext.getSession( token ); if( ss == null ) { return ResultData.fail("请先登录!"); } List<User> list = um.getAll(); for(User u:list) { u.setPassword(null); } return ResultData.success().setData( list ); } @PostMapping("logout.action") ResultData getAllUser(String token) { HttpSession ss = MySessionContext.getSession( token ); if( ss != null ) { ss.invalidate(); } return ResultData.success(); } @PostMapping("login.action") ResultData login(@RequestBody User user,HttpSession ss) { User rs = um.Login( user ); if(rs != null ) { rs.setPassword( null ); ss.setAttribute("login_user", rs ); MySessionContext.AddSession( ss ); return ResultData.success().setData( rs ).setToken(ss.getId() ); }else { return ResultData.fail("用户名或密码错误!"); } } }
package com.common.wx; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.TextWebSocketHandler; import com.common.bean.WebSocketProductHolder; public class WebSocketServerService extends TextWebSocketHandler{ @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { WebSocketProductHolder.setSession( session ); } }
package com.common.bean; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; import com.alibaba.fastjson.JSONObject; import com.entity.Product; import com.mapper.ProductMapper; @Component public class WebSocketProductHolder implements ApplicationContextAware{ private volatile static WebSocketSession oneSession; private volatile static Socket client; public WebSocketProductHolder() { initServer(); } public static void setSession(WebSocketSession ss) { oneSession = ss; } private static void initServer() { new Thread() { public void run() { ServerSocket ss = null; try { ss = new ServerSocket(9988); System.out.println("初始化"); while(true) { client = ss.accept(); byte [] b = new byte[128]; try { while(true) { int num = client.getInputStream().read(b);//数据少,一次读完就阻塞。 if(num != -1 ) { String cmd = new String(b,0,num); parseCMD( cmd); } } }catch (Exception e) { System.out.println("连接断开..."); } } }catch (Exception e) { } } }.start(); } public static void register(String cardid)throws IOException { if(cardid!=null && cardid.length() >0 && client!=null && client.isConnected()) { client.getOutputStream().write(("register:"+cardid+"\r\n").getBytes()); } } private static void parseCMD(String cmd) { if(cmd.startsWith("query")) { try { String cardid = cmd.split(":")[1].trim(); if( oneSession != null ) { oneSession.sendMessage( new TextMessage( cardid ) ); } }catch (Exception e) { System.out.println("数据错误:"+cmd); } } } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { initServer(); } }
<template> <view> <Menu></Menu> <view class="view_content mc" > <view style="width:400px;"> <view class="commonrow v_center"> <text class="simpletitle">商品名称</text> <uni-easyinput v-model="addModel.name" /> </view> <view class="commonrow v_center mt_5"> <text class="simpletitle">商品价格</text> <uni-easyinput type="number" v-model="addModel.price" placeholder="单位为分,例如,16元请填写1600" /> </view> <view class="commonrow v_center mt_5"> <text class="simpletitle">商品数量</text> <uni-easyinput type="number" v-model="addModel.num" /> </view> <view class="commonrow v_center mt_5"> <text class="simpletitle">商品分类</text> <uni-easyinput v-model="addModel.sortname" /> </view> <view class="commonrow v_center mt_5"> <text class="simpletitle">商品描述</text> <uni-easyinput type="textarea" v-model="addModel.detail" /> </view> <view class="commonrow v_center mt_5"> <text class="simpletitle">商品图片</text> <uni-upload-one-image v-model="addModel.imgurl" /> </view> <view class="commonrow v_center mt_5"> <text class="simpletitle"></text> <text class="submitbtn hand_point" @click="submit">提交</text> </view> </view> </view> </view> </template> <script> import Menu from '@/pages/common/Menu.vue' export default { components:{Menu}, data() { return { addModel:{ } } }, methods: { async submit(){ if(!this.addModel.name){ return this.$api.alert("请填写商品名称!"); } if(!this.addModel.price){ return this.$api.alert("请填写商品价格!"); } if(!this.addModel.num){ return this.$api.alert("请填写商品数量!"); } if(!this.addModel.sortname){ return this.$api.alert("请填写商品分类!"); } if(!this.addModel.detail){ return this.$api.alert("请填写商品描述!"); } if(!this.addModel.imgurl){ return this.$api.alert("请填上传商品图片!"); } console.info( this.addModel ); let res = await this.$api.request("product/add.action",this.addModel); console.info( res ); this.$api.alert("添加成功!"); } } } </script> <style> </style>
<template> <view> <Menu></Menu> <view class="view_content mc"> <view v-show="mode=='query'"> <view class="commonrow h_center" style="width:600px;"> <uni-easyinput v-model="query.id" placeholder="请输入商品编号" /> <uni-easyinput v-model="query.name"placeholder="请输入商品名称" class="ml_10" /> <text class="submitbtn ml_10" @click="queryPro">查询</text> </view> <view class="up_down_content h_center commonrow"> 当前共 {{datalist.length}} 件商品 </view> <uni-table border stripe emptyText="暂无更多数据" type="checkbox" style="width:100%;max-height: 700px;overflow: auto;"> <!-- 表头行 --> <uni-tr> <uni-th align="center" width="150">商品编号</uni-th> <uni-th align="center" width="150">商品名称</uni-th> <uni-th align="left" width="150">商品分类</uni-th> <uni-th align="left" width="100">商品价格</uni-th> <uni-th align="left" width="100">商品数量</uni-th> <uni-th align="left" width="100">商品图片</uni-th> <uni-th align="left" >操作</uni-th> </uni-tr> <uni-tr v-for="(item , index ) in datalist" style="width: 100%;" > <uni-td align="center" > <uni-easyinput v-model="item.id" :disabled="true" /> </uni-td> <uni-td align="center" > {{item.name}} </uni-td> <uni-td> {{item.sortname}} </uni-td> <uni-td> {{item.price|priceText}} </uni-td> <uni-td> {{item.num}} </uni-td> <uni-td> <uni-img :src="item.imgurl"></uni-img> </uni-td> <uni-td> <view class="commonrow"> <text class="submitbtn hand_point" @click="showdetail(item)">详情</text> <text class="deletebtn hand_point ml_10" @click="del(item)">删除</text> <text class="submitbtn hand_point ml_10" @click="edit(item)">修改</text> </view> </uni-td> </uni-tr> </uni-table> </view> <view v-show="mode=='detail'" style="padding-left: 50px;"> <view class="commonrow"> <text class="cancelbtn" @click="mode='query';">返回</text> </view> <view class="commonrow v_center" style="margin-top: 30px;"> <text class="simpletitle">商品编号</text> {{detail.id}} </view> <view class="commonrow v_center mt_5"> <text class="simpletitle">商品名称</text> {{detail.name}} </view> <view class="commonrow v_center mt_5"> <text class="simpletitle">商品价格</text> {{detail.price|priceText}} </view> <view class="commonrow v_center mt_5"> <text class="simpletitle">商品数量</text> {{detail.num}} </view> <view class="commonrow v_center mt_5"> <text class="simpletitle">商品分类</text> {{detail.sortname}} </view> <view class="commonrow v_center mt_5"> <text class="simpletitle">商品描述</text> {{detail.detail}} </view> <view class="commonrow v_center mt_5"> <text class="simpletitle">商品图片</text> <uni-img :src="detail.imgurl"></uni-img> </view> </view> </view> </view> </template> <script> import Menu from '@/pages/common/Menu.vue' export default { components:{Menu}, data() { return { query:{}, datalist:[], detail:{}, mode:"query" } }, onLoad() { this.load(); }, methods: { showdetail( item ){ this.mode = "detail"; this.detail = item; }, async edit(item){ this.navTo("/pages/product/update?id="+item.id); }, async queryPro(){ if(!this.query.id)delete this.query.id; if(!this.query.name)delete this.query.name; if(this.query.id){ this.query.id = Number(this.query.id); } let res = await this.$api.request("product/query.action",this.query); this.datalist = res.data; }, async load(){ let res = await this.$api.request("product/all.action"); this.datalist = res.data; }, del(item){ this.$api.confirm(async ()=>{ let res = await this.$api.request("product/delete.action",item); this.$api.alert("删除成功!"); await this.load(); },"删除后不可恢复,确认删除吗?") } } } </script> <style> </style>
<template> <view> <Menu></Menu> <view class="view_content mc" > <view style="width:400px;" v-if="model"> <view class="commonrow v_center"> <text class="simpletitle">商品名称</text> <uni-easyinput v-model="model.name" /> </view> <view class="commonrow v_center mt_5"> <text class="simpletitle">商品价格</text> <uni-easyinput type="number" v-model="model.price" placeholder="单位为分,例如,16元请填写1600" /> </view> <view class="commonrow v_center mt_5"> <text class="simpletitle">商品数量</text> <uni-easyinput type="number" v-model="model.num" /> </view> <view class="commonrow v_center mt_5"> <text class="simpletitle">商品分类</text> <uni-easyinput v-model="model.sortname" /> </view> <view class="commonrow v_center mt_5"> <text class="simpletitle">商品描述</text> <uni-easyinput type="textarea" v-model="model.detail" /> </view> <view class="commonrow v_center mt_5"> <text class="simpletitle">商品图片</text> <uni-upload-one-image v-model="model.imgurl" /> </view> <view class="commonrow v_center mt_5"> <text class="simpletitle"></text> <text class="submitbtn hand_point" @click="submit">提交</text> </view> </view> </view> </view> </template> <script> import Menu from '@/pages/common/Menu.vue' export default { components:{Menu}, data() { return { model:null } }, onLoad({id}){ if(!id)return this.$api.alert("参数错误!"); this.loadProduct(id); }, methods: { async loadProduct(id){ let res = await this.$api.request("product/byid.action",{id}); if(res.data ){ this.model = res.data; } console.info(this.model); }, async submit(){ if(!this.model.name){ return this.$api.alert("请填写商品名称!"); } if(!this.model.price){ return this.$api.alert("请填写商品价格!"); } if(!this.model.num){ return this.$api.alert("请填写商品数量!"); } if(!this.model.sortname){ return this.$api.alert("请填写商品分类!"); } if(!this.model.detail){ return this.$api.alert("请填写商品描述!"); } if(!this.model.imgurl){ return this.$api.alert("请填上传商品图片!"); } console.info( this.model ); let res = await this.$api.request("product/update.action",this.model); this.$api.alert("修改成功!"); this.navTo("/pages/product/search"); } } } </script> <style> </style>