Browse Source

first commit

CJ 1 year ago
commit
491c183e2c

+ 0 - 0
.nojekyll


+ 0 - 0
_coverpage.md


+ 8 - 0
_sidebar.md

@@ -0,0 +1,8 @@
+<!-- docs/_sidebar.md -->
+
+* [个人简历](resume.html)
+* [软件发布及追溯系统](/project/软件发布及追溯系统.md)
+* [MES前端操作站](/project/MES前端操作站.md)
+* [Andon系统](/project/Andon系统.md)
+* [DFI友通资讯操作站](/project/DFI友通资讯操作站.md)
+* [BI报表](/project/BI报表.md)

+ 54 - 0
index.html

@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <title>Document</title>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
+  <meta name="description" content="Description">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
+  <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify/themes/buble.css">
+  <style>
+
+  </style>
+
+</head>
+
+<body>
+  <div id="app"></div>
+  
+  <script>
+    window.$docsify = {
+      search: 'auto', // 默认值
+      homepage: 'resume.html',
+      loadSidebar: true,
+      coverpage: false,
+      auto2top: true,
+      name: '项目经验',
+      repo: '',
+      search: {
+        maxAge: 86400000, // 过期时间,单位毫秒,默认一天
+        paths: [], // or 'auto'
+        placeholder: '搜索',
+
+      
+        noData: '找不到结果!',
+
+        
+
+        // 搜索标题的最大层级, 1 - 6
+        depth: 2,
+
+        hideOtherSidebarContent: false, // 是否隐藏其他侧边栏内容
+
+      }
+    }
+  </script>
+  <!-- Docsify v4 -->
+  <script src="//cdn.jsdelivr.net/npm/docsify@4"></script>
+  <script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"></script>
+  <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-bash.min.js"></script>
+  <script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-php.min.js"></script>
+</body>
+
+</html>

+ 41 - 0
project/Andon系统.md

@@ -0,0 +1,41 @@
+## **Andon系统**
+
+#### **项目介绍**
+Andon(按灯)系统,项目主要解决生产现场出现问题时,通过安灯系统极快做出响应。
+安灯内容包括:
+1. 物料呼叫,拉动现场生产,点取对应物料及数量订单发送到现场看板大屏,类似购物车逻辑,仓库立即响应使用AGV无人车搬运物料。
+2. 人员呼叫,生产出现问题,点取对应人员呼叫,以短信和车间广播通知对应人员。
+3. 设备呼叫,设备出现问题,点击对应设备,以广播形式通知班组。
+![Alt text](image-5.png)
+4. 工艺呼叫
+5. 呼叫记录
+
+事件升级:在ERP系统中的按灯模块维护基础数据,人员,设备,工艺,事件等,其中现场人员数据中会维护直接经理。当员工按灯后会系统开始计时,如果超过预设时间将会以短信形式发送通报至上级。
+
+
+#### **工作内容**
+WMS基础数据增删改查开发,Andon广播呼叫程序开发,MES操作界面开发,电子看板开发。
+
+#### **技术栈**
+WMS: ASP.NET SQLServer \
+MES: VUE  \
+Andon广播呼叫程序: JavaFx Lame转码 JAVA Native Interface SAPI
+
+#### **广播呼叫程序介绍**
+生产车间安装有ITC广播播放器,通过厂商提供的DLL文件对接广播使用。
+逻辑:程序轮询数据库检测当前是否有未呼叫的安灯事件,如果有将生成的文本通过微软SAPI MTTS文字转语音技术将文字转换成WAV语音文件,并通过lame程序将音频转码为MP3格式发送至广播。
+
+其他详情:https://cybersicko.net/article/24.html
+
+#### **预览**
+广播呼叫程序
+![Alt text](image-6.png)
+
+看板
+![Alt text](image-7.png)
+
+操作界面
+![Alt text](image-8.png)
+
+WMS基础数据
+![Alt text](image-9.png)

+ 2 - 0
project/BI报表.md

@@ -0,0 +1,2 @@
+## **BI报表**
+

+ 216 - 0
project/DFI友通资讯操作站.md

