有趣生活

当前位置:首页>科技>正规的仓储出入库管理系统报价工厂订单出入库信息管理系统模块2

正规的仓储出入库管理系统报价工厂订单出入库信息管理系统模块2

发布时间:2026-06-22阅读(1)

导读一、前言工厂订单及出入库业务的趋势是客户要求越来越高,客户需要快捷、方便、简单、一站式的出入库手续。因此,货物出入库管理信息系统要简化出入库手续,减轻人员作.... 一、前言

工厂订单及出入库业务的趋势是客户要求越来越高,客户需要快捷、方便、简单、一站式的出入库手续。因此,货物出入库管理信息系统要简化出入库手续,减轻人员作业量,提高工作效率,助力企业数字信息化转型

之前整理过该系统的完整解决方案,有兴趣的可以参考文章:《工厂订单出入库信息管理系统》完整解决方案(含演示账号)

二、整体架构设计开发语言:
  • Golang:Go 极其地快。其性能与 Java 或 C 相似。在我们的使用中,Go 一般比 Python 要快 30 倍。
  • Vue: 轻量级框架, 大小只有几十kb, 国人开发,中文文档,不存在语言障碍,易于理解和学习。运行速度更快,相比较与react而言,同样都是操作虚拟dom,就性能而言,vue存在很大的优势。
部署方式:
  • 服务器系统:基于免安装可执行程序:支持Windows、Linux,Centos,Ubuntu操作系统
  • 数据库类型:目前已支持PostgreSQL、MySQL、Oracle、Microsoft sql Server、SQLite等,还可以定制其它类型数据库
  • 热数据缓存服务:基于Key-Value 的Redis 数据库,关键热活数据存储在Redis服务中,提高响应速率。
  • 主备双活服务器:确保稳定性,如果主服务器故障,自动切换到备服务器。热数据
  • 数据库备份:定时增量备份,定期全量备份。
三、编码实现 (基于篇幅及可读性考虑,此处展示部分关键代码)

1、模块截图

2、Go 关键代码

