Commit 793b01fafe8c8d3a834c09f016400eadf85a9b76
1 parent
b5b0ca8a
下拉选择框增加筛选功能
Showing
6 changed files
with
602 additions
and
40 deletions
src/mobile/common/CommobileComponent.js
| 1 | 1 | /* eslint-disable */ |
| 2 | 2 | import { List, InputItem, Picker, TextareaItem, DatePicker, Checkbox, Toast } from 'antd-mobile-v2'; |
| 3 | +import SearchablePicker from '@/mobile/components/searchPicker' | |
| 3 | 4 | import moment from 'moment'; |
| 4 | 5 | import React, { Component } from 'react'; |
| 5 | 6 | import { debounce } from 'lodash'; |
| ... | ... | @@ -30,7 +31,8 @@ export default class CommonComponent extends Component { |
| 30 | 31 | dropDownData: [], |
| 31 | 32 | // eslint-disable-next-line react/no-unused-state |
| 32 | 33 | bReGetDropDown: false, |
| 33 | - bOpenKeyboard : props.bOpenKeyboard, | |
| 34 | + bOpenKeyboard: props.bOpenKeyboard, | |
| 35 | + pickerVisble: false | |
| 34 | 36 | |
| 35 | 37 | }; |
| 36 | 38 | this.firstDataIndex = props.showConfig.sName.substring(0, 1); /* 控件首字母(数据格式:字符串) */ |
| ... | ... | @@ -119,7 +121,7 @@ export default class CommonComponent extends Component { |
| 119 | 121 | dataValue, enabled, dropDownData, sFieldName, bNotEmpty, masterData, |
| 120 | 122 | } = this.state; |
| 121 | 123 | // console.log('bOpenKeyboard:', nextProps.bOpenKeyboard); |
| 122 | - if(nextProps.bOpenKeyboard !==undefined) { | |
| 124 | + if (nextProps.bOpenKeyboard !== undefined) { | |
| 123 | 125 | return true; |
| 124 | 126 | } |
| 125 | 127 | return nextProps.showConfig !== undefined && (dataValue !== nextState.dataValue || enabled !== nextState.enabled || |
| ... | ... | @@ -253,6 +255,7 @@ export default class CommonComponent extends Component { |
| 253 | 255 | |
| 254 | 256 | /** 处理下拉选择事件 */ |
| 255 | 257 | handleSelectOptionEvent = (newValue) => { |
| 258 | + console.log("🚀 ~ CommonComponent ~ newValue:", newValue) | |
| 256 | 259 | /* 下拉新增单独处理 */ |
| 257 | 260 | let value = newValue; |
| 258 | 261 | this.isDropdownFilter = true; |
| ... | ... | @@ -277,11 +280,11 @@ export default class CommonComponent extends Component { |
| 277 | 280 | const returnValue = {}; |
| 278 | 281 | /* 回带值赋值(sName:value) */ |
| 279 | 282 | returnValue[this.props.showConfig.sName] = |
| 280 | - // eslint-disable-next-line radix | |
| 281 | - this.firstDataIndex === 'i' ? commonUtils.isEmpty(value) ? undefined : parseInt(value) : | |
| 282 | - this.firstDataIndex === 'd' ? commonUtils.isEmpty(value) ? '' : this.floatNumberCheck(value) : | |
| 283 | - this.firstDataIndex === 't' ? commonUtils.isEmpty(value) ? null : value : | |
| 284 | - this.firstDataIndex === 'b' ? value.target.checked : value === null ? undefined : value; | |
| 283 | + // eslint-disable-next-line radix | |
| 284 | + this.firstDataIndex === 'i' ? commonUtils.isEmpty(value) ? undefined : parseInt(value) : | |
| 285 | + this.firstDataIndex === 'd' ? commonUtils.isEmpty(value) ? '' : this.floatNumberCheck(value) : | |
| 286 | + this.firstDataIndex === 't' ? commonUtils.isEmpty(value) ? null : value : | |
| 287 | + this.firstDataIndex === 'b' ? value.target.checked : value === null ? undefined : value; | |
| 285 | 288 | const { sAssignField } = this.props.showConfig; |
| 286 | 289 | const [changeData] = this.state.dropDownData.filter(item => (!commonUtils.isEmpty(item.sSlaveId) ? item.sSlaveId : item.sId) === value.toString()); |
| 287 | 290 | if (!commonUtils.isEmpty(sAssignField)) { |
| ... | ... | @@ -310,13 +313,13 @@ export default class CommonComponent extends Component { |
| 310 | 313 | }; |
| 311 | 314 | |
| 312 | 315 | handleFocus = () => { |
| 313 | - if(this.props.onFocus) { | |
| 316 | + if (this.props.onFocus) { | |
| 314 | 317 | this.props.onFocus(this.props.showConfig); |
| 315 | 318 | } |
| 316 | 319 | } |
| 317 | 320 | |
| 318 | 321 | handleBlur = () => { |
| 319 | - if(this.props.onBlur) { | |
| 322 | + if (this.props.onBlur) { | |
| 320 | 323 | this.props.onBlur(this.props.showConfig); |
| 321 | 324 | } |
| 322 | 325 | } |
| ... | ... | @@ -367,8 +370,8 @@ export default class CommonComponent extends Component { |
| 367 | 370 | }; |
| 368 | 371 | |
| 369 | 372 | cancelValue = () => { |
| 370 | - const bClear = this.props.showConfig.sName!=='sLocationId' && this.props.showConfig.sName!=='sLocationNo' && this.props.showConfig.sName!=='sLocationName'; | |
| 371 | - if(bClear) { | |
| 373 | + const bClear = this.props.showConfig.sName !== 'sLocationId' && this.props.showConfig.sName !== 'sLocationNo' && this.props.showConfig.sName !== 'sLocationName'; | |
| 374 | + if (bClear) { | |
| 372 | 375 | if (this.inputRef) this.inputRef.clearInput(); |
| 373 | 376 | } |
| 374 | 377 | } |
| ... | ... | @@ -387,8 +390,8 @@ export default class CommonComponent extends Component { |
| 387 | 390 | render() { |
| 388 | 391 | const { sDateFormat: sDateFormatOld, sFieldValidation, bNotEmpty, bOpenKeyboard } = this.props.showConfig; |
| 389 | 392 | let newValue = this.props.dataValue; |
| 390 | - if(commonUtils.isNotEmptyObject(sFieldValidation)) { | |
| 391 | - const [length1, length2] = commonUtils.isNotEmptyObject(sFieldValidation) ? sFieldValidation.split(',') :[]; | |
| 393 | + if (commonUtils.isNotEmptyObject(sFieldValidation)) { | |
| 394 | + const [length1, length2] = commonUtils.isNotEmptyObject(sFieldValidation) ? sFieldValidation.split(',') : []; | |
| 392 | 395 | if (length2 !== undefined) { |
| 393 | 396 | newValue = commonUtils.convertFixNum(this.props.dataValue, Number(length2)); |
| 394 | 397 | } |
| ... | ... | @@ -396,7 +399,7 @@ export default class CommonComponent extends Component { |
| 396 | 399 | let sTitle = this.props.showConfig.showName; |
| 397 | 400 | if (bNotEmpty) { /* 必填加星号 */ |
| 398 | 401 | sTitle = <div className='th-div' ><span className={styles.requireStyle}>*</span> {this.props.showConfig.showName}</div>; |
| 399 | - }else { | |
| 402 | + } else { | |
| 400 | 403 | sTitle = <div className='th-div' > {this.props.showConfig.showName}</div>; |
| 401 | 404 | } |
| 402 | 405 | const outFormItemProps = { |
| ... | ... | @@ -418,20 +421,32 @@ export default class CommonComponent extends Component { |
| 418 | 421 | outFormItemProps.onVisibleChange = (visible) => { |
| 419 | 422 | if (!visible) return; |
| 420 | 423 | Toast.loading('加载中 ....', 0); |
| 421 | - this.getDropDownData(this.props, false).finally( () => { | |
| 424 | + this.getDropDownData(this.props, false).finally(() => { | |
| 422 | 425 | Toast.hide(); |
| 423 | 426 | }); |
| 424 | 427 | } |
| 428 | + // input = ( | |
| 429 | + // <Picker data={this.getSelectOption()} cols={1} {...outFormItemProps} className="forss"> | |
| 430 | + // <List.Item arrow="horizontal"> | |
| 431 | + // {this.props.iconSettingShow ? | |
| 432 | + // // eslint-disable-next-line jsx-a11y/alt-text | |
| 433 | + // <img src={iconSetting} style={{ verticalAlign: 'sub', marginRight: '15px' }} alt="" /> : ''} | |
| 434 | + // {sTitle} | |
| 435 | + // </List.Item> | |
| 436 | + // </Picker> | |
| 437 | + // ); | |
| 438 | + | |
| 425 | 439 | input = ( |
| 426 | - <Picker data={this.getSelectOption()} cols={1} {...outFormItemProps} className="forss"> | |
| 427 | - <List.Item arrow="horizontal"> | |
| 428 | - {this.props.iconSettingShow ? | |
| 429 | - // eslint-disable-next-line jsx-a11y/alt-text | |
| 430 | - <img src={iconSetting} style={{ verticalAlign: 'sub', marginRight: '15px' }} alt="" /> : ''} | |
| 431 | - {sTitle} | |
| 432 | - </List.Item> | |
| 433 | - </Picker> | |
| 434 | - ); | |
| 440 | + <SearchablePicker | |
| 441 | + data={this.getSelectOption()} | |
| 442 | + cols={1} | |
| 443 | + sTitle={sTitle} | |
| 444 | + {...outFormItemProps} | |
| 445 | + className="forss" | |
| 446 | + iconSettingShow={this.props.iconSettingShow} | |
| 447 | + /> | |
| 448 | + | |
| 449 | + ) | |
| 435 | 450 | } else if (this.firstDataIndex === 's') { |
| 436 | 451 | if (this.props.textArea) { /* 大文本输入框 */ |
| 437 | 452 | input = (<TextareaItem title={this.props.showConfig.showName} {...outFormItemProps} autoHeight />); |
| ... | ... | @@ -439,7 +454,7 @@ export default class CommonComponent extends Component { |
| 439 | 454 | const pdaPro = { |
| 440 | 455 | disabled: !this.state.enabled, |
| 441 | 456 | placeholder: this.props.showConfig.placeholder || '请输入或扫码', |
| 442 | - onFocus:this.handleFocus, | |
| 457 | + onFocus: this.handleFocus, | |
| 443 | 458 | virtualkeyboardpolicy: 'manual', |
| 444 | 459 | inputmode: 'none', |
| 445 | 460 | }; | ... | ... |
src/mobile/common/CommobileListEvent.js
| ... | ... | @@ -9,7 +9,7 @@ import * as commonUtils from '../../utils/utils'; /* 通用方法 */ |
| 9 | 9 | import commonConfig from '../../utils/config'; |
| 10 | 10 | import * as commonFunc from '../../components/Common/commonFunc'; |
| 11 | 11 | import * as commonServices from '../../services/services'; |
| 12 | - | |
| 12 | +import instructSet from "@/components/Common/CommonInstructSet"; | |
| 13 | 13 | const alert = Modal.alert; |
| 14 | 14 | |
| 15 | 15 | export default (ChildComponent) => { |
| ... | ... | @@ -18,7 +18,13 @@ export default (ChildComponent) => { |
| 18 | 18 | super(props); |
| 19 | 19 | this.state = { |
| 20 | 20 | textAreaContent: '', |
| 21 | + cameraVisible: false, | |
| 22 | + videoStream: null, | |
| 23 | + cameraError: null, | |
| 24 | + autoCaptureTimer: null, | |
| 25 | + faceRecognizing: false, | |
| 21 | 26 | }; |
| 27 | + this.videoRef = React.createRef(); | |
| 22 | 28 | } |
| 23 | 29 | |
| 24 | 30 | async componentWillReceiveProps(nextProps) { |
| ... | ... | @@ -389,10 +395,423 @@ export default (ChildComponent) => { |
| 389 | 395 | this.handleBatchCancelExamine(); |
| 390 | 396 | } else if (name === 'BtnAdd') { |
| 391 | 397 | this.handleAdd(); |
| 398 | + } else if (name.includes('BtnScanFace')) { | |
| 399 | + console.log("🚀 ~ name:", name) | |
| 400 | + this.startCamera() | |
| 401 | + } | |
| 402 | + }; | |
| 403 | + // 调用扫脸 | |
| 404 | + startCamera = () => { | |
| 405 | + navigator.mediaDevices.getUserMedia({ | |
| 406 | + video: { | |
| 407 | + facingMode: 'user', | |
| 408 | + width: { ideal: 640 }, | |
| 409 | + height: { ideal: 480 }, | |
| 410 | + }, | |
| 411 | + }) | |
| 412 | + .then(stream => { | |
| 413 | + this.setState({ | |
| 414 | + cameraVisible: true, | |
| 415 | + videoStream: stream, | |
| 416 | + cameraError: null, | |
| 417 | + autoCaptureTimer: setTimeout(() => { | |
| 418 | + this.capturePhoto(); | |
| 419 | + }, 2000), | |
| 420 | + }, () => { | |
| 421 | + if (this.videoRef.current) { | |
| 422 | + this.videoRef.current.srcObject = stream; | |
| 423 | + this.videoRef.current.play(); | |
| 424 | + } | |
| 425 | + }); | |
| 426 | + }) | |
| 427 | + .catch(error => { | |
| 428 | + console.error('无法访问摄像头:', error); | |
| 429 | + this.setState({ | |
| 430 | + cameraError: '无法访问摄像头,请检查权限设置', | |
| 431 | + cameraVisible: false, | |
| 432 | + }); | |
| 433 | + Toast.fail('无法访问摄像头,请检查权限'); | |
| 434 | + }); | |
| 435 | + }; | |
| 436 | + capturePhoto = () => { | |
| 437 | + if (!this.videoRef.current || !this.state.cameraVisible) return; | |
| 438 | + | |
| 439 | + const video = this.videoRef.current; | |
| 440 | + const canvas = document.createElement('canvas'); | |
| 441 | + canvas.width = video.videoWidth; | |
| 442 | + canvas.height = video.videoHeight; | |
| 443 | + const ctx = canvas.getContext('2d'); | |
| 444 | + ctx.drawImage(video, 0, 0, canvas.width, canvas.height); | |
| 445 | + | |
| 446 | + const base64 = canvas.toDataURL('image/jpeg', 0.85).split(',')[1]; | |
| 447 | + // 不再立即 closeCamera(),而是进入识别状态 | |
| 448 | + this.setState({ faceRecognizing: true }); | |
| 449 | + this.processFaceRecognition(base64); | |
| 450 | + }; | |
| 451 | + processFaceRecognition = (base64) => { | |
| 452 | + const url = `${commonConfig.face_host}/face/faceSearch`; | |
| 453 | + commonServices.postValueService(null, [{ | |
| 454 | + image: base64, | |
| 455 | + image_type: "BASE64", | |
| 456 | + face_field: "age", | |
| 457 | + option: "COMMON" | |
| 458 | + }], url) | |
| 459 | + .then(({ data: dataReturn }) => { | |
| 460 | + console.log("🚀 ~ dataReturn:", dataReturn) | |
| 461 | + if (dataReturn?.code === 1 && dataReturn.dataset.rows.length > 0) { | |
| 462 | + const value = { | |
| 463 | + sEmployeeNo: dataReturn.dataset.rows[0].sEmployeeNo, | |
| 464 | + sParentId: dataReturn.dataset.rows[0].sBrandsId, | |
| 465 | + sId: dataReturn.dataset.rows[0].sSubsidiaryId | |
| 466 | + }; | |
| 467 | + this.handleLogin(value, dataReturn.dataset.rows[0]); | |
| 468 | + } | |
| 469 | + }) | |
| 470 | + .finally(() => { | |
| 471 | + this.closeCamera(); | |
| 472 | + this.setState({ | |
| 473 | + cameraVisible: false, | |
| 474 | + faceRecognizing: false | |
| 475 | + }); | |
| 476 | + }); | |
| 477 | + }; | |
| 478 | + closeCamera = () => { | |
| 479 | + if (this.state.videoStream) { | |
| 480 | + this.state.videoStream.getTracks().forEach(track => track.stop()); | |
| 481 | + this.setState({ videoStream: null }); | |
| 482 | + } | |
| 483 | + if (this.videoRef.current) { | |
| 484 | + this.videoRef.current.srcObject = null; | |
| 485 | + } | |
| 486 | + if (this.state.autoCaptureTimer) { | |
| 487 | + clearTimeout(this.state.autoCaptureTimer); | |
| 392 | 488 | } |
| 393 | 489 | }; |
| 490 | + handleLogin = (result, dataReturn) => { | |
| 491 | + const { faceData = [] } = result; | |
| 492 | + const { slaveConfig, masterData } = this.props; | |
| 493 | + const btnConfig = slaveConfig.gdsconfigformslave?.find(item => item.sControlName.toLowerCase().includes('btnscanface')); | |
| 494 | + const { sButtonParam: sButtonParamStr } = btnConfig; | |
| 495 | + const sButtonParam = commonUtils.convertStrToObj(sButtonParamStr); | |
| 496 | + const { addData } = sButtonParam; | |
| 497 | + console.log(this.props, btnConfig, '=====this.props'); | |
| 498 | + this.handleProcedureCall( | |
| 499 | + { | |
| 500 | + btnConfig, | |
| 501 | + faceData: result, | |
| 502 | + ...dataReturn, | |
| 503 | + onSuccess: (_, dataset) => { | |
| 504 | + console.log("🚀 ~ dataset:", dataset) | |
| 505 | + const { proData = [] } = dataset.rows[0].dataSet; | |
| 506 | + const { [`${addData}Data`]: tableData = [], [`${addData}Config`]: config = {} } = this.props; | |
| 507 | + const copyConfig = config?.gdsconfigformslave?.find(item => item.sControlName.toLowerCase().includes('btnscanface')) | |
| 508 | + proData.forEach(item => { | |
| 509 | + const data = commonFunc.getAssignFieldValue(copyConfig?.sAssignField, item) | |
| 510 | + const index = tableData.findIndex(x => x.sEmployeeNo === item.sEmployeeNo) | |
| 511 | + if (index !== -1) { | |
| 512 | + Toast.fail('人员重复,请重新添加', 5); | |
| 513 | + } else { | |
| 514 | + tableData.push({ | |
| 515 | + ...item, | |
| 516 | + ...data, | |
| 517 | + sId: commonUtils.createSid(), | |
| 518 | + handleType: "add", | |
| 519 | + sParentId: props.masterData.sId, | |
| 520 | + slaveId: props?.slaveData ? props?.slaveData[0].sId : '' | |
| 521 | + }) | |
| 522 | + } | |
| 523 | + | |
| 524 | + }); | |
| 525 | + console.log(tableData, 'tableData'); | |
| 526 | + | |
| 527 | + // props.onSaveState({ | |
| 528 | + // [`${addData}Data`]: tableData, | |
| 529 | + // mesRefresh: true | |
| 530 | + // }); | |
| 531 | + }, | |
| 532 | + onConfirm: () => { }, | |
| 533 | + onError: () => { } | |
| 534 | + | |
| 535 | + }) | |
| 536 | + // instructSet({ | |
| 537 | + // btnConfig, | |
| 538 | + // faceData: result, | |
| 539 | + // onSuccess: (_, dataset) => { | |
| 540 | + // const { proData = [] } = dataset.rows[0].dataSet; | |
| 541 | + // const { [`${addData}Data`]: tableData = [], [`${addData}Config`]: config = {} } = this.props; | |
| 542 | + // const copyConfig = config?.gdsconfigformslave?.find(item => item.sControlName.toLowerCase().includes('btnscanface')) | |
| 543 | + // proData.forEach(item => { | |
| 544 | + // const data = commonFunc.getAssignFieldValue(copyConfig?.sAssignField, item) | |
| 545 | + // const index = tableData.findIndex(x => x.sEmployeeNo === item.sEmployeeNo) | |
| 546 | + // if (index !== -1) { | |
| 547 | + // message.error('人员重复,请重新添加', 5) | |
| 548 | + // } else { | |
| 549 | + // tableData.push({ | |
| 550 | + // ...item, | |
| 551 | + // ...data, | |
| 552 | + // sId: commonUtils.createSid(), | |
| 553 | + // handleType: "add", | |
| 554 | + // sParentId: props.masterData.sId, | |
| 555 | + // slaveId: props?.slaveData ? props?.slaveData[0].sId : '' | |
| 556 | + // }) | |
| 557 | + // } | |
| 558 | + | |
| 559 | + // }); | |
| 560 | + | |
| 561 | + // // props.onSaveState({ | |
| 562 | + // // [`${addData}Data`]: tableData, | |
| 563 | + // // mesRefresh: true | |
| 564 | + // // }); | |
| 565 | + // }, | |
| 566 | + // onConfirm: () => { }, | |
| 567 | + // onError: () => { } | |
| 568 | + // }); | |
| 569 | + } | |
| 570 | + handleProcedureCall = async (params, iFlag) => { | |
| 571 | + const { | |
| 572 | + btnConfig = {}, // 按钮配置 | |
| 573 | + sValue = {}, // 额外参数 | |
| 574 | + tableData: tableDataSelected, // 传过来的数据 | |
| 575 | + faceData = {}, // 人脸数据 | |
| 576 | + onSuccess, | |
| 577 | + onConfirm, | |
| 578 | + onError, | |
| 579 | + nextProps, | |
| 580 | + sUserId, | |
| 581 | + sParentId, | |
| 582 | + sEmployeeNo, | |
| 583 | + | |
| 584 | + } = params; | |
| 585 | + | |
| 586 | + const currentState = this.props || this.state; | |
| 587 | + const { slaveSelectedRowKeys = [] } = this.props; | |
| 588 | + | |
| 589 | + // 加入mes通用参数 | |
| 590 | + const { app } = this.props; | |
| 591 | + const { tableNameCompareJson = {} } = currentState; | |
| 592 | + const { | |
| 593 | + sMachineNameSId: sMachineGuid, | |
| 594 | + sTeamNameSId: sTeamGuid, | |
| 595 | + sShift | |
| 596 | + } = app; | |
| 597 | + const commonData = { | |
| 598 | + sMachineGuid, | |
| 599 | + sTeamGuid, | |
| 600 | + sShift | |
| 601 | + }; | |
| 602 | + | |
| 603 | + const { sButtonParam } = btnConfig; | |
| 604 | + console.log("🚀 ~ sButtonParam:", sButtonParam) | |
| 605 | + const btn = commonUtils.convertStrToObj(sButtonParam, {}); | |
| 606 | + if (commonUtils.isEmptyObject(btn)) { | |
| 607 | + onSuccess && onSuccess(false); | |
| 608 | + return; | |
| 609 | + } | |
| 610 | + const { sproName: sProName, inMap, sTableName, staticData = {} } = btn; | |
| 611 | + console.log("🚀 ~ inMap:", inMap, sButtonParam) | |
| 612 | + | |
| 613 | + const inParams = []; | |
| 614 | + const arr = {}; | |
| 615 | + | |
| 616 | + if (inMap) { | |
| 617 | + const inlist = inMap.split(","); | |
| 618 | + inlist.forEach(item => { | |
| 619 | + const [ | |
| 620 | + tableNameOld, | |
| 621 | + sFieldName, | |
| 622 | + sFieldNameNew = sFieldName | |
| 623 | + ] = item.split("."); | |
| 624 | + | |
| 625 | + const tableName = tableNameCompareJson[tableNameOld] || tableNameOld; | |
| 626 | + if (!tableName) return; | |
| 627 | + if (!arr[tableName]) { | |
| 628 | + arr[tableName] = []; | |
| 629 | + } | |
| 630 | + arr[tableName].push({ sFieldName, sFieldNameNew }); | |
| 631 | + }); | |
| 632 | + } | |
| 394 | 633 | |
| 395 | - /** 点击新增按钮 */ | |
| 634 | + // 拼接params参数 | |
| 635 | + Object.keys(arr).forEach(tableName => { | |
| 636 | + const addState = { key: tableName }; | |
| 637 | + if (tableName.includes("master")) { | |
| 638 | + const { [`${tableName}Data`]: tableData = {} } = currentState; | |
| 639 | + const allValue = []; | |
| 640 | + const value = { ...commonData, ...staticData, ...faceData }; | |
| 641 | + arr[tableName].forEach(({ sFieldName, sFieldNameNew }) => { | |
| 642 | + value[`${sFieldNameNew}`] = tableData[`${sFieldName}`]; | |
| 643 | + }); | |
| 644 | + allValue.push(value); | |
| 645 | + addState.value = allValue; | |
| 646 | + inParams.push(addState); | |
| 647 | + } else { | |
| 648 | + let filterData = tableDataSelected; | |
| 649 | + if (commonUtils.isEmptyArr(filterData)) { | |
| 650 | + if ( | |
| 651 | + [ | |
| 652 | + "userinfo", | |
| 653 | + "currentSelectedMachineTask", | |
| 654 | + "currentStartWorkMachineTask", | |
| 655 | + "currentWorkOrderInfo" | |
| 656 | + ].includes(tableName) | |
| 657 | + ) { | |
| 658 | + // 如果是全局变量 | |
| 659 | + const globalData = commonUtils.getAppData("globalData"); | |
| 660 | + const tempProps = { | |
| 661 | + userinfo: app.userinfo, | |
| 662 | + currentSelectedMachineTask: globalData.currentSelectedMachineTask, | |
| 663 | + currentStartWorkMachineTask: | |
| 664 | + globalData.currentStartWorkMachineTask, | |
| 665 | + currentWorkOrderInfo: globalData.currentWorkOrderInfo | |
| 666 | + }; | |
| 667 | + filterData = [tempProps[tableName]]; | |
| 668 | + } else { | |
| 669 | + // 如果不是全局变量 | |
| 670 | + const { | |
| 671 | + [`${tableName}Data`]: tableData = [], | |
| 672 | + [`${tableName}SelectedRowKeys`]: selectedRowKeys = [] | |
| 673 | + } = currentState; | |
| 674 | + if (selectedRowKeys.length === 0 && nextProps) { | |
| 675 | + filterData = tableData; | |
| 676 | + } else { | |
| 677 | + const iIndex = arr[tableName].findIndex( | |
| 678 | + item => item.sFieldNameNew === "*" | |
| 679 | + ); | |
| 680 | + if (iIndex > -1) { | |
| 681 | + filterData = tableData; | |
| 682 | + } else { | |
| 683 | + filterData = tableData.filter( | |
| 684 | + item => | |
| 685 | + true && | |
| 686 | + (selectedRowKeys.includes(item.sId) || | |
| 687 | + selectedRowKeys.includes(item.sSlaveId)) | |
| 688 | + ); | |
| 689 | + } | |
| 690 | + } | |
| 691 | + } | |
| 692 | + if (sProName === "Sp_Mes_BindMaterials") { | |
| 693 | + filterData = filterData.filter(item => item.sAdded == "1"); | |
| 694 | + } | |
| 695 | + } | |
| 696 | + const addState = { key: tableName }; | |
| 697 | + const allValue = []; | |
| 698 | + filterData.forEach(currData => { | |
| 699 | + let value = { ...commonData, ...staticData, ...faceData }; | |
| 700 | + arr[tableName].forEach(({ sFieldName, sFieldNameNew }) => { | |
| 701 | + if (sFieldNameNew === "*") { | |
| 702 | + value = { ...value, ...currData }; | |
| 703 | + delete value.sColumnConfig; | |
| 704 | + } else { | |
| 705 | + value[`${sFieldNameNew}`] = currData[`${sFieldName}`]; | |
| 706 | + } | |
| 707 | + }); | |
| 708 | + allValue.push(value); | |
| 709 | + }); | |
| 710 | + addState.value = allValue; | |
| 711 | + inParams.push(addState); | |
| 712 | + } | |
| 713 | + }); | |
| 714 | + | |
| 715 | + if ( | |
| 716 | + commonUtils.isNotEmptyStr(sTableName) && | |
| 717 | + commonUtils.isNotEmptyArr(inParams) | |
| 718 | + ) { | |
| 719 | + inParams.forEach(item => { | |
| 720 | + if (commonUtils.isNotEmptyArr(item.value)) { | |
| 721 | + item.value.forEach(item1 => { | |
| 722 | + item1.sTableName = sTableName; | |
| 723 | + }); | |
| 724 | + } | |
| 725 | + }); | |
| 726 | + } | |
| 727 | + | |
| 728 | + const { token } = app; | |
| 729 | + const { sModelsId } = this.props; | |
| 730 | + | |
| 731 | + const { sControlName: sBtnName } = btnConfig; | |
| 732 | + | |
| 733 | + if (iFlag !== undefined) { | |
| 734 | + inParams[0]?.value?.forEach(item => { | |
| 735 | + item.iFlag = iFlag; | |
| 736 | + }); | |
| 737 | + } | |
| 738 | + | |
| 739 | + const proInParam = JSON.stringify({ | |
| 740 | + params: inParams.map(item => ({ | |
| 741 | + ...item, | |
| 742 | + sUserName: app.userinfo.sUserName, | |
| 743 | + value: [{ | |
| 744 | + sUserId, | |
| 745 | + sParentId, | |
| 746 | + sEmployeeNo, | |
| 747 | + sId: slaveSelectedRowKeys[0], | |
| 748 | + "sOperate": "start", | |
| 749 | + ...commonData, | |
| 750 | + | |
| 751 | + }] | |
| 752 | + })), | |
| 753 | + changeValue: sValue, | |
| 754 | + sButtonParam: btn | |
| 755 | + }); | |
| 756 | + const value = { sProName, sProInParam: proInParam, sBtnName }; | |
| 757 | + if (iFlag !== undefined) { | |
| 758 | + value.iFlag = iFlag; | |
| 759 | + } | |
| 760 | + | |
| 761 | + console.log("=====存储过程参数", { | |
| 762 | + params: inParams, | |
| 763 | + changeValue: sValue, | |
| 764 | + sButtonParam: btn | |
| 765 | + }); | |
| 766 | + console.log(value, 'value '); | |
| 767 | + const url = `${commonConfig.server_host | |
| 768 | + }procedureCall/doGenericProcedureCall?sModelsId=${sModelsId}`; | |
| 769 | + const returnData = (await commonServices.postValueService( | |
| 770 | + token, | |
| 771 | + value, | |
| 772 | + url | |
| 773 | + )).data; | |
| 774 | + const { code, msg, dataset } = returnData; | |
| 775 | + if (code === 1) { | |
| 776 | + Toast.info(msg); | |
| 777 | + onSuccess && onSuccess(true, dataset); | |
| 778 | + } else if (code === -7) { | |
| 779 | + // Modal.confirm({ | |
| 780 | + // title: FriendlyReminder, | |
| 781 | + // content: <div>{this.handleGetMsg(msg)}</div>, | |
| 782 | + // onOk() { | |
| 783 | + // this.handleProcedureCall(params, 1); | |
| 784 | + // }, | |
| 785 | + // onCancel() { | |
| 786 | + // onError && onError(); | |
| 787 | + // } | |
| 788 | + // }); | |
| 789 | + } else if (code === -8) { | |
| 790 | + // Modal.info({ | |
| 791 | + // title: FriendlyReminder, | |
| 792 | + // content: <div>{this.handleGetMsg(msg)}</div>, | |
| 793 | + // onOk() { | |
| 794 | + // onConfirm && onConfirm(); | |
| 795 | + // }, | |
| 796 | + // onCancel() { | |
| 797 | + // onError && onError(); | |
| 798 | + // } | |
| 799 | + // }); | |
| 800 | + } else { | |
| 801 | + | |
| 802 | + } | |
| 803 | + }; | |
| 804 | + handleGetMsg = str => { | |
| 805 | + const msgArr = commonUtils.isNotEmptyObject(str) ? str.split("xpm") : ""; | |
| 806 | + const divStr = []; | |
| 807 | + if (commonUtils.isNotEmptyArr(msgArr)) { | |
| 808 | + for (let i = 0; i < msgArr.length; i++) { | |
| 809 | + divStr.push(<p>{msgArr[i]}</p>); | |
| 810 | + } | |
| 811 | + } | |
| 812 | + return divStr; | |
| 813 | + }; | |
| 814 | + /** 点击新增按钮 */ | |
| 396 | 815 | handleAdd = () => { |
| 397 | 816 | const { |
| 398 | 817 | slaveConfig, dispatch, slaveFilterCondition, slavePagination, slaveOrderBy, formRoute, |
| ... | ... | @@ -612,20 +1031,37 @@ export default (ChildComponent) => { |
| 612 | 1031 | slaveSelectedRowKeys, |
| 613 | 1032 | }); |
| 614 | 1033 | }; |
| 1034 | + | |
| 615 | 1035 | render() { |
| 1036 | + const { loginCompany, companys, cameraVisible, cameraError } = this.state; | |
| 616 | 1037 | return ( |
| 617 | - <ChildComponent | |
| 618 | - {...this.props} | |
| 619 | - {...this.state} | |
| 620 | - onReturnForm={this.handleForm} | |
| 621 | - onGetData={this.handleGetData} | |
| 622 | - onCopyToClick={this.handleCopyToClick} | |
| 623 | - onPrintView={this.handlePrintView} | |
| 624 | - onCheckboxChange={this.handleCheckboxChange} | |
| 625 | - onButtonClick={this.handleButtonClick} | |
| 626 | - onDoubleClick={this.handleDoubleClick} | |
| 627 | - onSelectAllClick={this.handleSelectAllClick} | |
| 628 | - /> | |
| 1038 | + <div> | |
| 1039 | + {cameraVisible && ( | |
| 1040 | + <div className='cameraOverlay' style={{ width: '100%', height: '100vh', position: 'fixed', top: 0, left: 0, zIndex: 1000, backgroundColor: '#000' }}> | |
| 1041 | + <video | |
| 1042 | + ref={this.videoRef} | |
| 1043 | + autoPlay | |
| 1044 | + playsInline | |
| 1045 | + style={{ width: '100%', height: '100vh', objectFit: 'cover' }} | |
| 1046 | + /> | |
| 1047 | + {cameraError && ( | |
| 1048 | + <div className={styles.cameraError}>{cameraError}</div> | |
| 1049 | + )} | |
| 1050 | + </div> | |
| 1051 | + )} | |
| 1052 | + <ChildComponent | |
| 1053 | + {...this.props} | |
| 1054 | + {...this.state} | |
| 1055 | + onReturnForm={this.handleForm} | |
| 1056 | + onGetData={this.handleGetData} | |
| 1057 | + onCopyToClick={this.handleCopyToClick} | |
| 1058 | + onPrintView={this.handlePrintView} | |
| 1059 | + onCheckboxChange={this.handleCheckboxChange} | |
| 1060 | + onButtonClick={this.handleButtonClick} | |
| 1061 | + onDoubleClick={this.handleDoubleClick} | |
| 1062 | + onSelectAllClick={this.handleSelectAllClick} | |
| 1063 | + /> | |
| 1064 | + </div> | |
| 629 | 1065 | ); |
| 630 | 1066 | } |
| 631 | 1067 | }; | ... | ... |
src/mobile/components/searchPicker.jsx
0 → 100644
| 1 | +import { Popup, SearchBar, PickerView, Button } from 'antd-mobile'; | |
| 2 | +import { List,} from 'antd-mobile-v2'; | |
| 3 | +import { useState, useMemo } from 'react'; | |
| 4 | +import styles from "./selectInput.less"; | |
| 5 | +export default function SearchablePicker(props) { | |
| 6 | + console.log("🚀 ~ SearchablePicker ~ props:", props) | |
| 7 | + const { onConfirm, initialValue, data, sTitle, onChange, value:newValue } = props; | |
| 8 | + | |
| 9 | + const [searchValue, setSearchValue] = useState(''); | |
| 10 | + const [visible, setVisible] = useState(false) | |
| 11 | + | |
| 12 | + // 安全初始化 values | |
| 13 | + const initialVal = useMemo(() => { | |
| 14 | + if (!initialValue || !Array.isArray(data)) return []; | |
| 15 | + const exists = data.some(item => item?.value === initialValue); | |
| 16 | + return exists ? [initialValue] : []; | |
| 17 | + }, [initialValue, data]); | |
| 18 | + | |
| 19 | + const [values, setValues] = useState(initialVal); | |
| 20 | + | |
| 21 | + // 安全过滤选项 | |
| 22 | + const filteredOptions = useMemo(() => { | |
| 23 | + const options = Array.isArray(data) ? data : []; | |
| 24 | + | |
| 25 | + if (!searchValue.trim()) { | |
| 26 | + return options; | |
| 27 | + } | |
| 28 | + | |
| 29 | + return options.filter(item => | |
| 30 | + item && | |
| 31 | + typeof item.label === 'string' && | |
| 32 | + item.label.toLowerCase().includes(searchValue.toLowerCase()) | |
| 33 | + ); | |
| 34 | + }, [searchValue, data]); // ✅ 必须包含 data | |
| 35 | + const label = filteredOptions?.find(x=>x.value === newValue[0])?.label || '' | |
| 36 | + const handleConfirm = () => { | |
| 37 | + onChange(values); | |
| 38 | + setVisible(false); | |
| 39 | + }; | |
| 40 | + | |
| 41 | + const handleCancel = () => { | |
| 42 | + setVisible(false); | |
| 43 | + }; | |
| 44 | + | |
| 45 | + const changeOption = (val) => { | |
| 46 | + setValues(val); | |
| 47 | + }; | |
| 48 | + | |
| 49 | + return ( | |
| 50 | + <div> | |
| 51 | + <List.Item arrow="horizontal" className={styles.searchPickerList} onClick={() => { | |
| 52 | + setVisible(true) | |
| 53 | + }} extra={label}> | |
| 54 | + {props.iconSettingShow ? | |
| 55 | + // eslint-disable-next-line jsx-a11y/alt-text | |
| 56 | + <img src={iconSetting} style={{ verticalAlign: 'sub', marginRight: '15px' }} alt="" /> : ''} | |
| 57 | + {sTitle} | |
| 58 | + </List.Item> | |
| 59 | + <Popup | |
| 60 | + visible={visible} | |
| 61 | + onMaskClick={handleCancel} | |
| 62 | + onClose={handleCancel} | |
| 63 | + bodyStyle={{ height: '50vh' }} | |
| 64 | + > | |
| 65 | + <div style={{ display: 'flex', justifyContent: 'space-between', padding: '0 1.5rem', marginTop: '1rem' }}> | |
| 66 | + <Button onClick={handleCancel} color="primary" fill="none"> | |
| 67 | + 取消 | |
| 68 | + </Button> | |
| 69 | + <Button onClick={handleConfirm} color="primary" fill="none"> | |
| 70 | + 确认 | |
| 71 | + </Button> | |
| 72 | + </div> | |
| 73 | + | |
| 74 | + <div style={{ padding: '0 1.5rem', marginTop: '1rem' }}> | |
| 75 | + <SearchBar | |
| 76 | + placeholder="请输入内容" | |
| 77 | + value={searchValue} | |
| 78 | + onChange={setSearchValue} | |
| 79 | + /> | |
| 80 | + </div> | |
| 81 | + | |
| 82 | + <PickerView | |
| 83 | + columns={[filteredOptions]} | |
| 84 | + value={values} | |
| 85 | + onChange={changeOption} | |
| 86 | + style={{ '--height': '200px', '--item-height': '2.8rem' }} | |
| 87 | + /> | |
| 88 | + </Popup> | |
| 89 | + </div> | |
| 90 | + | |
| 91 | + ); | |
| 92 | +} | |
| 0 | 93 | \ No newline at end of file | ... | ... |
src/mobile/components/selectInput.css
src/mobile/components/selectInput.less
| ... | ... | @@ -23,4 +23,13 @@ |
| 23 | 23 | align-items: center; |
| 24 | 24 | justify-content: space-between; |
| 25 | 25 | margin: 0.2rem; |
| 26 | +} | |
| 27 | +.searchPickerList{ | |
| 28 | + :global .am-list-line{ | |
| 29 | + justify-content: space-between; | |
| 30 | + // .am-list-extra{ | |
| 31 | + // text-align: right !important; | |
| 32 | + // } | |
| 33 | + } | |
| 34 | + | |
| 26 | 35 | } |
| 27 | 36 | \ No newline at end of file | ... | ... |
src/utils/utils.js
| ... | ... | @@ -29,7 +29,14 @@ export function getCursortPosition(obj) { |
| 29 | 29 | } |
| 30 | 30 | return cursorIndex; |
| 31 | 31 | } |
| 32 | - | |
| 32 | +export function getAppData(name, key) { | |
| 33 | + const appData = convertStrToObj(localStorage.getItem(`${config.prefix}${name}`)); | |
| 34 | + if (key === undefined) { | |
| 35 | + return appData; | |
| 36 | + } else { | |
| 37 | + return appData[key]; | |
| 38 | + } | |
| 39 | +} | |
| 33 | 40 | /* 为输入框聚焦 */ |
| 34 | 41 | export function focus(id, e, currentRef = document) { |
| 35 | 42 | const element = currentRef.querySelector(`#${id}`); | ... | ... |