@@ -0,0 +1,216 @@
+## **DFI友通资讯操作站**
+
+#### **项目介绍**
+客户为台湾厂商,通过操作站结合WMS及AGV无人车实现智慧仓储物流系统。
+今年4月开发重构第二个版本,目前已完成。
+
+#### **主要工作**
+负责开发前端操作站界面。
+
+#### **主要功能**
+繁体中文及英语多语言功能,业务功能包括:派單,有單上架,無單上架,揀貨,條碼綁定,貨架報表,盤點等功能。
+其中包括ASRS 防潮柜/线边仓版本。
+
+#### **技术栈**
+Vue2  Vuetify
+RabbitMQ 订阅
+
+#### **预览**
+现场操作视频
+
+[WeChat_20231017211753.mp4](WeChat_20231017211753.mp4 ':include :type=video controls width=100%')
+
+
+派单界面
+![Alt text](image-10.png)
+
+拣货界面
+![Alt text](image-11.png)
+
+上架界面
+![Alt text](image-12.png)
+
+
+#### **代码片段(业务封装类)**
+
+```JavaScript
+import $EventBus from '@/utils/$EventBus'
+
+const NO_ITEM = (text = '', $vuetify) => {
+  let message = $vuetify.lang.t('$vuetify.common.message.no_item')
+  return message + ' ' + text
+}
+const SHELF_FULL = (text = '', $vuetify) => {
+  let message = $vuetify.lang.t('$vuetify.common.message.shelf_full')
+  return message + ' ' + text
+}
+
+const NOT_FOUND_BARCODE = ($vuetify) => {
+  return $vuetify.lang.t('$vuetify.common.message.not_found_barcode')
+}
+
+const NOT_FOUND_ITEM = ($vuetify) => {
+  return $vuetify.lang.t('$vuetify.common.message.not_found_item')
+}
+const NUMBER_OUT = ($vuetify) => {
+  return $vuetify.lang.t('$vuetify.common.message.number_out')
+}
+
+const NOT_FOUND_ORDER = ($vuetify) => {
+  return $vuetify.lang.t('$vuetify.common.message.not_found_order')
+}
+
+const REPEAT_SCAN = ($vuetify) => {
+  return $vuetify.lang.t('$vuetify.common.message.repeat_scan')
+}
+
+//刪除條碼,扣回來
+
+export const deleteBarcodeOutInBin = (barcode, inboundOrderDetail, that) => {
+  return new Promise((resolve, reject) => {
+    let hu_idx = that.currentHuList.findIndex((item) => item.HuId === barcode)
+    if (hu_idx < 0) {
+      $EventBus.$emit('MESSAGE_RECEIVE', {
+        text: NOT_FOUND_BARCODE(that.$vuetify),
+        type: 'ErrorMessages'
+      })
+      reject()
+    }
+    let barcodeInfo = that.currentHuList[hu_idx]
+
+    let det_idx = inboundOrderDetail.findIndex((item) => item.Id === barcodeInfo.InboundTaskDetId)
+
+    if (det_idx < 0) {
+      $EventBus.$emit('MESSAGE_RECEIVE', {
+        text: NOT_FOUND_ORDER(that.$vuetify),
+        type: 'ErrorMessages'
+      })
+      reject()
+    }
+    let det = inboundOrderDetail[det_idx]
+    det.EntryQty -= barcodeInfo.Qty
+    that.$set(that.inboundOrderInfo.Details, det_idx, det)
+    that.inboundOrderInfo.SumFinishedQty -= barcodeInfo.Qty
+    that.table.deleteRow(barcodeInfo.HuId)
+    that.currentHuList.splice(hu_idx, 1)
+    resolve(barcodeInfo)
+  })
+}
+
+export const semiProductCartonCheck = (barcodeInfoList, inboundOrderDetail, that) => {
+  let qtys = barcodeInfoList.map((item) => {
+    return item.Qty
+  })
+  let huMaxQty = qtys.reduce((n, m) => n + m)
+  let old_qtys = that.currentHuList.map((item) => {
+    return item.Qty
+  })
+  if (huMaxQty > that.inboundOrderInfo.SumUnfinishedQty) {
+    $EventBus.$emit('MESSAGE_RECEIVE', {
+      text: NUMBER_OUT(that.$vuetify),
+      type: 'ErrorMessages'
+    })
+    return false
+  }
+  inboundOrderDetail = JSON.parse(JSON.stringify(that.inboundOrderDetailsCopy))
+  for (let i = 0; i < inboundOrderDetail.length; i++) {
+    if (inboundOrderDetail[i].EntryQty === inboundOrderDetail[i].Qty) {
+      continue
+    }
+
+    for (let j = 0; j < barcodeInfoList.length; j++) {
+      if (inboundOrderDetail[i].ItemCode === barcodeInfoList[j].Item) {
+
+        if (barcodeInfoList[j].Qty > (inboundOrderDetail[i].Qty - inboundOrderDetail[i].EntryQty)) {
+          continue
+        }
+        if (barcodeInfoList[j].InboundTaskDetId) {
+          continue
+        }
+
+        inboundOrderDetail[i].EntryQty += barcodeInfoList[j].Qty
+        barcodeInfoList[j].InboundTaskDetId = inboundOrderDetail[i].Id
+
+        if (inboundOrderDetail[i].ErpLoc !== null && inboundOrderDetail[i].ErpLoc !== '') {
+          barcodeInfoList[j].ErpLoc = inboundOrderDetail[i].ErpLoc
+        }
+      }
+    }
+    if (i === (inboundOrderDetail.length - 1)) {
+      that.itemInfo.item = inboundOrderDetail[i].ItemCode
+      that.itemInfo.qty = inboundOrderDetail[i].Qty
+      that.itemInfo.item_desc = inboundOrderDetail[i].ItemName
+      that.itemInfo.remaining = inboundOrderDetail[i].Qty - inboundOrderDetail[i].EntryQty
+      that.itemInfo.enter_qty = inboundOrderDetail[i].EntryQty
+    }
+  }
+  that.$set(that.inboundOrderInfo, 'Details', inboundOrderDetail)
+  if (old_qtys.length > 0) {
+    that.inboundOrderInfo.SumFinishedQty -= old_qtys.reduce((n, m) => n + m)
+  }
+  that.inboundOrderInfo.SumFinishedQty += qtys.reduce((n, m) => n + m)
+  return true
+}
+
+//條碼邏輯
+export const checkPutInBin = (barcodeInfo, inboundOrderDetail, that) => {
+  return new Promise((resolve, reject) => {
+    let hu_idx = that.currentHuList.findIndex((item) => item.HuId === barcodeInfo.HuId)
+    if (hu_idx > -1) {
+      $EventBus.$emit('MESSAGE_RECEIVE', {
+        text: REPEAT_SCAN(that.$vuetify),
+        type: 'ErrorMessages'
+      })
+      reject()
+    }
+
+    let matchId = null
+    let matchItem = null
+    // let itemDet = inboundOrderDetail.filter((item,i) => item.ItemCode === barcodeInfo.Item)
+    let itemDet = []
+    for (let i = 0; i < inboundOrderDetail.length; i++) {
+      if (inboundOrderDetail[i].ItemCode === barcodeInfo.Item) {
+        itemDet.push({
+          index: i,
+          item: inboundOrderDetail[i]
+        })
+      }
+    }
+    if (itemDet.length === 0) {
+      $EventBus.$emit('MESSAGE_RECEIVE', {
+        text: NO_ITEM(barcodeInfo.HuId, that.$vuetify),
+        type: 'ErrorMessages'
+      })
+      reject()
+    } else {
+      for (let i = 0; i < itemDet.length; i++) {
+        if (!matchId) {
+          if (itemDet[i].item.EntryQty < itemDet[i].item.Qty && (itemDet[i].item.Qty - itemDet[i].item.EntryQty) >= barcodeInfo.Qty) {
+            itemDet[i].item.EntryQty += barcodeInfo.Qty
+            that.$set(that.inboundOrderInfo.Details, itemDet[i].index, itemDet[i].item)
+            //set info
+            that.itemInfo.item = itemDet[i].item.ItemCode
+            that.itemInfo.qty = itemDet[i].item.Qty
+            that.itemInfo.item_desc = itemDet[i].item.ItemName
+            that.itemInfo.remaining = itemDet[i].item.Qty - itemDet[i].item.EntryQty
+            that.itemInfo.enter_qty = itemDet[i].item.EntryQty
+
+            matchId = itemDet[i].item.Id
+            matchItem = itemDet[i].item
+          }
+        }
+      }
+      if (!matchId) {
+        $EventBus.$emit('MESSAGE_RECEIVE', {
+          text: SHELF_FULL(barcodeInfo.HuId, that.$vuetify),
+          type: 'ErrorMessages'
+        })
+        reject()
+      } else {
+        resolve(matchItem)
+      }
+    }
+  })
+}
+
+```