package modelsimport ("fmt""github.com/astaxie/beego/orm""productManage/common"writelog "productManage/log""strconv""time")type Sn struct {Sn string `orm:"column(Sn);size(255);pk" description:"唯一SN"`BoxNum int `orm:"column(BoxNum)" description:"SN所在的箱号"`BoxTotal int `orm:"column(BoxTotal)" description:"总箱数,对应order表的box_total"`CreateTime int64 `orm:"column(CreateTime)" description:"生成时间"`Ksn string `orm:"column(Ksn);size(255)" description:"唯一KSN"`OrderID string `orm:"column(OrderID);size(255)" description:"订单号,对应order表的order_id"`StatusBox int8 `orm:"column(StatusBox)" description:"装箱状态:0 未确认;1正确;2异常;"`StatusPrepare int8 `orm:"column(StatusPrepare)" description:"备货状态:0 未确认;1正确;2异常;"`StatusQc int8 `orm:"column(StatusQc)" description:"品管状态"`DevId string `orm:"column(DevId);size(255)" description:"五码合一用的"`Sim string `orm:"column(Sim);size(255)" description:"五码合一用的"`Imei string `orm:"column(Imei);size(255)" description:"五码合一用的"`RecipientID int64 `orm:"column(RecipientID);" description:"收件编号"`}type Sn2 struct {BoxNumCount int `orm:"column(BoxNumCount)" description:"SN所在的箱号的sn总数"`BoxNum int `orm:"column(BoxNum)" description:"SN所在的箱号"`}func (t *Sn) TableName() string {return "sn"}func (t *Sn) TableIndex() [][]string {return [][]string{[]string{"OrderID"},}}func init() {orm.RegisterModel(new(Sn))}// AddSn insert a new Sn into database and returns// last inserted Id on success.func AddSn(m *Sn) (id int64, err error) {o := orm.NewOrm()id, err = o.Insert(m)//success id == 0, err == nilreturn}func AddSnList(sn_list []Sn) (err error, error_sn string) {o := orm.NewOrm()o.Begin()writelog.WriteDebug("AddSnList o.Begin() count%d", len(sn_list))_, err = o.InsertMulti(100, sn_list)if err != nil {writelog.WriteError("AddSnList 事务执行错误:err=%s", err.Error())o.Rollback()return err, "InsertMulti"}err = o.Commit()if err != nil {writelog.WriteError("AddSnList 事务提交错误:err=%s", err.Error())return err, "Commit"}writelog.WriteDebug("AddSnList End")return nil, ""}func DelSn(sn string) (num int64, err error) {o := orm.NewOrm()num, err = o.Delete(&Sn{Sn: sn})return num, err}func DelSnByOrderID(OrderID string) (num int64, err error) {o := orm.NewOrm()sql := fmt.Sprintf(`DELETE FROM sn WHERE OrderID=%s`, OrderID)res, err := o.Raw(sql).Exec()if err == nil {num, _ = res.RowsAffected()}return num, err}func GetSnList(StartTime, EndTime int64, OrderID string, Sn string, BoxNum, BoxTotal, StatusBox, Page, RowNum int) (recordcount int64, num int64, sn []Sn, err error, sql string) {if RowNum <= 0 {RowNum = common.Row_Num_Default}sql = fmt.Sprintf(`SELECT * FROM sn WHERE 1=1`)if StartTime > 0 {sql = fmt.Sprintf(` %s AND CreateTime >= %d`, sql, StartTime)}if EndTime > 0 {sql = fmt.Sprintf(` %s AND CreateTime <= %d`, sql, EndTime)}if len(OrderID) > 0 {sql = fmt.Sprintf(` %s AND OrderID like %%%s%%`, sql, OrderID)}if len(Sn) > 0 {sql = fmt.Sprintf(` %s AND Sn like %%%s%%`, sql, Sn)}if BoxNum > 0 {sql = fmt.Sprintf(` %s AND BoxNum = %d`, sql, BoxNum)}if BoxTotal > 0 {sql = fmt.Sprintf(` %s AND BoxTotal = %d`, sql, BoxTotal)}if StatusBox > 0 {sql = fmt.Sprintf(` %s AND StatusBox = %d`, sql, StatusBox)}o := orm.NewOrm()sql_num := "SELECT COUNT(*) FROM ( " sql " ) AS a"err = o.Raw(sql_num).QueryRow(&recordcount)if err != nil {//writelog.WriteDebug(sql_num)return 0, 0, sn, err, sql}if Page >= 0 {sql = sql " limit " strconv.Itoa(Page*RowNum) "," strconv.Itoa(RowNum)}writelog.WriteDebug(sql)num, err = o.Raw(sql).QueryRows(&sn)return recordcount, num, sn, err, sql}func GetSnBySn(strSn string) (v *Sn, err error) {o := orm.NewOrm()var ArraySn []Snnum, err := o.QueryTable("sn").Filter("Sn", strSn).All(&ArraySn)if err == nil {if num <= 0 {writelog.WriteDebug("没找到%s", strSn)return nil, orm.ErrNoRows} else if num > 1 {writelog.WriteDebug("多条报错%s", strSn)return nil, orm.ErrMultiRows} else { //num==1return &ArraySn[0], nil}}return nil, err}func GetSnByKsn(strKsn string) (sn string, err error, _type string) {o := orm.NewOrm()var ArraySn []Snnum, err := o.QueryTable("sn").Filter("Ksn", strKsn).All(&ArraySn)if err == nil {if num <= 0 {writelog.WriteDebug("没找到%s", strKsn)return "", orm.ErrNoRows, ""} else if num > 1 {writelog.WriteDebug("多条报错%s", strKsn)return "", orm.ErrMultiRows, ""} else { //num==1return ArraySn[0].Sn, nil, "ksn"//通过Ksn找到的}}return "", err, ""}//不知道输入的是Sn还是Ksn,通过还原成Snfunc GetSnBySnOrKsn(strSn string) (sn string, err error, _type string) {v, err := GetSnBySn(strSn)if err == nil && v != nil {return v.Sn, nil, "sn"//通过sn找到的}return GetSnByKsn(strSn)}//导入sn的时候,计算每个sn对应的BoxNumfunc SetBoxNumInSn(OrderID string, BoxTotal, NumberPerBox int) {writelog.WriteDebug("--------%s,%d,%d", OrderID, BoxTotal, NumberPerBox)sql := fmt.Sprintf(`SELECT * FROM sn WHERE OrderID=%s`, OrderID)o := orm.NewOrm()sql_num := "SELECT COUNT(*) FROM ( " sql " ) AS a"var recordcount int64err := o.Raw(sql_num).QueryRow(&recordcount)if err != nil {return}Page := 0for 1 == 1 {BoxNum := Page 1sql_update := fmt.Sprintf(`UPDATE sn AS A INNER JOIN (SELECT Sn FROM sn WHERE OrderID=%s LIMIT %s,%s) As B ON A.Sn=B.Sn SET A.BoxNum=%d`,OrderID, strconv.Itoa(Page*NumberPerBox), strconv.Itoa(NumberPerBox), BoxNum)writelog.WriteDebug("sn分箱 start %v", sql_update)o := orm.NewOrm()_, err = o.Raw(sql_update).Exec()if err != nil {writelog.WriteDebug("%s %s", sql_update, err.Error())}writelog.WriteDebug("sn分箱 end")//创建box表sql = fmt.Sprintf(`SELECT Sn FROM sn WHERE OrderID=%s AND BoxNum=%d ORDER BY Sn`, OrderID, BoxNum)var s []Snwritelog.WriteDebug("box分箱 start")n, err := o.Raw(sql).QueryRows(&s)if err != nil {writelog.WriteDebug("%s %s", sql, err.Error())}if n <= 0 {writelog.WriteDebug("n %d error ", n)} else {var box Boxbox.BoxNum = BoxNumbox.OrderID = OrderIDbox.BoxTotal = BoxTotalbox.SnStart = s[0].Snbox.SnEnd = s[n-1].Snbox.CreateTime = time.Now().Unix()_, err = AddBox(&box)if err != nil {writelog.WriteDebug("AddBox BoxNum:%s OrderID:%s, err:%s", BoxNum, OrderID, err.Error())}writelog.WriteDebug("box分箱 end, %v, %v" , BoxNum, box.SnStart )}Page = Page 1time.Sleep(time.Nanosecond)if int64(Page*NumberPerBox) >= recordcount {break}}}func GetSnListByOrderIDAndBoxNum(OrderID string, BoxNum int) (num int64, sn []Sn, err error, sql string) {sql = fmt.Sprintf(`SELECT * FROM sn WHERE 1=1`)if len(OrderID) > 0 {sql = fmt.Sprintf(` %s AND OrderID=%s`, sql, OrderID)}if BoxNum > 0 {sql = fmt.Sprintf(` %s AND BoxNum=%d`, sql, BoxNum)}//writelog.WriteDebug(sql)o := orm.NewOrm()num, err = o.Raw(sql).QueryRows(&sn)return num, sn, err, sql}func UpdateSnStatusBox( SnList []string, StatusBox int) {writelog.WriteDebug("UpdateSnStatusBox begin")sql_update := fmt.Sprintf(`UPDATE sn SET StatusBox=%d WHERE 1 = 1`, StatusBox)Len := len(SnList)if Len > 0 {sql_update = sql_update " and Sn in ("for k, v := range SnList {if k < Len-1 {sql_update = sql_update fmt.Sprintf("%s ,", v)} else {sql_update = sql_update fmt.Sprintf("%s ", v)}}sql_update = sql_update " )"}o := orm.NewOrm()_, err := o.Raw(sql_update).Exec()if err != nil {writelog.WriteDebug("%s %s", sql_update, err.Error())}writelog.WriteDebug("UpdateSnStatusBox %s ok", sql_update)}func UpdateSnBoxStatusBySn(BoxNum int, OrderID string, Sn string, StatusBox int) {sql_update := fmt.Sprintf(`UPDATE sn SET StatusBox=%d WHERE OrderID=%s and BoxNum=%d and Sn=%s`, StatusBox, OrderID, BoxNum, Sn)o := orm.NewOrm()_, err := o.Raw(sql_update).Exec()if err != nil {writelog.WriteDebug("%s %s", sql_update, err.Error())}writelog.WriteDebug("UpdateSnBoxStatusBySn %s ok", sql_update)}// 查询OrderId, BoxNum的 StatusBox 为OK的个数是否等于 NumPerBoxfunc CountSnByBoxNumAndOrderID(BoxNum int, OrderID string) (recordcount int, err error) {o := orm.NewOrm()sql_num := fmt.Sprintf(`SELECT COUNT(*) FROM sn WHERE OrderID=%s and BoxNum=%d `, OrderID, BoxNum)err = o.Raw(sql_num).QueryRow(&recordcount)return recordcount, err}// 查询OrderId, BoxNum的 StatusBox 为OK的个数是否等于 NumPerBoxfunc CountSnByStatusBox(BoxNum int, OrderID string, StatusBox int) (recordcount int, err error) {o := orm.NewOrm()sql_num := fmt.Sprintf(`SELECT COUNT(*) FROM sn WHERE StatusBox=%d and OrderID=%s and BoxNum=%d `, StatusBox, OrderID, BoxNum)err = o.Raw(sql_num).QueryRow(&recordcount)return recordcount, err}func CountSnBySnStartToSnEnd(SnStart, SnEnd string) (recordcount int, err error) {o := orm.NewOrm()sql_num := fmt.Sprintf(`SELECT COUNT(*) FROM sn WHERE Sn>=%s AND Sn<=%s`, SnStart, SnEnd)err = o.Raw(sql_num).QueryRow(&recordcount)writelog.WriteDebug("CountSnBySnStartToSnEnd %s %d", sql_num, recordcount)return recordcount, err}func GetKsnBySn(sn string) (s Sn, err error) {sql := fmt.Sprintf(`select Sn,Ksn from sn where Sn=%s`, sn)o := orm.NewOrm()err = o.Raw(sql).QueryRow(&s)writelog.WriteDebug("GetKsnBySn % v" ,s)return s, err}//更新五码合一数据func Update5Code(sn_s []Sn) {writelog.WriteDebug("% v", sn_s)for _, s := range sn_s {o := orm.NewOrm()sql := fmt.Sprintf(`Update sn set DevId=%s,Sim=%s,Imei=%s WHERE Sn=%s`, s.DevId, s.Sim, s.Sim, s.Sn)//writelog.WriteDebug(sql)o.Raw(sql).Exec()}}func GetSnListByRecipientID(OrderID string , RecipientID int64) (num int64, sn []Sn2, err error) {sql := fmt.Sprintf(`SELECT count(BoxNum) as BoxNumCount, BoxNum FROM sn WHERE RecipientID=%d and OrderID = %s group by BoxNum `, RecipientID, OrderID )o := orm.NewOrm()num, err = o.Raw(sql).QueryRows(&sn)writelog.WriteDebug("%v, %v", sql, sn)return num, sn, err}func EditRecipientIDByOrderIDAndBox(RecipientID int64, OrderID string, BoxNum int , SnStart, SnEnd string) (num int64, err error) {o := orm.NewOrm()sql := fmt.Sprintf(`Update sn set RecipientID=%d WHERE BoxNum=%d And OrderID = %s And Sn >=%s And Sn <=%s `, RecipientID, BoxNum, OrderID, SnStart, SnEnd)writelog.WriteDebug(sql)res, err := o.Raw(sql).Exec()if err == nil {num, _ = res.RowsAffected()writelog.WriteDebug("EditRecipientIDByOrderIDAndBox ok, rows=%d", num)} else {writelog.WriteDebug("EditRecipientIDByOrderIDAndBox err:%s", err.Error())}return num, err}func GetSnListByOrderIDAndBoxNumAndRecipientId(OrderID string, BoxNum int) (num int64, sn []Sn, err error, sql string) {sql = fmt.Sprintf(`SELECT * FROM sn WHERE RecipientId=0`)if len(OrderID) > 0 {sql = fmt.Sprintf(` %s AND OrderID=%s`, sql, OrderID)}if BoxNum > 0 {sql = fmt.Sprintf(` %s AND BoxNum=%d`, sql, BoxNum)}//writelog.WriteDebug(sql)o := orm.NewOrm()num, err = o.Raw(sql).QueryRows(&sn)return num, sn, err, sql}func ResetSnRecipientId(RecipientID int64) (num int64, err error) {o := orm.NewOrm()sql := fmt.Sprintf(`Update sn set RecipientID=0 WHERE RecipientID=%d`, RecipientID)writelog.WriteDebug(sql)res, err := o.Raw(sql).Exec()if err == nil {num, _ = res.RowsAffected()writelog.WriteDebug("ResetSnRecipientId ok, rows=%d", num)} else {writelog.WriteDebug("ResetSnRecipientId err:%s", err.Error())}return num, err}

