codeSplit.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. <template>
  2. <gui-page :custom-header="true" :header-class="['gui-theme-background-color']">
  3. <template #gHeader>
  4. <view style="height:44px;" class="gui-flex gui-nowrap gui-rows gui-align-items-center">
  5. <!-- 使用组件实现返回按钮及返回首页按钮 -->
  6. <text
  7. style="font-size:44rpx;"
  8. class="gui-header-leader-btns gui-color-white font-icons"
  9. @tap="goHome"
  10. >&#xe6c5;</text>
  11. <!-- 导航文本此处也可以是其他自定义内容 -->
  12. <text
  13. class="gui-h4 gui-blod gui-flex1 gui-text-center gui-ellipsis gui-color-white gui-primary-text"
  14. >条码拆分</text>
  15. <!-- 此处加一个右侧展位元素与左侧同宽,实现标题居中 -->
  16. <!-- 实际宽度请根据自己情况设置 -->
  17. <view style="width:40px;" />
  18. <!-- 如果右侧有其他内容可以利用条件编译和定位来实现-->
  19. </view>
  20. </template>
  21. <template #gBody>
  22. <view class="list-content">
  23. <view class="scan">
  24. <view class="scan-card">
  25. <uni-easyinput
  26. ref="easyinput"
  27. v-model="scanNumber"
  28. :input-border="false"
  29. :clearable="false"
  30. type="text"
  31. focus
  32. @focus="handleInputFocus"
  33. placeholder="扫描内部标签"
  34. @confirm="handleKeydown"
  35. />
  36. <text class="font-icons" @click="handleMapass">&#xe6b7;</text>
  37. </view>
  38. </view>
  39. <view class="card-list-flexbox">
  40. <text class="card-list-title" :style="[isPad?'font-size: 18px':'font-size: 14px']">批次内容</text>
  41. <view class="card-list-item">
  42. <text>料号</text>
  43. <text>{{ paramsDetail.erpMaterialNo }}</text>
  44. </view>
  45. <view class="card-list-item">
  46. <text>批号</text>
  47. <text>{{ paramsDetail.batchNumber }}</text>
  48. </view>
  49. <view class="card-list-item">
  50. <text>件数</text>
  51. <text>{{ paramsDetail.qty }}</text>
  52. </view>
  53. </view>
  54. <view class="table-title">
  55. <view><text style="font-size: 16px;">拆分列表</text></view>
  56. <view class="">
  57. <text class="c-button" @click="handleAddPackage">新增项</text>
  58. </view>
  59. </view>
  60. <view class="split-list">
  61. <!-- eslint-disable-next-line vue/valid-v-for -->
  62. <view v-for="(item, key) in packageList" v-key="key">
  63. <uni-swipe-action>
  64. <!-- 基础用法 -->
  65. <uni-swipe-action-item :right-options="options" @click="handleRemoveDetail(key)">
  66. <template #left>
  67. <view />
  68. </template>
  69. <div class="split-list-item">
  70. <text>第{{ key + 1 }}条</text>
  71. <input v-model="item.num" type="digit">
  72. <text>PCS</text>
  73. </div>
  74. </uni-swipe-action-item>
  75. </uni-swipe-action>
  76. </view>
  77. </view>
  78. <view class="operation-panel">
  79. <view class="operation-title">余数:
  80. <text style="font-size: 16px;font-weight: bold;">{{ computedRemainder }}</text>
  81. <text
  82. style="color: #f85661;font-size: 16px;font-weight: bold;"
  83. >&nbsp;&nbsp;{{ computedReadonlyText }}</text>
  84. </view>
  85. <button
  86. type="primary"
  87. :disabled="paramsDetail.qty <= 0? true: false"
  88. style="width: calc(100% - 8px);margin: 0 4px;"
  89. @click="hanleSplitLabelCode"
  90. >拆分</button>
  91. </view>
  92. </view>
  93. <uni-popup ref="errorTip" type="dialog">
  94. <uni-popup-dialog
  95. type="error"
  96. cancel-text="关闭"
  97. confirm-text="确认"
  98. title="提示"
  99. :content="errorTipMessage"
  100. @confirm="handleCloseErrorTipsModal"
  101. @close="handleCloseErrorTipsModal"
  102. />
  103. </uni-popup>
  104. </template>
  105. </gui-page>
  106. </template>
  107. <script>
  108. import {
  109. computed,
  110. defineComponent,
  111. onBeforeMount,
  112. ref
  113. } from 'vue'
  114. import {
  115. add
  116. } from '@/unit/Math.js'
  117. import tsc from '@/unit/CHITEN_SDK_APP/tsc.js'
  118. export default defineComponent({
  119. setup() {
  120. const bluetooth = ref()
  121. const modalForm = ref('')
  122. const errorState = ref(0)
  123. const easyinput = ref()
  124. const errorTip = ref('')
  125. const errorTipMessage = ref('')
  126. const scanNumber = ref('')
  127. const paramsDetail = ref({
  128. batchNumber: '-',
  129. erpMaterialNo: '-',
  130. qty: 0
  131. })
  132. const packageList = ref([{
  133. index: 1,
  134. num: ''
  135. }])
  136. const blueConfig = ref({
  137. loopBuffer: 0,
  138. currentTime: 1,
  139. lastData: 0,
  140. onBufferSize: 20,
  141. printerNum: 1,
  142. currentPrint: 1,
  143. isLabelSend: false
  144. })
  145. const countRemainder = function() {
  146. let remainder = 0
  147. for (let i = 0; i < packageList.value.length; i++) {
  148. remainder = add(packageList.value[i].num, remainder)
  149. }
  150. return remainder
  151. }
  152. const computedRemainder = computed(() => {
  153. const remainder = countRemainder()
  154. return paramsDetail.value.qty - remainder
  155. })
  156. const computedReadonlyText = computed(() => {
  157. const remainder = countRemainder()
  158. return paramsDetail.value.qty - remainder < 0 ? '余数不正确' : ''
  159. })
  160. onBeforeMount(() => {
  161. // #ifdef APP-PLUS
  162. const bluetoothConfig = uni.getStorageSync('bluetoothConfig')
  163. if ([null, '', undefined].includes(bluetoothConfig)) {
  164. bluetooth.value = {
  165. 'isOpenBle': false,
  166. 'deviceId': '',
  167. 'serviceId': '',
  168. 'writeId': '',
  169. 'notifyId': ''
  170. }
  171. setTimeout(() => {
  172. // #ifdef APP-PLUS
  173. plus.device.beep(2)
  174. // #endif
  175. errorTipMessage.value = '蓝牙打印机未连接'
  176. errorState.value = -1
  177. errorTip.value.open()
  178. }, 800)
  179. } else {
  180. bluetooth.value = JSON.parse(bluetoothConfig)
  181. }
  182. // #endif
  183. })
  184. const handleMapass = function() {
  185. // #ifdef APP-PLUS
  186. const mpaasScanModule = uni.requireNativePlugin('Mpaas-Scan-Module')
  187. mpaasScanModule.mpaasScan({
  188. // 扫码识别类型,参数可多选,qrCode、barCode,不设置,默认识别所有
  189. 'scanType': ['qrCode', 'barCode'],
  190. // 是否隐藏相册,默认false不隐藏
  191. 'hideAlbum': false
  192. },
  193. (ret) => {
  194. if (ret.resp_code === 1000) {
  195. uni.$reqGet('getQrCodeInfo', {
  196. qrCode: ret.resp_result
  197. })
  198. .then(({
  199. code,
  200. data,
  201. msg
  202. }) => {
  203. if (code === 0) {
  204. Object.assign(paramsDetail.value, data)
  205. } else {
  206. // #ifdef APP-PLUS
  207. plus.device.beep(2)
  208. // #endif
  209. errorTipMessage.value = msg
  210. errorTip.value.open()
  211. errorState.value = 0
  212. }
  213. })
  214. }
  215. })
  216. // #endif
  217. }
  218. // 扫描完成品标签输入框回车事件
  219. const handleKeydown = function(e) {
  220. uni.$reqGet('getQrCodeInfo', {
  221. qrCode: e
  222. })
  223. .then(({
  224. code,
  225. data,
  226. msg
  227. }) => {
  228. if (code === 0) {
  229. Object.assign(paramsDetail.value, data)
  230. setInputFocus()
  231. } else {
  232. // #ifdef APP-PLUS
  233. plus.device.beep(2)
  234. // #endif
  235. errorTipMessage.value = msg
  236. errorTip.value.open()
  237. errorState.value = 0
  238. }
  239. })
  240. }
  241. const Send = function(buff) {
  242. var currentTime = blueConfig.value.currentTime
  243. var loopBuffer = blueConfig.value.loopBuffer
  244. var lastData = blueConfig.value.lastData
  245. var onBufferSize = blueConfig.value.onBufferSize
  246. var printNum = blueConfig.value.printerNum
  247. var currentPrint = blueConfig.value.currentPrint
  248. var buf
  249. var dataView
  250. if (currentTime < loopBuffer) {
  251. buf = new ArrayBuffer(onBufferSize)
  252. dataView = new DataView(buf)
  253. for (let i = 0; i < onBufferSize; ++i) {
  254. dataView.setUint8(i, buff[(currentTime - 1) * onBufferSize + i])
  255. }
  256. } else {
  257. buf = new ArrayBuffer(lastData)
  258. dataView = new DataView(buf)
  259. for (let i = 0; i < lastData; ++i) {
  260. dataView.setUint8(i, buff[(currentTime - 1) * onBufferSize + i])
  261. }
  262. }
  263. plus.bluetooth.writeBLECharacteristicValue({
  264. deviceId: bluetooth.value.deviceId,
  265. serviceId: bluetooth.value.serviceId,
  266. characteristicId: bluetooth.value.writeId,
  267. value: buf,
  268. success: function(res) {
  269. if (currentPrint <= printNum) {
  270. wx.showToast({
  271. title: '数据打印中',
  272. icon: 'loading'
  273. })
  274. }
  275. // 将complete中处理数据的代码挪过来,增加30ms延迟, 解决蓝牙打印数据传输10007问题
  276. setTimeout(() => {
  277. currentTime += 1
  278. if (currentTime <= loopBuffer) {
  279. blueConfig.value.isLabelSend = true
  280. blueConfig.value.currentTime = currentTime
  281. Send(buff)
  282. }
  283. // end
  284. if (currentTime === loopBuffer) {
  285. blueConfig.value.currentPrint += 1
  286. blueConfig.value.isLabelSend = false
  287. }
  288. }, 10)
  289. },
  290. fail: function(e) {
  291. wx.showToast({
  292. title: '打印第' + currentPrint + '张失败' + 'error: code ' + e
  293. ?.code + ', message ' + e?.message,
  294. icon: 'none',
  295. duration: 4000
  296. })
  297. },
  298. complete: function() {}
  299. })
  300. }
  301. const prepareSend = function(buff) {
  302. var time = blueConfig.value.onBufferSize
  303. var loopBuffer = parseInt(buff.length / time)
  304. var lastData = parseInt(buff.length % time)
  305. blueConfig.value.loopBuffer = loopBuffer + 1
  306. blueConfig.value.lastData = lastData
  307. blueConfig.value.currentTime = 1
  308. Send(buff)
  309. }
  310. const labelTest = function(ret) {
  311. var command = tsc.dlabelPrinter.createNew()
  312. command.setBackFeed(6)
  313. // (480 * 200)dots
  314. command.setSize(60, 25)
  315. command.setCls()
  316. command.setGap(6)
  317. command.setBox(0, 0, 475, 200, 1)
  318. // 1
  319. command.setBar(108, 0, 2, 40)
  320. command.setBar(108, 40, 2, 40)
  321. command.setBar(108, 80, 2, 40)
  322. command.setBar(108, 120, 2, 40)
  323. command.setBar(108, 160, 2, 40)
  324. command.setBar(108, 200, 2, 40)
  325. // 竖
  326. command.setBar(210, 80, 2, 40)
  327. command.setBar(210, 120, 2, 40)
  328. command.setBar(210, 160, 2, 40)
  329. command.setBar(210, 200, 2, 40)
  330. // 横
  331. command.setBar(0, 40, 480, 2)
  332. command.setBar(0, 80, 320, 2)
  333. command.setBar(0, 120, 210, 2)
  334. command.setBar(0, 160, 210, 2)
  335. // 横
  336. command.setBar(320, 80, 480, 2)
  337. command.setBar(320, 120, 480, 2)
  338. command.setBar(320, 160, 480, 2)
  339. // 竖
  340. command.setBar(322, 40, 2, 40)
  341. command.setBar(322, 80, 2, 40)
  342. command.setBar(322, 120, 2, 40)
  343. command.setBar(322, 160, 2, 40)
  344. // 竖
  345. command.setBar(378, 40, 2, 40)
  346. command.setBar(378, 80, 2, 40)
  347. command.setBar(378, 120, 2, 40)
  348. command.setBar(378, 160, 2, 40)
  349. // row1
  350. command.setText(4, 8, 'TSS24.BF2', 0, 1, 1, '料号')
  351. command.setText(112, 10, '2', 0, 1, 1, ret.pn)
  352. // row2
  353. command.setText(4, 48, 'TSS24.BF2', 0, 1, 1, '工令单')
  354. command.setText(112, 50, '2', 0, 1, 1, ret.wordOrderNo)
  355. command.setText(328, 48, 'TSS24.BF2', 0, 1, 1, '数量')
  356. command.setText(384, 50, '2', 0, 1, 1, ret.qty)
  357. // row3
  358. command.setText(4, 88, 'TSS24.BF2', 0, 1, 1, '生产日期')
  359. command.setText(110, 90, '1', 0, 1, 1, ret.dateOfManufacture)
  360. command.setText(328, 88, 'TSS24.BF2', 0, 1, 1, '库位')
  361. command.setText(384, 90, '1', 0, 1, 1, ret.storageLocation)
  362. // row4
  363. command.setText(4, 128, 'TSS24.BF2', 0, 1, 1, '供应商')
  364. command.setText(112, 130, '3', 0, 1, 1, ret.vendor)
  365. command.setText(328, 128, 'TSS24.BF2', 0, 1, 1, '后制')
  366. command.setText(384, 130, '1', 0, 1, 1, ret.postProduction)
  367. // row5
  368. command.setText(4, 168, 'TSS24.BF2', 0, 1, 1, '包装')
  369. command.setText(112, 170, '1', 0, 1, 1, ret.packaging)
  370. command.setText(328, 168, 'TSS24.BF2', 0, 1, 1, 'QC')
  371. command.setText(384, 170, '1', 0, 1, 1, ret.qc)
  372. command.setQrcode(214, 88, 'L', 5, 'A', ret.qrCode)
  373. command.setPagePrint()
  374. prepareSend(command.getData())
  375. }
  376. const hanleSplitLabelCode = function() {
  377. let list = []
  378. const subBatchVOList = []
  379. packageList.value.forEach(ret => {
  380. if (ret.num) {
  381. subBatchVOList.push({
  382. qty: ret.num
  383. })
  384. }
  385. })
  386. uni.$reqPost('batchQrCodeSplit', {
  387. batchNumber: paramsDetail.value.batchNumber,
  388. subBatchVOList
  389. })
  390. .then(async({
  391. code,
  392. data,
  393. msg
  394. }) => {
  395. if (code === 0) {
  396. list = data
  397. if (list.length > 0) {
  398. blueConfig.value.currentPrint = 1
  399. blueConfig.value.printNum = list.length
  400. const timer = setInterval(async() => {
  401. const currentPrint = blueConfig.value.currentPrint - 1
  402. if (blueConfig.value.isLabelSend === false &&
  403. currentPrint <
  404. blueConfig.value.printNum) {
  405. const paramsObj = {
  406. pn: list[currentPrint]
  407. .pn ?? '',
  408. wordOrderNo: list[currentPrint]
  409. .wordOrderNo ??
  410. '',
  411. qty: list[currentPrint]
  412. .qty ??
  413. '',
  414. dateOfManufacture: list[currentPrint]
  415. .dateOfManufacture ??
  416. '',
  417. storageLocation: list[currentPrint]
  418. .storageLocation ??
  419. '',
  420. postProduction: list[currentPrint]
  421. .postProduction ??
  422. '',
  423. vendor: list[currentPrint]
  424. .vendor ??
  425. '',
  426. packaging: list[currentPrint]
  427. .packaging ??
  428. '',
  429. qc: list[currentPrint]
  430. .qc ??
  431. '',
  432. qrCode: list[currentPrint]
  433. .qrCode ??
  434. ''
  435. }
  436. await labelTest(paramsObj)
  437. }
  438. if (currentPrint === blueConfig.value.printNum) {
  439. await clearInterval(timer)
  440. }
  441. }, 3000)
  442. }
  443. paramsDetail.value = {
  444. batchNumber: '-',
  445. erpMaterialNo: '-',
  446. qty: 0
  447. }
  448. packageList.value = [{
  449. index: 1,
  450. num: ''
  451. }]
  452. setInputFocus()
  453. } else {
  454. // #ifdef APP-PLUS
  455. plus.device.beep(2)
  456. // #endif
  457. errorTipMessage.value = msg
  458. errorTip.value.open()
  459. errorState.value = 0
  460. }
  461. })
  462. }
  463. const handleAddPackage = function() {
  464. packageList.value.push({
  465. index: packageList.value.length,
  466. num: ''
  467. })
  468. }
  469. const goHome = function() {
  470. uni.$goHome()
  471. }
  472. const setInputFocus = function() {
  473. scanNumber.value = ''
  474. easyinput.value.onBlur()
  475. easyinput.value.onFocus()
  476. }
  477. // 关闭错误信息弹窗
  478. const handleCloseErrorTipsModal = async function() {
  479. errorTip.value.close()
  480. if (errorState.value === 0) {
  481. await setInputFocus()
  482. }
  483. }
  484. const handleRemoveDetail = function(key) {
  485. if (packageList.value.length === 1) {
  486. // #ifdef APP-PLUS
  487. plus.device.beep(2)
  488. // #endif
  489. errorTipMessage.value = '最少保留一条'
  490. errorTip.value.open()
  491. errorState.value = -1
  492. }
  493. if (packageList.value.length > 1) {
  494. packageList.value.splice(key, 1)
  495. }
  496. }
  497. // 禁用软键盘
  498. const handleInputFocus = function() {
  499. setTimeout(() => {
  500. uni.hideKeyboard()
  501. }, 100)
  502. }
  503. return {
  504. options: [{
  505. text: '删除',
  506. style: {
  507. backgroundColor: '#dd524d'
  508. }
  509. }],
  510. goHome,
  511. paramsDetail,
  512. easyinput,
  513. errorTip,
  514. errorTipMessage,
  515. modalForm,
  516. packageList,
  517. scanNumber,
  518. handleMapass,
  519. handleKeydown,
  520. handleInputFocus,
  521. computedRemainder,
  522. computedReadonlyText,
  523. handleAddPackage,
  524. handleRemoveDetail,
  525. handleCloseErrorTipsModal,
  526. hanleSplitLabelCode
  527. }
  528. }
  529. })
  530. </script>
  531. <style lang="scss" scoped>
  532. .gui-header-leader-btns {
  533. color: black;
  534. font-size: 24px !important;
  535. }
  536. .list-content {
  537. margin-top: 80px;
  538. background-color: #edeeee;
  539. }
  540. .input-200 {
  541. width: 200px;
  542. padding-left: 10px;
  543. }
  544. .font-icons {
  545. width: 40px;
  546. font-size: 20px;
  547. text-align: right;
  548. }
  549. .scan {
  550. height: 45px;
  551. width: calc(100% - 48px);
  552. margin: 12px;
  553. padding: 0 12px;
  554. display: flex;
  555. justify-content: space-between;
  556. align-items: center;
  557. border-radius: 6px;
  558. background-color: white;
  559. .scan-card {
  560. width: 100%;
  561. display: grid;
  562. grid-template-rows: 1fr;
  563. grid-template-columns: 7fr 2fr;
  564. align-items: center;
  565. input {
  566. height: 35px;
  567. line-height: 35px;
  568. }
  569. text {
  570. width: 100%;
  571. text-align: right;
  572. }
  573. }
  574. }
  575. .card-list-flexbox {
  576. width: calc(100vw - 24px);
  577. min-height: 150px;
  578. margin: 0 12px;
  579. display: flex;
  580. justify-content: center;
  581. flex-direction: column;
  582. align-items: center;
  583. overflow-y: scroll;
  584. .card-list-title {
  585. width: 100%;
  586. height: 35px;
  587. line-height: 35px;
  588. margin: 0 4px 0 4px;
  589. border-radius: 4px 4px 0 0;
  590. text-align: center;
  591. color: white;
  592. background-color: rgba(0, 160, 233, 1.0);
  593. }
  594. .card-list-item,
  595. .card-list-item-operation {
  596. width: 100%;
  597. min-height: 35px;
  598. margin: 0 4px 3rpx 4px;
  599. border-radius: 4px;
  600. display: flex;
  601. flex-direction: row;
  602. align-items: center;
  603. justify-content: space-between;
  604. background-color: #fff;
  605. & text:nth-of-type(1) {
  606. min-width: 40px;
  607. }
  608. uni-text {
  609. font-size: 14px;
  610. min-height: 50rpx;
  611. line-height: 50rpx;
  612. text-align: left;
  613. padding: 0 8px;
  614. display: flex;
  615. flex-direction: row;
  616. align-items: center;
  617. }
  618. }
  619. }
  620. .table-title {
  621. height: 40px;
  622. line-height: 40px;
  623. margin: 4px 0 0px 0;
  624. padding: 4px 12px;
  625. font-size: 16px;
  626. font-weight: bold;
  627. display: flex;
  628. border-bottom: 1px solid #dddddd;
  629. background-color: white;
  630. & view {
  631. flex: 1;
  632. display: flex;
  633. }
  634. & view:nth-of-type(2) {
  635. justify-content: end;
  636. align-items: center;
  637. }
  638. }
  639. .c-button {
  640. display: flex;
  641. width: 60px;
  642. height: 30px;
  643. border: 1px solid #55aaff;
  644. border-radius: 4px;
  645. box-shadow: 2px 2px 2px 1px #dddddd;
  646. justify-content: center;
  647. align-items: center;
  648. cursor: pointer;
  649. color: white;
  650. background-color: rgb(0, 160, 233);
  651. }
  652. .custom-table {
  653. height: calc(100vh - 265px);
  654. min-height: 230px;
  655. margin: 5px 0;
  656. overflow-y: scroll;
  657. }
  658. .operation-panel {
  659. padding: 0 0 12px 0;
  660. position: fixed;
  661. bottom: 0;
  662. width: 100%;
  663. display: grid;
  664. grid-template-columns: 1fr;
  665. grid-template-rows: 1fr;
  666. background-color: white;
  667. .operation-title {
  668. height: 40px;
  669. line-height: 40px;
  670. padding: 0 14px;
  671. font-size: 16px;
  672. font-weight: bold;
  673. }
  674. }
  675. .split-list {
  676. min-height: 460px;
  677. padding: 0 14px;
  678. margin-bottom: 96px;
  679. background-color: white;
  680. .split-list-item {
  681. height: 60px;
  682. line-height: 60px;
  683. width: 100%;
  684. display: flex;
  685. justify-content: space-between;
  686. align-items: center;
  687. text:nth-of-type(1) {
  688. font-size: 14px;
  689. text-align: left;
  690. }
  691. input:nth-of-type(1) {
  692. width: 70% !important;
  693. height: 40px;
  694. border-bottom: 1px dotted gray;
  695. }
  696. text:nth-of-type(2) {
  697. font-size: 14px;
  698. text-align: right;
  699. margin-right: 4px;
  700. }
  701. }
  702. }
  703. </style>