+ 37 - 0
project/MES前端操作站.md

@@ -0,0 +1,37 @@
+## **MES操作站**
+
+#### **项目背景**
+为江苏天宝汽车电子有限公司MES项目,替换旧的MES厂家,在原有系统上实现降本增效。
+
+#### **人员情况**
+由我负责前端搭建及开发。
+
+#### **技术栈**
+前端:Vue2 Vuetify \
+后端:.net core \
+中间件:RabbitMQ \
+数据库:SqlServer 
+
+#### **功能介绍**
+此系统为工厂车间操作工人使用,功能包括:工单查询,工单签发,工单提交,工单完工,工单收货,工单执行,送修,投料,物料追溯,安灯呼叫,洗版补录,容器管理,条码解绑,包装,等功能。
+该系统以扫码为核心驱动所有功能。
+
+#### **主要工作**
+负责页面开发,需求讨论,车间现场调研等工作。
+
+#### **问题与难点**
+敏捷开发,需求变化快,需要快速响应,否则影响生产。
+
+#### **成果**
+现已在江苏天宝汽车电子有限公司,华域电子分公司,绍兴怡东汽车零配件等公司生产车间使用。
+
+#### **预览**
+工单执行
+![Alt text](image.png)
+
+工单查询
+![Alt text](image-2.png)
+
+安灯呼叫
+![Alt text](image-3.png)
+

