hreenshan112 9 months ago
parent
commit
96c6695343
  1. 2
      index.html
  2. 106
      package-lock.json
  3. 6
      package.json
  4. 171
      src/components/lowCode/formItem.vue
  5. 154
      src/views/formTable/page/cardPage.vue
  6. 7
      src/views/formTable/taskListPage.vue
  7. 378
      src/views/home/scanQrCode.vue
  8. 184
      src/views/home/scanQrCode1.vue
  9. 396
      src/views/home/scanQrCodeInput.vue
  10. 195
      src/views/home/scanQrCodeInput1.vue

2
index.html

@ -6,11 +6,11 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta content="yes" name="apple-mobile-web-app-capable">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>数通智联化工云平台</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
<script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
</body>
</html>

106
package-lock.json

@ -9,6 +9,8 @@
"version": "0.0.0",
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
"@zxing/browser": "^0.1.5",
"@zxing/library": "^0.21.3",
"axios": "^1.7.7",
"element-plus": "^2.8.6",
"font-awesome": "^4.7.0",
@ -26,9 +28,11 @@
"ts-md5": "^1.3.1",
"vue": "^3.5.10",
"vue-pdf-embed": "^1.2.1",
"vue-qrcode-reader": "^5.7.0",
"vue-router": "^4.4.5",
"vue3-pdf-embed": "^1.1.7",
"vue3-pdfjs": "^0.1.6"
"vue3-pdfjs": "^0.1.6",
"weixin-js-sdk": "^1.6.5"
},
"devDependencies": {
"@types/js-beautify": "^1.14.3",
@ -1458,6 +1462,16 @@
"node": ">=10.13.0"
}
},
"node_modules/@types/dom-webcodecs": {
"version": "0.1.13",
"resolved": "https://registry.npmmirror.com/@types/dom-webcodecs/-/dom-webcodecs-0.1.13.tgz",
"integrity": "sha512-O5hkiFIcjjszPIYyUSyvScyvrBoV3NOEEZx/pMlsu44TKzWNkLVBBxnxJz42in5n3QIolYOcBYFCPZZ0h8SkwQ=="
},
"node_modules/@types/emscripten": {
"version": "1.40.0",
"resolved": "https://registry.npmmirror.com/@types/emscripten/-/emscripten-1.40.0.tgz",
"integrity": "sha512-MD2JJ25S4tnjnhjWyalMS6K6p0h+zQV6+Ylm+aGbiS8tSn/aHLSGNzBgduj6FB4zH0ax2GRMGYi/8G1uOxhXWA=="
},
"node_modules/@types/estree": {
"version": "1.0.6",
"resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.6.tgz",
@ -1769,6 +1783,37 @@
}
}
},
"node_modules/@zxing/browser": {
"version": "0.1.5",
"resolved": "https://registry.npmmirror.com/@zxing/browser/-/browser-0.1.5.tgz",
"integrity": "sha512-4Lmrn/il4+UNb87Gk8h1iWnhj39TASEHpd91CwwSJtY5u+wa0iH9qS0wNLAWbNVYXR66WmT5uiMhZ7oVTrKfxw==",
"optionalDependencies": {
"@zxing/text-encoding": "^0.9.0"
},
"peerDependencies": {
"@zxing/library": "^0.21.0"
}
},
"node_modules/@zxing/library": {
"version": "0.21.3",
"resolved": "https://registry.npmmirror.com/@zxing/library/-/library-0.21.3.tgz",
"integrity": "sha512-hZHqFe2JyH/ZxviJZosZjV+2s6EDSY0O24R+FQmlWZBZXP9IqMo7S3nb3+2LBWxodJQkSurdQGnqE7KXqrYgow==",
"dependencies": {
"ts-custom-error": "^3.2.1"
},
"engines": {
"node": ">= 10.4.0"
},
"optionalDependencies": {
"@zxing/text-encoding": "~0.9.0"
}
},
"node_modules/@zxing/text-encoding": {
"version": "0.9.0",
"resolved": "https://registry.npmmirror.com/@zxing/text-encoding/-/text-encoding-0.9.0.tgz",
"integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==",
"optional": true
},
"node_modules/abbrev": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/abbrev/-/abbrev-2.0.0.tgz",
@ -1955,6 +2000,15 @@
"resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"node_modules/barcode-detector": {
"version": "2.2.2",
"resolved": "https://registry.npmmirror.com/barcode-detector/-/barcode-detector-2.2.2.tgz",
"integrity": "sha512-JcSekql+EV93evfzF9zBr+Y6aRfkR+QFvgyzbwQ0dbymZXoAI9+WgT7H1E429f+3RKNncHz2CW98VQtaaKpmfQ==",
"dependencies": {
"@types/dom-webcodecs": "^0.1.11",
"zxing-wasm": "1.1.3"
}
},
"node_modules/base": {
"version": "0.11.2",
"resolved": "https://registry.npmmirror.com/base/-/base-0.11.2.tgz",
@ -5981,6 +6035,11 @@
"resolved": "https://registry.npmmirror.com/scule/-/scule-1.3.0.tgz",
"integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g=="
},
"node_modules/sdp": {
"version": "3.2.0",
"resolved": "https://registry.npmmirror.com/sdp/-/sdp-3.2.0.tgz",
"integrity": "sha512-d7wDPgDV3DDiqulJjKiV2865wKsJ34YI+NDREbm+FySq6WuKOikwyNQcm+doLAZ1O6ltdO0SeKle2xMpN3Brgw=="
},
"node_modules/semver": {
"version": "7.6.3",
"resolved": "https://registry.npmmirror.com/semver/-/semver-7.6.3.tgz",
@ -7013,6 +7072,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/ts-custom-error": {
"version": "3.3.1",
"resolved": "https://registry.npmmirror.com/ts-custom-error/-/ts-custom-error-3.3.1.tgz",
"integrity": "sha512-5OX1tzOjxWEgsr/YEUWSuPrQ00deKLh6D7OTWcvNHm12/7QPyRh8SYpyWvA4IZv8H/+GQWQEh/kwo95Q9OVW1A==",
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/ts-md5": {
"version": "1.3.1",
"resolved": "https://registry.npmmirror.com/ts-md5/-/ts-md5-1.3.1.tgz",
@ -7693,6 +7760,18 @@
"vue": "^2.x || ^3.x"
}
},
"node_modules/vue-qrcode-reader": {
"version": "5.7.0",
"resolved": "https://registry.npmmirror.com/vue-qrcode-reader/-/vue-qrcode-reader-5.7.0.tgz",
"integrity": "sha512-NuLBK3madyMhM35n2libd0i5GH3Rcvq2d7qB1Qyf5FqdIdC6GaMEC8Wi8v0HFuv5V5aptOLhHVBfSczBpO3lvA==",
"dependencies": {
"barcode-detector": "2.2.2",
"webrtc-adapter": "8.2.3"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/vue-router": {
"version": "4.4.5",
"resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.4.5.tgz",
@ -7774,6 +7853,23 @@
"resolved": "https://registry.npmmirror.com/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz",
"integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="
},
"node_modules/webrtc-adapter": {
"version": "8.2.3",
"resolved": "https://registry.npmmirror.com/webrtc-adapter/-/webrtc-adapter-8.2.3.tgz",
"integrity": "sha512-gnmRz++suzmvxtp3ehQts6s2JtAGPuDPjA1F3a9ckNpG1kYdYuHWYpazoAnL9FS5/B21tKlhkorbdCXat0+4xQ==",
"dependencies": {
"sdp": "^3.2.0"
},
"engines": {
"node": ">=6.0.0",
"npm": ">=3.10.0"
}
},
"node_modules/weixin-js-sdk": {
"version": "1.6.5",
"resolved": "https://registry.npmmirror.com/weixin-js-sdk/-/weixin-js-sdk-1.6.5.tgz",
"integrity": "sha512-Gph1WAWB2YN/lMOFB/ymb+hbU/wYazzJgu6PMMktCy9cSCeW5wA6Zwt0dpahJbJ+RJEwtTv2x9iIu0U4enuVSQ=="
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz",
@ -7969,6 +8065,14 @@
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"node_modules/zxing-wasm": {
"version": "1.1.3",
"resolved": "https://registry.npmmirror.com/zxing-wasm/-/zxing-wasm-1.1.3.tgz",
"integrity": "sha512-MYm9k/5YVs4ZOTIFwlRjfFKD0crhefgbnt1+6TEpmKUDFp3E2uwqGSKwQOd2hOIsta/7Usq4hnpNRYTLoljnfA==",
"dependencies": {
"@types/emscripten": "^1.39.10"
}
}
}
}

