vue+element 实现input批量查询条件

 有时候工作需要某个字段实现批量查询,但是EXCEL又比较麻烦,可以使用动态批量查询

 下面是我亲测可用的批量查询界面:

组件实现了字段校验,可使用空格、回车、分号、逗号、excel拷贝、进行输入下一个的能力

大家可以根据自己实际情况调整组件

外部引用批量查询组件:

<CompVin v-model="queryParams.vin" ref="vinRef" />

批量查询组件:

<template>
  <div class="component-vin-input" label-position="top">
    <el-form-item label="VIN">
    <template #label>
        <span>VIN码</span>
      </template>
    <div class="vin-input-wrapper">
      <div v-for="(vin, index) in vinGroup" :key="index" :class="vin.result ? '' : 'input-error'" class="vin-edit">
        <el-input v-model="vin.vin" maxlength="17" @input="value => handleVinItemChange(value, index)"
          @blur="validate([], index)" />
        <div class="error-tip">{{ vin.message }}</div>
      </div>
      <el-input v-model="vinInput" class="vin-input" placeholder="请输入或粘贴VIN码" @input="handleVinInput"
        @blur="handleVinInputBlur" @keyup.enter.native="handleVinInputBlur" />
    </div>
    <div class="vin-tip">每个VIN码输入完成后,以分号(;)结束</div>
    </el-form-item>
  </div>
</template>

<script>
export default {
  name: 'CompVin',
  props: {
    value: {
      type: Array,
      default: () => ([])
    }
  },
  data() {
    return {
      vinGroup: [],
      vinInput: '',
      vinList: []
    }
  },
  mounted() {
    this.value.forEach(vin => {
      this.vinGroup.push({
        result: true,
        vin,
        message: ''
      })
    })
  },
  methods: {
    /**
     * 清空
     */
    clearInput() {
      this.vinGroup = []
      this.vinInput = ''
      this.vinList = []
    },
    /**
     * 更新vin的页面显示
     * @param vinList vin的列表
     */
    updateVinGroup(vinList) {
      // 先清空vin
      this.vinGroup = []
      // 遍历列表数据
      vinList.forEach(vin => {
        this.vinGroup.push({
          result: true,
          vin,
          message: ''
        })
      })
    },

    /**
     * vin改变的方法,将其格式化成数组
     */
    handleVinInput() {
      // 如果当前没有输入
      if (!this.vinInput) {
        return
      }
      // 替换中文的分号
      const replaceChinessSemicolon = this.vinInput.replace(/[;,,\s\r\n]/g, ';')
      // 按逗号分割
      const vinList = replaceChinessSemicolon.split(';')
      // 取出最后一个当成输入项目
      this.vinInput = vinList.pop()
      // 重新赋值vin的集合
      this.vinList = [
        ...(this.vinList || []),
        ...vinList.filter(vin => !!vin)
      ]
      // 先清空之前的数据
      this.vinGroup = [
        ...this.vinGroup,
        ...vinList.filter(vin => !!vin).map(vin => ({
          result: vin.length === 17,
          vin,
          message: vin.length === 17 ? '' : '请输入合法的vin号'
        }))
      ]
      // 双向绑定vinList
      this.$emit('input', this.vinList)
    },

    /**
     * vin输入框失去焦点的方法
     */
    handleVinInputBlur() {
      // 给vin加上;
      this.vinInput = this.vinInput + ';'
      // 将当前输入的vin初始化成需要校验的参数
      this.handleVinInput()
    },

    /**
     * vin输入的改变方法
     */
    handleVinItemChange(value, index) {
      // 如果当前没有输入值
      if (!value) {
        this.vinGroup.splice(index, 1)
      } else {
        // 替换中文的分号
        const replaceChinessSemicolon = value.replace(/[;,,\s\r\n]/g, ';')
        // 按逗号分割
        const vinList = replaceChinessSemicolon.split(';').filter(vin => !!vin)
        // 如果当前长度大于1个,说明输入了;
        if (vinList.length >= 1) {
          // 将当前输入的数据插到原来的对象中
          vinList.forEach((vin, vIndex) => {
            this.vinGroup.splice(index + vIndex, vIndex === 0 ? 1 : 0, {
              result: vin.length === 17,
              vin,
              message: vin.length === 17 ? '' : '请输入合法的vin号'
            })
          })
        }
      }
      // 重新赋值
      this.vinList = this.vinGroup.map(vin => vin.vin)
      // 双向绑定vinList
      this.$emit('input', this.vinList)
    },

    /**
     * 校验方法
     * @param results 需要回显的校验结果
     * @param index 当前需要校验的项目
     */
    validate(results = [], index = -1) {
      // 当前是否是错误
      let isError = true
      // 当前vin的集合
      const vinList = []
      // 写入错误信息
      this.vinGroup.forEach((group, gIndex) => {
        // 如果当前传入了需要校验的项目,则直接校验,如果没传,则全量校验
        if (index === -1 || gIndex === index) {
          // 如果当前vin输入的不合法
          if (group.vin.length !== 17) {
            isError = false
            group.result = false
            group.message = '请输入合法的vin号'
          } else {
            group.result = true
            group.message = ''
          }
          // 现在开始校验输入的结果
          results.forEach(result => {
            if (group.vin === result.vin) {
              group.result = result.checkResult
              group.message = result.errorMsg
              isError = isError && result.checkResult
            }
          })
          vinList.push(group.vin)
        }
      })
      // 如果校验有错误
      if (!isError) {
        throw new Error('请输入正确的VIN号')
      }
      return vinList
    }
  }
}
</script>

