剩余模块:生产退料

This commit is contained in:
刘晓鹏 2025-06-03 02:55:51 +08:00
parent a12f56d2be
commit a59dd54c27
24 changed files with 9139 additions and 0 deletions

1230
README.md Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,140 @@
<template>
<view>
<view class="input-box">
<view class="input-item" v-if="state.show">
<up-input :placeholder="props.placeholder" border="none" clearable inputAlign="left" v-model="state.inputText"
@confirm="confirmfun">
<template #prefix>
<up-icon :name="props.icon" color="#2979ff" size="24"></up-icon>
</template>
</up-input>
</view>
<view class="codeBox" v-else>
<tki-qrcode cid="qrcode" ref="qrcode" :val="state.inputText" :size="170" unit="upx" :loadMake="true"
:usingComponents="true" />
<view class="codeBoxText">
<view>单据{{ props.dataType }}</view>
<view>编码</view>
<view class="container chinese-text">{{ state.inputText }}</view>
</view>
</view>
</view>
<!-- #ifdef APP-PLUS -->
<qs-scanlistener @scan="scanFun" />
<!-- #endif -->
</view>
</template>
<script lang="ts" setup>
import { reactive, nextTick, defineProps, defineEmits, defineExpose,watch } from 'vue';
import { useI18n } from 'vue-i18n'
const getI18n = useI18n()
const { t, locale } = getI18n
const emits = defineEmits(['inputConfirm', 'scanConfirm'])
const props = defineProps({
icon: {
type: String,
default: () => 'search'
},
placeholder: {
type: String,
default: () => '请输入内容'
},
dataType: {
type: String,
default: () => '来料验证'
},
fence: {
type: Array,
default: () => {
return [false]
}
}
})
watch(()=> props.fence,(val1,val2) => {
console.log(val1,val2);
})
const state = reactive({
inputText: '',
show: true
})
const scanFun = (res : any) => {
console.log(props.fence.filter((item : any) => item));
if (props.fence.filter((item : any) => item).length === 0) {
state.inputText = res
state.show = false
console.log(res);
emits('scanConfirm', res)
}
}
const confirmfun = (e : any) => {
emits('inputConfirm', e)
}
const closeFun = (time : number = 2000) => {
setTimeout(() => {
state.inputText = ''
state.show = true
emits('inputConfirm', '')
},time)
}
defineExpose({
closeFun
})
</script>
<style lang="scss">
.container {
overflow-wrap: break-word;
word-break: normal;
hyphens: auto;
/* 支持连字符换行 */
}
/* 中文强制换行 */
.chinese-text {
word-break: break-all;
}
.input-box {
background-color: white;
box-sizing: border-box;
padding: 0 16rpx;
border-radius: 24rpx;
margin: 0 0 32rpx 0;
.u-textarea {
padding: 0 !important;
font-size: 24rpx !important;
color: #999999 !important;
}
.input-item {
box-sizing: border-box;
padding: 16rpx 0;
color: #222222;
font-size: 28rpx;
font-weight: 400;
.item-title {
//font-weight: 500;
font-size: 32rpx;
color: #333333;
}
.item-text {
font-weight: 400;
font-size: 27rpx;
color: #999999;
}
}
}
.codeBox {
padding: 36rpx 24rpx 24rpx 18rpx;
display: flex;
.codeBoxText {
margin-left: 32rpx;
}
}
</style>

View File

@ -0,0 +1,40 @@
<template>
<fuiInput :focus="state.focusState" @focus="inputFocusFun">
<template #left>
<up-icon name="search" color="#2979ff" size="28" style="margin-right: 8rpx;"></up-icon>
</template>
</fuiInput>
</template>
<script lang="ts" setup>
import { reactive, ref, defineEmits, defineProps, computed, watch } from 'vue';
import fuiInput from '../fui-input/fui-input.vue'
import i18n from '../../locale/index'
import { useI18n } from 'vue-i18n'
const getI18n = useI18n()
const { t, locale } = getI18n
const props = defineProps({
icon:{
type:String,
default: ''
}
})
const state = reactive({
focusState: true
})
const inputFocusFun = (e:any) => {
uni.onKeyboardHeightChange(res => {
console.log(res.height)
if(res.height > 0){
uni.hideKeyboard()
}
})
}
</script>
<style scoped lang="scss">
.fui-input__wrap{
padding: 0 !important;
}
</style>

View File