3、vue代码

<template><div ><div ><div > <span >开始时间</span> <el-date-picker v-model="searchForm.startTime" type="date":clearable="true" format="yyyy-MM-dd 00:00:00" placeholder="选择日期"> </el-date-picker> </div> <div > <span >结束时间</span> <el-date-picker v-model="searchForm.endTime" type="date" :clearable="true" format="yyyy-MM-dd 23:59:59" placeholder="选择日期"> </el-date-picker> </div><div ><div >订单号</div><el-input v-model="searchForm.orderId"></el-input></div><div ><div >箱号</div><el-input v-model="searchForm.boxNum"></el-input></div><div ><div >扫描装箱状态</div><el-select v-model="searchForm.status" placeholder="请选择"> <el-option v-for="item in status" :key="item.id" :label="item.name" :value="item.id"> </el-option> </el-select></div> <div ><div >SN</div><el-input v-model="searchForm.sn"></el-input></div> <div > <el-button type="primary" @click="searchClick">查询</el-button> <el-button type="primary" @click="resetClick">重置</el-button></div></div><el-table :data="tableData" style="width:100%"> <el-table-column prop="OrderID" label="订单号" > </el-table-column> <el-table-column prop="Sn" label="SN" > </el-table-column> <el-table-column prop="Ksn" label="KSN"> </el-table-column> <el-table-column prop="BoxNum" label="箱号" > </el-table-column> <el-table-column prop="CreateTime" label="创建时间" > </el-table-column> <el-table-column prop="StatusBox" label="扫描装箱状态" > <template slot-scope="scope"> <div v-if="scope.row.StatusBox==0">无</div> <div v-if="scope.row.StatusBox==1">正确</div> <div v-if="scope.row.StatusBox==2">异常</div> <div v-if="scope.row.StatusBox==3">进行中</div> </template> </el-table-column> </el-table> <el-pagination @current-change="pageChange" :current-page.sync="pageData.Page" :page-size="pageData.RowNum" layout="total, prev, pager, next" :total="RowNum"> </el-pagination></div></template><script>import {SN_API_PATH} from "../../service/api"let StatusDefinite = [{ id:0, name:"全部"},{ id:1, name:"正确"},{ id:2, name:"异常"}]export default{ data(){ return{ orderId:"", searchForm:{ startTime:new Date(new Date().toLocaleDateString()), endTime:new Date(new Date().toLocaleDateString()),boxNum:"",status:0, orderId:"", sn:"" }, tableData:[],status:StatusDefinite, RowNum:0, pageData:{ Page:1, RowNum:20 } } }, created(){ this.searchForm.orderId = this.$route.query.orderId?this.$route.query.orderId:""this.searchForm.boxNum = this.$route.query.boxNum?this.$route.query.boxNum:"" if(this.$route.query.startTime){this.searchForm.startTime = new Date(this.$route.query.startTime)}if(this.$route.query.endTime){this.searchForm.endTime = new Date(this.$route.query.endTime)} this.getSnList() }, methods:{pageChange(){this.getSnList()}, getSnList(){ let formData = new FormData() formData.append("Token",sessionStorage.getItem("token")) formData.append("Act","GetSnList")formData.append("Box",this.searchForm.boxNum)formData.append("StatusBox",this.searchForm.status) formData.append("Page",this.pageData.Page-1) formData.append("RowNum",this.pageData.RowNum) let startTime = this.moment(this.searchForm.startTime).format("YYYY-MM-DD 00:00:00") let endTime = this.moment(this.searchForm.endTime).format("YYYY-MM-DD 23:59:59") formData.append("StartTime",new Date(startTime).getTime()/1000) formData.append("EndTime",new Date(endTime).getTime()/1000) formData.append("OrderID",this.searchForm.orderId) formData.append("Sn",this.searchForm.sn) this.$axios.post(SN_API_PATH,formData).then(res=>{ if(res.data.Ret == 0){ if(res.data.Data){ res.data.Data.map(v=>{ v.CreateTime = this.moment((v.CreateTime*1000)).format("YYYY-MM-DD HH:mm:ss") }) }else{ res.data.Data = [] } this.tableData = res.data.Data this.RowNum = res.data.Recordcount }else{ this.$message({ message:res.data.Msg, type:"error", duration:3000 }); } }) }, resetClick(){ this.searchForm = { orderId:"", startTime:new Date(new Date().toLocaleDateString()), endTime:new Date(new Date().toLocaleDateString()), sn:"" } }, searchClick(){ this.getSnList() }, repairClick(scope){ this.$prompt(SN号, , { confirmButtonText: 确定, cancelButtonText: 取消, }).then(res=>{ }) } }}</script><style scoped>.search-wrapper{display:flex;justy-content:flex-start;flex-wrap:wrap;}</style>

四、结语

本次分享结束,欢迎来撩!

完整方案介绍:《工厂订单出入库信息管理系统》完整解决方案(含演示账号)

系统演示网址:factory http://47.113.115.218:81 演示密码:123456

Copyright © 2024 有趣生活 All Rights Reserve吉ICP备19000289号-5 TXT地图HTML地图XML地图