<style lang="scss">
.component-vin-input {
  .el-textarea {
    width: 836px;
    height: 100px;

    .el-textarea__inner {
      padding: 12px;
    }
  }

  .vin-input-wrapper {
    border: 1px solid #DCDFE6;
    border-radius: 4px;
    width: 836px;
    min-height: 100px;

    .vin-edit {
      display: inline-block;
      width: 199px;
      margin-left: 8px;
      margin-top: 8px;

      .el-input {
        width: 100%;
        height: 36px;

        .el-input__inner {
          background-color: #F7F8FA;
          border-color: #ffffff;
          box-shadow: none;
          color: #212026;
          font-size: 14px;
          font-weight: 400;
          padding: 0 10px;
        }
      }

      .error-tip {
        display: none;
        color: #FF4D4F;
        font-weight: 400;
        font-size: 12px;
        line-height: 18px;
        height: 18px;
        margin-top: 2px;
        position: absolute;
      }

      &.input-error {
        margin-bottom: 20px;

        .el-input {
          .el-input__inner {
            border-color: #FF4D4F;
          }
        }

        .error-tip {
          display: block;
        }
      }
    }

    .vin-input {
      display: inline-block;
      width: 199px;
      margin-left: 8px;
      margin-top: 8px;

      .el-input__inner {
        background-color: #FFFFFF;
        border-color: #ffffff;
        box-shadow: none;
        color: #212026;
        font-size: 14px;
        font-weight: 400;
        padding: 0 10px;
      }
    }
  }

  .vin-tip {
    color: rgba(132, 133, 138, 0.7);
    font-size: 12px;
    font-weight: 400;
    line-height: 18px;
    height: 18px;
    margin-top: 10px;
  }
}
</style>