@ -0,0 +1,136 @@
<template>
<view class="app status-bar-gap">
<l-header title="批量销售出库" sticky #right>
<view style="margin-right: 32rpx;" v-if="state.tabsIndex === '1'" @click="submit()">{{ t('verify.tj') }}</view>
</l-header>
<view class="page">
<view class="input-box">
<up-tabs :scrollable="false" :list="state.tabsList" @click="upTabsItemFun"></up-tabs>
</view>
<architecture ref="architectureRef" :dataType="t('home.scrk')" :placeholder="t('receive.djbh')"
@scanConfirm="scanConfirmFun" @inputConfirm="changeFun" />
<packing ref="packingRef" v-if="state.tabsIndex === '1'" :queryString="state.queryString"
@clearOut="clearOut()" />
<scattered v-if="state.tabsIndex === '2'" :queryString="state.queryString" @clearOut="clearOut()" />
</view>
</view>
</template>
<script lang="ts" setup>
import { reactive, nextTick, onMounted, ref, computed } from 'vue';
import { onLoad, onShow, onReachBottom } from '@dcloudio/uni-app'
import { useI18n } from 'vue-i18n'
import { parseTime } from '../../utils/tools.js';
import { PRD_MORPTList, receiveBillList } from '../../common/request/api/api';
import packing from './packing.vue'
import scattered from './scattered.vue'
const architectureRef = ref()
const packingRef = ref()
const getI18n = useI18n()
const { t, locale } = getI18n
const state = reactive({
queryString: '',
tabsIndex: '1',
tabsList: [
{ name: computed(() => '所选单据'), type: '1' },
{ name: computed(() => '验证单据'), type: '2' },
],
})
const scanConfirmFun = (e : any) => {
state.queryString = e
architectureRef.value.closeFun()
}
const changeFun = (e : any) => {
if (e != '') state.queryString = e
}
const upTabsItemFun = (e : any) => {
state.tabsIndex = e.type
}
const clearOut = () => {
state.queryString = ''
}
const submit = () => {
packingRef.value.dataPushNotification()
}
</script>
<style lang="scss">
.app {
background-color: #F5F5F5;
.page {
padding: 18px 32rpx;
display: flex;
flex-direction: column;
height: 100%;
flex: 1;
.input-box {
background-color: white;
box-sizing: border-box;
padding: 0 16rpx;
border-radius: 24rpx;
margin: 0 0 32rpx 0;
.u-textarea {
padding: 0 !important;
font-size: 24rpx !important;
color: #999999 !important;
}
.input-item {
box-sizing: border-box;
padding: 16rpx 0;
color: #222222;
font-size: 28rpx;
font-weight: 400;
.item-title {
//font-weight: 500;
font-size: 32rpx;
color: #333333;
}
.item-text {
font-weight: 400;
font-size: 27rpx;
color: #999999;
}
}
}
.receive-listBox {
flex: 1;
.list-box-list {
width: 100%;
// margin: 20rpx auto;
.data-item {
border: 1px solid #efeaea;
border-radius: 20rpx;
box-shadow: 0rpx 15rpx 15rpx #efeaea;
padding: 20rpx 20rpx 0;
margin-bottom: 20rpx;
background-color: #ffffff;
.tit {
font-size: 30rpx;
font-weight: bold;
padding: 20rpx 0;
}
.line-p {
border: 1px solid #efeaea;
}
.b-font {
font-size: 25rpx;
padding: 20rpx 0;
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,427 @@
<template>
<view class="app status-bar-gap">
<view class="page">
<l-header :title="state.FBillNo" sticky #right>
<view style="margin-right: 32rpx;" @click="dataPushNotification">{{ t('receive.tj') }}</view>
</l-header>
<architecture ref="architectureRef" :dataType="t('home.llyz')" icon="scan" :placeholder="t('verify.tm')"
@scanConfirm="scanConfirmFun" @inputConfirm="changeFun"
:fence="[state.scanFrameRefShow,state.shortcutRefShow]" />
<view class="material-listBox">
<scroll-view id="scroll-box1" class="scroll-box" scroll-y="true" :style="{'height':state.scrollHeight+'px'}">
<view class="list-box-list" v-if="state.dataList.length > 0">
<view class="data-item" v-for="(item, index) in state.dataList"
:style="[{'background-color':interpolation(item)},{'margin-bottom':index + 1 === state.dataList.length ? '80px' : '20px'}]"
:key="index">
<view class="text" style="margin-bottom: 20px;display: flex;">
<view>{{ item.MaterialName }}</view>
</view>
<view class="itemBox">
<view>{{t('receive.djbh')}}</view>
<view class="zongjian"></view>
<view>{{ state.FBillNo }}</view>
</view>
<view class="itemBox">
<view>{{t('receive.wlbm')}}</view>
<view class="zongjian"></view>
<view>{{ item.MaterialNo }}</view>
</view>
<view class="itemBox">
<view>{{t('receive.ph')}}</view>
<view class="zongjian"></view>
<view>{{ item.Lot }}</view>
</view>
<!-- <view class="itemBox">
<view>仓库</view>
<view class="zongjian"></view>
<view>{{ item.MultiLanguageText }}</view>
</view> -->
<view class="itemBox">
<view>{{t('receive.ys')}}</view>
<view class="zongjian"></view>
<view>{{ item.CheckJoinQty }}</view>
</view>
<view class="itemBox">
<view>{{t('receive.ws')}}</view>
<view class="zongjian"></view>
<view>{{ item.NoCheckQty }}</view>
</view>
<view class="itemBox">
<view>{{t('receive.yss')}}</view>
<view class="zongjian"></view>
<view>{{ item.CheckQty }}</view>
</view>
</view>
<view style="text-align: center;color: #F5F5F5;height: 20px;"></view>
</view>
<view v-if="state.dataList.length==0">
<up-empty mode="list"></up-empty>
</view>
</scroll-view>
</view>
</view>
</view>
<scanFrame ref="scanFrameRef" @confirmation="scanFrameCnfirmation"
@scanFrameDataFeedback="(res:object)=>{state.scanFrameDataFeedback = res}"
@fast="(row:any)=>{state.scanFrameDataFeedback = row}" @err="scanFrameErrFun" @boxShow="scanFrameBoxShowShow" />
<shortcut ref="shortcutRef" @dataToscanFrame="dataToscanFrameFun" @boxShow="shortcutBoxShowShow" />
<tools ref="toolsRef" @defaultPopup="defaultPopupFun" @scanRecord="scanRecordFun" />
</template>
<script lang="ts" setup>
import { reactive, nextTick, onMounted, ref, computed, watch } from 'vue';
import { onLoad, onShow, onReachBottom, } from '@dcloudio/uni-app'
import { useI18n } from 'vue-i18n'
import { parseTime } from '../../utils/tools.js';
import { PRD_MORPTPush, PRD_MORPTScanData, PRD_MORPTView, SAL_OUTSTOCKCheck, SAL_OUTSTOCKScanData, SAL_OUTSTOCKView, fStockFlexDetailDelete, temporaryScanDraftSave, temporaryScanList } from '../../common/request/api/api';
import scanFrame from '../../components/scan-frame/scan-frame.vue'
import tools from '../../components/tools/tools.vue'
import shortcut from '../../components/tools/shortcut.vue'
import { sqlite } from '../../stores/sqlite'
const architectureRef = ref()
const DB = sqlite()
const inputRef = ref()
const scanFrameRef = ref()
const shortcutRef = ref()
const getI18n = useI18n()
const { t, locale } = getI18n
const state = reactive({
scanFrameRefShow: false,
shortcutRefShow: false,
queryString: '',
dataList: [],
scrollHeight: 0,
page: {
pageIndex: 1,
pageSize: 200,
totalCount: 0
},
tabsIndex: '1',
FBillNo: '',
materialId: '',
supplierName: '',
inputFocus: true,
scanFrameDataFeedback: {},
shortcutDataFeedback: {},
})
onLoad((pageData : any) => {
console.log(pageData);
state.materialId = pageData.id
state.FBillNo = pageData.fBillNo
fnDataList(state.materialId);
})
onShow(() => {
if (state.materialId) {
fnDataList(state.materialId);
}
})
onMounted(() => {
const query = uni.createSelectorQuery().in(this);
query.select(".material-listBox").boundingClientRect((data) => {
state.scrollHeight = data.height
}).exec();
// scanFrameRef.value.stateShow(true)
})
const scanConfirmFun = (e : any) => {
getReceiveBillScanData(e)
}
const shortcutBoxShowShow = (val : boolean) => {
state.shortcutRefShow = val
}
const scanFrameBoxShowShow = (val : boolean) => {
state.scanFrameRefShow = val
}
/**
* 数据逻辑
*/
const interpolation = (item : any) => {
if (item.CheckJoinQty === 0 && item.CheckJoinQty + item.NoCheckQty === item.CheckQty) {
return '#ffffff'
}
if (item.CheckJoinQty !== 0 && item.NoCheckQty !== 0 && item.CheckJoinQty + item.NoCheckQty === item.CheckQty) {
return 'rgb(254 227 87)'
}
if (item.CheckJoinQty === item.CheckQty) {
return 'rgb(87 191 254)'
}
}
//
const debounceTimer = ref()
const changeFun = (e : any) => {
if (debounceTimer.value !== null) clearTimeout(debounceTimer.value)
debounceTimer.value = setTimeout(() => {
state.queryString = e
if (state.queryString !== '') getReceiveBillScanData(e)
})
}
//
const getReceiveBillScanData = (val : string) => {
SAL_OUTSTOCKScanData({
FBarCode: val,
FBillNo: state.FBillNo,
}).then((res : any) => {
if (res.data !== null) {
console.log(res);
scanFrameRef.value.getreceiveBillScanData({ ...res.data, queryString: state.queryString, scanFrameShowSate: state.shortcutDataFeedback.scanFrameShowSate, stashVerify: true })
if (Object.keys(state.shortcutDataFeedback).length) {
if (state.shortcutDataFeedback.scanFrameShowSate) {
scanFrameRef.value.stateShow(true)
} else {
postTemporaryScanDraftSaveFun(state.scanFrameDataFeedback)
}
} else {
scanFrameRef.value.stateShow(true)
}
} else {
uni.$u.toast(t('index.bmygtsj'))
state.queryString = ''
}
architectureRef.value.closeFun()
})
}
//
const scanFrameCnfirmation = (row : any) => {
state.scanFrameDataFeedback = row
postTemporaryScanDraftSaveFun(state.scanFrameDataFeedback)
}
const scanFrameErrFun = () => {
scanFrameRef.value.stateShow(true)
}
//
const postTemporaryScanDraftSaveFun = (item : any) => {
const obj = {};
if (item.warehouseData.FIsOpenLocation) {
const key = `FVHUBSTOCKFLEX__FF${item.warehouseData.FFlexId}`; //Id
obj[key] = { FNumber: item.locationData.FlexEntryId.Number }; //
}
const str = JSON.stringify(obj);
console.log(item);
temporaryScanDraftSave({
FVHUBFormId: "SAL_DELIVERYNOTICE", //
FVHUBFBillNo: state.FBillNo, //
FVHUBScanNumber: state.queryString, //
FVHUBMaterialNumber: item.articlesStr, //
FVHUBScanQty: item.quantityStr + '', //
FVHUBEntryId: scanFrameRef.value.state.receiveBillScanData.Id, //ID
FVHUBFlot: item.batchNumberStr, //
FVHUBStock: {
FNUMBER: item.warehouseData.FNUMBER //
},
FVHUBMaterial: {
FNUMBER: item.articlesStr
},
...JSON.parse(str),
}).then((res : any) => {
console.log(res);
state.queryString = ''
if (res.data.IsSuccess) {
fnDataList(state.materialId);
uni.$u.toast('成功')
scanFrameRef.value.stateShow(false)
}
})
}
//
const dataToscanFrameFun = (res : object) => {
state.shortcutDataFeedback = res
scanFrameRef.value.getComponentsData(res)
shortcutRef.value.stateShow(false)
}
//
const defaultPopupFun = () => {
shortcutRef.value.stateShow(true)
}
const scanRecordFun = () => {
toPages('/pages/records/index', {
FormId: 'SAL_DELIVERYNOTICE',
FbillNo: state.FBillNo
})
}
/**
* 数据推送
*/
const dataPushNotification = () => {
uni.showModal({
title: t('public.ts'), content: t('public.tjMessage'), cancelText: t('public.cancel'), confirmText: t('public.confirm'),
success(res) {
if (res.confirm) {
let EntryIds : any = []
let ids : any = []
let ScanEntry : any = []
let param = {
FormId: 'SAL_DELIVERYNOTICE',
UserId: uni.getStorageSync('userInfo').Context.UserId,
FbillNo: state.FBillNo
};
uni.showLoading({ mask: true });
//
temporaryScanList(param).then(res => {
if (res.code == 200) {
if (res.data.list.length != 0) {
res.data.list.forEach((item : any) => {
EntryIds.push(item.FVHUBEntryId)
ids.push(item.FID)
ScanEntry.push({
FENTRYID: item.FVHUBEntryId,
Qty: item.FVHUBScanQty,
Flot: item.FVHUBFlot,
StockId: item.FVHUBStock,
StockFlex: item.FVHUBStockFlex,
Sno: item.FVHUBJSON
})
})
//
SAL_OUTSTOCKCheck({
Ids: ids,
EntryIds: EntryIds.toString(),
}).then((res : any) => {
if (res.code === 200) {
fStockFlexDetailDelete({ Ids: ids.toString() }).then((res : any) => {
if (res.code === 200) {
fnDataList(state.materialId);
uni.$u.toast('操作成功')
}
})
}
})
} else {
uni.$u.toast('暂无扫描数据')
}
}
});
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
}
/**
* 数据请求
*/
const fnDataList = (FBillNo : any) => {
let param = {
id: FBillNo,
};
uni.showLoading({ mask: true });
SAL_OUTSTOCKView(param).then(res => {
uni.hideLoading();
if (res.code == 200) {
state.dataList = []
let dataListArray = res.data.Entry;
if (dataListArray.length > 0) {
dataListArray.forEach((p : any) => {
let item = {
Id: p.Id,
MaterialNo: p.MaterialNumber,//
MaterialName: formatLangTextValue(p.MaterialName),//
Lot: p.FLot_Text,//
CheckQty: p.Qty, //
CheckJoinQty: p.ScanedQty,//
NoCheckQty: p.UnScanQty,//
MultiLanguageText: Object.keys(p.StockId).length ? formatLangTextValue(p.StockId.Name) : '暂无仓库'
};
state.dataList.push(item);
});
}
}
});
}
//
const formatLangTextValue = (val : any) => {
let lang_Id = uni.getStorageSync('locale')
let item = val.find(p => p.Key == (lang_Id == 'cn' ? 2052 : 1033));
if (item != null) {
return item.Value;
}
return val[0].Value;
}
const toPages = (url : string, data : any = {}) => {
uni.$u.route({
url: url,
params: data
})
}
</script>
<style lang="scss">
.app {
background-color: #F5F5F5;
.page {
padding: 18px 32rpx;
display: flex;
flex-direction: column;
height: 100%;
flex: 1;
.input-box {
background-color: white;
box-sizing: border-box;
padding: 0 16rpx;
border-radius: 24rpx;
margin: 0 0 32rpx 0;
.u-textarea {
padding: 0 !important;
font-size: 24rpx !important;
color: #999999 !important;
}
.input-item {
box-sizing: border-box;
padding: 16rpx 0;
color: #222222;
font-size: 28rpx;
font-weight: 400;
.item-title {
//font-weight: 500;
font-size: 32rpx;
color: #333333;
}
.item-text {
font-weight: 400;
font-size: 27rpx;
color: #999999;
}
}
}
.material-listBox {
flex: 1;
.list-box-list {
width: 100%;
.data-item {
border: 1px solid #efeaea;
border-radius: 20rpx;
box-shadow: 0rpx 15rpx 15rpx #efeaea;
padding: 20rpx 22rpx;
margin-bottom: 16rpx;
background-color: #ffffff;
.itemBox {
line-height: 50rpx;
display: flex;
justify-content: space-between;
align-items: center;
.zongjian {
height: 1px;
flex: 1;
background-color: #f0f0f0;
margin: 0 16rpx;
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,264 @@
<template>
<view class="material-listBox1">
<scroll-view id="scroll-box1" class="scroll-box1" scroll-y="true" :style="{'height':state.scrollHeight+'px'}">
<view class="list-box-list">
<uni-swipe-action>
<uni-swipe-action-item :right-options="state.options" v-for="(item, index) in state.dataList">
<template #right>
<view class="itemRight" @click="fStockFlexDetailDeleteFun(item)">
<up-icon name="trash" color="#ffffff" size="28"></up-icon>
</view>
</template>
<view class="data-item" :style="[{'background-color':'#ffffff'}]" :key="index">
<view class="text" style="margin-bottom: 20px;display: flex;">
<view>{{ item['FVHUBMaterial.FName'] }}</view>
</view>
<view class="itemBox">
<view>{{ t('receive.wlbm') }}</view>
<view class="zongjian"></view>
<view>{{ item.FVHUBMaterialNumber }}</view>
</view>
<view class="itemBox">
<view>{{ t('public.qty') }}</view>
<view class="zongjian"></view>
<view>{{ item.FVHUBScanQty }}</view>
</view>
<view class="itemBox">
<view>{{ t('index.ck') }}</view>
<view class="zongjian"></view>
<view>{{ item['FVHUBStock.FName'] }}</view>
</view>
<view class="itemBox">
<view>{{ t('receive.ph') }}</view>
<view class="zongjian"></view>
<view>{{ item.FVHUBFlot }}</view>
</view>
<view class="itemBox">
<view>{{ t('public.xxh') }}</view>
<view class="zongjian"></view>
<view>{{ item.FVHUBJSON }}</view>
</view>
</view>
</uni-swipe-action-item>
</uni-swipe-action>
</view>
<view v-if="state.dataList.length==0">
<up-empty mode="list"></up-empty>
</view>
</scroll-view>
</view>
</template>
<script lang="ts" setup>
import { reactive, nextTick, onMounted, ref, computed, watch, defineProps, defineEmits, defineExpose } from 'vue';
import { onLoad, onShow, onReachBottom, } from '@dcloudio/uni-app'
import { useI18n } from 'vue-i18n'
import { parseTime } from '../../utils/tools.js';
import { BarcodePackBillList, BarcodePackBillSave, BarcodePackBillScanData, PRD_MORPTPush, PRD_MORPTScanData, PURReceiveBillScanCheck, PURReceiveBillScanData, PURReceiveBillView, SAL_DELIVERYNOTICEPush, ScanDataAndSave, fStockFlexDetailDelete, temporaryScanDraftSave, temporaryScanList } from '../../common/request/api/api';
import scanFrame from '../../components/scan-frame/scan-frame.vue'
import shortcut from '../../components/tools/shortcut.vue'
const emits = defineEmits(['clearOut'])
const inputRef = ref()
const scanFrameRef = ref()
const shortcutRef = ref()
const getI18n = useI18n()
const { t, locale } = getI18n
const props = defineProps({
queryString: {
type: String,
default: () => {
return ''
}
}
})
const state = reactive({
dataList: [],
scrollHeight: 0,
options: []
})
watch(() => props.queryString, () => {
if (props.queryString !== '') getReceiveBillScanData(props.queryString)
})
onShow(() => {
// fnDataList()
})
onMounted(() => {
const query = uni.createSelectorQuery().in(this);
query.select(".material-listBox1").boundingClientRect((data : any) => {
state.scrollHeight = data.height
}).exec();
fnDataList()
})
//
const getReceiveBillScanData = (val : string) => {
ScanDataAndSave({
FBillNo: val,
}).then((res : any) => {
emits('clearOut')
if (res.code === 200) {
fnDataList()
}
})
}
//
const fStockFlexDetailDeleteFun = (item : any) => {
uni.showModal({
title: t('index.ts'), content: t('index.qdysc'), cancelText: t('index.qx'), confirmText: t('index.qd'),
success(res) {
if (res.confirm) {
fStockFlexDetailDelete({ Ids: item.FID + '' }).then((res : any) => {
if (res.code === 200) {
uni.$u.toast(t('index.ysc'))
fnDataList()
}
})
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
}
/**
* 数据推送
*/
const dataPushNotification = () => {
uni.showModal({
title: t('public.ts'), content: t('public.tjMessage'), cancelText: t('public.cancel'), confirmText: t('public.confirm'),
success(res) {
if (res.confirm) {
let EntryIds : any = []
let ids : any = []
let ScanEntry : any = []
let param = {
FormId: 'SAL_DELIVERYNOTICE',
UserId: uni.getStorageSync('userInfo').Context.UserId,
FbillNo: state.FBillNo,
FType: "Whole"
};
uni.showLoading({ mask: true });
//
temporaryScanList(param).then(res => {
if (res.code == 200) {
if (res.data.list.length != 0) {
res.data.list.forEach((item : any) => {
EntryIds.push(item.FVHUBEntryId)
ids.push(item.FID)
ScanEntry.push({
FENTRYID: item.FVHUBEntryId,
Qty: item.FVHUBScanQty,
Flot: item.FVHUBFlot,
StockId: item.FVHUBStock,
StockFlex: item.FVHUBStockFlex,
Sno: item.FVHUBJSON
})
})
//
SAL_DELIVERYNOTICEPush({
EntryIds: EntryIds.toString(),
TargetFormId: 'SAL_OUTSTOCK',
IsEnableDefaultRule: 'true',
CustomParams: {
AutoAudit: 'true',
ScanEntry: ScanEntry
}
}).then((res : any) => {
if (res.code === 200) {
fStockFlexDetailDelete({ Ids: ids.toString() }).then((res : any) => {
if (res.code === 200) {
fnDataList();
uni.$u.toast(t('public.cg'))
}
})
} else {
uni.$u.toast(res.msg)
}
})
} else {
uni.$u.toast(t('index.zwsmsj'))
}
}
});
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
}
/**
* 数据请求
*/
const fnDataList = () => {
uni.showLoading({ mask: true });
temporaryScanList({
FormId: 'SAL_DELIVERYNOTICE',
UserId: uni.getStorageSync('userInfo').Context.UserId,
FType: "Whole"
}).then((res : any) => {
if (res.code == 200) {
state.dataList = res.data.list
}
});
}
//
const formatLangTextValue = (val : any) => {
let lang_Id = uni.getStorageSync('locale')
let item = val.find(p => p.Key == (lang_Id == 'cn' ? 2052 : 1033));
if (item != null) {
return item.Value;
}
return val[0].Value;
}
const toPages = (url : string, data : any = {}) => {
uni.$u.route({
url: url,
params: data
})
}
defineExpose({
dataPushNotification
})
</script>
<style lang="scss">
.material-listBox1 {
flex: 1;
.list-box-list {
width: 100%;
.itemRight {
display: flex;
align-items: center;
padding: 34rpx;
background-color: #ff5a5d;
border-radius: 20rpx;
}
.data-item {
border: 1px solid #efeaea;
border-radius: 20rpx;
box-shadow: 0rpx 15rpx 15rpx #efeaea;
padding: 20rpx 22rpx;
margin-bottom: 16rpx;
background-color: #ffffff;
.itemBox {
line-height: 50rpx;
display: flex;
justify-content: space-between;
align-items: center;
.zongjian {
height: 1px;
flex: 1;
background-color: #f0f0f0;
margin: 0 16rpx;
}
}
}
}
}
</style>

View File

@ -0,0 +1,148 @@
<template>
<view class="receive-listBox">
<scroll-view id="scroll-box" class="scroll-box" scroll-y="true"
:style="{'height':state.scrollHeight+'px'}" @scrolltolower="fnScrollBottom()">
<view class="list-box-list" v-if="state.dataList.length > 0">
<view class="data-item" @click.stop="fnToUrl(item)"
v-for="(item, index) in state.dataList" :key="index">
<view class="tit">销售出库单单号{{item.FBillNo}}</view>
<view class="line-p"></view>
<view class="b-font">{{ t('receive.rq') }}{{item.FDateFormat}}</view>
</view>
</view>
<view v-if="state.dataList.length==0">
<up-empty mode="list"></up-empty>
</view>
</scroll-view>
</view>
</template>
<script lang="ts" setup>
import { reactive, nextTick, onMounted,watch, ref,computed,defineProps } from 'vue';
import { useI18n } from 'vue-i18n'
import { parseTime } from '../../utils/tools.js';
import { PRD_MORPTList, SAL_OUTSTOCKList, receiveBillList } from '../../common/request/api/api';
const getI18n = useI18n()
const { t, locale } = getI18n
const props = defineProps({
queryString: {
type: String,
default: () => {
return ''
}
}
})
const state = reactive({
queryString: '',
dataList: [],
scrollHeight: 0,
tabsIndex:'1',
page: {
pageIndex: 1,
pageSize: 200,
totalCount: 0
},
})
watch(() => props.queryString, () => {
if (props.queryString !== ''){
state.page.pageIndex = 1
state.queryString = props.queryString
fnDataList()
}
})
onMounted(() => {
initialization()
})
const initialization = () => {
const query = uni.createSelectorQuery().in(this);
query.select(".receive-listBox").boundingClientRect((data:any) => {
state.scrollHeight = data.height
}).exec();
fnDataList()
}
const upTabsItemFun = (e:any) => {
state.tabsIndex = e.type
}
const fnScrollBottom = () => {
console.log(state.page.pageIndex * state.page.pageSize,state.page.totalCount);
if (state.page.pageIndex * state.page.pageSize <= state.page.totalCount) {
state.page.pageIndex ++;
uni.showLoading({ mask: true });
setTimeout(() => {
fnDataList();
}, 500);
}
}
const fnToUrl = (item : any) => {
toPages('/pages/BatchOutOftock/material',{id:item.FID,fBillNo:item.FBillNo})
}
const fnDataList = () => {
let param = {
queryString: state.queryString,
pageIndex: state.page.pageIndex,
pageSize: state.page.pageSize,
};
if (state.page.pageIndex == 1) {
uni.showLoading({ mask: true });
}
SAL_OUTSTOCKList(param).then(res => {
uni.hideLoading();
if (res.code == 200) {
let result = res.data;
let dataArray = result.list;
dataArray.forEach(p => {
p.FDateFormat = parseTime(p.FDate, '{y}-{m}-{d}');
});
if (state.page.pageIndex == 1) {
state.dataList = dataArray;
}
else {
state.dataList = state.dataList.concat(dataArray);
}
state.page.totalCount = result.total;
if (state.dataList.length == state.page.totalCount) {
// more_status.value = 'nomore';
}
}
});
}
const toPages = (url : string, data : any = {}) => {
uni.$u.route({
url: url,
params: data
})
}
</script>
<style lang="scss">
.receive-listBox {
flex: 1;
.list-box-list{
width: 100%;
// margin: 20rpx auto;
.data-item{
border: 1px solid #efeaea;
border-radius: 20rpx;
box-shadow: 0rpx 15rpx 15rpx #efeaea;
padding: 20rpx 20rpx 0;
margin-bottom: 20rpx;
background-color: #ffffff;
.tit{
font-size: 30rpx;
font-weight: bold;
padding: 20rpx 0;
}
.line-p{
border: 1px solid #efeaea;
}
.b-font{
font-size: 25rpx;
padding: 20rpx 0;
}
}
}
}
</style>

View File

@ -0,0 +1,142 @@
<template>
<up-popup :show="state.show" @close="close">
<view class="warehouse-listBox" ref="listBoxRef">
<scroll-view id="scroll-box" class="scroll-box" scroll-y="true" :style="{'height':state.scrollHeight+'px'}" >
<view class="list-box-list">
<view class="data-item" v-for="(item, index) of state.dataList" :key="index" @click="getAddressFun(item)">
<view class="tit">{{ t('index.sbmc') }}{{ item.name }}</view>
<view class="line-p"></view>
<view class="b-font">{{ t('index.sbbm') }}{{ item.address }}</view>
</view>
</view>
</scroll-view>
</view>
</up-popup>
</template>
<script lang="ts" setup>
import { reactive, nextTick, onMounted, ref, computed, defineProps, defineEmits, watch } from 'vue';
import { onLoad, onShow, onReachBottom, } from '@dcloudio/uni-app'
import { useI18n } from 'vue-i18n'
const getI18n = useI18n()
const { t, locale } = getI18n
const emits = defineEmits(['getAddress'])
const state = reactive({
show:false,
dataList: [],
scrollHeight: 0,
})
const getAddressFun = (row:any) => {
emits('getAddress',row)
}
const open = () => {
state.show = true
nextTick(() => {
if (state.show) {
const query = uni.createSelectorQuery().in(this);
query.select(".warehouse-listBox").boundingClientRect((data : any) => {
state.scrollHeight = data.height
}).exec();
}
})
}
const getList = (item:any) => {
state.dataList.push(item)
}
const close = () => {
state.show = false
state.dataList = []
}
defineExpose({
open,
close,
getList
})
</script>
<style scoped lang="scss">
:deep(.u-popup__content) {
border-top-left-radius: 16rpx;
border-top-right-radius: 16rpx;
box-sizing: border-box;
padding: 32rpx;
background-color: #F5F5F5;
min-height: 85vh;
display: flex;
flex-direction: column;
}
.popupText {
text-align: center;
font-size: 32rpx;
margin: 16rpx 0;
}
.input-box {
background-color: white;
box-sizing: border-box;
padding: 0 16rpx;
border-radius: 24rpx;
margin: 0 0 16rpx 0;
.u-textarea {
padding: 0 !important;
font-size: 24rpx !important;
color: #999999 !important;
}
.input-item {
box-sizing: border-box;
padding: 16rpx 0;
color: #222222;
font-size: 28rpx;
font-weight: 400;
.item-title {
//font-weight: 500;
font-size: 32rpx;
color: #333333;
}
.item-text {
font-weight: 400;
font-size: 27rpx;
color: #999999;
}
}
}
.warehouse-listBox {
display: block;
flex: 1;
.list-box-list {
width: 100%;
// margin: 20rpx auto;
.data-item {
border: 1px solid #efeaea;
border-radius: 20rpx;
box-shadow: 0rpx 15rpx 15rpx #efeaea;
padding: 20rpx 20rpx 0;
margin-bottom: 20rpx;
background-color: #ffffff;
.tit {
font-size: 30rpx;
font-weight: bold;
padding: 20rpx 0;
}
.line-p {
border: 1px solid #efeaea;
}
.b-font {
font-size: 25rpx;
padding: 20rpx 0;
}
}
}
}
</style>

230
pages/split/index.vue Normal file
View File

@ -0,0 +1,230 @@
<template>
<view class="app status-bar-gap">
<view class="page">
<l-header title="Split" sticky #right>
<view style="margin-right: 32rpx;">{{ t('receive.tj') }}</view>
</l-header>
<architecture ref="architectureRef" :dataType="t('home.scfl')" icon="scan" :placeholder="t('verify.tm')"
@scanConfirm="scanConfirmFun" @inputConfirm="changeFun" />
<view class="material-listBox">
<scroll-view id="scroll-box" class="scroll-box" scroll-y="true" :style="{'height':state.scrollHeight+'px'}">
<view class="list-box-list" v-if="Object.keys(state.pageData).length > 0">
<view class="data-item" :style="{'height':state.scrollHeight+'px'}">
<view class="itemBox">
<view>Supplier Name</view>
<view class="zongjian"></view>
<view>{{ state.pageData.FSupplierId }}</view>
</view>
<view class="itemBox">
<view>P/N</view>
<view class="zongjian"></view>
<view>{{ state.pageData.FMaterialId }}</view>
</view>
<view class="itemBox">
<view>Qty</view>
<view class="zongjian"></view>
<view>{{ state.pageData.FQty }}</view>
</view>
<view class="itemBox">
<view>Batch No</view>
<view class="zongjian"></view>
<view>{{ state.pageData.FLotText }}</view>
</view>
<view class="itemBox">
<view>Supplier Lot No</view>
<view class="zongjian"></view>
<view>{{ state.pageData.FSupplierLot }}</view>
</view>
<view class="itemBox">
<view>PO</view>
<view class="zongjian"></view>
<view>{{ state.pageData.PO }}</view>
</view>
<view class="itemBox">
<view>Delivery Date</view>
<view class="zongjian"></view>
<view>{{ state.pageData.Date }}</view>
</view>
<view class="itemBox">
<view>GRN #</view>
<view class="zongjian"></view>
<view>{{ state.pageData.FBillCode }}</view>
</view>
<view class="itemBox">
<view>Take it out</view>
<up-input clearable inputmode="numeric" v-model="state.qty"></up-input>
</view>
<up-button style="margin-top: 36px;width: 70vw;" class="btnItem" type="primary" shape="circle" :text="t('public.confirm')" @click="toPrint"></up-button>
</view>
</view>
<view v-if="Object.keys(state.pageData).length === 0">
<up-empty mode="list"></up-empty>
</view>
</scroll-view>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import { reactive, nextTick, onMounted, ref, computed, watch } from 'vue';
import { onLoad, onShow, onReachBottom, } from '@dcloudio/uni-app'
import { useI18n } from 'vue-i18n'
import { parseTime } from '../../utils/tools.js';
import { UHIK_BD_BarCodeMainFileView } from '../../common/request/api/api';
const architectureRef = ref()
const getI18n = useI18n()
const { t, locale } = getI18n
const state = reactive({
qty: 0,
queryString: '',
pageData: {},
scrollHeight: 0
})
onLoad(() => { })
onShow(() => { })
onMounted(() => {
const query = uni.createSelectorQuery().in(this);
query.select(".material-listBox").boundingClientRect((data) => {
state.scrollHeight = data.height
}).exec();
})
/**
* 数据逻辑
*/
const interpolation = (item : any) => {
if (item.CheckJoinQty === 0 && item.CheckJoinQty + item.NoCheckQty === item.CheckQty) {
return '#ffffff'
}
if (item.CheckJoinQty !== 0 && item.NoCheckQty !== 0 && item.CheckJoinQty + item.NoCheckQty === item.CheckQty) {
return 'rgb(254 227 87)'
}
if (item.CheckJoinQty === item.CheckQty) {
return 'rgb(87 191 254)'
}
}
//
const debounceTimer = ref()
const changeFun = (e : any) => {
if (debounceTimer.value !== null) clearTimeout(debounceTimer.value)
debounceTimer.value = setTimeout(() => {
state.queryString = e
if (state.queryString !== '') getReceiveBillScanData(e)
})
}
const scanConfirmFun = (e : any) => {
getReceiveBillScanData(e)
}
const toPrint = () => {
if(state.qty === 0){
uni.$u.toast('Qty cannot be empty')
return
}
toPages('/pages/split/print',{data:JSON.stringify({...state.pageData,splitQty:state.qty})})
}
//
const getReceiveBillScanData = (val : string) => {
UHIK_BD_BarCodeMainFileView({
FBarCode: val,
}).then((res : any) => {
console.log(res);
state.pageData = res.data[0]
architectureRef.value.closeFun()
})
}
//
const formatLangTextValue = (val : any) => {
let lang_Id = uni.getStorageSync('locale')
let item = val.find(p => p.Key == (lang_Id == 'cn' ? 2052 : 1033));
if (item != null) {
return item.Value;
}
return val[0].Value;
}
const toPages = (url : string, data : any = {}) => {
uni.$u.route({
url: url,
params: data
})
}
</script>
<style lang="scss">
.app {
background-color: #F5F5F5;
.page {
padding: 18px 32rpx;
display: flex;
flex-direction: column;
height: 100%;
flex: 1;
.input-box {
background-color: white;
box-sizing: border-box;
padding: 0 16rpx;
border-radius: 24rpx;
margin: 0 0 32rpx 0;
.u-textarea {
padding: 0 !important;
font-size: 24rpx !important;
color: #999999 !important;
}
.input-item {
box-sizing: border-box;
padding: 16rpx 0;
color: #222222;
font-size: 28rpx;
font-weight: 400;
.item-title {
//font-weight: 500;
font-size: 32rpx;
color: #333333;
}
.item-text {
font-weight: 400;
font-size: 27rpx;
color: #999999;
}
}
}
.material-listBox {
flex: 1;
.list-box-list {
width: 100%;
.data-item {
border: 1px solid #efeaea;
border-radius: 20rpx;
box-shadow: 0rpx 15rpx 15rpx #efeaea;
padding: 20rpx 22rpx;
margin-bottom: 16rpx;
background-color: #ffffff;
.itemBox {
line-height: 50rpx;
display: flex;
justify-content: space-between;
align-items: center;
.zongjian {
height: 1px;
flex: 1;
background-color: #f0f0f0;
margin: 0 16rpx;
}
}
}
}
}
}
}
</style>

382
pages/split/print.vue Normal file
View File

@ -0,0 +1,382 @@
<template>
<view class="app status-bar-gap">
<view class="page">
<l-header :title="t('index.zbdy')" sticky></l-header>
<view class="input-box" @click="printingMachineSelectFun">
<view class="input-item">
<up-input :placeholder="t('index.qxzdyj')" border="none" clearable inputAlign="left" v-model="state.printingMachine.name"
confirmType="next" :disabled="true">
<template #prefix>
<view class="item-title" style="margin-right: 16rpx;">{{ t('index.dyj') }}</view>
</template>
<template #suffix>
<up-icon name="search" color="#6c6c6c" size="24"></up-icon>
</template>
</up-input>
</view>
</view>
<view class="btnList" style="margin-top: 32rpx;">
<up-button class="btnItem" type="primary" shape="circle" :text="t('index.dyj')" @click="sendHexStr"></up-button>
</view>
</view>
<bluetoothList ref="bluetoothListRef" :dataList="state.bluetoothList" @getAddress="getAddressFun" />
</view>
</template>
<script setup lang="ts">
import { reactive, nextTick, onMounted, ref, computed, watch } from 'vue';
import { onLoad, onShow, onReachBottom, } from '@dcloudio/uni-app'
import tkiQrcode from '@/components/tki-qrcode/tki-qrcode.vue'
import { PRD_MOEnterIntoPro, PRD_MORPTGetPrintData, UHIK_BD_BarCodeMainFileSave } from '../../common/request/api/api';
import { timeFormat } from '@/uni_modules/uview-plus';
import bluetoothList from './bluetoothList.vue'
import { useI18n } from 'vue-i18n'
const getI18n = useI18n()
const { t, locale } = getI18n
const bluetoothListRef = ref()
// #ifdef APP-PLUS
const blueModule = uni.requireNativePlugin("gp-bluetooth")
import * as tsc from '../../components/gprint/tsc.js'
// #endif
const state = reactive({
id: '',
FBillNo: '',
pageData: {},
printingMachine: {
name: '',
address: ''
},
bluetoothList: [],
sendData: undefined,
prontList: [],
timer: null,
printState: '0'
})
onLoad((pageData : any) => {
state.pageData = JSON.parse(pageData.data)
console.log(state.pageData);
})
onShow(() => {
uni.getLocation({
type: 'wgs84',
success(res) {
console.log('开启定位权限', res)
},
fail: (err:any) => { }
});
// #ifdef APP-PLUS
hasPermission()
// #endif
})
//
const hasPermission = () => {
console.log(uni.getStorageSync('printInfo'));
blueModule.checkConnect({
mac: uni.getStorageSync('printInfo').address,
uuid: '00001101-0000-1000-8000-00805f9b34fb'
}, (ret : any) => {
console.log(ret);
if (!ret.success) {
uni.setStorageSync('printInfo', {})
state.printingMachine = {
name: '',
address: ''
}
setTimeout(() => {
uni.showToast({
icon: 'none',
mask: true,
title: t('index.ljydk'),
})
}, 500)
}
});
blueModule.hasPermission((res : any) => {
if (res.success) {
blueModule.isOpen((isOpenRes : any) => {
console.log(isOpenRes)
if (isOpenRes.success) {
state.printingMachine.name = uni.getStorageSync('printInfo').name
state.printingMachine.address = uni.getStorageSync('printInfo').address
} else {
uni.setStorageSync('printInfo', {})
state.printingMachine.name = ''
state.printingMachine.address = ''
blueModule.openBT((openBTRes : any) => {
console.log(openBTRes)
});
}
});
} else {
uni.$u.toast(t('index.'))
}
});
}
//
const ReadTheAttachedBluetoothDevice = () => {
state.bluetoothList = []
blueModule.searchBT((res : any) => {
if (res.success) {
console.log(res);
if (res.data?.name) {
bluetoothListRef.value.getList(res.data)
}
}
});
}
const printingMachineSelectFun = () => {
ReadTheAttachedBluetoothDevice()
bluetoothListRef.value.open()
}
const getAddressFun = (row : any) => {
blueModule.connect({
MACAddress: row.address,
uuid: '00001101-0000-1000-8000-00805f9b34fb',
sleepTime: 50
}, (result : any) => {
if (result.success) {
uni.$u.toast(t('index.ljcg'))
state.printingMachine.name = row.name
state.printingMachine.address = row.address
bluetoothListRef.value.close()
uni.setStorageSync('printInfo', { name: row.name, address: row.address })
} else {
uni.$u.toast(t('index.ljsb'))
}
}, (data : any) => { })
}
const createLabel = (item : any) => {
var command = tsc.default.createNew()
command.setSize(100, 50)
command.setGap(2)
command.setCls()
command.setQR(15, 15, "L", 3, "A", item.FBarCode)
command.setText(120, 15, "TSS24.BF2", 1, 1, `Date:${item.FDate.split('T')[0]}`)
command.setText(120, 40, "TSS24.BF2", 1, 1, `MO#:${item.FSrcBillNo}`)
command.setText(120, 65, "TSS24.BF2", 1, 1, `P/N:${item.FMaterialId}`)
command.setText(120, 90, "TSS24.BF2", 1, 1, `SN#:${item.FSno}`)
command.setPagePrint()
state.sendData = command.getData();
}
const sendHexStr = () => {
let arr = []
let data1 = {
FBarCodeRule: "171064",
FBarCode: `${state.pageData.FBillCode}*${state.pageData.FMaterialId}*${state.pageData.FLotText}*${Number(state.pageData.FQty) - Number(state.pageData.splitQty)}`,
FBillCode:state.pageData.FBillCode,
FMaterialId: state.pageData.FMaterialId,
FSupplierLot: state.pageData.FSupplierId,
FQty: Number(state.pageData.FQty) - Number(state.pageData.splitQty)
}
let data2 = {
FBarCodeRule: "171064",
FBarCode: `${state.pageData.FBillCode}*${state.pageData.FMaterialId}*${state.pageData.FLotText}*${Number(state.pageData.splitQty)}`,
FBillCode:state.pageData.FBillCode,
FMaterialId: state.pageData.FMaterialId,
FSupplierLot: state.pageData.FSupplierId,
FQty: Number(state.pageData.splitQty)
}
arr = [data1,data2]
UHIK_BD_BarCodeMainFileSave({
Key: 'qwe123!@#',
Items: arr
},true).then((res : any) => {
console.log(res);
// if (res.code == 200) {
// let i : number = 0;
// state.timer = setInterval(() => {
// if (state.printState === '0') {
// createLabel(state.prontList[i])
// initPrint()
// i++;
// }
// if (state.prontList.length == i) {
// clearInterval(state.timer);
// state.timer = null;
// state.printState = '0';
// }
// }, 2000);
// } else {
// let str = JSON.stringify(res)
// if(str.indexOf('') !== -1 || str.indexOf('is already been used') !== -1){
// let i : number = 0;
// state.timer = setInterval(() => {
// if (state.printState === '0') {
// createLabel(state.prontList[i])
// initPrint()
// i++;
// }
// if (state.prontList.length == i) {
// clearInterval(state.timer);
// state.timer = null;
// state.printState = '0';
// }
// }, 2000);
// } else {
// uni.$u.toast(t('index.cjbqsb'))
// }
// }
})
}
const initPrint = () => {
if (state.sendData == null) {
// uni.$u.toast('')
return
}
state.printState = '1';
let hexStr = ''
var data = Array.from(state.sendData)
for (var i = 0; i < data.length; i++) {
var str = Number(data[i]).toString(16)
str = str.length == 1 ? "0" + str : str
hexStr += str
}
function splitString(str, length) {
var strLen = str.length
var resArr = []
for (var i = 0; i < strLen; i += length) {
resArr.push(str.substring(i, i + length))
}
return resArr
}
var sendloop = splitString(hexStr, 250);
console.log(sendloop.length)
function realWriteData(sendloop, i) {
var data = sendloop[i]
if (typeof (data) == "undefined") {
return
}
console.log("第【" + i + "】次写数据" + data)
var ret = blueModule.sendHexStr(data, (result) => {
//
console.log('发送结果')
console.log(result)
if (!result.success) {
uni.$u.toast(t('index.ljydk'))
uni.setStorageSync('printInfo', {})
state.printingMachine = {
name: '',
address: ''
}
return
}
if (result.success) {
realWriteData(sendloop, i + 1);
}
});
}
var i = 0;
realWriteData(sendloop, i);
state.printState = '0';
}
const formatLangTextValue = (val : any) => {
let lang_Id = uni.getStorageSync('locale')
let item = val.find(p => p.Key == (lang_Id == 'cn' ? 2052 : 1033));
if (item != null) {
return item.Value;
}
return val[0].Value;
}
</script>
<style lang="scss" scoped>
:deep(.uni-date__x-input) {
color: black !important;
}
:deep(.u-input) {
background-color: #ffffff !important;
}
.app {
background-color: #F5F5F5;
.page {
padding: 18px 32rpx;
display: flex;
flex-direction: column;
height: 100%;
flex: 1;
.input-box {
background-color: white;
box-sizing: border-box;
padding: 0 16rpx;
border-radius: 16rpx;
margin: 16rpx 0;
.u-textarea {
padding: 0 !important;
font-size: 24rpx !important;
color: #999999 !important;
}
.input-item {
box-sizing: border-box;
padding: 16rpx 0;
color: #222222;
font-size: 28rpx;
font-weight: 400;
.item-title {
//font-weight: 500;
font-size: 28rpx;
color: #333333;
}
.item-text {
font-weight: 400;
font-size: 27rpx;
color: #999999;
}
}
}
.data-item {
border: 1px solid #efeaea;
border-radius: 20rpx;
padding: 20rpx 22rpx;
background-color: #ffffff;
display: flex;
flex-direction: column;
justify-content: space-between;
.btnList {
display: flex;
margin-bottom: 32rpx;
.btnItem {
width: 40%;
}
}
.timebox {
display: flex;
align-items: center;
margin-top: 32rpx;
}
.itemBox {
line-height: 50rpx;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8rpx;
.zongjian {
height: 1px;
flex: 1;
background-color: #f0f0f0;
margin: 0 16rpx;
}
}
}
}
}
</style>

54
scanInput.js Normal file
View File

@ -0,0 +1,54 @@
let main, receiver, filter, _codeQueryTag = false, temp = [], init = false, start = false;
export default {
initScan() {
if(init) return
let _this = this;
main = plus.android.runtimeMainActivity(); //获取activity
var IntentFilter = plus.android.importClass('android.content.IntentFilter');
filter = new IntentFilter();
//android.intent.ACTION_DECODE_DATA
filter.addAction(uni._qs_scanlistener_action || "com.uniappPda.ACTION"); // 换你的广播动作你的pda设备里面看
receiver = plus.android.implements('io.dcloud.feature.internal.reflect.BroadcastReceiver', {
onReceive: function(context, intent) {
plus.android.importClass(intent);
let code = intent.getStringExtra(uni._qs_scanlistener_label || "com.uniapp.gatedge"); // 换你的广播标签你的pda设备里面看
_this.queryCode(code);
}
});
init = true
},
startScan() {
if(!start) {
start = true
main.registerReceiver(receiver, filter);
}
},
stopScan() {
if(start) {
start = false
main.unregisterReceiver(receiver);
}
},
install(fn) {
if(typeof fn == 'function' && !~temp.indexOf(fn)) temp.push(fn)
},
uninstall(fn) {
if(typeof fn == 'function') {
const index = temp.find(i=>i == fn)
if(~index) temp.splice(index, 1)
}
},
queryCode: function(code) {
//防重复
// if (_codeQueryTag) return false;
// _codeQueryTag = true;
// setTimeout(function() {
// _codeQueryTag = false;
// }, 150);
if(temp && temp.length) {
temp[temp.length - 1](code)
}
uni.vibrateShort()
uni.$emit("qs_scanlistener_handle", code);
}
}

View File

@ -0,0 +1,2 @@
## 1.0.02022-12-17
create

View File

@ -0,0 +1,73 @@
<template>
<view></view>
</template>
<script>
import scaninput from './scanInput.js'
// #ifdef APP-PLUS
scaninput.initScan()
scaninput.startScan()
// #endif
export default {
name:"scan-listener",
created() {
scaninput.install(this.scanHandle)
uni.$on('scan_handle', this.scanHandle)
},
beforeDestroy() {
scaninput.uninstall(this.scanHandle)
},
methods: {
changeFun(str) {
if (this.debounceTimer !== null) clearTimeout(this.debounceTimer)
this.debounceTimer = setTimeout(() => {
this.$emit('scan', this.inputVal)
this.inputVal = ''
}, 500)
},
onEvent(event) {
console.log(event);
if (event.key != 'Enter' && event.key != 'PrintScreen' && event.key != 'Shift' && event.key != 'Unidentified') { // EnterPrintScreen
this.inputVal = this.inputVal + event.key
}
if(this.inputVal) {
this.changeFun(this.inputVal)
}
},
scanHandle(code) {
this.$emit('scan', code)
}
},
data() {
return {
inputVal: '',
debounceTimer:null
};
}
}
</script>
<script module="keyboard" lang="renderjs">
export default {
mounted () {
const onKey = (event) => {
const keys1 = ['type', 'timeStamp']
const keys2 = ['altKey', 'code', 'ctrlKey', 'isComposing', 'key', 'location', 'metaKey', 'repeat', 'shiftKey']
const keys3 = ['char', 'charCode', 'keyCode', 'keyIdentifier', 'keyLocation', 'which']
const data = {}
keys1.concat(keys2, keys3).forEach(key => {
data[key] = event[key]
})
this.$ownerInstance.callMethod('onEvent', data)
}
const names = ['keyup'] //'keydown',
names.forEach(name => {
document.addEventListener(name, onKey, false)
})
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,55 @@
let main, receiver, filter, _codeQueryTag = false, temp = [], init = false, start = false;
export default {
initScan() {
if(init) return
let _this = this;
main = plus.android.runtimeMainActivity(); //获取activity
var IntentFilter = plus.android.importClass('android.content.IntentFilter');
filter = new IntentFilter();
//android.intent.ACTION_DECODE_DATA
filter.addAction("com.uniappPda.ACTION"); // 换你的广播动作你的pda设备里面看
receiver = plus.android.implements('io.dcloud.feature.internal.reflect.BroadcastReceiver', {
onReceive: function(context, intent) {
plus.android.importClass(intent);
let code = intent.getStringExtra("com.uniapp.gatedge"); // 换你的广播标签你的pda设备里面看
_this.queryCode(code);
}
});
init = true
},
startScan() {
if(!start) {
start = true
main.registerReceiver(receiver, filter);
}
},
stopScan() {
if(start) {
start = false
main.unregisterReceiver(receiver);
}
},
install(fn) {
if(typeof fn == 'function' && !~temp.indexOf(fn)) temp.push(fn)
},
uninstall(fn) {
if(typeof fn == 'function') {
const index = temp.find(i=>i == fn)
if(~index) temp.splice(index, 1)
}
},
queryCode: function(code) {
//防重复
// if (_codeQueryTag) return false;
// _codeQueryTag = true;
// setTimeout(function() {
// _codeQueryTag = false;
// }, 150);
if(temp && temp.length) {
temp[temp.length - 1](code)
}
uni.vibrateShort()
uni.$emit("qs_scanlistener_handle", code);
}
}

View File

@ -0,0 +1,82 @@
{
"id": "qs-scanlistener",
"displayName": "qs-scanlistener PDA扫码",
"version": "1.0.0",
"description": "PDA扫码 兼容广播和键盘",
"keywords": [
"pda",
"扫码"
],
"repository": "",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"type": "component-vue",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"Vue": {
"vue2": "y",
"vue3": "y"
},
"App": {
"app-vue": "y",
"app-nvue": "n"
},
"H5-mobile": {
"Safari": "n",
"Android Browser": "n",
"微信浏览器(Android)": "n",
"QQ浏览器(Android)": "n"
},
"H5-pc": {
"Chrome": "n",
"IE": "n",
"Edge": "n",
"Firefox": "n",
"Safari": "n"
},
"小程序": {
"微信": "n",
"阿里": "n",
"百度": "n",
"字节跳动": "n",
"QQ": "n",
"钉钉": "n",
"快手": "n",
"飞书": "n",
"京东": "n"
},
"快应用": {
"华为": "n",
"联盟": "n"
}
}
}
}
}

View File

@ -0,0 +1,20 @@
## qs-scanlistener PDA扫码
## 支持广播和键盘
---
### 广播动作可在main.js设置uni._qs_scanlistener_action = 你的广播动作名称, 默认android.intent.ACTION_DECODE_DATA
### 广播标签可在main.js设置uni._qs_scanlistener_label = 你的广播标签名称, 默认barcode_string
---
### 扫码结果也可以uni.$on('qs_scanlistener_handle', code=>{}) 中获取
---
Template
```html
<qs-scanlistener @scan="scan"></qs-scanlistener>
```
js
```javascript
methods: {
scan(code) {
console.log(code)
}
}
```

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff