添加扫描商品
This commit is contained in:
parent
17b927213a
commit
77aac21317
7
package-lock.json
generated
7
package-lock.json
generated
@ -23,6 +23,7 @@
|
||||
"moment": "^2.30.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.0.14",
|
||||
"tracking": "^1.1.3",
|
||||
"vditor": "^3.9.9",
|
||||
"vue": "^3.5.12",
|
||||
"vue-clipboard3": "^2.0.0",
|
||||
@ -8028,6 +8029,12 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tracking": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmmirror.com/tracking/-/tracking-1.1.3.tgz",
|
||||
"integrity": "sha512-XS9CVMzjp6AHT5e7oRamU8U5Lz3k6BIRTkBVs0XqepwgwXQ4kbbmxrWzTG2v6RMvJC/9MKuSBQiX/5hwsQFcCQ==",
|
||||
"license": "BSD"
|
||||
},
|
||||
"node_modules/traverse": {
|
||||
"version": "0.6.8",
|
||||
"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.8.tgz",
|
||||
|
@ -25,6 +25,7 @@
|
||||
"moment": "^2.30.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.0.14",
|
||||
"tracking": "^1.1.3",
|
||||
"vditor": "^3.9.9",
|
||||
"vue": "^3.5.12",
|
||||
"vue-clipboard3": "^2.0.0",
|
||||
|
@ -63,3 +63,11 @@ export function apiPurchaseProductOffersetStoreroomInfoTwo(params: any) {
|
||||
export function apiPurchaseProductOfferDetail(params: any) {
|
||||
return request.get({ url: '/purchase_product_offer/purchaseproductoffer/detail', params })
|
||||
}
|
||||
|
||||
// 上传商品图片
|
||||
export function apiPurchaseProductOfferUpload(params: any) {
|
||||
return request.post({
|
||||
url: '/purchase_product_offer/purchaseproductoffer/upload',
|
||||
params
|
||||
})
|
||||
}
|
@ -17,6 +17,11 @@
|
||||
</el-form>
|
||||
</el-card>
|
||||
<el-card class="!border-none" v-loading="pager.loading" shadow="never">
|
||||
<router-link v-perms="['order/sort_list/scan']" :to="{
|
||||
path: 'order_sort_list/scan'
|
||||
}" class="ml-4 mr-4">
|
||||
<el-button type="primary"> 扫描商品 </el-button>
|
||||
</router-link>
|
||||
<div class="mt-4">
|
||||
<el-table :data="pager.lists">
|
||||
<el-table-column label="ID" prop="id" show-overflow-tooltip />
|
||||
|
170
src/views/order/sort_list/scan.vue
Normal file
170
src/views/order/sort_list/scan.vue
Normal file
@ -0,0 +1,170 @@
|
||||
<template>
|
||||
<div class="demo-frame">
|
||||
<div class="demo-container">
|
||||
<video ref="videoRef" id="video" width="400" height="300" preload autoplay loop muted></video>
|
||||
<canvas ref="canvasRef" id="canvas" width="400" height="300"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import 'tracking';
|
||||
import { ElMessage, type FormInstance } from 'element-plus'
|
||||
import { apiPurchaseProductOfferUpload } from '@/api/purchase_product_offer'
|
||||
export default {
|
||||
name: 'App',
|
||||
data() {
|
||||
return {
|
||||
canvas: null,
|
||||
context: null,
|
||||
video: null,
|
||||
tracker: null,
|
||||
needInit: false,
|
||||
stream: null,
|
||||
};
|
||||
},
|
||||
async mounted() {
|
||||
this.canvas = this.$refs.canvasRef;
|
||||
this.context = this.canvas.getContext('2d');
|
||||
this.video = this.$refs.videoRef;
|
||||
|
||||
this.startTrack()
|
||||
},
|
||||
methods: {
|
||||
startTrack() {
|
||||
let getUserMedia = function(constrains, success, error) {
|
||||
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
|
||||
navigator.mediaDevices.getUserMedia(constrains).then(success).catch(error);
|
||||
} else if (navigator.webkitGetUserMedia) {
|
||||
//webkit内核浏览器
|
||||
navigator.webkitGetUserMedia(constrains).then(success).catch(error);
|
||||
} else if (navigator.mozGetUserMedia) {
|
||||
//Firefox浏览器
|
||||
navagator.mozGetUserMedia(constrains).then(success).catch(error);
|
||||
} else if (navigator.getUserMedia) {
|
||||
//旧版API
|
||||
navigator.getUserMedia(constrains).then(success).catch(error);
|
||||
} else {
|
||||
ElMessage.error('浏览器不支持getUserMedia')
|
||||
}
|
||||
}
|
||||
window.tracking.initUserMedia_ = function (element, opt_options) {
|
||||
const options = {
|
||||
video: true,
|
||||
audio: !!(opt_options && opt_options.audio)
|
||||
};
|
||||
getUserMedia(options, function (stream) {
|
||||
try {
|
||||
element.srcObject = stream;
|
||||
} catch (err) {
|
||||
element.src = window.URL.createObjectURL(stream);
|
||||
}
|
||||
}, function (e) {
|
||||
ElMessage.error(e.message)
|
||||
});
|
||||
};
|
||||
|
||||
// 重写视频捕获方法,因为不能停止 stop无效的bug
|
||||
window.tracking.trackVideo_ = function (element, tracker) {
|
||||
var canvas = document.createElement('canvas');
|
||||
var context = canvas.getContext('2d');
|
||||
var width;
|
||||
var height;
|
||||
|
||||
var resizeCanvas_ = function () {
|
||||
width = element.offsetWidth;
|
||||
height = element.offsetHeight;
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
};
|
||||
resizeCanvas_();
|
||||
element.addEventListener('resize', resizeCanvas_);
|
||||
|
||||
var requestId;
|
||||
var stopped = false;
|
||||
var requestAnimationFrame_ = function () {
|
||||
requestId = window.requestAnimationFrame(function () {
|
||||
if (element.readyState === element.HAVE_ENOUGH_DATA) {
|
||||
try {
|
||||
context.drawImage(element, 0, 0, width, height);
|
||||
} catch (err) { }
|
||||
tracking.trackCanvasInternal_(canvas, tracker);
|
||||
}
|
||||
if (stopped !== true) {
|
||||
requestAnimationFrame_();
|
||||
}
|
||||
});
|
||||
};
|
||||
var task = new tracking.TrackerTask(tracker);
|
||||
task.on('stop', function () {
|
||||
stopped = true;
|
||||
window.cancelAnimationFrame(requestId);
|
||||
});
|
||||
task.on('run', function () {
|
||||
stopped = false;
|
||||
requestAnimationFrame_();
|
||||
});
|
||||
return task.run();
|
||||
};
|
||||
|
||||
|
||||
const FastTracker = function () {
|
||||
FastTracker.base(this, 'constructor');
|
||||
};
|
||||
tracking.inherits(FastTracker, tracking.Tracker);
|
||||
|
||||
tracking.Fast.THRESHOLD = 8;
|
||||
FastTracker.prototype.threshold = tracking.Fast.THRESHOLD;
|
||||
|
||||
FastTracker.prototype.track = function (pixels, width, height) {
|
||||
const gray = tracking.Image.grayscale(pixels, width, height);
|
||||
const corners = tracking.Fast.findCorners(gray, width, height);
|
||||
|
||||
this.emit('track', {
|
||||
data: corners
|
||||
});
|
||||
};
|
||||
|
||||
this.tracker = new FastTracker();
|
||||
|
||||
this.tracker.on('track', (event) => {
|
||||
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||
const corners = event.data;
|
||||
if (corners.length > 220) {
|
||||
this.context.drawImage(this.video, 0, 0, this.canvas.width, this.canvas.height);
|
||||
if (!this.needInit) {
|
||||
this.needInit = true
|
||||
setTimeout(() => {
|
||||
this.upload()
|
||||
}, 1000)
|
||||
}
|
||||
} else {
|
||||
this.needInit = false
|
||||
}
|
||||
});
|
||||
|
||||
tracking.track('#video', this.tracker, {
|
||||
camera: true
|
||||
});
|
||||
},
|
||||
upload() {
|
||||
this.canvas.toBlob(async (blob) => {
|
||||
if (blob) {
|
||||
try {
|
||||
const formData = new FormData();
|
||||
formData.append('file', blob, 'motion_photo.jpg');
|
||||
await apiPurchaseProductOfferUpload(formData).then(res => {
|
||||
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('上传过程出错:', error);
|
||||
}
|
||||
}
|
||||
}, 'image/jpeg');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
Loading…
x
Reference in New Issue
Block a user