feat:样品库管理
This commit is contained in:
7
App.vue
7
App.vue
@@ -4,7 +4,7 @@ import { onLaunch, onShow, onError } from '@dcloudio/uni-app'
|
||||
import { NxInit } from './nx'
|
||||
import $store from '@/nx/store'
|
||||
// #ifdef APP-PLUS
|
||||
import * as chainway from '@/uni_modules/zzjc-chainway-p100'
|
||||
import * as urovo from '@/uni_modules/zzjc-urovo'
|
||||
// #endif
|
||||
onLaunch(async () => {
|
||||
// 加载nx底层依赖
|
||||
@@ -15,9 +15,8 @@ onLaunch(async () => {
|
||||
if (brand === 'chainway') {
|
||||
plus.screen.lockOrientation('landscape')
|
||||
}
|
||||
|
||||
chainway.scanRegister(data => {
|
||||
console.log('扫码结果:' + data)
|
||||
urovo.scanRegister(data => {
|
||||
console.log('优博讯扫码结果:' + data)
|
||||
$store('biz').scanQRInfo = data
|
||||
})
|
||||
// #endif
|
||||
|
||||
@@ -363,7 +363,10 @@ defineExpose({
|
||||
<style lang="scss" scoped>
|
||||
.s-verify-mask {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.45);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -427,6 +430,8 @@ defineExpose({
|
||||
.s-verify-image-block {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
@@ -447,7 +452,9 @@ defineExpose({
|
||||
|
||||
.s-verify-loading {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -484,8 +491,8 @@ defineExpose({
|
||||
}
|
||||
|
||||
.s-verify-slider-track {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 20px;
|
||||
background: #f2f3f5;
|
||||
}
|
||||
@@ -529,7 +536,9 @@ defineExpose({
|
||||
|
||||
.s-verify-slider-text {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
9
nx/api/sampleWarehouse.js
Normal file
9
nx/api/sampleWarehouse.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import request from '@/nx/request'
|
||||
export default {
|
||||
execReturnToStock: data =>
|
||||
request({
|
||||
url: '/qms/business-sub-sample/execReturnToStock',
|
||||
method: 'GET',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -11,8 +11,7 @@ export function calcAnalysisValue(group) {
|
||||
try {
|
||||
for (const g of group) {
|
||||
for (const ele of g.fields) {
|
||||
if (!ele.formula || ele.formula == '') continue
|
||||
if (ele.valueTypeManual && ele.valueTypeManual == '1') continue
|
||||
if (!ele.formula || ele.formula == '' || ele.formula.startsWith('From')) continue
|
||||
let formula = ele.formula
|
||||
let formulas = formula.split('|')
|
||||
let formulaVal = ''
|
||||
@@ -20,11 +19,9 @@ export function calcAnalysisValue(group) {
|
||||
formulas.forEach(f => {
|
||||
let value = ''
|
||||
if (f.charAt(0) === 'p') {
|
||||
// let o = elementParamValueData.find((i) => 'p' + i.paramNo === f);
|
||||
let o = findFieldInGroup(f, group, 'p')
|
||||
value = o.value
|
||||
} else if (f.charAt(0) === 'e') {
|
||||
// let o = elementParamValueData.find((i) => 'e' + i.paramNo === f);
|
||||
let o = findFieldInGroup(f, group, 'e')
|
||||
value = o.value
|
||||
} else if (f.charAt(0) === '<' || f.charAt(0) === '>') {
|
||||
@@ -48,7 +45,7 @@ export function calcAnalysisValue(group) {
|
||||
v = eval(formulaVal)
|
||||
} else {
|
||||
v = math.evaluate(formulaVal).toString()
|
||||
v = isFinite(v) ? v.toString() : ''
|
||||
v = isFinite(v) ? v.toString() : 0
|
||||
}
|
||||
ele.value = handleRoundFiveNumber(v, ele.decimalPosition)
|
||||
}
|
||||
|
||||
@@ -206,7 +206,6 @@ export default {
|
||||
data: data
|
||||
}
|
||||
let printData = {
|
||||
// type: "preview",
|
||||
type: 'print',
|
||||
reportTemplate: reportTemplate,
|
||||
reportData: JSON.stringify(reportData)
|
||||
|
||||
@@ -71,10 +71,18 @@ const user = defineStore({
|
||||
// await this.getRoleMenus()
|
||||
// await this.getDeviceTimeout()
|
||||
// this.startTimeoutChecker()
|
||||
// 如果已经存在默认模块就跳转到对应的模块
|
||||
const defaultModulePath = uni.getStorageSync('defaultModule')
|
||||
if (defaultModulePath) {
|
||||
uni.reLaunch({
|
||||
url: defaultModulePath
|
||||
})
|
||||
} else {
|
||||
uni.reLaunch({
|
||||
url: '/pages/index/index'
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
async getUserInfo() {
|
||||
const { user } = await userApi.getInfo()
|
||||
|
||||
37
pages.json
37
pages.json
@@ -225,16 +225,38 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/analysis/setting/print",
|
||||
"path": "pages/analysis/auncel/auncel-status",
|
||||
"style": {
|
||||
"navigationBarTitleText": "打印",
|
||||
"navigationBarTitleText": "天平",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
// 样品库管理
|
||||
{
|
||||
"path": "pages/sampleWarehouse/index/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "样品库管理",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/analysis/auncel/auncel-status",
|
||||
"path": "pages/sampleWarehouse/sampleSearch/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "天平",
|
||||
"navigationBarTitleText": "样品查询",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/sampleWarehouse/returnToStock/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "样品归库",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/sampleWarehouse/execChangeLocation/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "库位变更",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
@@ -256,6 +278,13 @@
|
||||
"navigationBarTitleText": "关于我们"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/setting/print",
|
||||
"style": {
|
||||
"navigationBarTitleText": "打印",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/me/index",
|
||||
"style": {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
leftIcon=""
|
||||
:leftText="`您好!${userInfo.nickname}`"
|
||||
>
|
||||
<u-icon @click="popupShow = true" size="28" color="#FFF" name="account-fill" />
|
||||
<u-icon @click="popupShow = true" size="28" color="#FFF" name="setting-fill" />
|
||||
</navbar-back>
|
||||
|
||||
<up-grid :col="gridCol" :border="false">
|
||||
@@ -29,7 +29,6 @@ import mePopup from '@/pages/index/me-popup.vue'
|
||||
|
||||
// 响应式数据
|
||||
const popupShow = ref(false)
|
||||
const isAllowAgainPrint = ref(false)
|
||||
|
||||
const menuItemList = ref([
|
||||
{
|
||||
@@ -57,63 +56,13 @@ const goTo = url => {
|
||||
nx.$router.go(url)
|
||||
}
|
||||
|
||||
const checkAllowAgainPrint = () => {
|
||||
const param = {
|
||||
userId: userInfo.value.id,
|
||||
clientId: 'auncel'
|
||||
}
|
||||
nx.$api.user.getAppPermission(param).then(res => {
|
||||
if (!res.success) return
|
||||
const ret = res.result || []
|
||||
if (ret.length === 0) return
|
||||
for (let i = 0; i < ret.length; i++) {
|
||||
if (ret[i].roleValue && ret[i].roleValue === 2) {
|
||||
isAllowAgainPrint.value = true
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const openLaboratoryWs = () => {
|
||||
const regData = {
|
||||
msgId: nx.$helper.uuid(),
|
||||
cmd: 'register',
|
||||
clientType: 'caaClient',
|
||||
data: {
|
||||
userId: userInfo.value.id,
|
||||
tenantId: userInfo.value.loginTenantId,
|
||||
userRealName: userInfo.value.realname
|
||||
}
|
||||
}
|
||||
nx.$measure.setRegData(JSON.stringify(regData))
|
||||
nx.$measure.open()
|
||||
}
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
// checkAllowAgainPrint()
|
||||
// openLaboratoryWs()
|
||||
})
|
||||
onMounted(() => {})
|
||||
// 动态设置 grid 列数
|
||||
const { gridCol } = useGridCol([400], [2, 3])
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.title_content {
|
||||
text-align: center;
|
||||
padding-top: 75px;
|
||||
letter-spacing: 10px;
|
||||
width: 100%;
|
||||
font-size: 36px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.banner {
|
||||
overflow: hidden;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
.grid-text {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
@@ -1,583 +0,0 @@
|
||||
<template>
|
||||
<view class="page">
|
||||
<u-navbar
|
||||
title="化学分析天平"
|
||||
:is-back="false"
|
||||
:border-bottom="false"
|
||||
title-color="#fff"
|
||||
:background="{ 'background-image': 'linear-gradient(45deg, rgb(54, 138, 217), rgb(64, 160, 255))' }"
|
||||
></u-navbar>
|
||||
<view style="text-align: center"><u-loading mode="flower" :show="showLoading" size="48"></u-loading></view>
|
||||
<view class="container">
|
||||
<view class="auncel" v-for="(item, index) in deviceLaboratoryList" :key="item.id">
|
||||
<view class="title">
|
||||
<u-row style="width: 100%; padding-bottom: 18rpx" gutter="16">
|
||||
<u-col span="8">
|
||||
<text class="measurePointName"
|
||||
>{{ item.name }} {{ item.controlUserName ? '[' + item.controlUserName + ']远程控制' : '' }}</text
|
||||
>
|
||||
</u-col>
|
||||
<u-col span="4">
|
||||
<!--
|
||||
<view style="width: 100%; display: flex; flex-direction: row; justify-content: flex-end;">
|
||||
<text class="measurePointName" >{{item.isAutoWork ? '自动计量' : '集控接管'}}</text>
|
||||
<u-icon style="padding: 0 20rpx;" name="file-text" label-pos="bottom" color="#2979ff" size="40" @click="goto(item.measurePointId)"></u-icon>
|
||||
<u-icon style="padding: 0 20rpx;" name="setting" label-pos="bottom" label="设置" color="#2979ff" size="40" @click="goto(item.measurePointId)"></u-icon>
|
||||
</view>
|
||||
-->
|
||||
</u-col>
|
||||
</u-row>
|
||||
</view>
|
||||
<view :class="item.isConnected == 1 ? 'title-line-green' : 'title-line-gray'"></view>
|
||||
<view class="weight-container">
|
||||
<!-- <view class="infrared-container">
|
||||
<view :class="item.infraredLeft == 0 ? 'infrared-line-gray' : item.infraredLeft == 1 ? 'infrared-line-green':'infrared-line-red'"></view>
|
||||
</view>
|
||||
-->
|
||||
<block v-if="item.deviceType == 'auncel'">
|
||||
<view class="weight">
|
||||
<view
|
||||
:class="
|
||||
item.weightStable == 0
|
||||
? 'weight-data-yellow'
|
||||
: item.weightStable == 1
|
||||
? 'weight-data'
|
||||
: 'weight-data-warning'
|
||||
"
|
||||
>
|
||||
{{ item.weightData }}
|
||||
</view>
|
||||
<view class="weight-unit">{{ item.weightUnit }}</view>
|
||||
</view>
|
||||
</block>
|
||||
<block v-if="item.deviceType == 'temp'">
|
||||
<view class="temp">
|
||||
<view class="charts-box"
|
||||
><qiun-data-charts
|
||||
type="gauge"
|
||||
:opts="temperatureOpts"
|
||||
:chartData="temperatureChartData"
|
||||
background="none"
|
||||
/></view>
|
||||
<view class="charts-box"
|
||||
><qiun-data-charts type="gauge" :opts="humidityOpts" :chartData="humidityChartData" background="none"
|
||||
/></view>
|
||||
</view>
|
||||
</block>
|
||||
<!--
|
||||
<view class="infrared-container">
|
||||
<view :class="item.infraredRight == 0 ? 'infrared-line-gray' : item.infraredRight == 1 ? 'infrared-line-green':'infrared-line-red'"></view>
|
||||
</view>
|
||||
-->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
showLoading: false,
|
||||
runLogMaxLength: 8,
|
||||
deviceLaboratoryList: [],
|
||||
temperatureOpts: {},
|
||||
temperatureChartData: {
|
||||
categories: [
|
||||
{
|
||||
value: 0.2,
|
||||
color: '#1890ff'
|
||||
},
|
||||
{
|
||||
value: 1,
|
||||
color: '#2fc25b'
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: '温度',
|
||||
data: 0.66
|
||||
}
|
||||
]
|
||||
},
|
||||
humidityOpts: {},
|
||||
humidityChartData: {
|
||||
categories: [
|
||||
{
|
||||
value: 1,
|
||||
color: '#1890ff'
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: '湿度',
|
||||
data: 0.66
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
//获取数据
|
||||
this.getPageData()
|
||||
|
||||
//监听websocket返回来的数据
|
||||
//设备数据
|
||||
uni.$on('deviceData', res => {
|
||||
switch (res.deviceType) {
|
||||
case 'weighbridge':
|
||||
this.mearsuPointList.forEach((item, index) => {
|
||||
if (item.measurePointId === res.measurePointId) {
|
||||
//item.weightData = (index + Number(res.deviceValue)).toFixed(2) + " "+ res.deviceUnit;
|
||||
item.weightData = res.deviceValue
|
||||
item.weightUnit = res.deviceUnit
|
||||
item.weightStable = res.deviceStable
|
||||
item.measureIsConnected = 1
|
||||
item.isAutoWork = res.isAutoWork
|
||||
}
|
||||
})
|
||||
break
|
||||
case 'auncel':
|
||||
this.deviceLaboratoryList.forEach((item, index) => {
|
||||
if (item.id === res.deviceId) {
|
||||
//item.weightData = (index + Number(res.deviceValue)).toFixed(2) + " "+ res.deviceUnit;
|
||||
item.weightData = res.weightData
|
||||
item.weightUnit = res.weightUnit
|
||||
item.weightStable = 1
|
||||
item.isConnected = 1
|
||||
}
|
||||
})
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
// this.weight = res.weighbridge;
|
||||
// this.infraredLeft = res.infrared;
|
||||
// this.infraredRight = res.infrared;
|
||||
})
|
||||
|
||||
//设备状态
|
||||
uni.$on('deviceStatus', res => {
|
||||
this.mearsuPointList.forEach((item, index) => {
|
||||
if (item.measurePointId === res.measurePointId) {
|
||||
item.devices.forEach((d, i) => {
|
||||
if (d.id === res.deviceId) {
|
||||
d.isConnected = res.connected
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
//日志数据
|
||||
uni.$on('logData', res => {
|
||||
this.mearsuPointList.forEach((item, index) => {
|
||||
if (item.measurePointId === res.measurePointId) {
|
||||
if (item.runLogs.length >= this.runLogMaxLength) {
|
||||
//删除并返回数组的第一个元素
|
||||
//item.runLogs.shift();
|
||||
//删除并返回数组的最后一个元素
|
||||
item.runLogs.pop()
|
||||
}
|
||||
//向数组的末尾添加
|
||||
//item.runLogs.push(res);
|
||||
//向数组的开头添
|
||||
item.runLogs.unshift(res)
|
||||
|
||||
//滚动
|
||||
// this.$nextTick(function() {
|
||||
// item.scrollTop = 20*item.runLogs.length;
|
||||
// });
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
//监听控制
|
||||
uni.$on('controlMeasurePoint', res => {
|
||||
console.log(res)
|
||||
let data = res.data
|
||||
this.mearsuPointList.forEach(i => {
|
||||
if (i.measurePointId === data.measurePointId) {
|
||||
if (data.success && data.isControl) {
|
||||
i.controlUserName = data.controlUserName
|
||||
} else {
|
||||
i.controlUserName = ''
|
||||
}
|
||||
console.log(i)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
//计量点状态
|
||||
uni.$on('measurePointStatus', res => {
|
||||
//断开
|
||||
this.mearsuPointList.forEach(i => {
|
||||
if (i.measurePointId === res.measurePointId) {
|
||||
if (res.measureIsConnected != 1) {
|
||||
i.weightData = ''
|
||||
i.weightUnit = ''
|
||||
i.weightStable = 0
|
||||
i.infraredLeft = 0
|
||||
i.infraredRight = 0
|
||||
i.measureIsConnected = 0
|
||||
if (i.runLogs.length >= this.runLogMaxLength) {
|
||||
i.runLogs.pop()
|
||||
}
|
||||
i.runLogs.unshift({
|
||||
id: this.$helper.uuid(),
|
||||
content: '计量点连接断开!',
|
||||
measurePointId: i.measurePointId,
|
||||
time: this.$helper.dateFormat(new Date(), 'yy-MM-dd hh:mm:ss')
|
||||
})
|
||||
i.devices.forEach(d => {
|
||||
d.isConnected = 0
|
||||
})
|
||||
} else {
|
||||
i.measureIsConnected = 1
|
||||
/* if(i.runLogs.length >= 8) {
|
||||
i.runLogs.shift();
|
||||
}
|
||||
i.runLogs.push({
|
||||
id: this.$helper.uuid(),
|
||||
content: "计量点连接成功!",
|
||||
measurePointId: i.measurePointId,
|
||||
time: this.$helper.dateFormat(new Date(), "yy-MM-dd hh:mm:ss")
|
||||
}); */
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
//连接断开
|
||||
uni.$on('connClose', res => {
|
||||
//重置
|
||||
this.mearsuPointList.forEach(i => {
|
||||
i.weightData = ''
|
||||
i.weightUnit = ''
|
||||
i.weightStable = 0
|
||||
i.controlUserName = ''
|
||||
i.measureIsConnected = 0
|
||||
if (i.runLogs.length >= this.runLogMaxLength) {
|
||||
i.runLogs.pop()
|
||||
}
|
||||
let lastLog = i.runLogs[i.runLogs.length - 1]
|
||||
if (lastLog && lastLog.content !== '控制中心连接断开!') {
|
||||
i.runLogs.unshift({
|
||||
id: this.$helper.uuid(),
|
||||
content: '控制中心连接断开!',
|
||||
measurePointId: i.measurePointId,
|
||||
time: this.$helper.dateFormat(new Date(), 'yy-MM-dd hh:mm:ss')
|
||||
})
|
||||
}
|
||||
i.devices.forEach(d => {
|
||||
d.isConnected = 0
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
onUnload() {
|
||||
//移除监听websocket返回来的数据
|
||||
uni.$off('deviceData')
|
||||
uni.$off('deviceStatus')
|
||||
uni.$off('logData')
|
||||
uni.$off('controlMeasurePoint')
|
||||
|
||||
uni.$off('measurePointStatus')
|
||||
uni.$off('connClose')
|
||||
},
|
||||
filters: {
|
||||
numFilter(value) {
|
||||
// 截取当前数据到小数点后两位
|
||||
let realVal = value.toFixed(2)
|
||||
return realVal
|
||||
}
|
||||
},
|
||||
computed: {},
|
||||
methods: {
|
||||
getPageData() {
|
||||
//显示loading
|
||||
this.showLoading = true
|
||||
//获取计量点数量
|
||||
this.$u.api
|
||||
.getDeviceLaboratoryListBy()
|
||||
.then(res => {
|
||||
let dataList = res.data
|
||||
dataList.forEach(i => {
|
||||
i.weightData = ''
|
||||
i.weightUnit = ''
|
||||
i.isConnected = 0
|
||||
i.weightStable = 0
|
||||
i.temperature = 0
|
||||
i.humidity = 0
|
||||
i.controlUserName = ''
|
||||
})
|
||||
this.deviceLaboratoryList = dataList
|
||||
this.showLoading = false
|
||||
|
||||
//打开websocket
|
||||
this.openLaboratoryWs()
|
||||
|
||||
//发送检查计量点控制情况
|
||||
let checkControl = {
|
||||
msgId: this.$helper.uuid(),
|
||||
cmd: 'checkControl',
|
||||
clientType: 'consoleClient'
|
||||
}
|
||||
if (this.$measure.isOpen) {
|
||||
this.$measure.send(JSON.stringify(checkControl))
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
this.showLoading = false
|
||||
console.log(err)
|
||||
})
|
||||
},
|
||||
openLaboratoryWs() {
|
||||
//注册websocket
|
||||
let regData = {
|
||||
msgId: this.$helper.uuid(),
|
||||
cmd: 'register',
|
||||
clientType: 'caaClient',
|
||||
data: {
|
||||
userId: this.userInfo.user_id,
|
||||
tenantId: this.userInfo.tenant_id,
|
||||
userRealName: this.userInfo.real_name
|
||||
}
|
||||
}
|
||||
this.$measure.setRegData(JSON.stringify(regData))
|
||||
this.$measure.open()
|
||||
},
|
||||
scroll(e) {
|
||||
// console.log(e);
|
||||
// this.mearsuPointList.forEach((i) => {
|
||||
// if(i.measurepointid === e.currentTarget.dataset.measurepointid) {
|
||||
// i.oldScrollTop = e.detail.scrollTop;
|
||||
// }
|
||||
// });
|
||||
},
|
||||
goto(measurePointId) {
|
||||
uni.reLaunch({
|
||||
url: '/pages/measure/measure?measurePointId=' + measurePointId
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
/* #ifdef H5 */
|
||||
.auncel {
|
||||
width: 31.33%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 20rpx;
|
||||
margin: 1%;
|
||||
border-radius: 24rpx;
|
||||
box-shadow: 1px 1px 10px #909399;
|
||||
}
|
||||
@media only screen and (max-width: 1200px) {
|
||||
.auncel {
|
||||
width: 48%;
|
||||
}
|
||||
}
|
||||
@media only screen and (max-width: 600px) {
|
||||
.auncel {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
/* #endif */
|
||||
/* #ifndef H5 */
|
||||
.auncel {
|
||||
width: 98%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 20rpx;
|
||||
margin: 1%;
|
||||
border-radius: 24rpx;
|
||||
box-shadow: 1px 1px 10px #909399;
|
||||
}
|
||||
/* #endif */
|
||||
.title-line-gray {
|
||||
width: 100%;
|
||||
height: 6rpx;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: rgb(128, 134, 149);
|
||||
border-radius: 4rpx 4rpx 0 0;
|
||||
}
|
||||
.title-line-green {
|
||||
width: 100%;
|
||||
height: 6rpx;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: rgb(27, 201, 142);
|
||||
border-radius: 4rpx 4rpx 0 0;
|
||||
}
|
||||
.title {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
}
|
||||
.temp {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
}
|
||||
.charts-box {
|
||||
width: 50%;
|
||||
height: 200px;
|
||||
}
|
||||
.measurePointName {
|
||||
font-size: 30rpx;
|
||||
}
|
||||
.weight-container {
|
||||
padding: 10rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.infrared-container {
|
||||
width: 30%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
.infrared-line-green {
|
||||
width: 8rpx;
|
||||
height: 90rpx;
|
||||
background-color: #18b566;
|
||||
}
|
||||
.infrared-line-red {
|
||||
width: 8rpx;
|
||||
height: 90rpx;
|
||||
background-color: #ff3333;
|
||||
}
|
||||
.infrared-line-gray {
|
||||
width: 8rpx;
|
||||
height: 90rpx;
|
||||
background-color: #909399;
|
||||
}
|
||||
.infrared-left {
|
||||
width: 8rpx;
|
||||
height: 90rpx;
|
||||
background-color: #18b566;
|
||||
}
|
||||
.infrared-left-warning {
|
||||
width: 8rpx;
|
||||
height: 90rpx;
|
||||
background-color: #ff3333;
|
||||
}
|
||||
.weight {
|
||||
width: 100%;
|
||||
min-width: 200px;
|
||||
height: 90rpx;
|
||||
padding: 0 8rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
background-color: #2c405a;
|
||||
}
|
||||
.weight-data {
|
||||
flex-grow: 1;
|
||||
height: 100%;
|
||||
color: #4cd964;
|
||||
text-align: right;
|
||||
line-height: 90rpx;
|
||||
letter-spacing: 4rpx;
|
||||
font-size: 90rpx;
|
||||
font-family: zzjc-lcd;
|
||||
}
|
||||
.weight-data-yellow {
|
||||
flex-grow: 1;
|
||||
height: 100%;
|
||||
color: #ffff00;
|
||||
text-align: right;
|
||||
line-height: 90rpx;
|
||||
letter-spacing: 4rpx;
|
||||
font-size: 90rpx;
|
||||
font-family: zzjc-lcd;
|
||||
}
|
||||
.weight-data-warning {
|
||||
flex-grow: 1;
|
||||
height: 100%;
|
||||
color: #ff3333;
|
||||
text-align: right;
|
||||
line-height: 90rpx;
|
||||
font-size: 90rpx;
|
||||
font-family: zzjc-lcd;
|
||||
}
|
||||
.weight-unit {
|
||||
color: #ffffff;
|
||||
font-size: 60rpx;
|
||||
line-height: 90rpx;
|
||||
padding-left: 20rpx;
|
||||
}
|
||||
.infrared-right {
|
||||
width: 8rpx;
|
||||
height: 90rpx;
|
||||
background-color: #18b566;
|
||||
}
|
||||
.infrared-right-warning {
|
||||
width: 8rpx;
|
||||
height: 90rpx;
|
||||
background-color: #ff3333;
|
||||
}
|
||||
.device-container {
|
||||
padding: 20rpx;
|
||||
width: 100%;
|
||||
height: 200rpx;
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.device {
|
||||
width: 25%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
.device-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
background-color: #ff3333;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.device-icon-green {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
background-color: #18b566;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.device-icon-gray {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
background-color: rgb(128, 134, 149);
|
||||
border-radius: 50%;
|
||||
}
|
||||
.device-icon-red {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
background-color: #ff3333;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.run-log {
|
||||
width: 100%;
|
||||
padding: 10rpx 20rpx;
|
||||
height: 400rpx;
|
||||
background-color: #ecf5ff;
|
||||
border-radius: 24rpx;
|
||||
--box-shadow: 1px 1px 10px #909399;
|
||||
}
|
||||
.log-content {
|
||||
font-size: 28rpx;
|
||||
font-weight: 200;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -84,13 +84,25 @@
|
||||
>
|
||||
</u-col>
|
||||
<u-col span="6">
|
||||
<view class="x-bc">
|
||||
<view class="field-name" v-html="selectedField.title" />
|
||||
<u-button
|
||||
v-if="fillingWay.length > 1"
|
||||
type="primary"
|
||||
shape="circle"
|
||||
plain
|
||||
size="small"
|
||||
style="width: 15%"
|
||||
:text="`切换${currentFillingWay == 'collect' ? '录入' : '采集'}`"
|
||||
@click="switchFillingWay"
|
||||
></u-button>
|
||||
</view>
|
||||
<zzjc-num-keyboard
|
||||
ref="myKeyboard"
|
||||
v-show="selectedField.fillingWay == 'keyboard' && selectedField.type != 'select'"
|
||||
v-show="currentFillingWay == 'keyboard'"
|
||||
:numKeyboardParam="numKeyboardParam"
|
||||
></zzjc-num-keyboard>
|
||||
<view v-if="selectedField.fillingWay == 'collect'" class="y-f">
|
||||
<view v-if="currentFillingWay == 'collect'" class="y-f">
|
||||
<view class="auncel" @click="selectAuncel">
|
||||
<view class="code">{{ currentAuncel.code }}</view>
|
||||
<view class="auncel-title"> 杯号:{{ currentCupNum }} </view>
|
||||
@@ -123,7 +135,7 @@
|
||||
确认采集
|
||||
</u-button>
|
||||
</view>
|
||||
<view v-if="selectedField.fillingWay === 'input'" class="p8">
|
||||
<view v-if="currentFillingWay === 'input'" class="p8">
|
||||
<up-textarea v-model="inputValue" placeholder="请输入内容"></up-textarea>
|
||||
<view class="x-c mt20 pl100 pr100">
|
||||
<up-button @click="handleResetInputValue" style="width: 30%" :plain="true" text="清空"></up-button>
|
||||
@@ -354,7 +366,7 @@ const parameterClassifyChange = v => {
|
||||
|
||||
const fieldClick = (field, key) => {
|
||||
if (!field.isEdit) return
|
||||
if (field.fillingWay === 'input') {
|
||||
if (currentFillingWay.value === 'input') {
|
||||
inputValue.value = field.value
|
||||
}
|
||||
selectedField.value = field
|
||||
@@ -366,13 +378,26 @@ const fieldClick = (field, key) => {
|
||||
let decimalPosition = field.decimalPosition
|
||||
if (decimalPosition == null || decimalPosition < -1) decimalPosition = -1
|
||||
numKeyboardParam.decimal = decimalPosition
|
||||
if (field.fillingWay == 'collect') {
|
||||
if (currentFillingWay.value == 'collect') {
|
||||
listenDeviceData()
|
||||
} else {
|
||||
closeDeviceListener()
|
||||
}
|
||||
}
|
||||
|
||||
const currentFillingIndex = ref(0)
|
||||
const fillingWay = computed(() => {
|
||||
if (selectedField.value.fillingWay) {
|
||||
return selectedField.value.fillingWay.split(',')
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
})
|
||||
const currentFillingWay = computed(() => {
|
||||
return fillingWay.value[currentFillingIndex.value] || ''
|
||||
})
|
||||
const switchFillingWay = () => {
|
||||
currentFillingIndex.value = (currentFillingIndex.value + 1) % fillingWay.value.length
|
||||
}
|
||||
//自动切换到下一个字段
|
||||
const autoNextField = () => {
|
||||
let groupIndex = 0
|
||||
@@ -1053,9 +1078,13 @@ const listenNumKeyboard = () => {
|
||||
return
|
||||
}
|
||||
//自动补全小数位数
|
||||
const decimalPosition = selectedField.value.decimalPosition || 0
|
||||
const decimalPosition = selectedField.value.decimalPosition
|
||||
let val = res.val
|
||||
if (decimalPosition == null) {
|
||||
selectedField.value.value = val
|
||||
} else {
|
||||
selectedField.value.value = handleRoundFiveNumber(val, decimalPosition)
|
||||
}
|
||||
calcAnalysisValue(fieldGroup.value)
|
||||
//自动跳转下一个字段
|
||||
setTimeout(() => {
|
||||
@@ -1098,7 +1127,8 @@ const releaseDeviceControl = deviceId => {
|
||||
data: {
|
||||
deviceId: deviceId,
|
||||
isControl: false,
|
||||
controlRealName: userInfo.value.nickname
|
||||
controlRealName: userInfo.value.nickname,
|
||||
controlUserId: userInfo.value.id
|
||||
}
|
||||
}
|
||||
//发送控制数据
|
||||
@@ -1304,8 +1334,8 @@ onBackPress(() => {
|
||||
position: relative;
|
||||
.code {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 50px;
|
||||
top: 15px;
|
||||
left: 55px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1375,6 +1405,7 @@ onBackPress(() => {
|
||||
.field-name {
|
||||
font-size: 26px;
|
||||
padding: 8px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.my-collapse {
|
||||
@@ -1401,6 +1432,7 @@ onBackPress(() => {
|
||||
}
|
||||
.field-name {
|
||||
font-size: 16px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -14,11 +14,13 @@ import nx from '@/nx'
|
||||
import { useGridCol } from '@/nx/hooks/useGridCol'
|
||||
let list = reactive([
|
||||
{ url: '/pages/lims/index/index', name: '设备管理', icon: 'device' },
|
||||
{ url: '/pages/analysis/index/index', name: '分析管理', icon: 'analyse' }
|
||||
{ url: '/pages/analysis/index/index', name: '分析管理', icon: 'analyse' },
|
||||
{ url: '/pages/sampleWarehouse/index/index', name: '样品库管理', icon: 'sampleWarehouse' }
|
||||
])
|
||||
|
||||
// const sysMenus = computed(() => nx.$store('user').sysMenus)
|
||||
function goSystem(url) {
|
||||
uni.setStorageSync('defaultModule', url)
|
||||
uni.reLaunch({ url })
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
<u-cell-group>
|
||||
<u-cell icon="grid-fill" title="模块选择" :is-link="true" @click="handleTo('/pages/index/index')" />
|
||||
<u-cell icon="order" title="打印设置" :isLink="true" @click="handleTo('/pages/setting/print')"></u-cell>
|
||||
<u-cell icon="info-circle-fill" title="关于我们" :is-link="true" @click="handleTo('/pages/me/aboutMe')" />
|
||||
</u-cell-group>
|
||||
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
<template>
|
||||
<view>
|
||||
<navbar-back title="设备管理系统" :autoBack="false" leftIcon="" :leftText="`您好!${userInfo.realname}`">
|
||||
<u-icon @click="popupShow = true" size="28" color="#FFF" name="account-fill" />
|
||||
<navbar-back
|
||||
title="实验室管理系统【设备管理】"
|
||||
:autoBack="false"
|
||||
leftIcon=""
|
||||
:leftText="`您好!${userInfo.realname}`"
|
||||
>
|
||||
<u-icon @click="popupShow = true" size="28" color="#FFF" name="setting-fill" />
|
||||
</navbar-back>
|
||||
<up-grid :border="false" :col="gridCol">
|
||||
<up-grid-item
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
</view>
|
||||
<u-cell-group>
|
||||
<u-cell icon="setting-fill" title="切换系统" :isLink="true" @click="handleTo('/pages/index/index')"></u-cell>
|
||||
<u-cell icon="order" title="打印设置" :isLink="true" @click="handleTo('/pages/setting/print')"></u-cell>
|
||||
<u-cell icon="info-circle-fill" title="关于我们" :isLink="true" @click="handleTo('/pages/me/aboutMe')"></u-cell>
|
||||
</u-cell-group>
|
||||
<u-button class="mt40" type="warning" :plain="true" text="退出当前账号" @click="handleLoginOut"></u-button>
|
||||
|
||||
148
pages/sampleWarehouse/execChangeLocation/index.vue
Normal file
148
pages/sampleWarehouse/execChangeLocation/index.vue
Normal file
@@ -0,0 +1,148 @@
|
||||
<template>
|
||||
<view class="p8">
|
||||
<navbar-back title="库位变更"></navbar-back>
|
||||
<uni-section type="line" title="库位信息修改"> </uni-section>
|
||||
<up-input
|
||||
v-model="locationCode"
|
||||
placeholder="请扫描库位编码"
|
||||
prefixIcon="scan"
|
||||
fontSize="16"
|
||||
prefixIconStyle="font-size: 30px;"
|
||||
>
|
||||
</up-input>
|
||||
|
||||
<up-radio-group v-model="changeType">
|
||||
<up-radio
|
||||
:customStyle="{ marginBottom: '8px' }"
|
||||
v-for="(item, index) in changeTypeOptions"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
:name="item.name"
|
||||
>
|
||||
</up-radio>
|
||||
</up-radio-group>
|
||||
<up-input
|
||||
v-model="sampleCode"
|
||||
:placeholder="`请扫描${changeType == 'sample' ? '样品编号' : '库位编码'}`"
|
||||
prefixIcon="scan"
|
||||
fontSize="16"
|
||||
prefixIconStyle="font-size: 30px;"
|
||||
>
|
||||
</up-input>
|
||||
<uni-section type="line" title="样品及当前归库信息">
|
||||
<uni-card>
|
||||
<view
|
||||
>样品名称:<text>{{ sampleData.sampleName }}</text></view
|
||||
>
|
||||
<view class="mt4"
|
||||
>样品库名称:<text>{{ sampleData.sampleCode }}</text></view
|
||||
>
|
||||
<view class="mt4"
|
||||
>归库编码:<text>{{ sampleData.sampleCode }}</text></view
|
||||
>
|
||||
<view class="mt4"
|
||||
>(原)库位编码:<text>{{ sampleData.sampleCode }}</text></view
|
||||
>
|
||||
</uni-card>
|
||||
</uni-section>
|
||||
<up-button class="mt20" type="primary" style="width: 50%" text="提交" @click="handleReset"></up-button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, computed, onMounted, toRefs, watch } from 'vue'
|
||||
import { onShow } from '@dcloudio/uni-app'
|
||||
import nx from '@/nx'
|
||||
|
||||
const changeType = ref('sample')
|
||||
const changeTypeOptions = reactive([
|
||||
{
|
||||
name: 'sample',
|
||||
label: '按样品变更'
|
||||
},
|
||||
{
|
||||
name: 'location',
|
||||
label: '按库位变更'
|
||||
}
|
||||
])
|
||||
function isJsonString(str) {
|
||||
if (typeof str !== 'string') return false
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(str)
|
||||
return typeof parsed === 'object' && parsed !== null
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
const { scanQRInfo } = toRefs(nx.$store('biz'))
|
||||
watch(scanQRInfo, newVal => {
|
||||
if (newVal && nx.$router.getCurrentPage().route == 'pages/sampleWarehouse/returnToStock/index') {
|
||||
try {
|
||||
if (!isJsonString(newVal)) {
|
||||
if (!locationCode.value) {
|
||||
uni.showToast({
|
||||
title: '请先扫描库位码',
|
||||
icon: 'none'
|
||||
})
|
||||
scanQRInfo.value = ''
|
||||
return
|
||||
} else {
|
||||
if (changeType.value == 'sample') {
|
||||
sampleCode.value = newVal
|
||||
} else {
|
||||
}
|
||||
// 执行
|
||||
// handleReturnToStock()
|
||||
}
|
||||
} else {
|
||||
const codeObj = JSON.parse(newVal)
|
||||
locationCode.value = codeObj.code
|
||||
}
|
||||
scanQRInfo.value = ''
|
||||
} catch (error) {
|
||||
scanQRInfo.value = ''
|
||||
uni.showToast({
|
||||
title: '请扫描样品编码',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
onShow(() => {
|
||||
scanQRInfo.value = ''
|
||||
})
|
||||
let needPrint = ref(false)
|
||||
|
||||
let locationCode = ref('')
|
||||
let sampleCode = ref('')
|
||||
|
||||
function handleReturnToStock() {
|
||||
nx.$api.sampleWarehouse
|
||||
.execReturnToStock({
|
||||
warehouseLocationCode: locationCode.value,
|
||||
sampleCode: sampleCode.value
|
||||
})
|
||||
.then(res => {
|
||||
successCount.value++
|
||||
if (res.print) {
|
||||
uni.showToast({
|
||||
title: `归库成功,归库码为【${res.code}】`,
|
||||
duration: 3000,
|
||||
icon: 'none'
|
||||
})
|
||||
// 执行打印
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const successCount = ref(2)
|
||||
function handleReset() {
|
||||
locationCode.value = ''
|
||||
sampleCode.value = ''
|
||||
successCount.value = 0
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
89
pages/sampleWarehouse/index/index.vue
Normal file
89
pages/sampleWarehouse/index/index.vue
Normal file
@@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<view>
|
||||
<navbar-back
|
||||
title="样品库管理"
|
||||
titleWidth="800"
|
||||
:autoBack="false"
|
||||
leftIcon=""
|
||||
:leftText="`您好!${userInfo.nickname}`"
|
||||
>
|
||||
<u-icon @click="popupShow = true" size="28" color="#FFF" name="setting-fill" />
|
||||
</navbar-back>
|
||||
|
||||
<up-grid :col="gridCol" :border="false">
|
||||
<up-grid-item class="mb20 mt20" v-for="item in menuItemList" :key="item.url" @click="goTo(item.url)">
|
||||
<u-icon :name="item.otherConf.icon" color="#0055A2" size="80" />
|
||||
<view class="grid-text">{{ item.name }}</view>
|
||||
</up-grid-item>
|
||||
</up-grid>
|
||||
|
||||
<mePopup :show="popupShow" @update:show="val => (popupShow = val)" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import nx from '@/nx'
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app'
|
||||
import { useGridCol } from '@/nx/hooks/useGridCol'
|
||||
import mePopup from '@/pages/index/me-popup.vue'
|
||||
|
||||
// 响应式数据
|
||||
const popupShow = ref(false)
|
||||
|
||||
const menuItemList = ref([
|
||||
{
|
||||
url: '/pages/sampleWarehouse/sampleSearch/index',
|
||||
otherConf: { icon: '/static/images/menus/records.png' },
|
||||
name: '样品查询'
|
||||
},
|
||||
{
|
||||
url: '/pages/sampleWarehouse/returnToStock/index',
|
||||
otherConf: { icon: '/static/images/menus/returnToStock.png' },
|
||||
name: '样品归库'
|
||||
},
|
||||
{
|
||||
url: '/pages/sampleWarehouse/execChangeLocation/index',
|
||||
otherConf: { icon: '/static/images/menus/execChangeLocation.png' },
|
||||
name: '库位变更'
|
||||
}
|
||||
])
|
||||
|
||||
// 计算属性
|
||||
const userInfo = computed(() => nx.$store('user').userInfo)
|
||||
|
||||
// 方法
|
||||
const goTo = url => {
|
||||
nx.$router.go(url)
|
||||
}
|
||||
onShow(() => {
|
||||
//连接打印服务
|
||||
let printList = uni.getStorageSync('KEY_PRINT_LIST')
|
||||
if (printList && printList.length > 0) {
|
||||
for (let print of printList) {
|
||||
nx.$print.open(print.printIp, print.printPort)
|
||||
}
|
||||
} else {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
showCancel: false,
|
||||
content: '打印服务未配置,请在系统设置中配置打印服务',
|
||||
success: function (res) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/setting/print'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
// 生命周期
|
||||
onMounted(() => {})
|
||||
// 动态设置 grid 列数
|
||||
const { gridCol } = useGridCol([400], [2, 3])
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.grid-text {
|
||||
font-size: 24px;
|
||||
}
|
||||
</style>
|
||||
111
pages/sampleWarehouse/returnToStock/index.vue
Normal file
111
pages/sampleWarehouse/returnToStock/index.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<view class="p8">
|
||||
<navbar-back title="样品归库"></navbar-back>
|
||||
<uni-section type="line" title="库位编码"> </uni-section>
|
||||
<up-input
|
||||
v-model="locationCode"
|
||||
placeholder="请扫描库位编码"
|
||||
prefixIcon="scan"
|
||||
fontSize="16"
|
||||
prefixIconStyle="font-size: 30px;"
|
||||
>
|
||||
</up-input>
|
||||
<uni-section type="line" title="样品编号"> </uni-section>
|
||||
<up-input
|
||||
v-model="sampleCode"
|
||||
placeholder="请扫描样品编号"
|
||||
prefixIcon="scan"
|
||||
fontSize="16"
|
||||
prefixIconStyle="font-size: 30px;"
|
||||
>
|
||||
<template #suffix>
|
||||
<view class="fs18 font-bold" style="color: red" v-if="successCount > 0">{{ successCount }}</view>
|
||||
</template>
|
||||
</up-input>
|
||||
<up-button class="mt20" type="primary" style="width: 50%" text="清空" @click="handleReset"></up-button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, computed, onMounted, toRefs, watch } from 'vue'
|
||||
import { onShow } from '@dcloudio/uni-app'
|
||||
import nx from '@/nx'
|
||||
|
||||
function isJsonString(str) {
|
||||
if (typeof str !== 'string') return false
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(str)
|
||||
return typeof parsed === 'object' && parsed !== null
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
const { scanQRInfo } = toRefs(nx.$store('biz'))
|
||||
watch(scanQRInfo, newVal => {
|
||||
if (newVal && nx.$router.getCurrentPage().route == 'pages/sampleWarehouse/returnToStock/index') {
|
||||
try {
|
||||
if (!isJsonString(newVal)) {
|
||||
if (!locationCode.value) {
|
||||
uni.showToast({
|
||||
title: '请先扫描库位码',
|
||||
icon: 'none'
|
||||
})
|
||||
scanQRInfo.value = ''
|
||||
return
|
||||
} else {
|
||||
sampleCode.value = newVal
|
||||
// 执行归库
|
||||
handleReturnToStock()
|
||||
}
|
||||
} else {
|
||||
const codeObj = JSON.parse(newVal)
|
||||
locationCode.value = codeObj.code
|
||||
}
|
||||
scanQRInfo.value = ''
|
||||
} catch (error) {
|
||||
scanQRInfo.value = ''
|
||||
uni.showToast({
|
||||
title: '请扫描样品编码',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
onShow(() => {
|
||||
scanQRInfo.value = ''
|
||||
})
|
||||
let needPrint = ref(false)
|
||||
|
||||
let locationCode = ref('')
|
||||
let sampleCode = ref('')
|
||||
|
||||
function handleReturnToStock() {
|
||||
nx.$api.sampleWarehouse
|
||||
.execReturnToStock({
|
||||
warehouseLocationCode: locationCode.value,
|
||||
sampleCode: sampleCode.value
|
||||
})
|
||||
.then(res => {
|
||||
successCount.value++
|
||||
if (res.print) {
|
||||
uni.showToast({
|
||||
title: `归库成功,归库码为【${res.code}】`,
|
||||
duration: 3000,
|
||||
icon: 'none'
|
||||
})
|
||||
// 执行打印
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const successCount = ref(2)
|
||||
function handleReset() {
|
||||
locationCode.value = ''
|
||||
sampleCode.value = ''
|
||||
successCount.value = 0
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
85
pages/sampleWarehouse/sampleSearch/index.vue
Normal file
85
pages/sampleWarehouse/sampleSearch/index.vue
Normal file
@@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<view class="p4 pt8">
|
||||
<navbar-back title="样品查询"></navbar-back>
|
||||
<up-input
|
||||
v-model="sampleCode"
|
||||
placeholder="请扫描或者输入样品编号"
|
||||
prefixIcon="scan"
|
||||
fontSize="16"
|
||||
prefixIconStyle="font-size: 30px;"
|
||||
>
|
||||
<template #suffix>
|
||||
<!-- <up-button type="primary" text="查询" icon="search"></up-button> -->
|
||||
<!-- <up-icon size="20" name="search" @click="handleSearch"></up-icon> -->
|
||||
</template>
|
||||
</up-input>
|
||||
|
||||
<uni-section type="line" title="样品详情">
|
||||
<uni-card>
|
||||
<view>
|
||||
<view class="x-bc">
|
||||
<view
|
||||
>样品名称:<text>{{ sampleData.sampleName }}</text></view
|
||||
>
|
||||
<up-tag :text="sampleData.returnStatus_dictText"></up-tag>
|
||||
</view>
|
||||
<view
|
||||
>样品编号:<text>{{ sampleData.sampleCode }}</text></view
|
||||
>
|
||||
<view class="mt4"
|
||||
>归库编码:<text>{{ sampleData.sampleCode }}</text></view
|
||||
>
|
||||
<view class="mt4"
|
||||
>样品库名称:<text>{{ sampleData.sampleCode }}</text></view
|
||||
>
|
||||
<view class="mt4"
|
||||
>库位信息:<text>{{ sampleData.sampleCode }}</text></view
|
||||
>
|
||||
</view>
|
||||
</uni-card>
|
||||
</uni-section>
|
||||
<up-button type="primary" style="width: 90%" text="打印归库标签" @click="handlePrint"></up-button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, toRefs, watch } from 'vue'
|
||||
import { onShow } from '@dcloudio/uni-app'
|
||||
import nx from '@/nx'
|
||||
|
||||
const { scanQRInfo } = toRefs(nx.$store('biz'))
|
||||
watch(scanQRInfo, newVal => {
|
||||
if (newVal && nx.$router.getCurrentPage().route == 'pages/sampleWarehouse/sampleSearch/index') {
|
||||
try {
|
||||
sampleCode.value = newVal
|
||||
handleSearch()
|
||||
scanQRInfo.value = ''
|
||||
} catch (error) {
|
||||
scanQRInfo.value = ''
|
||||
uni.showToast({
|
||||
title: '请扫描样品编码',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
onShow(() => {
|
||||
scanQRInfo.value = ''
|
||||
})
|
||||
let sampleCode = ref('')
|
||||
function handleSearch() {
|
||||
getSampleDetail()
|
||||
}
|
||||
|
||||
let sampleData = ref({})
|
||||
async function getSampleDetail() {
|
||||
sampleData.value = await nx.$api.sample.getSampleDetail({ sampleReturnCode: sampleCode.value })
|
||||
}
|
||||
function handlePrint() {}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
text {
|
||||
color: #000;
|
||||
}
|
||||
</style>
|
||||
233
pages/setting/print.vue
Normal file
233
pages/setting/print.vue
Normal file
@@ -0,0 +1,233 @@
|
||||
<template>
|
||||
<view>
|
||||
<navbar-back title="打印服务">
|
||||
<view class="navbar-right" slot="right">
|
||||
<view class="message-box right-item" @click="refreshPrint">
|
||||
<up-icon name="reload" color="#fff" size="20" />
|
||||
</view>
|
||||
<view class="dot-box right-item" @click="addPrintShow">
|
||||
<up-icon name="plus" color="#fff" size="20" />
|
||||
</view>
|
||||
</view>
|
||||
</navbar-back>
|
||||
|
||||
<view>
|
||||
<up-swipe-action>
|
||||
<up-swipe-action-item
|
||||
v-for="(print, index) in printList"
|
||||
:key="index"
|
||||
:index="index"
|
||||
:options="options"
|
||||
@click="printSwipeClick"
|
||||
>
|
||||
<view class="x-f p10 border-b">
|
||||
<image :src="`/static/images/print${print.isOpen ? '' : '-close'}.png`" mode="aspectFill" />
|
||||
<view>
|
||||
<view>服务名称:{{ print.printName }}</view>
|
||||
|
||||
<view>服务IP地址:{{ print.printIp }}</view>
|
||||
|
||||
<view>服务端口:{{ print.printPort }}</view>
|
||||
|
||||
<view>连接状态:{{ print.isOpen ? '连接正常!!!' : '连接关闭!!!' }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</up-swipe-action-item>
|
||||
</up-swipe-action>
|
||||
</view>
|
||||
|
||||
<u-modal
|
||||
:show="printShow"
|
||||
title="添加打印服务"
|
||||
show-cancel-button
|
||||
confirm-text="添加"
|
||||
@confirm="addPrint"
|
||||
@cancel="printShow = false"
|
||||
>
|
||||
<view class="slot-content">
|
||||
<u-form :model="form">
|
||||
<u-form-item label="名称">
|
||||
<u-input v-model="form.printName" />
|
||||
</u-form-item>
|
||||
<u-form-item label="IP">
|
||||
<u-input v-model="form.printIp" />
|
||||
</u-form-item>
|
||||
<u-form-item label="端口">
|
||||
<u-input v-model="form.printPort" type="number" />
|
||||
</u-form-item>
|
||||
</u-form>
|
||||
</view>
|
||||
</u-modal>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
import nx from '@/nx'
|
||||
|
||||
// 响应式数据
|
||||
const printShow = ref(false)
|
||||
const printList = ref([])
|
||||
|
||||
const form = ref({
|
||||
printName: '',
|
||||
printIp: '',
|
||||
printPort: 22333
|
||||
})
|
||||
|
||||
const options = [
|
||||
{
|
||||
text: '删除',
|
||||
style: {
|
||||
fontSize: '14px',
|
||||
backgroundColor: 'rgb(255,58,49)'
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 方法
|
||||
const addPrintShow = () => {
|
||||
if (printList.value.length > 0) {
|
||||
uni.showToast({
|
||||
title: '已存在打印服务!',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
form.value = {
|
||||
printName: '',
|
||||
printIp: '',
|
||||
printPort: 22333
|
||||
}
|
||||
printShow.value = true
|
||||
}
|
||||
|
||||
const refreshPrint = () => {
|
||||
const printListData = uni.getStorageSync('KEY_PRINT_LIST') || []
|
||||
if (printListData.length > 0) {
|
||||
printListData.forEach(print => {
|
||||
nx.$print.open(print.printIp)
|
||||
})
|
||||
uni.showToast({
|
||||
title: '刷新成功!',
|
||||
icon: 'none'
|
||||
})
|
||||
} else {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '未配置打印服务,请点击右边的“+”配置打印服务!',
|
||||
showCancel: false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const addPrint = () => {
|
||||
const { printName, printIp, printPort } = form.value
|
||||
|
||||
if (!printName.trim()) {
|
||||
uni.showToast({ title: '打印服务名称不允许为空!', icon: 'none' })
|
||||
return
|
||||
}
|
||||
if (!printIp.trim()) {
|
||||
uni.showToast({ title: '打印服务IP不允许为空!', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
const ipReg =
|
||||
/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/
|
||||
if (!ipReg.test(printIp)) {
|
||||
uni.showToast({ title: '打印服务IP不正确!', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
let storedList = uni.getStorageSync('KEY_PRINT_LIST') || []
|
||||
const exists = storedList.some(p => p.printIp === printIp)
|
||||
if (exists) {
|
||||
uni.showToast({ title: '打印服务已存在!', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
storedList.push({
|
||||
printName,
|
||||
printIp,
|
||||
printPort,
|
||||
isDefault: storedList.length === 0
|
||||
})
|
||||
|
||||
nx.$print.open(printIp)
|
||||
uni.setStorageSync('KEY_PRINT_LIST', storedList)
|
||||
refreshList()
|
||||
printShow.value = false
|
||||
}
|
||||
|
||||
const printSwipeClick = ({ index }) => {
|
||||
if (index === 0) {
|
||||
const delPrint = printList.value[index]
|
||||
nx.$print.close(delPrint.printIp)
|
||||
|
||||
printList.value.splice(index, 1)
|
||||
|
||||
if (delPrint.isDefault && printList.value.length > 0) {
|
||||
printList.value[0].isDefault = true
|
||||
}
|
||||
|
||||
uni.setStorageSync('KEY_PRINT_LIST', printList.value)
|
||||
uni.showToast({ title: '删除成功!', icon: 'none' })
|
||||
}
|
||||
}
|
||||
|
||||
const refreshList = () => {
|
||||
const stored = uni.getStorageSync('KEY_PRINT_LIST') || []
|
||||
printList.value = stored.map(print => {
|
||||
const printer = nx.$print.printMap?.get(print.printIp)
|
||||
return {
|
||||
...print,
|
||||
isOpen: printer ? printer.isOpen : false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
refreshList()
|
||||
uni.$on('printStatus', refreshList)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
uni.$off('printStatus', refreshList)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.navbar-right {
|
||||
margin-right: 12px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.right-item {
|
||||
margin: 0 6px;
|
||||
position: relative;
|
||||
color: #ffffff;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.slot-content {
|
||||
font-size: 14px;
|
||||
color: $u-content-color;
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 60px;
|
||||
flex: 0 0 60px;
|
||||
height: 60px;
|
||||
margin-right: 10px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
</style>
|
||||
BIN
static/images/menus/execChangeLocation.png
Normal file
BIN
static/images/menus/execChangeLocation.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.1 KiB |
BIN
static/images/menus/returnToStock.png
Normal file
BIN
static/images/menus/returnToStock.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
BIN
static/images/menus/sampleWarehouse.png
Normal file
BIN
static/images/menus/sampleWarehouse.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.5 KiB |
0
uni_modules/zzjc-urovo/changelog.md
Normal file
0
uni_modules/zzjc-urovo/changelog.md
Normal file
84
uni_modules/zzjc-urovo/package.json
Normal file
84
uni_modules/zzjc-urovo/package.json
Normal file
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"id": "zzjc-urovo",
|
||||
"displayName": "优博讯PDA插件",
|
||||
"version": "1.0.0",
|
||||
"description": "优博讯PDA插件",
|
||||
"keywords": [
|
||||
"zzjc-urovo",
|
||||
"PDA",
|
||||
"优博讯"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.6.8"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "uts",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "",
|
||||
"data": "",
|
||||
"permissions": ""
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "u",
|
||||
"aliyun": "u",
|
||||
"alipay": "u"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "u",
|
||||
"vue3": "u"
|
||||
},
|
||||
"App": {
|
||||
"app-android": "u",
|
||||
"app-ios": "u"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "u",
|
||||
"Android Browser": "u",
|
||||
"微信浏览器(Android)": "u",
|
||||
"QQ浏览器(Android)": "u"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "u",
|
||||
"IE": "u",
|
||||
"Edge": "u",
|
||||
"Firefox": "u",
|
||||
"Safari": "u"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "u",
|
||||
"阿里": "u",
|
||||
"百度": "u",
|
||||
"字节跳动": "u",
|
||||
"QQ": "u",
|
||||
"钉钉": "u",
|
||||
"快手": "u",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
14
uni_modules/zzjc-urovo/readme.md
Normal file
14
uni_modules/zzjc-urovo/readme.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# zzjc-urovo 优博讯PDA插件
|
||||
|
||||
## 方法清单
|
||||
| 方法名称 | 说明 |
|
||||
| --- | ------------ |
|
||||
| scanRegister | 扫码注册 (该方法参数里的所有回调都会在内存中持续存在,使用者避免频繁调用此方法)|
|
||||
| scanUnRegister | 扫码卸载 |
|
||||
|
||||
|
||||
### 开发文档
|
||||
[UTS 语法](https://uniapp.dcloud.net.cn/tutorial/syntax-uts.html)
|
||||
[UTS API插件](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html)
|
||||
[UTS 组件插件](https://uniapp.dcloud.net.cn/plugin/uts-component.html)
|
||||
[Hello UTS](https://gitcode.net/dcloud/hello-uts)
|
||||
3
uni_modules/zzjc-urovo/utssdk/app-android/config.json
Normal file
3
uni_modules/zzjc-urovo/utssdk/app-android/config.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"minSdkVersion": "21"
|
||||
}
|
||||
118
uni_modules/zzjc-urovo/utssdk/app-android/index.uts
Normal file
118
uni_modules/zzjc-urovo/utssdk/app-android/index.uts
Normal file
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* 引用 Android 系统库,示例如下:
|
||||
* import { Context } from "android.content.Context";
|
||||
* [可选实现,按需引入]
|
||||
*/
|
||||
import Activity from 'android.app.Activity';
|
||||
import IntentFilter from 'android.content.IntentFilter';
|
||||
import BroadcastReceiver from 'android.content.BroadcastReceiver';
|
||||
import Context from 'android.content.Context';
|
||||
import Intent from 'android.content.Intent';
|
||||
|
||||
/* 引入 interface.uts 文件中定义的变量 */
|
||||
import { MyApiOptions, MyApiResult, MyApi, MyApiSync, OnScanReceiverCallback, ScanRegister, ScanUnRegister } from '../interface.uts';
|
||||
|
||||
/* 引入 unierror.uts 文件中定义的变量 */
|
||||
import { MyApiFailImpl } from '../unierror';
|
||||
|
||||
import ScanBroadcastReceiver from './scan/ScanBroadcastReceiver';
|
||||
|
||||
/**
|
||||
* 引入三方库
|
||||
* [可选实现,按需引入]
|
||||
*
|
||||
* 在 Android 平台引入三方库有以下两种方式:
|
||||
* 1、[推荐] 通过 仓储 方式引入,将 三方库的依赖信息 配置到 config.json 文件下的 dependencies 字段下。详细配置方式[详见](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html#dependencies)
|
||||
* 2、直接引入,将 三方库的aar或jar文件 放到libs目录下。更多信息[详见](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html#android%E5%B9%B3%E5%8F%B0%E5%8E%9F%E7%94%9F%E9%85%8D%E7%BD%AE)
|
||||
*
|
||||
* 在通过上述任意方式依赖三方库后,使用时需要在文件中 import,如下示例:
|
||||
* import { LottieAnimationView } from 'com.airbnb.lottie.LottieAnimationView'
|
||||
*/
|
||||
|
||||
/**
|
||||
* UTSAndroid 为平台内置对象,不需要 import 可直接调用其API,[详见](https://uniapp.dcloud.net.cn/uts/utsandroid.html#utsandroid)
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* 异步方法
|
||||
*
|
||||
* uni-app项目中(vue/nvue)调用示例:
|
||||
* 1、引入方法声明 import { myApi } from "@/uni_modules/uts-api"
|
||||
* 2、方法调用
|
||||
* myApi({
|
||||
* paramA: false,
|
||||
* complete: (res) => {
|
||||
* console.log(res)
|
||||
* }
|
||||
* });
|
||||
* uni-app x项目(uvue)中调用示例:
|
||||
* 1、引入方法及参数声明 import { myApi, MyApiOptions } from "@/uni_modules/uts-api";
|
||||
* 2、方法调用
|
||||
* let options = {
|
||||
* paramA: false,
|
||||
* complete: (res : any) => {
|
||||
* console.log(res)
|
||||
* }
|
||||
* } as MyApiOptions;
|
||||
* myApi(options);
|
||||
*
|
||||
*/
|
||||
export const myApi : MyApi = function (options : MyApiOptions) {
|
||||
if (options.paramA == true) {
|
||||
// 返回数据
|
||||
const res : MyApiResult = {
|
||||
fieldA: 85,
|
||||
fieldB: true,
|
||||
fieldC: 'some message'
|
||||
};
|
||||
options.success?.(res);
|
||||
options.complete?.(res);
|
||||
} else {
|
||||
// 返回错误
|
||||
const err = new MyApiFailImpl(9010001);
|
||||
options.fail?.(err)
|
||||
options.complete?.(err)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步方法
|
||||
*
|
||||
* uni-app项目中(vue/nvue)调用示例:
|
||||
* 1、引入方法声明 import { myApiSync } from "@/uni_modules/uts-api"
|
||||
* 2、方法调用 myApiSync(true)
|
||||
*
|
||||
* uni-app x项目(uvue)中调用示例:
|
||||
* 1、引入方法及参数声明 import { myApiSync } from "@/uni_modules/uts-api";
|
||||
* 2、方法调用 myApiSync(true)
|
||||
*/
|
||||
export const myApiSync : MyApiSync = function (paramA : boolean) : MyApiResult {
|
||||
// 返回数据,根据插件功能获取实际的返回值
|
||||
const res : MyApiResult = {
|
||||
fieldA: 85,
|
||||
fieldB: paramA,
|
||||
fieldC: 'some message'
|
||||
};
|
||||
return res;
|
||||
}
|
||||
|
||||
// 目前装饰器不支持 export const test:Test = ()=>{} // 这种导出方式,需要使用export function test(){}
|
||||
// @UTSJS.keepAlive
|
||||
// export const scanRegister : ScanRegister = function (callback: OnScanReceiverCallback) {
|
||||
// const sbr = ScanBroadcastReceiver.getInstance(UTSAndroid.getAppContext());
|
||||
// sbr.registerReceiver(callback);
|
||||
// }
|
||||
|
||||
@UTSJS.keepAlive
|
||||
export function scanRegister(callback: OnScanReceiverCallback) {
|
||||
const sbr = ScanBroadcastReceiver.getInstance(UTSAndroid.getAppContext());
|
||||
sbr.registerReceiver(callback);
|
||||
}
|
||||
|
||||
export const scanUnRegister : ScanUnRegister = function () {
|
||||
const sbr = ScanBroadcastReceiver.getInstance(UTSAndroid.getAppContext());
|
||||
sbr.unregisterReceiver();
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,86 @@
|
||||
import Activity from 'android.app.Activity';
|
||||
import IntentFilter from 'android.content.IntentFilter';
|
||||
import BroadcastReceiver from 'android.content.BroadcastReceiver';
|
||||
import Context from 'android.content.Context';
|
||||
import Intent from 'android.content.Intent';
|
||||
|
||||
import ScanManager from 'android.device.ScanManager';
|
||||
import PropertyID from 'android.device.scanner.configuration.PropertyID';
|
||||
|
||||
import { OnScanReceiverCallback } from '../../interface.uts';
|
||||
|
||||
export default class ScanBroadcastReceiver {
|
||||
private static instance : ScanBroadcastReceiver = new ScanBroadcastReceiver();
|
||||
|
||||
private context : Context | null = null;
|
||||
|
||||
private scanBroadcastReceiver: UrovoScanBroadcastReceiver | null = null;
|
||||
|
||||
private scanManager: ScanManager | null = null;
|
||||
|
||||
private intentFilter: IntentFilter | null = null;
|
||||
|
||||
private constructor() {
|
||||
}
|
||||
|
||||
static getInstance(context : Context | null) : ScanBroadcastReceiver {
|
||||
ScanBroadcastReceiver.instance.context = context;
|
||||
return ScanBroadcastReceiver.instance;
|
||||
}
|
||||
|
||||
registerReceiver(callback: OnScanReceiverCallback) {
|
||||
this.scanBroadcastReceiver = new UrovoScanBroadcastReceiver(callback);
|
||||
if(this.scanManager == null) {
|
||||
this.scanManager = new ScanManager();
|
||||
this.scanManager!.openScanner();
|
||||
this.scanManager!.switchOutputMode(0);
|
||||
}
|
||||
this.intentFilter = new IntentFilter();
|
||||
let idbuf = intArrayOf(PropertyID.WEDGE_INTENT_ACTION_NAME, PropertyID.WEDGE_INTENT_DATA_STRING_TAG);
|
||||
let value_buf = this.scanManager!.getParameterString(idbuf);
|
||||
if (value_buf != null && value_buf[0] != null && !value_buf[0].equals("")) {
|
||||
this.intentFilter!.addAction(value_buf[0]);
|
||||
} else {
|
||||
this.intentFilter!.addAction(ScanManager.ACTION_DECODE);
|
||||
}
|
||||
//this.intentFilter!.addAction(ScanManager.ACTION_CAPTURE_IMAGE);
|
||||
|
||||
UTSAndroid.getUniActivity()!.registerReceiver(this.scanBroadcastReceiver, this.intentFilter);
|
||||
}
|
||||
|
||||
unregisterReceiver () {
|
||||
let uniActivity: Activity | null = UTSAndroid.getUniActivity();
|
||||
if(this.scanBroadcastReceiver != null) {
|
||||
uniActivity!.unregisterReceiver(this.scanBroadcastReceiver);
|
||||
}
|
||||
|
||||
//停止扫描
|
||||
if (this.scanManager != null){
|
||||
this.scanManager?.stopDecode();
|
||||
}
|
||||
|
||||
this.scanBroadcastReceiver = null;
|
||||
}
|
||||
}
|
||||
|
||||
class UrovoScanBroadcastReceiver extends BroadcastReceiver {
|
||||
|
||||
private callback: OnScanReceiverCallback;
|
||||
|
||||
constructor(callback: OnScanReceiverCallback) {
|
||||
super();
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
override onReceive(context : Context, intent : Intent) {
|
||||
let barcode = intent.getByteArrayExtra(ScanManager.DECODE_DATA_TAG);
|
||||
let barcodelen = intent.getIntExtra(ScanManager.BARCODE_LENGTH_TAG, 0);
|
||||
let temp = intent.getByteExtra(ScanManager.BARCODE_TYPE_TAG, 0);
|
||||
console.log("----codetype--:" + temp);
|
||||
if(barcode != null) {
|
||||
let barcodeStr : string = new String(barcode, 0, barcodelen.toInt());
|
||||
this.callback(barcodeStr);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
3
uni_modules/zzjc-urovo/utssdk/app-ios/config.json
Normal file
3
uni_modules/zzjc-urovo/utssdk/app-ios/config.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"deploymentTarget": "9"
|
||||
}
|
||||
85
uni_modules/zzjc-urovo/utssdk/app-ios/index.uts
Normal file
85
uni_modules/zzjc-urovo/utssdk/app-ios/index.uts
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* 引用 iOS 系统库,示例如下:
|
||||
* import { UIDevice } from "UIKit";
|
||||
* [可选实现,按需引入]
|
||||
*/
|
||||
|
||||
/* 引入 interface.uts 文件中定义的变量 */
|
||||
import { MyApiOptions, MyApiResult, MyApi, MyApiSync } from '../interface.uts';
|
||||
|
||||
/* 引入 unierror.uts 文件中定义的变量 */
|
||||
import { MyApiFailImpl } from '../unierror';
|
||||
|
||||
/**
|
||||
* 引入三方库
|
||||
* [可选实现,按需引入]
|
||||
*
|
||||
* 在 iOS 平台引入三方库有以下两种方式:
|
||||
* 1、通过引入三方库framework 或者.a 等方式,需要将 .framework 放到 ./Frameworks 目录下,将.a 放到 ./Libs 目录下。更多信息[详见](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html#ios-平台原生配置)
|
||||
* 2、通过 cocoaPods 方式引入,将要引入的 pod 信息配置到 config.json 文件下的 dependencies-pods 字段下。详细配置方式[详见](https://uniapp.dcloud.net.cn/plugin/uts-ios-cocoapods.html)
|
||||
*
|
||||
* 在通过上述任意方式依赖三方库后,使用时需要在文件中 import:
|
||||
* 示例:import { LottieLoopMode } from 'Lottie'
|
||||
*/
|
||||
|
||||
/**
|
||||
* UTSiOS 为平台内置对象,不需要 import 可直接调用其API,[详见](https://uniapp.dcloud.net.cn/uts/utsios.html)
|
||||
*/
|
||||
|
||||
/**
|
||||
* 异步方法
|
||||
*
|
||||
* uni-app项目中(vue/nvue)调用示例:
|
||||
* 1、引入方法声明 import { myApi } from "@/uni_modules/uts-api"
|
||||
* 2、方法调用
|
||||
* myApi({
|
||||
* paramA: false,
|
||||
* complete: (res) => {
|
||||
* console.log(res)
|
||||
* }
|
||||
* });
|
||||
*
|
||||
*/
|
||||
export const myApi : MyApi = function (options : MyApiOptions) {
|
||||
|
||||
if (options.paramA == true) {
|
||||
// 返回数据
|
||||
const res : MyApiResult = {
|
||||
fieldA: 85,
|
||||
fieldB: true,
|
||||
fieldC: 'some message'
|
||||
};
|
||||
options.success?.(res);
|
||||
options.complete?.(res);
|
||||
|
||||
} else {
|
||||
// 返回错误
|
||||
let failResult = new MyApiFailImpl(9010001);
|
||||
options.fail?.(failResult)
|
||||
options.complete?.(failResult)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步方法
|
||||
*
|
||||
* uni-app项目中(vue/nvue)调用示例:
|
||||
* 1、引入方法声明 import { myApiSync } from "@/uni_modules/uts-api"
|
||||
* 2、方法调用
|
||||
* myApiSync(true);
|
||||
*
|
||||
*/
|
||||
export const myApiSync : MyApiSync = function (paramA : boolean) : MyApiResult {
|
||||
// 返回数据,根据插件功能获取实际的返回值
|
||||
const res : MyApiResult = {
|
||||
fieldA: 85,
|
||||
fieldB: paramA,
|
||||
fieldC: 'some message'
|
||||
};
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更多插件开发的信息详见:https://uniapp.dcloud.net.cn/plugin/uts-plugin.html
|
||||
*/
|
||||
54
uni_modules/zzjc-urovo/utssdk/interface.uts
Normal file
54
uni_modules/zzjc-urovo/utssdk/interface.uts
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* interface.uts
|
||||
* uts插件接口定义文件,按规范定义接口文件可以在HBuilderX中更好的做到语法提示
|
||||
*/
|
||||
|
||||
/**
|
||||
* myApi 异步函数的参数,在type里定义函数需要的参数以及api成功、失败的相关回调函数。
|
||||
*/
|
||||
export type MyApiOptions = {
|
||||
paramA : boolean
|
||||
success ?: (res : MyApiResult) => void
|
||||
fail ?: (res : MyApiFail) => void
|
||||
complete ?: (res : any) => void
|
||||
}
|
||||
|
||||
/**
|
||||
* 函数返回结果
|
||||
* 可以是void, 基本数据类型,自定义type, 或者其他类型。
|
||||
* [可选实现]
|
||||
*/
|
||||
export type MyApiResult = {
|
||||
fieldA : number,
|
||||
fieldB : boolean,
|
||||
fieldC : string
|
||||
}
|
||||
|
||||
/**
|
||||
* 错误码
|
||||
* 根据uni错误码规范要求,建议错误码以90开头,以下是错误码示例:
|
||||
* - 9010001 错误信息1
|
||||
* - 9010002 错误信息2
|
||||
*/
|
||||
export type MyApiErrorCode = 9010001 | 9010002;
|
||||
/**
|
||||
* myApi 的错误回调参数
|
||||
*/
|
||||
export interface MyApiFail extends IUniError {
|
||||
errCode : MyApiErrorCode
|
||||
};
|
||||
|
||||
/* 异步函数定义 */
|
||||
export type MyApi = (options : MyApiOptions) => void
|
||||
|
||||
/* 同步函数定义 */
|
||||
export type MyApiSync = (paramA : boolean) => MyApiResult
|
||||
|
||||
/* 扫码接收回调 */
|
||||
export type OnScanReceiverCallback = (data: string) => void;
|
||||
|
||||
/* 扫码注册 */
|
||||
export type ScanRegister = (callback : OnScanReceiverCallback) => void
|
||||
|
||||
/* 扫码卸载 */
|
||||
export type ScanUnRegister = () => void
|
||||
39
uni_modules/zzjc-urovo/utssdk/unierror.uts
Normal file
39
uni_modules/zzjc-urovo/utssdk/unierror.uts
Normal file
@@ -0,0 +1,39 @@
|
||||
/* 此规范为 uni 规范,可以按照自己的需要选择是否实现 */
|
||||
import { MyApiErrorCode, MyApiFail } from "./interface.uts"
|
||||
/**
|
||||
* 错误主题
|
||||
* 注意:错误主题一般为插件名称,每个组件不同,需要使用时请更改。
|
||||
* [可选实现]
|
||||
*/
|
||||
export const UniErrorSubject = 'zzjc-urovo';
|
||||
|
||||
|
||||
/**
|
||||
* 错误信息
|
||||
* @UniError
|
||||
* [可选实现]
|
||||
*/
|
||||
export const MyAPIErrors : Map<MyApiErrorCode, string> = new Map([
|
||||
/**
|
||||
* 错误码及对应的错误信息
|
||||
*/
|
||||
[9010001, 'custom error mseeage1'],
|
||||
[9010002, 'custom error mseeage2'],
|
||||
]);
|
||||
|
||||
|
||||
/**
|
||||
* 错误对象实现
|
||||
*/
|
||||
export class MyApiFailImpl extends UniError implements MyApiFail {
|
||||
|
||||
/**
|
||||
* 错误对象构造函数
|
||||
*/
|
||||
constructor(errCode : MyApiErrorCode) {
|
||||
super();
|
||||
this.errSubject = UniErrorSubject;
|
||||
this.errCode = errCode;
|
||||
this.errMsg = MyAPIErrors.get(errCode) ?? "";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user