<think>好的,用户需要实现根据库存物品的ID和Code生成条形码,并建立接口,同时用VueElement UI做前端,还要支持扫描识别。首先,我得考虑如何生成条形码。Java后端通常会用库来生成,比如ZXing。然后,接口部分需要接收id和code参数,生成条形码图片返回。前端部分用Vue,通过axios调用接口,显示图片。Element UI的组件可以用来布局和上传扫描的图片。 生成条形码的话,ZXing比较常用,需要添加依赖。后端接口用SpringBoot,接受GET或POST请求,生成条形码图片,可能需要将id和code组合成一个字符串,比如用分隔符连接。生成的图片以流的形式返回,设置正确的Content-Type。前端部分,需要有一个表单输入id和code,提交后调用接口获取图片URL并显示。同时,可能需要一个上传组件,让用户上传扫描到的条形码图片,然后解析出id和code。解析可以用前端的JS库,比如jsqr或者qrcode-reader,不过条形码可能需要后端解析,或者找合适的前端库。 测试的时候要注意编码格式,确保生成的条形码能被扫描器正确识别。可能的问题包括参数传递、图片生成格式、前端显示和解析的正确性。此外,需要考虑接口的安全性和参数校验,比如防止非法参数导致错误。现在要写代码的话,后端用Spring Boot的RestController,生成条形码的service类,处理参数并生成图片。前端用Vue组件,表单提交和图片显示,以及上传解析功能。可能需要处理跨域问题,后端配置CORS。 相关问题可能会涉及二维码生成、不同条形码格式的选择、参数加密、扫描性能优化等。用户可能还想知道如何存储生成的条形码图片,或者如何批量生成。此外,前端解析条形码的具体实现步骤也是一个常见问题。</think>### 1. Java后端实现条形码生成接口 ```java // 添加ZXing依赖(pom.xml) <dependency> <groupId>com.google.zxing</groupId> <artifactId>core</artifactId> <version>3.4.1</version> </dependency> <dependency> <groupId>com.google.zxing</groupId> <artifactId>javase</artifactId> <version>3.4.1</version> </dependency> // Controller @RestController @RequestMapping("/barcode") public class BarcodeController { @GetMapping(value = "/generate", produces = MediaType.IMAGE_PNG_VALUE) public ResponseEntity<byte[]> generateBarcode( @RequestParam String id, @RequestParam String code) throws WriterException, IOException { String content = id + "|" + code; // 使用|分隔ID和CODE Map<EncodeHintType, Object> hints = new HashMap<>(); hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); BitMatrix matrix = new MultiFormatWriter().encode( content, BarcodeFormat.CODE_128, 300, 100, hints); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); MatrixToImageWriter.writeToStream(matrix, "PNG", outputStream); return ResponseEntity.ok() .contentType(MediaType.IMAGE_PNG) .body(outputStream.toByteArray()); } } ``` ### 2. Vue前端实现(使用element-ui) ```vue <template> <div> <el-form :inline="true"> <el-form-item label="ID"> <el-input v-model="form.id"></el-input> </el-form-item> <el-form-item label="CODE"> <el-input v-model="form.code"></el-input> </el-form-item> <el-button @click="generateBarcode">生成条形码</el-button> </el-form> <el-image v-if="barcodeUrl" :src="barcodeUrl" style="width: 300px; height: 100px"> </el-image> <el-upload action="#" :auto-upload="false" :on-change="handleScan"> <el-button>上传扫描图片</el-button> </el-upload> </div> </template> <script> export default { data() { return { form: { id: '', code: '' }, barcodeUrl: '' } }, methods: { generateBarcode() { const params = new URLSearchParams({ id: this.form.id, code: this.form.code }) this.barcodeUrl = `/api/barcode/generate?${params.toString()}` }, async handleScan(file) { const formData = new FormData(); formData.append('file', file.raw); try { const res = await axios.post('/api/barcode/decode', formData); this.$message.success(`识别结果:ID=${res.data.id}, CODE=${res.data.code}`); } catch (error) { this.$message.error('识别失败'); } } } } </script> ``` ### 3. Java条形码解码接口 ```java @PostMapping("/decode") public ResponseEntity<Map<String, String>> decodeBarcode(@RequestParam("file") MultipartFile file) { try { BufferedImage image = ImageIO.read(file.getInputStream()); LuminanceSource source = new BufferedImageLuminanceSource(image); BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); Result result = new MultiFormatReader().decode(bitmap); String[] parts = result.getText().split("\\|"); Map<String, String> response = new HashMap<>(); response.put("id", parts[0]); response.put("code", parts[1]); return ResponseEntity.ok(response); } catch (Exception e) { return ResponseEntity.badRequest().build(); } } ``` 实现说明: 1. 后端使用ZXing库生成CODE_128格式条形码 2. ID和CODE使用竖线分隔符组合存储 3. 前端通过URL参数调用接口获取动态生成的条形码 4. 上传扫描图片时通过解码接口解析内容 5. 使用Vue+Element实现简洁的UI交互
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柠檬不萌c

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值