6
package.json

@ -11,6 +11,8 @@
},
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
"@zxing/browser": "^0.1.5",
"@zxing/library": "^0.21.3",
"axios": "^1.7.7",
"element-plus": "^2.8.6",
"font-awesome": "^4.7.0",
@ -28,9 +30,11 @@
"ts-md5": "^1.3.1",
"vue": "^3.5.10",
"vue-pdf-embed": "^1.2.1",
"vue-qrcode-reader": "^5.7.0",
"vue-router": "^4.4.5",
"vue3-pdf-embed": "^1.1.7",
"vue3-pdfjs": "^0.1.6"
"vue3-pdfjs": "^0.1.6",
"weixin-js-sdk": "^1.6.5"
},
"devDependencies": {
"@types/js-beautify": "^1.14.3",

171
src/components/lowCode/formItem.vue

@ -5,6 +5,7 @@
-->
<script lang='ts' setup>
import { useRoute,useRouter } from 'vue-router'
import ScanQrCodeInput from '@/views/home/scanQrCodeInput.vue'
import {
formatNumber,
objectToArray,
@ -15,6 +16,8 @@ import {
} from '@/api/lowCode/utils';
import { AnalysisCss,AnalysisInputCss } from '@/api/common/cssInfo'
import validate from "@/api/lowCode/form/validate"
import wx from 'weixin-js-sdk'
import request from '@/utils/axios/index'
import { Md5 } from 'ts-md5'
import { debounce } from '@/utils/lowCode/item/index'
@ -57,6 +60,7 @@ const props = withDefaults(
}>(),
{}
)
const router = useRouter()
const emits = defineEmits<{
(e: 'update:modelValue', val: any): void
(e: 'optionsValue3Get1', val: any,fieldName: string): void
@ -89,6 +93,7 @@ const control = computed(() => {
})
const options = ref(props.data.options) //
const changeEvent = inject(constControlChange, '') as any
//
const updateModel = (val: any) => {
let controlAttribute = ""
@ -107,6 +112,76 @@ const updateModel = (val: any) => {
attribute: controlAttribute
})
}
//liwenxuan 20250217 start
const qrScaning = ref(false)
const handleQrScaning = (val: any) => {
qrScaning.value = false
}
const handleScanResult = (val: any) => {
//console.log(''+val)
updateModel(val)
qrScaning.value = false
}
const isQywx = ref(false)
onMounted(()=>{
if (/wxwork\//.test(navigator.userAgent)) {
isQywx.value = true
}
})
const handelScan = ()=>{
if(isQywx.value == true){//
initWxConfig()
}else{//
qrScaning.value=true
}
}
function getQyWxSignature() {
let url = window.location.href.split("#")[0];
var req = {url:"1"};
req.url = url;
return request({
url: "/javasys/lowCode/QrCode/QyWxSignature",
method: "get",
data: req,
});
}
async function initWxConfig() {
getQyWxSignature().then(({ data }) => {
//alert(data.corpid)
wx.config({
beta: true,// wx.invokejsapi
debug: false, // ,apialertpclogpc
appId: data.corpid, // corpID
timestamp: data.timestamp, //
nonceStr: data.noncestr, //
signature: data.jsapi_ticket_enterprises,// -JS-SDK使
jsApiList: ['scanQRCode'] // 使JS
});
startScan()
});
}
//
function startScan() {
wx.ready(() => {
wx.scanQRCode({
needResult: 1, //
scanType: ['qrCode','barCode'], //
success: (res) => {
const result = res.resultStr;
handleScanResult(result);
},
fail: (err) => {
alert(err.errMsg)
}
});
});
}
//liwenxuan 20250217 end
//
const value = computed({
get() {
@ -497,7 +572,7 @@ const currentComponent = computed(() => {
<template #label v-else>
<span :style="getFormItemLableStyle(configStyle)" >{{ getLabel(data.item) }}</span>
</template>
<!-- 单行文本 password -->
<el-input
v-bind="control"
v-model="value"
@ -505,7 +580,7 @@ const currentComponent = computed(() => {
:type="data.type === 'password' ? 'password' : 'text'"
:style="getFormItemInputStyle(configStyle,2)"
:input-style="getFormItemInputStyle(configStyle,3)"
v-if="['input', 'password'].includes(data.type)"
v-if="['password'].includes(data.type)"
:placeholder="data.control.placeholder?data.control.placeholder:'请输入'+getLabel(data.item)"
>
<template #prepend v-if="config.prepend">
@ -533,6 +608,89 @@ const currentComponent = computed(() => {
<span v-else>{{ config.append }}</span>
</template>
</el-input>
<!-- 单行文本 input 二维码扫码录入 -->
<!--
-->
<el-input
v-bind="control"
v-model="value"
:disabled="judgeIsDisabled(data.name)"
:type="data.type === 'password' ? 'password' : 'text'"
:style="getFormItemInputStyle(configStyle,2)"
:input-style="getFormItemInputStyle(configStyle,3)"
v-if="['input'].includes(data.type)&&data.control.scanInputFlag==true&&data.control.scanType=='QrCode'"
:placeholder="data.control.placeholder?data.control.placeholder:'请输入或扫码'+getLabel(data.item)"
>
<template #prepend v-if="config.prepend">
<div v-if="getInputSlot('p')">
<SelectDesign
:data="getInputSlot('p')"
:disabled="judgeIsDisabled(data.name)"
:transform-option="transformOption"
@change="inputSlotChange"
type="slot"
/>
</div>
<span v-else>{{ config.append }}</span>
</template>
<template #append>
<div style="display: flex; justify-content: center; max-width: 20px;"><SvgIcon icon-class="scanQrCode" :size="'30px'" @click="handelScan" /></div>
</template>
<template #append v-if="config.append">
<div v-if="getInputSlot()">
<SelectDesign
:data="getInputSlot()"
:disabled="judgeIsDisabled(data.name)"
:transform-option="transformOption"
@change="inputSlotChange"
type="slot"
/>
</div>
<span v-else>{{ config.append }}</span>
</template>
</el-input>
<!--单行文本 input OCR识别录入 -->
<el-input
v-bind="control"
v-model="value"
:disabled="judgeIsDisabled(data.name)"
:type="data.type === 'password' ? 'password' : 'text'"
:style="getFormItemInputStyle(configStyle,2)"
:input-style="getFormItemInputStyle(configStyle,3)"
v-if="['input'].includes(data.type)&&data.control.scanInputFlag==true&&data.control.scanType=='OCR'"
:placeholder="data.control.placeholder?data.control.placeholder:'请输入或扫描文字'+getLabel(data.item)"
>
<template #prepend v-if="config.prepend">
<div v-if="getInputSlot('p')">
<SelectDesign
:data="getInputSlot('p')"
:disabled="judgeIsDisabled(data.name)"
:transform-option="transformOption"
@change="inputSlotChange"
type="slot"
/>
</div>
<span v-else>{{ config.append }}</span>
</template>
<template #append v-if="config.append">
<div v-if="getInputSlot()">
<SelectDesign
:data="getInputSlot()"
:disabled="judgeIsDisabled(data.name)"
:transform-option="transformOption"
@change="inputSlotChange"
type="slot"
/>
</div>
<span v-else>{{ config.append }}</span>
</template>
</el-input>
<!--多行文本-->
<el-input
v-bind="control"
@ -820,6 +978,15 @@ const currentComponent = computed(() => {
</el-form-item>
<!-- liwenxuan 二维码扫描录入组件抽屉 20250218 start -->
<el-drawer
v-model="qrScaning"
:with-header="false"
size="100%"
>
<ScanQrCodeInput v-if="qrScaning&&!isQywx" @update-qrScaning="handleQrScaning" @update-scanResult="handleScanResult"></ScanQrCodeInput>
</el-drawer>
<!-- liwenxuan 二维码扫描录入组件抽屉 20250218 end -->
</template>
</div>
</template>

154
src/views/formTable/page/cardPage.vue

@ -175,7 +175,8 @@ const asfGetPageData = (asfFormId: any,asfToSelectMastersKey: any) => {
console.log(data.data.list)
for(let i = 0;i<data.data.list.length;i++){
let asfMasterAndAsfId:any = {}
asfMasterAndAsfId.asfId = data.data.list[i][asfDetails[j].field]
//asfMasterAndAsfId.asfId = data.data.list[i][asfDetails[j].field]
asfMasterAndAsfId.asfId = data.data.list[i].id
asfMasterAndAsfId.asfMasterId = data.data.list[i].id
asfToSelectIds.push(asfMasterAndAsfId)
@ -234,9 +235,12 @@ const asfGetPageData = (asfFormId: any,asfToSelectMastersKey: any) => {
/* tablePageClass.value = 4;
drawerWith.value = container.value?.clientWidth
*/
props.stateForm.type=3
//lookInfo.value = itval
asflookPageInfoIsShow.value = true;
setTimeout(()=>{
props.stateForm.type=3
//lookInfo.value = itval
asflookPageInfoIsShow.value = true;
},500)
})
@ -358,7 +362,125 @@ const columnsFilter = computed(() => {
const searchQuery = computed(() => {
return json2string(props.stateListInfo.searchData);
});
//liwenxuan 20250117 start
const qrJumpGetPageData = (qrDetailId: string) => {
let qrJumpSearchData = [{"id":"id","label":"Id","field":"id","type":"bigint(20)","attribute":"","pattern":"bigint","fieldClass":"id","activeValue":"","inactiveValue":"","config":{"optionsType":0},"control":{"optionsValue3Formid":"","optionsValue3Field":""},"options":[],"isSearch":true,"value":qrDetailId}]
loadText.value = "数据加载中,请稍后......"
loadingList.value = true
console.log(searchQuery.value)
let sendData = {
formId: props.appId,
page:1,
pagesize:1,
searchData:json2string(qrJumpSearchData)
}
state.loading = true;
gainFormPageListCont(sendData)
.then((data) => {
console.log("获取列表详细信息----------ee------->",data.data)
// tableDataList.value = data.data.list;
if(Array.isArray(data.data.list)){
//liwenxuan start
//liwenxuan start
let dataList = data;
//console.log(dataList)
asfDetails = props.stateListInfo.tableData.columns.filter((item: any) => {
return item.fieldClass == "associatedForms";
});
if (asfDetails.length > 0 && data.data.list != null) {
//console.log(data.data.list)
//,asf
asfQueryParams = [];
for (let j = 0; j < asfDetails.length; j++) {
let asfQueryParamsItem: any = {};
//console.log(asfDetails[j])
asfQueryParamsItem.formId = asfDetails[j].control.formid;
asfQueryParamsItem.field = asfDetails[j].field;
let asfToSelectIds = [];
// console.log(data.data.list)
for (let i = 0; i < data.data.list.length; i++) {
let asfMasterAndAsfId: any = {};
asfMasterAndAsfId.asfId = data.data.list[i][asfDetails[j].field];
asfMasterAndAsfId.asfMasterId = data.data.list[i].id;
asfToSelectIds.push(asfMasterAndAsfId);
}
asfQueryParamsItem.asfToSelectIds = asfToSelectIds;
asfQueryParams.push(asfQueryParamsItem);
}
let queryCount = 0;
for (let i = 0; i < asfQueryParams[0].asfToSelectIds.length; i++) {
if (asfQueryParams[0].asfToSelectIds[i].asfId != "") {
queryCount++;
}
}
//console.log(asfQueryParams)
if (queryCount > 0) {
getAsfDataTitlesByIds(asfQueryParams).then(({ data }) => {
//console.log(data)
for (let i = 0; i < dataList.data.list.length; i++) {
//console.log(dataList.data.list[i])
for (let j = 0; j < data.length; j++) {
//console.log(data[j])
for (let n = 0; n < data[j].list.length; n++) {
if (dataList.data.list[i].id == data[j].list[n].asfMasterId) {
dataList.data.list[i][data[j].field] = data[j].list[n].label;
}
//console.log(data[j].list[n])
}
}
}
//tableDataList.value = dataList.data.list;
tableDataList.value.push(... dataList.data.list)
});
} else {
//tableDataList.value = data.data.list;
tableDataList.value.push(...data.data.list)
}
} else {
//tableDataList.value = data.data.list;
tableDataList.value.push(...data.data.list)
}
//tableDataList.value = data.data.list
//liwenxuan end
//liwenxuan end
/* tableDataList.value.push(...data.data.list)
console.log(tableDataList.value) */
}
pageTotal.value = pageTotal.value + data.data.count
if(data.data.total > 0){
if(pageTotal.value < data.data.total){
let pagenum = state.pagesize - data.data.count
if (pagenum > 0) {
loadText.value = ""
loadingList.value = true
}else{
loadText.value = ""
loadingList.value = false
}
}else{
loadText.value = ""
loadingList.value = true
}
}else{
loadText.value = "此选项没有数据!"
loadingList.value = true
}
})
}
//liwenxuan 20250117 end
/**
@ 作者: 秦东
@ 时间: 2024-11-05 10:15:38
@ -367,6 +489,7 @@ const searchQuery = computed(() => {
const getPageData = () => {
loadText.value = "数据加载中,请稍后......"
loadingList.value = true
//console.log(searchQuery.value)
let sendData = {
formId: props.appId,
page: state.page,
@ -479,10 +602,28 @@ const getPageData = () => {
})
}
// 使 ref URL
const fullUrl = ref(window.location.href);
onMounted(()=>{
nextTick(()=>{
requeryList()
//console.log(fullUrl.value)
if(fullUrl.value.includes("&qrDetailId=")){
let urlSplitArray = fullUrl.value.split("&qrDetailId=")
let qrDetailId = urlSplitArray[1]
qrJumpGetPageData(qrDetailId)
//
setTimeout(() => {
openLook(tableDataList.value[0])
}, 500);
}else{
requeryList()
}
})
})
@ -717,9 +858,10 @@ defineExpose({
<el-checkbox-group v-model="pageIdAry">
<el-card v-for="(itval,itIndex) in tableDataList" :key="itIndex" class="taskCardBox" shadow="always">
<el-card v-for="(itval,itIndex) in tableDataList" :key="itIndex" class="taskCardBox" shadow="always" >
<table class="talbelBox">
<tbody>
<tr v-if="itval.flowIsOpen==1">
<td class="cardInfoTitle">状态</td>
<td class="cardInfoTitle" align="right">

7
src/views/formTable/taskListPage.vue

@ -245,7 +245,13 @@ const initLoadData = () => {
}
}
}
//liwenxuan 20250123 start
stateData.tableData.controlBtn = stateData.tableData.controlBtn.filter(
(item: any) => item.key != "showQrCode"
);
//liwenxuan 20250123 end
stateList.tableData = stateData.tableData
stateList.searchData = stateData.searchData
if(stateList.searchData == null){
stateList.searchData = new Array()
@ -502,7 +508,6 @@ const performAction = (val) => {}
<div class="contentBetween">
<div v-if="stateList.tableData.controlBtn.length > 0">
<el-button
v-for="item in stateList.tableData.controlBtn"
v-bind="item"
:key="item.type"

378
src/views/home/scanQrCode.vue

@ -1,205 +1,193 @@
<template>
<div class="scanCode">
<div class="container">
<div class="qrcode">
<div class="btn">
<div class="left-back" style="float: left;">
<el-icon @click="clickBack" style="border: white solid 0px;">
<Back />
</el-icon>
<div style="height: 100vh">
<qrcode-stream @detect="onDecode" @error="onInit" style="height: 100%">
<div>
<div class="qr-scanner">
<!--顶部左边的返回箭头-->
<div>
<!-- <van-icon class="scanImg" @click="onClickLeft" name="arrow-left" /> -->
<!-- <el-button type="primary" @click="onClickLeft" ></el-button> -->
<el-icon @click="onClickLeft" style="margin:15px;width: 20px;height: 20px;">
<Close style="width: 20px;height: 20px;" />
</el-icon>
</div>
<!--中间的扫码框-->
<div class="box">
<div class="line"></div>
<div class="angle"></div>
</div>
<div class="txt">
将二维码/条码放入框内即自动扫描
</div>
</div>
</div>
<!-- <div class="right-file">
<van-uploader
v-model="fileList"
:preview-image="false"
:after-read="dealSelectFiles"
>
<el-icon><Picture /></el-icon>
</van-uploader>
</div> -->
</div>
<div id="reader"></div>
</div>
</div>
<!--<div class="btn">
<div class="left-back">
<el-icon @click="clickBack">
<Back />
</el-icon>
</div>
<div class="right-file">
<van-uploader
v-model="fileList"
:preview-image="false"
:after-read="dealSelectFiles"
>
<el-icon><Picture /></el-icon>
</van-uploader>
</div>
</div> -->
</qrcode-stream>
</div>
</template>
<script setup>
import { reactive } from "vue";
import { defineComponent, toRefs, onMounted, onUnmounted } from "vue";
import { Html5Qrcode } from "html5-qrcode";
import { useRouter } from 'vue-router'
const router = useRouter()
const state = reactive({
html5QrCode: null,
fileList: [],
});
const start = () => {
state.html5QrCode
.start(
{ facingMode: "environment" },
{
fps: 5,
qrbox: { width: 300, height: 210 },
aspectRatio: 1.7,//
},
(decodedText, decodedResult) => {
window.location.href = decodedText;
console.log("decodedText", decodedText);
console.log("decodedResult", decodedResult);
}
)
.catch((err) => {
console.log("扫码错误信息", err);
let message = ""; //
if (typeof err == "string") {
message = "二维码识别失败!";
alert(message)
} else {
if (err.name == "NotAllowedError") {
message = "您需要授予相机访问权限!";
}
if (err.name == "NotFoundError") {
message = "这个设备上没有摄像头!";
}
if (err.name == "NotSupportedError") {
message =
"摄像头访问只支持在安全的上下文中,如https或localhost!";
}
if (err.name == "NotReadableError") {
message = "相机被占用!";
}
if (err.name == "OverconstrainedError") {
message = "安装摄像头不合适!";
}
if (err.name == "StreamApiNotSupportedError") {
message = "此浏览器不支持流API!";
}
alert(message)
}
});
};
const clickBack = () => {
//console.log(1)
router.back();
}
const getCameras = () => {
Html5Qrcode.getCameras()
.then((devices) => {
if (devices && devices.length) {
state.html5QrCode = new Html5Qrcode("reader");
start();
}
})
.catch((err) => {
alert("摄像头无访问权限!");
});
};
const stop = () => {
state.html5QrCode
.stop()
.then((ignore) => {
console.log("停止扫码", ignore);
})
.catch((err) => {
console.log(err);
alert("停止扫码失败");
});
};
const dealSelectFiles = () => {
try {
window.qrcode.callback = (result) => {
alert("成功了,结果是:" + result);
}; // get select files.
let file = state.fileList[0].file;
var reader = new FileReader();
reader.onload = (function () {
return function (e) {
window.qrcode.decode(e.target.result);
};
})(file);
reader.readAsDataURL(file);
} catch (error) {
alert("图片识别失败!");
}
};
onMounted(() => {
getCameras();
});
onUnmounted(() => {
//
if (state.html5QrCode&&state.html5QrCode.isScanning) {
stop();
</template>
<script setup lang="ts">
import { QrcodeStream } from "vue-qrcode-reader";
import { ref } from "vue";
//
const dataList = ref('')
const result = ref(true)
const error = ref('')
//
const onDecode = (res: any) => {
dataList.value = res
result.value = false
//console.log('',dataList.value)
//alert(dataList.value)
//showSuccessToast('')---------------------------------------
window.location.href = dataList.value[0].rawValue;
//
//
}
//
const onInit = async (promise: any) => {
console.log('初始化摄像头', promise)
try {
await promise
} catch (err: any) {
if (err.name === 'NotAllowedError') {
error.value = 'ERROR: 您需要授予相机访问权限';
} else if (err.name === 'NotFoundError') {
error.value = 'ERROR: 这个设备上没有摄像头';
} else if (err.name === 'NotSupportedError') {
error.value = 'ERROR: 所需的安全上下文(HTTPS、本地主机)';
} else if (err.name === 'NotReadableError') {
error.value = 'ERROR: 相机被占用';
} else if (err.name === 'OverconstrainedError') {
error.value = 'ERROR: 安装摄像头不合适';
} else if (err.name === 'StreamApiNotSupportedError') {
error.value = 'ERROR: 此浏览器不支持流API';
}
});
</script>
}
}
//
const onClickLeft = () => {
history.back();
}
</script>
<style scoped>
:deep(i.van-badge__wrapper.van-icon.van-icon-arrow-left.scanImg) {
font-size: 40px;
color: white;
}
.scanImg {
margin-top: 30px;
margin-left: 10px;
}
.error {
font-weight: bold;
color: red;
}
.cameraMessage {
width: 100%;
height: 60px;
}
<style lang="scss" scoped>
.scanCode {
height: 100vh;
display: flex;
flex-direction: column;
background: rgba(0, 0, 0);
}
.container {
.qr-scanner {
background-size: 3rem 3rem;
background-position: -1rem -1rem;
width: 100%;
/* height: 100%; */
height: 100vh;
/* height: 288px; */
position: relative;
background-color: #1110;
}
.qr-scanner .box {
width: 213px;
height: 213px;
position: absolute;
left: 50%;
top: 40%;
transform: translate(-50%, -50%);
overflow: hidden;
border: 1px solid #3aa5ff;
}
.qr-scanner .txt {
width: 100%;
/* border: red solid 7px; */
}
.qrcode {
height: 90%;
/* width: 100%;*/
/* border: white solid 7px; */
}
#reader {
display: block;
height: 35px;
line-height: 35px;
font-size: 14px;
text-align: center;
/* color: #f9f9f9; */
margin: 0 auto;
position: absolute;
top: 60%;
left: 0;
}
height: 90vh;
/* top: 50%;
.qr-scanner .myQrcode {
text-align: center;
color: #3aa5ff;
}
.qr-scanner .line {
height: calc(100% - 2px);
width: 100%;
background: linear-gradient(180deg, rgba(0, 255, 51, 0) 43%, #3aa5ff 211%);
border-bottom: 1px solid #3aa5ff;
transform: translateY(-100%);
animation: radar-beam 2s infinite alternate;
animation-timing-function: cubic-bezier(0.53, 0, 0.43, 0.99);
animation-delay: 1.4s;
}
.qr-scanner .box:after,
.qr-scanner .box:before,
.qr-scanner .angle:after,
.qr-scanner .angle:before {
content: '';
display: block;
position: absolute;
width: 3vw;
height: 3vw;
}
.qr-scanner .box:after,
.qr-scanner .box:before {
top: 0;
border-top-color: #3aa5ff;
}
.qr-scanner .angle:after,
.qr-scanner .angle:before {
bottom: 0;
border-bottom-color: #3aa5ff;
}
.qr-scanner .box:before,
.qr-scanner .angle:before {
left: 0;
transform: translateY(-50%); */
/* border: yellow solid 5px; */
}
.btn {
flex: 1;
padding-top: 2vw;
display: flex;
padding-left: 3vw;
color: #fff;
font-size: 6vw;
align-items: flex-start;
/* border: green solid 7px; */
}
</style>
border-left-color: #3aa5ff;
}
.qr-scanner .box:after,
.qr-scanner .angle:after {
right: 0;
border-right-color: #3aa5ff;
}
@keyframes radar-beam {
0% {
transform: translateY(-100%);
}
100% {
transform: translateY(0);
}
}
</style>

184
src/views/home/scanQrCode1.vue

@ -0,0 +1,184 @@
<template>
<div style="height: 100vh">
<qrcode-stream @detect="onDecode" @error="onInit" style="height: 100%">
<div>
<div class="qr-scanner">
<!--顶部左边的返回箭头-->
<div>
<!-- <van-icon class="scanImg" @click="onClickLeft" name="arrow-left" /> -->
<!-- <el-button type="primary" @click="onClickLeft" ></el-button> -->
<el-icon @click="onClickLeft" style="margin:15px;width: 20px;height: 20px;"><Close style="width: 20px;height: 20px;" /></el-icon>
</div>
<!--中间的扫码框-->
<div class="box">
<div class="line"></div>
<div class="angle"></div>
</div>
<div class="txt">
将二维码/条码放入框内即自动扫描
</div>
</div>
</div>
</qrcode-stream>
</div>
</template>
<script setup lang="ts">
import {QrcodeStream} from "vue-qrcode-reader";
import {ref} from "vue";
//
const dataList = ref('')
const result = ref(true)
const error = ref('')
//
const onDecode = (res: any) => {
dataList.value = res
result.value = false
//console.log('',dataList.value)
//alert(dataList.value)
//showSuccessToast('')---------------------------------------
window.location.href = dataList.value[0].rawValue;
//
//
}
//
const onInit = async (promise: any) => {
console.log('初始化摄像头',promise)
try {
await promise
}catch (err: any) {
if (err.name === 'NotAllowedError') {
error.value = 'ERROR: 您需要授予相机访问权限';
} else if (err.name === 'NotFoundError') {
error.value = 'ERROR: 这个设备上没有摄像头';
} else if (err.name === 'NotSupportedError') {
error.value = 'ERROR: 所需的安全上下文(HTTPS、本地主机)';
} else if (err.name === 'NotReadableError') {
error.value = 'ERROR: 相机被占用';
} else if (err.name === 'OverconstrainedError') {
error.value = 'ERROR: 安装摄像头不合适';
} else if (err.name === 'StreamApiNotSupportedError') {
error.value = 'ERROR: 此浏览器不支持流API';
}
}
}
//
const onClickLeft = () => {
history.back();
}
</script>
<style scoped>
:deep(i.van-badge__wrapper.van-icon.van-icon-arrow-left.scanImg){
font-size: 40px;
color: white;
}
.scanImg{
margin-top: 30px;
margin-left: 10px;
}
.error {
font-weight: bold;
color: red;
}
.cameraMessage {
width: 100%;
height: 60px;
}
.qr-scanner {
background-size: 3rem 3rem;
background-position: -1rem -1rem;
width: 100%;
/* height: 100%; */
height: 100vh;
/* height: 288px; */
position: relative;
background-color: #1110;
}
.qr-scanner .box {
width: 213px;
height: 213px;
position: absolute;
left: 50%;
top: 40%;
transform: translate(-50%, -50%);
overflow: hidden;
border: 1px solid #3aa5ff;
}
.qr-scanner .txt {
width: 100%;
height: 35px;
line-height: 35px;
font-size: 14px;
text-align: center;
/* color: #f9f9f9; */
margin: 0 auto;
position: absolute;
top: 60%;
left: 0;
}
.qr-scanner .myQrcode {
text-align: center;
color: #3aa5ff;
}
.qr-scanner .line {
height: calc(100% - 2px);
width: 100%;
background: linear-gradient(180deg, rgba(0, 255, 51, 0) 43%, #3aa5ff 211%);
border-bottom: 1px solid #3aa5ff;
transform: translateY(-100%);
animation: radar-beam 2s infinite alternate;
animation-timing-function: cubic-bezier(0.53, 0, 0.43, 0.99);
animation-delay: 1.4s;
}
.qr-scanner .box:after,
.qr-scanner .box:before,
.qr-scanner .angle:after,
.qr-scanner .angle:before {
content: '';
display: block;
position: absolute;
width: 3vw;
height: 3vw;
}
.qr-scanner .box:after,
.qr-scanner .box:before {
top: 0;
border-top-color: #3aa5ff;
}
.qr-scanner .angle:after,
.qr-scanner .angle:before {
bottom: 0;
border-bottom-color: #3aa5ff;
}
.qr-scanner .box:before,
.qr-scanner .angle:before {
left: 0;
border-left-color: #3aa5ff;
}
.qr-scanner .box:after,
.qr-scanner .angle:after {
right: 0;
border-right-color: #3aa5ff;
}
@keyframes radar-beam {
0% {
transform: translateY(-100%);
}
100% {
transform: translateY(0);
}
}
</style>

396
src/views/home/scanQrCodeInput.vue

@ -0,0 +1,396 @@
<template>
<div class="page-scan">
<!-- 扫码区域 -->
<!-- <div style="z-index: 1000; position: relative;"> -->
<el-icon @click="onClickLeft" class= "close-icon" style="width: 30px;height: 30px;"><!-- style="margin:15px;width: 20px;height: 20px;color: white;" -->
<Close style="width: 30px;height: 30px;" /><!-- style="width: 20px;height: 20px;" -->
</el-icon>
<!-- </div> -->
<div class="QrCode">
<video ref="video" height="100%" width="100%" id="video" autoplay></video>
</div>
<!-- 扫码样式一 -->
<div class="Qr_scanner">
<div class="box">
<div class="line_row">
<div class="line"></div>
</div>
<div class="angle"></div>
</div>
</div>
<div class="txt">
将二维码/条码放入框内即自动扫描
</div>
</div>
</template>
<script>
// WebRTC ok
import 'webrtc-adapter'
import { BrowserMultiFormatReader } from '@zxing/library'
import request from '@/utils/axios/index'
import wx from 'weixin-js-sdk';
export default {
name: 'scanCodePage',
data() {
return {
codeReader: null,
isIOS: false
}
},
mounted() {
const ua = navigator.userAgent
//isIOS.value = /iPhone|iPad|iPod/i.test(ua)
this.isIOS = /iPhone|iPad|iPod/i.test(ua) && !window.MSStream;
this.codeReader = new BrowserMultiFormatReader()
//alert(navigator.userAgent)
if (/wxwork\//.test(navigator.userAgent)) {
//alert('')
this.initWxConfig();
} else {
// 使WebRTC
this.openScan()
//this.initWxConfig();
}
},
beforeUnmount() {
this.codeReader && this.codeReader.reset()
},
methods: {
getQyWxSignature() {
let url = window.location.href.split("#")[0];
var req = {};
req.url = url;
return request({
url: "/javasys/lowCode/QrCode/QyWxSignature",
method: "get",
data: req,
});
},
//
async initWxConfig() {
this.getQyWxSignature().then(({ data }) => {
//alert(data.corpid)
wx.config({
beta: true,// wx.invokejsapi
debug: false, // ,apialertpclogpc
appId: data.corpid, // corpID
timestamp: data.timestamp, //
nonceStr: data.noncestr, //
signature: data.jsapi_ticket_enterprises,// -JS-SDK使
jsApiList: ['scanQRCode'] // 使JS
});
this.startScan()
});
},
//
startScan() {
wx.ready(() => {
wx.scanQRCode({
needResult: 1, //
scanType: ['qrCode','barCode'], //
success: (res) => {
const result = res.resultStr;
this.handleScanResult(result);
},
fail: (err) => {
alert(err.errMsg)
}
});
});
},
onClickLeft(){
this.codeReader && this.codeReader.reset()
this.codeReader = null
this.$emit('update-qrScaning', '1') // 触发父组件事件 emits('update-scanResult', dataList.value[0].rawValue) // 触发父组件事件
},
//
handleScanResult(code) {
/* this.$axios.post('/api/verify-code', { code })
.then(res => {
//
}); */
this.$emit('update-scanResult', code) //
},
async openScan() {
this.codeReader
.listVideoInputDevices()
.then((videoInputDevices) => {
// id
let firstDeviceId = videoInputDevices[0].deviceId
//
let noBackAndroidFlag = false
//
//console.log(videoInputDevices)
//
//alert(videoInputDevices.length)
videoInputDevices.some(element => {
if (videoInputDevices.length > 1) {//
//alert(element.label)
if (element.label.startsWith("Video device")) {//
//alert(element.label)
if (this.isIOS) {//
firstDeviceId = element.deviceId
return true;
} else {//
if (videoInputDevices.length == 2) {
noBackAndroidFlag = true
//if(element.label.startsWith("Video device 2")){
//firstDeviceId = element.deviceId
//return true
//}
} else if (videoInputDevices.length >= 3) {
if (element.label.startsWith("Video device 3")) {
firstDeviceId = element.deviceId
return true
}
}
}
} else {
if (element.label.includes("back")) {
firstDeviceId = element.deviceId
return true;
} else {
return false;
}
}
} else {//
return true
}
});
this.codeReader && this.codeReader.reset() //
this.decodeFromInputVideoFunc(firstDeviceId)
})
.catch((err) => {
console.error(err)
})
},
decodeFromInputVideoFunc(firstDeviceId) {
this.codeReader.decodeFromInputVideoDeviceContinuously(
firstDeviceId,
'video',
(result, err) => {
if (result) {
console.log('扫描结果', result)
if (result.text) {
// this.clickIndexLeft(result.text)
//alert(result.text)
this.$emit('update-scanResult', result.text)
}
}
if (err && !err) {
console.error(err)
}
}
)
},
/* // 停止扫描并返回上一页
clickIndexLeft(result) {
this.codeReader && this.codeReader.reset()
this.codeReader = null
// this.$route.params.result = result
// this.$router.back()
} */
}
}
</script>
<style lang="scss" scope>
.QrCode {
width: 100vw;
height: 100vh;
position: relative;
#video {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.Qr_scanner {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.3);
}
.Qr_scanner .box {
width: 65vw;
height: 65vw;
max-height: 75vh;
max-width: 75vh;
position: relative;
left: 50%;
top: 45%;
transform: translate(-50%, -50%);
border: 1px solid rgb(43, 113, 254);
.line_row {
width: 100%;
overflow: hidden;
background-image: linear-gradient(0deg,
transparent 24%,
rgba(136, 176, 255, 0.1) 25%,
rgba(136, 176, 255, 0.1) 26%,
transparent 27%,
transparent 74%,
rgba(136, 176, 255, 0.1) 75%,
rgba(136, 176, 255, 0.1) 76%,
transparent 77%,
transparent),
linear-gradient(90deg,
transparent 24%,
rgba(136, 176, 255, 0.1) 25%,
rgba(136, 176, 255, 0.1) 26%,
transparent 27%,
transparent 74%,
rgba(136, 176, 255, 0.1) 75%,
rgba(136, 176, 255, 0.1) 76%,
transparent 77%,
transparent);
background-size: 3rem 3rem;
background-position: -1rem -1rem;
animation: Heightchange 2s infinite;
animation-timing-function: cubic-bezier(0.53, 0, 0.43, 0.99);
animation-delay: 1.4s;
border-bottom: 1px solid rgba(136, 176, 255, 0.1);
display: flex;
justify-content: center;
align-items: flex-end;
}
}
.Qr_scanner .line {
width: 100%;
height: 3px;
background: #2b71fe;
// opacity: 0.58;
filter: blur(4px);
}
.Qr_scanner .box:after,
.Qr_scanner .box:before,
.Qr_scanner .angle:after,
.Qr_scanner .angle:before {
content: '';
display: block;
position: absolute;
width: 78px;
height: 78px;
border: 0.15rem solid transparent;
}
.Qr_scanner .box:after,
.Qr_scanner .box:before {
top: -7px;
border-top-color: #2b71fe;
}
.Qr_scanner .angle:after,
.Qr_scanner .angle:before {
bottom: -7px;
border-bottom-color: #2b71fe;
}
.Qr_scanner .box:before,
.Qr_scanner .angle:before {
left: -7px;
border-left-color: #2b71fe;
}
.Qr_scanner .box:after,
.Qr_scanner .angle:after {
right: -7px;
border-right-color: #2b71fe;
}
@keyframes radar-beam {
0% {
transform: translateY(-100%);
}
100% {
transform: translateY(0);
}
}
@keyframes Heightchange {
0% {
height: 0;
}
100% {
height: 100%;
}
}
.txt {
width: 100%;
height: 35px;
line-height: 35px;
font-size: 14px;
text-align: center;
/* color: #f9f9f9; */
margin: 0 auto;
position: absolute;
top: 63%;
left: 0;
color: white;
z-index: 1001;
}
.close-icon {
position: absolute;
top: 15px;
left: 15px;
width: 20px;
height: 20px;
color: white;
z-index: 1001;
cursor: pointer;
background: rgba(0, 0, 0, 0.3); /* 可选背景 */
border-radius: 50%; /* 圆形背景 */
padding: 5px;
/* 点击区域扩大 */
}
.Qr_scanner {
z-index: 999; /* 低于图标容器 */
/* 其他原有样式保持不变 */
}
</style>

195
src/views/home/scanQrCodeInput1.vue

@ -0,0 +1,195 @@
<template>
<div style="height: 100vh">
<qrcode-stream @detect="onDecode" @error="onInit" style="height: 100%">
<div>
<div class="qr-scanner">
<!--顶部左边的返回箭头-->
<div>
<el-icon @click="onClickLeft" style="margin:15px;width: 20px;height: 20px;">
<Close style="width: 20px;height: 20px;" />
</el-icon>
</div>
<!--中间的扫码框-->
<div class="box">
<div class="line"></div>
<div class="angle"></div>
</div>
<div class="txt">
将二维码/条码放入框内即自动扫描
</div>
</div>
</div>
</qrcode-stream>
</div>
</template>
<script setup lang="ts">
import { QrcodeStream } from "vue-qrcode-reader";
import { ref } from "vue";
const emits = defineEmits<{
(e: 'update-qrScaning', value: any): void
(e: 'update-scanResult', value: any): void
}>()
//
const dataList = ref('')
const result = ref(true)
const error = ref('')
//
const onDecode = (res: any) => {
dataList.value = res
result.value = false
//console.log('',dataList.value)
//alert(dataList.value)
//showSuccessToast('')---------------------------------------
//console.log(''+dataList.value[0].rawValue)
emits('update-scanResult', dataList.value[0].rawValue) //
//
//
}
//
const onInit = async (promise: any) => {
console.log('初始化摄像头', promise)
try {
await promise
} catch (err: any) {
if (err.name === 'NotAllowedError') {
error.value = 'ERROR: 您需要授予相机访问权限';
} else if (err.name === 'NotFoundError') {
error.value = 'ERROR: 这个设备上没有摄像头';
} else if (err.name === 'NotSupportedError') {
error.value = 'ERROR: 所需的安全上下文(HTTPS、本地主机)';
} else if (err.name === 'NotReadableError') {
error.value = 'ERROR: 相机被占用';
} else if (err.name === 'OverconstrainedError') {
error.value = 'ERROR: 安装摄像头不合适';
} else if (err.name === 'StreamApiNotSupportedError') {
error.value = 'ERROR: 此浏览器不支持流API';
}
}
}
//
const onClickLeft = () => {
//history.back();
emits('update-qrScaning', '1') //
}
</script>
<style scoped>
:deep(i.van-badge__wrapper.van-icon.van-icon-arrow-left.scanImg) {
font-size: 40px;
color: white;
}
.scanImg {
margin-top: 30px;
margin-left: 10px;
}
.error {
font-weight: bold;
color: red;
}
.cameraMessage {
width: 100%;
height: 60px;
}
.qr-scanner {
background-size: 3rem 3rem;
background-position: -1rem -1rem;
width: 100%;
/* height: 100%; */
height: 100vh;
/* height: 288px; */
position: relative;
background-color: #1110;
}
.qr-scanner .box {
width: 213px;
height: 213px;
position: absolute;
left: 50%;
top: 40%;
transform: translate(-50%, -50%);
overflow: hidden;
border: 1px solid #3aa5ff;
}
.qr-scanner .txt {
width: 100%;
height: 35px;
line-height: 35px;
font-size: 14px;
text-align: center;
/* color: #f9f9f9; */
margin: 0 auto;
position: absolute;
top: 60%;
left: 0;
}
.qr-scanner .myQrcode {
text-align: center;
color: #3aa5ff;
}
.qr-scanner .line {
height: calc(100% - 2px);
width: 100%;
background: linear-gradient(180deg, rgba(0, 255, 51, 0) 43%, #3aa5ff 211%);
border-bottom: 1px solid #3aa5ff;
transform: translateY(-100%);
animation: radar-beam 2s infinite alternate;
animation-timing-function: cubic-bezier(0.53, 0, 0.43, 0.99);
animation-delay: 1.4s;
}
.qr-scanner .box:after,
.qr-scanner .box:before,
.qr-scanner .angle:after,
.qr-scanner .angle:before {
content: '';
display: block;
position: absolute;
width: 3vw;
height: 3vw;
}
.qr-scanner .box:after,
.qr-scanner .box:before {
top: 0;
border-top-color: #3aa5ff;
}
.qr-scanner .angle:after,
.qr-scanner .angle:before {
bottom: 0;
border-bottom-color: #3aa5ff;
}
.qr-scanner .box:before,
.qr-scanner .angle:before {
left: 0;
border-left-color: #3aa5ff;
}
.qr-scanner .box:after,
.qr-scanner .angle:after {
right: 0;
border-right-color: #3aa5ff;
}
@keyframes radar-beam {
0% {
transform: translateY(-100%);
}
100% {
transform: translateY(0);
}
}
</style>
Loading…
Cancel
Save