一物一码模板由珈源科技制作。现在讲解一下模板制作方法:
模板下载地址/路径:钉钉 --> 宜搭 --> 模板中心 --> 按功能选择二维码 --> 一物一码
目录
一、使用场景
此模板为了方便对定制产品及贵重物品的管理,实施一物一码管理,每个产品一个二维码,出入库使用扫码枪扫码或手机扫码完成,通过本系统,⼤量的定制产品都可以准确、及时的查看、分析现状,或对贵重物品严格管理,提⾼⼯作的效率、准确度及安全性。
二、使用说明
下面是已定制产品为例的演示说明。
1、产品信息
模板基础信息,只设置里一个产品信息。只有名称及规格,其他信息可以自行搭建。
2、生产订单
添加生产订单,支持录入多个产品。录入开工和完工日期提交后生产工单。
3、生产报表
在生产报表里查看每个工单的产品数量信息,包括工单、打签、入库、库存、出库数量。单击“打签”跳转到二维码打印页面,进行标签打印。
4、二维码管理
图1.这个是二维码打印页面,打印二维码,粘贴在产品上,即可扫码出入库。
图2.展示了所有工单内产品的二维码信息
5、扫码出入库
扫码入库:可以在移动端扫描产品上的二维码,也可以在PC端通过扫码枪录入,选择“入库”时即可扫码入库,选择取消时,取消已入库的产品,对出库状态的二维码无效,扫码后二维码信息将显示在下方的提示信息里。
扫码出库:与扫码入库相同。
三、搭建方法
1、流程分析
2、步骤
1)产品信息
字段/组件:产品编号/下拉单选,产品名称/单行文本,规格型号/单行文本
说明:产品编号:是页面加载是用JS代码生成后自动填充的
// 当页面渲染完毕后马上调用下面的函数,这个函数是在当前页面 - 设置 - 生命周期 - 页面加载完成时中被关联的。
export function didMount() {
console.log(`「页面 JS」:当前页面地址 ${location.href}`);
// console.log(`「页面 JS」:当前页面 id 参数为 ${this.state.urlParams.id}`);
// 更多 this 相关 API 请参考:https://www.yuque.com/yida/support/ocmxyv#OCEXd
// document.title = window.loginUser.userName + ' | 宜搭';
this.$('selectField_l46fw35f').setValue(getBH('CP', '-'))
}
function pad(num, length) {
return (Array(length).join("0") + num).slice(-length);
}
//return:日期格式的唯一值编号 需要配合pad()一起使用
function getBH(head, str) {
let date = new Date()
let bh = head + str + date.getFullYear() + pad((date.getMonth() + 1), 2) + pad(date.getDate(), 2) + str + pad(date.getHours(), 2) + pad(date.getMinutes(), 2) + pad(date.getSeconds(), 2)
return bh
}
2)生产订单
主要字段:
生产单号/单行文本,开工日期/日期,完工日期/日期,工单/子表单
说明:
生产单号说明:与产品信息->产品编号一样
日期字段说明:公式自动填充
工单说明:子表单类型,手动添加,生产订单与产品关联,包括:编号、产品名称、规格型号、工单数量
工单.编号说明:
1、单击添加一项,新建一行,触发onAddClick事件,编号自动增加,
2、单击复制,复制此行数据,触发onCopyClick 事件,编号自动更新,
3、单击删除,删除此行数据,触发onDelClick 事件,编号自动更新。
/**
* TableField onAddClick 子表单编号添加(物品编号)
*/
export function onAddClick(newGroupId) {
console.lg
let tb = this.$("tableField_l46g0i13").getValue()
let tb1 = []
for(let i in tb){
tb1.push(tb[i])
}
let count = tb1.length - 1
tb1[count].textField_l46geitn = "" + pad(count, 3) + ""
this.$('tableField_l46g0i13').setValue(tb1)
}
/**
* TableField onDelClick 子表单编号删除
* @param groupId 被删除的ID
* @param removedItem 被删除的项数据
*/
export function onDelClick(groupId, removedItem){
let tb = this.$('tableField_l46g0i13').getValue()
let tb1 = []
for (let i in tb) {
tb[i].textField_l46geitn = "" + pad(i, 3) + ""
tb1.push(tb[i])
}
this.$('tableField_l46g0i13').setValue(tb1)
}
/**
* TableField onCopyClick 子表单编号复制
*/
export function onCopyClick(newGroupId, copiedItem){
const tableField = this.$('tableField_l46g0i13');//子表单唯一标识
tableField.model.items.map(items => {
tableField.updateItemValue(items.id, {
'textField_l46geitn': "" + pad(_.findIndex(tableField.model.items, ['id', items.id]), 3) + "" // 自增字段标识
});
})
}
工单.产品名称、工单.规格型号说明:产品名称关联产品信息表单,规格型号数据联动。
工单.工单数量说明:录入数量不能小于0
function validateRule(value) {
if(value<=0){
return false
}
return true
}
提交更新
提交后在生产工单表单里添加数据
3)生产工单
由生产订单生成的数据底表
4)生产报表
报表说明:展示生产工单的数据,单击打签跳转到二维码打印页面
组件说明:基础表格组件,选择生产工单数据集,新建公式字段(操作列),设置链接到二维码打印,携带参数为实例ID
5)二维码打印
说明:通过单击生产报表->打签,跳转到二维码打印页面,加载当前产品二维码打印情况。
1、页面初始化:判断url是否携带实例ID,为空时提示加载错误。
let formInstId = this.state.urlParams.id
if (formInstId == "" || formInstId === undefined){
this.utils.toast({
title: '加载错误', // 'success', 'warning', 'error', 'notice', 'help', 'loading'
type: 'error',
size: 'large',
duration: 2000, // 毫秒, type 为 loding 时无效
})
return false
}
2、将实例ID填充到单行文本
this.$('textField_l46iqnp1').setValue(formInstId)
3、根据实例ID查询生产工单的产品信息,填充到打印预览分组里。
const params = {
formInstId: formInstId
}
this.dataSourceMap["getDateById"].load(params).then(res => {
console.log("res",res)
if(res){
let data = res.formData
let ewm = data.selectField_l46g8c0z + "-" + pad(data.numberField_l46hq990 + 1, 5)//已打印数加1
this.$('selectField_l46glkgc').setValue(ewm)
let qrcode = document.getElementById("qrcode")
qrcode.innerHTML = makeCode(ewm).innerHTML
this.$('text_kwmuvveh').set('content', data.selectField_l46g8c0z)//产品编码(二维码)
this.$('text_l46gqfjq').set('content', data.selectField_l46g0i14)//产品名称
this.$('text_kwmuvvei').set('content', data.selectField_l46g0i15)//规格型号
this.$('numberField_l46gqfjm').setValue(data.numberField_l46hq990)//已打签数量
let sysl = data.numberField_l46g0i16 - data.numberField_l46hq990
this.$('numberField_l46gqfjn').setValue(sysl)
}
})
参照官方实例初始化二维码,与官方实例的区别,创建一个新的DIV,将二维码保存在DIV里。
let ewm = data.selectField_l46g8c0z + "-" + pad(data.numberField_l46hq990 + 1, 5)//已打印数加1
this.$('selectField_l46glkgc').setValue(ewm)
let qrcode = document.getElementById("qrcode")
qrcode.innerHTML = makeCode(ewm).innerHTML
/** makeCode(value)
* @params value 二维码值
* return 二维码图片<div>
*
*/
function makeCode(value) {
var qrcode = document.createElement("DIV")
qrcode.id = "qrcode"
var code1 = new QRCode(qrcode, {
text: value, // 二维码链接
width: 180, // 二维码宽度
height: 180, // 二维码高度
colorDark: "#000000",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.H
})
var canvas = code1._el.querySelector("canvas");//获取生成二维码中的canvas,并将canvas转换成base64
var base64Text = canvas.toDataURL("image/png");
var base64 = "<img src=" + "\"" + base64Text + "\"" + "/>"
//与官方的区别,创建一个新的DIV,将二维码保存在DIV里。
var qd = document.createElement("DIV")
qd.innerHTML = base64
//返回二维码图片<div>
return qd
}
前端补0方法:num需要补0的数字,length补0后的长度
//数字补0
function pad(num, length) {
return (Array(length).join("0") + num).slice(-length);
}
完整的页面初始化代码
export function didMount() {
console.log(`「页面 JS」:当前页面地址 ${location.href}`);
// console.log(`「页面 JS」:当前页面 id 参数为 ${this.state.urlParams.id}`);
// 更多 this 相关 API 请参考:https://www.yuque.com/yida/support/ocmxyv#OCEXd
// document.title = window.loginUser.userName + ' | 宜搭';
let formInstId = this.state.urlParams.id
if (formInstId == "" || formInstId === undefined){
this.utils.toast({
title: '加载错误', // 'success', 'warning', 'error', 'notice', 'help', 'loading'
type: 'error',
size: 'large',
duration: 2000, // 毫秒, type 为 loding 时无效
})
return false
}
this.$('textField_l46iqnp1').setValue(formInstId)
const params = {
formInstId: formInstId
}
this.dataSourceMap["getDateById"].load(params).then(res => {
console.log("res",res)
if(res){
let data = res.formData
let ewm = data.selectField_l46g8c0z + "-" + pad(data.numberField_l46hq990 + 1, 5)//已打印数加1
this.$('selectField_l46glkgc').setValue(ewm)
let qrcode = document.getElementById("qrcode")
qrcode.innerHTML = makeCode(ewm).innerHTML
this.$('text_kwmuvveh').set('content', data.selectField_l46g8c0z)//产品编码(二维码)
this.$('text_l46gqfjq').set('content', data.selectField_l46g0i14)//产品名称
this.$('text_kwmuvvei').set('content', data.selectField_l46g0i15)//规格型号
this.$('numberField_l46gqfjm').setValue(data.numberField_l46hq990)//已打签数量
let sysl = data.numberField_l46g0i16 - data.numberField_l46hq990
this.$('numberField_l46gqfjn').setValue(sysl)
}
})
}
4、打印逻辑说明:首先判断已打印数超过物品组数,然后更新生产工单,然后保存打印的二维码(二维码底表新增数据),然后打印二维码标签
/**
* 打印 onClick
*/
export function onClick(){
//已打印数超过物品组数,是否继续打印!
let sysl = this.$('numberField_l46gqfjn').getValue()
if (sysl <= 0) {
this.utils.dialog({
type: 'confirm',
title: '提示',
content: '已打印数超过物品组数,是否继续打印!', // 如需换行可传入 HTML/JSX 来实现
onOk: () => {
this.upDataGD()
this.saveDataEWM()
this.print()
},
onCancel: () => {},
})
} else {
this.upDataGD()//更新生产工单
this.saveDataEWM()//二维码底表新增数据,保存打印的二维码
this.print()//打印二维码
}
}
export function upDataGD() {
let ydsl = this.$('numberField_l46gqfjm').getValue()
let formInstId = this.$('textField_l46iqnp1').getValue()
let params = {
formInstId: formInstId,
updateFormDataJson: JSON.stringify({ numberField_l46hq990: ydsl+1}),
}
this.dataSourceMap['upDate'].load(params);
}
export function saveDataEWM() {
let ewmJson = {
selectField_l46glkgc: this.$('selectField_l46glkgc').getValue(),
selectField_l46glkgg: "打签",//状态
dateField_l46glkgd: Date.now(),//日期
textField_l46iqnp1: this.$('textField_l46iqnp1').getValue(),//工单formInstId
}
let ewmParams = {
formUuid: "FORM-AKA66FB1EG51S088DG3JZCXPWJR93U8LKG64L9",
appType: "APP_A3H6JM16PC2EMTWRZ0DK",
formDataJson: JSON.stringify(ewmJson)
}
this.dataSourceMap["saveData"].load(ewmParams)
}
export function print(){
//打印定义的网页区域
let oldstr = window.document.body.innerHTML
var printPart = document.getElementById('div_kwmuvvdt')
window.document.body.innerHTML = ""
window.document.body.appendChild(printPart)
window.print()
document.body.innerHTML = oldstr
location.reload()
}
6)二维码底表
保存二维码数据的底表,包括二维码(下拉单选)、状态(下拉单选)、打签日期、入库日期、出库日期、和工单formInstId(工单实例ID)
7)扫码入库
支持移动端扫码入库
字段说明
操作(下拉单选),可选值为入库和取消。
扫描二维码(单行文本),PC端可手动录入或使用扫码枪录入,移动端支持手机扫码
提示信息(多行文本),扫码后的产品信息提示(二维码的状态、打签、入库或出库日期等)
扫描二维码字段说明
绑定OnPressEnter()和OnScanCodeSuccess()两个动作
1、 onPressEnter()监控PC端扫键盘按下回车时调用,获取扫描二维码字段的值,作为查询条件,在二维码底表里面查找数据,若存在再查询生产工单。然后当操作是等于入库并且二维码状态等于打签时可完成入库;当操作等于取消并且二维码状态等于入库时可取消入库;否则提示产品当前状态。
/**
* PC端扫码成功 onPressEnter
*/
export function onPressEnter() {
let ewm = this.$('textField_l46lfbw1').getValue()
//查询二维码
let params = {
formUuid:"FORM-AKA66FB1EG51S088DG3JZCXPWJR93U8LKG64L9",
searchFieldJson: JSON.stringify({ selectField_l46glkgc:ewm})
}
this.dataSourceMap['getDateByEWM'].load(params).then(res=>{
if(res){
let data = res.formData
let kcgl = this.$('selectField_l46o309r').getValue()
let zt = data.selectField_l46glkgg
//查询生产工单
const gdParams = {
formInstId: data.textField_l46iqnp1
}
this.dataSourceMap["getDateById"].load(gdParams).then(r1 => {
if(r1){
if(kcgl == "入库" && zt =="打签"){
console.log(r1)
//更新入库数量
this.upDataGD(r1.formInstId, r1.formData.numberField_l46g8c11 + 1, r1.formData.numberField_l46g8c12 + 1)
this.upDataEWM(res.formInstId, Date.now(), "入库")//更新二维码
this.$('textareaField_l46lfbw3').setValue("入库成功")
}else if(kcgl == "取消" && zt == "入库"){
this.upDataGD(r1.formInstId, r1.formData.numberField_l46g8c11 - 1, r1.formData.numberField_l46g8c12 - 1)
this.upDataEWM(res.formInstId, "", "打签")//更新二维码
this.$('textareaField_l46lfbw3').setValue("取消入库成功")
}else{
let info = `产品当前状态为${data.selectField_l46glkgg}
打签日期:${this.utils.formatter('date', data.dateField_l46glkgd, 'yyyy/MM/dd') || "无"}
入库日期:${ this.utils.formatter('date', data.dateField_l46glkge, 'yyyy/MM/dd') || "无"}
出库日期:${ this.utils.formatter('date', data.dateField_l46glkgf, 'yyyy/MM/dd') || "无"}`
this.$('textareaField_l46lfbw3').setValue(info)
}
}else{
this.$('textareaField_l46lfbw3').setValue("生产工单错误")
}
})
}else{
this.$('textareaField_l46lfbw3').setValue("二维码错误")
}
})
}
2、移动端扫码:onScanCodeSuccess() 移动端扫码成功后直接调用this.onPressEnter()方法
/**
* 扫码成功后,可在此修改扫码结果
*/
export function onScanCodeSuccess(text) {
this.onPressEnter()
// 返回字符串会被填充到输入框中
return text;
}
3、两个工具方法 更新二维码和更新生产工单
// 更新二维码
export function upDataEWM(formInstId,date,zt) {
let params = {
formInstId: formInstId,//实例ID
updateFormDataJson: JSON.stringify({
dateField_l46glkge: date,//日期
selectField_l46glkgg: zt,//状态
}),
}
this.dataSourceMap['upDate'].load(params);//调用数据源更新
}
//更新生产工单
export function upDataGD(formInstId, rk, kc) {
let params = {
formInstId: formInstId,//实例ID
updateFormDataJson: JSON.stringify({
numberField_l46g8c11: rk,//入库数量
numberField_l46g8c12: kc,//库存数量
}),
}
this.dataSourceMap['upDate'].load(params);//调用数据源更新
}
4、页面完成JS代码
/**
* 尊敬的用户,你好:页面 JS 面板是高阶用法,一般不建议普通用户使用,如需使用,请确定你具备研发背景,能够自我排查问题。当然,你也可以咨询身边的技术顾问或者联系宜搭平台的技术支持获得服务(可能收费)。
* 我们可以用 JS 面板来开发一些定制度高功能,比如:调用阿里云接口用来做图像识别、上报用户使用数据(如加载完成打点)等等。
* 你可以点击面板上方的 「使用帮助」了解。
*/
// 当页面渲染完毕后马上调用下面的函数,这个函数是在当前页面 - 设置 - 生命周期 - 页面加载完成时中被关联的。
export function didMount() {
console.log(`「页面 JS」:当前页面地址 ${location.href}`);
// console.log(`「页面 JS」:当前页面 id 参数为 ${this.state.urlParams.id}`);
// 更多 this 相关 API 请参考:https://www.yuque.com/yida/support/ocmxyv#OCEXd
// document.title = window.loginUser.userName + ' | 宜搭';
}
/**
* textField onPressEnter
*/
export function onPressEnter() {
let ewm = this.$('textField_l46lfbw1').getValue()
let params = {
formUuid:"FORM-AKA66FB1EG51S088DG3JZCXPWJR93U8LKG64L9",
searchFieldJson: JSON.stringify({ selectField_l46glkgc:ewm})
}
this.dataSourceMap['getDateByEWM'].load(params).then(res=>{
if(res){
let data = res.formData
let kcgl = this.$('selectField_l46o309r').getValue()
let zt = data.selectField_l46glkgg
//查询生产工单
const gdParams = {
formInstId: data.textField_l46iqnp1
}
this.dataSourceMap["getDateById"].load(gdParams).then(r1 => {
if(r1){
if(kcgl == "入库" && zt =="打签"){
console.log(r1)
//更新入库数量
this.upDataGD(r1.formInstId, r1.formData.numberField_l46g8c11 + 1, r1.formData.numberField_l46g8c12 + 1)
this.upDataEWM(res.formInstId, Date.now(), "入库")//更新二维码
this.$('textareaField_l46lfbw3').setValue("入库成功")
}else if(kcgl == "取消" && zt == "入库"){
this.upDataGD(r1.formInstId, r1.formData.numberField_l46g8c11 - 1, r1.formData.numberField_l46g8c12 - 1)
this.upDataEWM(res.formInstId, "", "打签")//更新二维码
this.$('textareaField_l46lfbw3').setValue("取消入库成功")
}else{
let info = `产品当前状态为${data.selectField_l46glkgg}
打签日期:${this.utils.formatter('date', data.dateField_l46glkgd, 'yyyy/MM/dd') || "无"}
入库日期:${ this.utils.formatter('date', data.dateField_l46glkge, 'yyyy/MM/dd') || "无"}
出库日期:${ this.utils.formatter('date', data.dateField_l46glkgf, 'yyyy/MM/dd') || "无"}`
this.$('textareaField_l46lfbw3').setValue(info)
}
}else{
this.$('textareaField_l46lfbw3').setValue("生产工单错误")
}
})
}else{
this.$('textareaField_l46lfbw3').setValue("二维码错误")
}
})
}
export function upDataEWM(formInstId,date,zt) {
let params = {
formInstId: formInstId,
updateFormDataJson: JSON.stringify({
dateField_l46glkge: date,
selectField_l46glkgg: zt,
}),
}
this.dataSourceMap['upDate'].load(params);
}
export function upDataGD(formInstId, rk, kc) {
let params = {
formInstId: formInstId,
updateFormDataJson: JSON.stringify({
numberField_l46g8c11: rk,
numberField_l46g8c12: kc,
}),
}
this.dataSourceMap['upDate'].load(params);
}
/**
* 扫码成功后,可在此修改扫码结果
*/
export function onScanCodeSuccess(text) {
this.onPressEnter()
// 返回字符串会被填充到输入框中
return text;
}
8)扫码出库
扫码出库与扫码入库类似,不在详细介绍。