BIN
project/WeChat_20231017211753.mp4


BIN
project/image-1.png


BIN
project/image-10.png


BIN
project/image-11.png


BIN
project/image-12.png


BIN
project/image-2.png


BIN
project/image-3.png


BIN
project/image-4.png


BIN
project/image-5.png


BIN
project/image-6.png


BIN
project/image-7.png


BIN
project/image-8.png


BIN
project/image-9.png


BIN
project/image.png


BIN
project/img/image-1.png


BIN
project/img/image-2.png


BIN
project/img/image-20231017191643319.png


BIN
project/img/image-20231017191900500.png


BIN
project/img/image-20231017191911619.png


BIN
project/img/image-20231017191929458.png


BIN
project/img/image-3.png


BIN
project/img/image-4.png


BIN
project/img/image.png


File diff suppressed because it is too large
+ 381 - 0
project/软件发布 Timing Schedule.html


+ 191 - 0
project/软件发布及追溯系统.md

@@ -0,0 +1,191 @@
+## **软件发布及追溯系统**
+
+#### **项目背景**
+
+ 随着产品不断升级,产品复杂度不断升级,软件烧录和写入技术难度和产品使用的涉及面及软件更新频次不断增加,以往老的管理方式已经无法支撑目前的软件管理的新常态要求
+
+近期集团内各家工厂的几个软件重大投诉如软件版本代码写错和客户使用的IP地址以及ECU代码写错问题频发,引起客户强烈不满和管理层的高度重视
+
+经过讨论,拟在集团工厂层面导入“软件发布及追溯系统”,对嵌入式软件的发布和生产使用进行全面管控
+
+![image-20231017191643319](./img/image-20231017191643319.png)
+
+#### **人员情况**
+由我本人为主要开发人员,项目管理由经理把控。
+
+
+#### **技术栈**
+前端:Vue2 Quasar \
+后端:Java Mybatis Plus SpringBoot \
+中间件:Redis \
+文件上传:阿里云OSS \
+数据库:SqlServer \
+其他:C# WindowsService后台程序 
+
+#### **计划用时**
+[cinwell website](./软件发布%20Timing%20Schedule.html ':include :type=iframe width=100% height=400px ')
+
+#### **主要工作**
+负责前期需求调研,后端框架搭建,数据库建模,基础代码开发,Vue前端框架搭建,页面功能开发。
+以及核心功能:软件发布上传,下载,推送,通知等功能开发。
+包括进度汇报等。
+
+#### **问题与难点**
+集团领导派发的项目经理影响力不够,项目难以在TC(技术中心)推进,导致项目在一段时间内停滞,需求反复变更。
+
+#### **成果**
+一期UAT测试通过,交付客户IT团队进行维护。
+
+
+#### **预览(初版-测试数据)**
+软件上传界面(测试数据)
+![Alt text](./img/image-1.png)
+
+![Alt text](./img/image-3.png)
+
+产品簇界面(测试数据)
+![Alt text](./img/image-2.png)
+
+详情回顾
+![Alt text](./img/image-4.png)
+
+#### **代码片段**
+<p>C# 下载软件包</p>
+
+```html
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using Aliyun.OSS;
+using Aliyun.OSS.Common;
+using CiemisDownload.Entity;
+using CiemisDownload.Helper;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
+
+namespace CiemisDownload
+{
+    public class DownloadWorker : BackgroundService
+    {
+        private readonly ILogger<DownloadWorker> _logger;
+
+        private ClientService clientService;
+
+
+        public DownloadWorker(ILogger<DownloadWorker> logger)
+        {
+            _logger = logger;
+            clientService = ClientService.GetInstance();
+        }
+
+        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
+        {
+            while (!stoppingToken.IsCancellationRequested)
+            {
+                _logger.LogInformation("ping...");
+
+                try
+                {
+                    //List<DownloadItem> result = await clientService.GetDownloadUrls().ConfigureAwait(result => _logger.LogInformation()) ;
+                    List<DownloadItem> result = await clientService.GetDownloadUrls();
+                    if (result.Count > 0)
+                    {
+                        Sts sts = await clientService.GetStsAsync();
+                        DownloadFile(sts, result);
+                    }
+                }
+                catch (Exception e)
+                {
+                    _logger.LogError(e.Message);
+                }
+
+                await Task.Delay(1000, stoppingToken);
+            }
+        }
+
+        /**
+         * 创建下载信息文件
+         */
+        private void CreateDownloadFile(DownloadItem item)
+        {
+            string downloadPath = ConfigurationManager.AppSettings["DownloadPath"];
+            string savePath = downloadPath + item.burnAfterItemCode + "\\";
+            string filePath = savePath + "\\" + "point.d";
+            Directory.CreateDirectory(savePath);
+            if (!File.Exists(filePath))
+            {
+                FileStream fs1 = new FileStream(filePath, FileMode.Create, FileAccess.Write);
+                StreamWriter sw = new StreamWriter(fs1);
+                sw.WriteLine(JsonConvert.SerializeObject(item.point)); //开始写入值
+                sw.Close();
+                fs1.Close();
+            }
+        }
+
+
+        private void DownloadFile(Sts sts, List<DownloadItem> result)
+        {
+            new Task(() =>
+            {
+                var client = new OssClient("oss-cn-shanghai.aliyuncs.com", "LTAI5tQgUn4M9Pw8otJX4Evq",
+                    "vLtqLvGhEeYmhJS5P5ypO78W1xccd6");
+
+                string downloadPath = ConfigurationManager.AppSettings["DownloadPath"];
+                try
+                {
+                    // 
+                    foreach (DownloadItem item in result)
+                    {
+                        CreateDownloadFile(item);
+                        item.urls.ForEach((url) =>
+                        {
+                            _logger.LogInformation("/" + url.url);
+                            _logger.LogInformation(downloadPath + url.fileName);
+                            var savePath = downloadPath + item.burnAfterItemCode + "\\";
+
+
+                            Directory.CreateDirectory(savePath);
+
+
+                            DownloadObjectRequest request = new DownloadObjectRequest(sts.Bucket, url.url,
+                                savePath + url.fileName, "E:\\ciemis\\checkpoint\\")
+                            {
+                                // 指定下载的分片大小。
+                                PartSize = 8 * 1024 * 1024,
+                                // 指定并发线程数。
+                                ParallelThreadCount = 3
+                            };
+                            request.StreamTransferProgress += StreamProgressCallback;
+
+                            // 断点续传下载。
+                            client.ResumableDownloadObject(request);
+                        });
+                        int success = clientService.DownloadCompleteCallback(item.point.softwareId.ToString())
+                            .Result;
+                        _logger.LogInformation("下载完成:{0}", success);
+                    }
+                }
+                catch (OssException ex)
+                {
+                    _logger.LogError("Failed with error code: {0}; Error info: {1}. \nRequestID:{2}\tHostID:{3}",
+                        ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId);
+                }
+                catch (Exception ex)
+                {
+                    _logger.LogError("Failed with error info: {0}", ex.Message);
+                }
+            }).Start();
+        }
+
+        private  void StreamProgressCallback(object sender, StreamTransferProgressArgs args)
+        {
+           _logger.LogInformation("ProgressCallback - Progress: {0}%, TotalBytes:{1}, TransferredBytes:{2} ",
+                args.TransferredBytes * 100 / args.TotalBytes, args.TotalBytes, args.TransferredBytes);
+        }
+    }
+}
+```

File diff suppressed because it is too large
+ 16 - 0
resume.html


Some files were not shown because too many files changed in this diff