My_input.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. <template>
  2. <view>
  3. <u-modal
  4. ref="uModal"
  5. :show="show"
  6. @confirm="confirm"
  7. :asyncClose="true"
  8. :showCancelButton="true"
  9. @cancel="onCancel"
  10. :confirmText="confirmText"
  11. >
  12. <view class="content">
  13. <!-- 整数类型 -->
  14. <block v-if="item.inputType == 'int'">
  15. <view class="title u-line-1">
  16. {{ item.funcname }}{{ item.params.unit || "" }}
  17. </view>
  18. <block v-if="item.inputType == 'int'">
  19. <u--input
  20. :focus="intFocus"
  21. v-model="value"
  22. :type="item.num_scale == 0 ? 'number' : 'digit'"
  23. :placeholder="item.showValue || item.params.lastvalue"
  24. border="surround"
  25. />
  26. </block>
  27. <view class="tips" v-if="item.paramValue">
  28. <u-icon name="info-circle-fill" color="#E2201A" />
  29. <text style="margin-left: 4px">
  30. 有一条待更新记录,待更新值为:{{ item.paramValue
  31. }}{{ item.params.unit || "" }}
  32. </text>
  33. </view>
  34. </block>
  35. <!-- string类型 -->
  36. <block v-else-if="item.inputType == 'string'">
  37. <view class="title u-line-1">
  38. {{ item.funcname }}{{ item.params.unit || "" }}
  39. </view>
  40. <u--input
  41. :focus="intFocus"
  42. v-model="value"
  43. :placeholder="item.showValue || item.params.lastvalue"
  44. border="surround"
  45. />
  46. <view class="tips" v-if="item.paramValue">
  47. <u-icon name="info-circle-fill" color="#E2201A" />
  48. <text style="margin-left: 4px">
  49. 有一条待更新记录,待更新值为:{{ item.paramValue
  50. }}{{ item.params.unit || "" }}
  51. </text>
  52. </view>
  53. </block>
  54. <!-- 布尔开关 -->
  55. <block v-else-if="item.inputType == 'switch'">
  56. <view class="title u-line-1">
  57. {{ item.funcname || "" }}{{ item.params.unit || "" }}
  58. </view>
  59. {{ switchTips }}
  60. </block>
  61. <!-- 步进器 -->
  62. <block v-else-if="item.inputType == 'step'">
  63. <view class="title u-line-1">
  64. {{ item.funcname }}{{ item.params.unit || "" }}
  65. </view>
  66. <!-- if 和 else 是因为有时候decimal-length设置为0不能点击加减 -->
  67. <u-number-box
  68. v-if="item.params.num_scale"
  69. :asyncChange="true"
  70. v-model="value"
  71. :min="item.params.num_minvalue || -2147483648"
  72. :max="item.params.num_maxvalue || 2147483647"
  73. :step="item.params.num_step"
  74. :decimal-length="item.params.num_scale"
  75. @change="stepChange"
  76. @focus="stepFocus"
  77. @blur="stepBlue"
  78. inputWidth="100"
  79. />
  80. <u-number-box
  81. v-else
  82. :asyncChange="true"
  83. v-model="value"
  84. :min="item.params.num_minvalue || -2147483648"
  85. :max="item.params.num_maxvalue || 2147483647"
  86. :step="item.params.num_step"
  87. @change="stepChange"
  88. @focus="stepFocus"
  89. @blur="stepBlue"
  90. inputWidth="100"
  91. />
  92. <view class="tips" v-if="item.paramValue">
  93. <u-icon name="info-circle-fill" color="#E2201A" />
  94. <text style="margin-left: 4px">
  95. 有一条待更新记录,待更新值为:{{ item.paramValue
  96. }}{{ item.params.unit || "" }}
  97. </text>
  98. </view>
  99. <view class="tips">
  100. <u-icon name="info-circle-fill" color="#E2201A" />
  101. <text style="margin-left: 4px">
  102. 受步长限制,手动输入会计算为最接近的合法值
  103. </text>
  104. </view>
  105. </block>
  106. <!-- 时段 -->
  107. <block v-else-if="item.inputType == 'dayParting'">
  108. <view class="title u-line-1">
  109. {{ item.funcname }}{{ item.params[item.key + "P"].unit || "" }}
  110. </view>
  111. <view class="day-parting">
  112. <picker
  113. mode="time"
  114. :value="item.params[item.key + 'T'].lastvalue"
  115. @change="changeT_T"
  116. >
  117. <view class="row">
  118. <view class="label"> 时间: </view>
  119. <view class="day-parting-row">
  120. {{ item.params[item.key + "T"].lastvalue || "请选择时间" }}
  121. </view>
  122. </view>
  123. </picker>
  124. <view class="row" style="margin-top: 20px">
  125. <view class="label">压力:</view>
  126. <u--input
  127. :focus="dayPartingFocus"
  128. v-model="value"
  129. :type="
  130. item.params[item.key + 'P'].num_scale == 0
  131. ? 'number'
  132. : 'digit'
  133. "
  134. :placeholder="item.params[item.key + 'P'].lastvalue || '请输入'"
  135. border="surround"
  136. />
  137. </view>
  138. </view>
  139. </block>
  140. <!-- 选择 -->
  141. <block v-else-if="item.inputType == 'radio'">
  142. <view class="title u-line-1">
  143. {{ item.funcname }}{{ item.params.unit || "" }}
  144. </view>
  145. <view class="select-box">
  146. <view
  147. class="item"
  148. @click="onSelected(op, item.inputType)"
  149. :class="op.value == item.params.lastvalue ? 'active' : ''"
  150. v-for="op in item.params.options"
  151. :key="op.value"
  152. hover-class="navigator-hover"
  153. >
  154. {{ op.label }}
  155. </view>
  156. </view>
  157. </block>
  158. <!-- 特殊选择 -->
  159. <block v-else-if="item.inputType == 'radioNum'">
  160. <view class="title u-line-1">
  161. {{ item.funcname }}{{ item.params.unit || "" }}
  162. </view>
  163. <view class="select-box">
  164. <view
  165. class="item"
  166. @click="onSelected(op, item.inputType)"
  167. :class="op.value == 1 ? 'active' : ''"
  168. v-for="op in item.params.options"
  169. :key="op.key"
  170. hover-class="navigator-hover"
  171. >
  172. {{ op.label }}
  173. </view>
  174. </view>
  175. </block>
  176. <!-- slot -->
  177. <block v-else-if="isSlot">
  178. <view class="title u-line-1">
  179. {{ item.funcname || "" }}
  180. </view>
  181. <slot />
  182. </block>
  183. <!-- 其他类型 -->
  184. <block v-else> 其他类型 </block>
  185. <view class="tips" v-if="toBeUpdated">
  186. <u-icon name="info-circle-fill" color="#E2201A" />
  187. <text style="margin-left: 4px">
  188. {{ toBeUpdated }}
  189. </text>
  190. </view>
  191. <view class="tips" v-if="tips">
  192. <u-icon name="info-circle-fill" color="#55AAFF" />
  193. <text style="margin-left: 4px">
  194. {{ tips }}
  195. </text>
  196. </view>
  197. </view>
  198. </u-modal>
  199. </view>
  200. </template>
  201. <script>
  202. import currency from "../../utils/currency";
  203. export default {
  204. name: "My_input",
  205. props: {
  206. customMethod: {
  207. type: Function,
  208. },
  209. mode: {
  210. type: [Number || String],
  211. default: 0,
  212. },
  213. sendMsg: {
  214. type: Function,
  215. },
  216. },
  217. data() {
  218. return {
  219. show: false,
  220. item: {},
  221. tips: "",
  222. toBeUpdated: "",
  223. intFocus: false,
  224. dayPartingFocus: false,
  225. value: "",
  226. confirmText: "确定",
  227. loading: false,
  228. stepIsCalculate: false,
  229. stagingMethod: null,
  230. isSlot: false,
  231. switchTips: "",
  232. checkBeforeSending: null,
  233. };
  234. },
  235. methods: {
  236. /**
  237. * @param item.inputType int:数字 step:步进器 radio:单选 switch:开关 dayParting:分时段
  238. */
  239. openInput(item, isSlot = false, replenish = {}) {
  240. this.replenish = replenish;
  241. try {
  242. this.item = JSON.parse(JSON.stringify(item));
  243. } catch (error) {
  244. console.log("item JSON.parse 失败");
  245. this.item = item;
  246. }
  247. this.switchTips = "";
  248. this.show = true;
  249. let tips = "",
  250. toBeUpdated = "";
  251. this.confirmText = "确定";
  252. this.isSlot = isSlot;
  253. if (!isSlot) {
  254. let params = item.params;
  255. if (item.inputType == "int") {
  256. this.value = "";
  257. this.intFocus = false;
  258. if (params.num_minvalue || params.num_maxvalue)
  259. tips += `输入范围:${params.num_minvalue || 0} ~ ${
  260. params.num_maxvalue || "∞"
  261. }`;
  262. if (params.num_scale) tips += ` 保留${params.num_scale}位小数`;
  263. if (params.num_step) tips += ` 增量${params.num_step || 0}`;
  264. if (tips && params.unit) tips += ` 单位${params.unit}`;
  265. setTimeout(() => {
  266. this.intFocus = true;
  267. }, 300);
  268. } else if (item.inputType == "switch") {
  269. let paramValue = item.paramValue + "";
  270. if (paramValue.length && paramValue != item.params.lastvalue) {
  271. this.confirmText = "取消修改";
  272. this.switchTips = `查询到“${
  273. item.funcname
  274. }”有待更新记录,待更新值为“${
  275. params.options.find((v) => v.value == item.paramValue).label
  276. }”;您可通过“${this.confirmText}”按钮取消待更新请求`;
  277. } else {
  278. this.confirmText = "切换";
  279. console.log("paramValue", item.paramValue);
  280. this.switchTips = `是否将“${item.funcname}”${this.confirmText}为:“${
  281. params.options.find(
  282. (v) =>
  283. v.value !=
  284. (String(item.paramValue).length
  285. ? item.paramValue
  286. : item.params.lastvalue)
  287. ).label
  288. }”`;
  289. }
  290. } else if (item.inputType == "dayParting") {
  291. this.value = item.params[item.key + "p"] || "";
  292. this.dayPartingFocus = false;
  293. toBeUpdated =
  294. item.paramValue.time || item.paramValue.value
  295. ? `查询到一条待更新指令,更新内容为:时间${item.paramValue.time
  296. .split("_")
  297. .join(":")},压力${item.paramValue.value}MPA`
  298. : "";
  299. let p = item.params[item.key + "P"];
  300. if (p.num_minvalue || p.num_maxvalue)
  301. tips += `输入范围:${p.num_minvalue || 0} ~ ${
  302. p.num_maxvalue || "∞"
  303. }`;
  304. if (p.num_scale) tips += ` 保留${p.num_scale}位小数`;
  305. if (p.num_step) tips += ` 增量${p.num_step || 0}`;
  306. if (tips && p.unit) tips += ` 单位${p.unit}`;
  307. setTimeout(() => {
  308. this.dayPartingFocus = true;
  309. }, 300);
  310. } else if (item.inputType == "radio") {
  311. let paramValue = item.paramValue + "";
  312. if (paramValue.length && paramValue != item.params.lastvalue) {
  313. toBeUpdated = `查询到“${item.funcname}”有待更新记录,待更新值为“${
  314. params.options.find((v) => v.value == item.paramValue).label
  315. }”`;
  316. }
  317. } else if (item.inputType == "string") {
  318. this.value = "";
  319. this.intFocus = false;
  320. setTimeout(() => {
  321. this.intFocus = true;
  322. }, 300);
  323. }
  324. if (item.inputType == "radioNum") {
  325. if (item.paramValue)
  326. toBeUpdated = `查询到“${item.funcname}”有待更新记录,待更新值为“${item.paramValue}”`;
  327. } else if (item.inputType == "step") {
  328. this.value = params.lastvalue;
  329. /* if (this.value > params.num_maxvalue) this.value = params.num_maxvalue;
  330. if (this.value < params.num_minvalue) this.value = params.num_minvalue; */
  331. if (params.num_minvalue || params.num_maxvalue)
  332. tips += `输入范围:${params.num_minvalue || 0} ~ ${
  333. params.num_maxvalue || "∞"
  334. }`;
  335. if (params.num_scale) tips += ` 保留${params.num_scale}位小数`;
  336. if (params.num_step) tips += ` 增量${params.num_step || 0}`;
  337. if (tips && params.unit) tips += ` 单位${params.unit}`;
  338. setTimeout(() => {
  339. this.intFocus = true;
  340. }, 300);
  341. } else if (item.inputType == "step") {
  342. this.isSlot = true;
  343. } else {
  344. console.log(item);
  345. }
  346. }
  347. this.tips = tips;
  348. this.toBeUpdated = toBeUpdated;
  349. },
  350. onSelected(option, mode) {
  351. if (mode == "radio") {
  352. this.item.params.lastvalue = option.value;
  353. } else if (mode == "radioNum") {
  354. this.item.params.options = this.item.params.options.map((v) => {
  355. v.value = v.key == option.key ? 1 : 0;
  356. return v;
  357. });
  358. this.$Http.changeOptions &&
  359. this.$Http.changeOptions(this.item.params.options);
  360. }
  361. },
  362. stepChange(e) {
  363. if (!this.stepIsCalculate) this.value = e.value;
  364. },
  365. stepFocus(e) {
  366. this.stepIsCalculate = true;
  367. },
  368. stepBlue(e) {
  369. const { num_step, num_scale, num_maxvalue, num_minvalue } =
  370. this.item.params;
  371. this.value = currency(
  372. currency(e.value, {
  373. increment: num_step,
  374. precision: num_scale,
  375. }).format()
  376. ).value;
  377. if (num_minvalue != "" && this.value < num_minvalue)
  378. this.value = num_minvalue - 0;
  379. if (num_maxvalue != "" && this.value > num_maxvalue)
  380. this.value = num_maxvalue - 0;
  381. this.stepIsCalculate = false;
  382. if (this.stagingMethod) this.confirm();
  383. },
  384. /* 时段修改 */
  385. changeT_T(e) {
  386. this.item.params[this.item.key + "T"].lastvalue = e.detail.value;
  387. },
  388. submitBreak(content) {
  389. uni.showToast({
  390. title: content + "",
  391. icon: "none",
  392. });
  393. this.$refs.uModal.loading = false;
  394. },
  395. confirm() {
  396. if (this.loading) return;
  397. if (this.isSlot) return this.$emit("customMethod", "confirm");
  398. let item = this.item,
  399. params = item.params,
  400. value = "";
  401. if (item.inputType == "int" || item.inputType == "step") {
  402. value = this.value - 0;
  403. // if (value == 0) return this.submitBreak("还未输入值");
  404. if (params.num_scale != 0) value = value.toFixed(params.num_scale);
  405. if (params.num_minvalue && value - 0 < params.num_minvalue - 0)
  406. return this.submitBreak("输入值小于最低范围");
  407. if (params.num_maxvalue && value - 0 > params.num_maxvalue - 0)
  408. return this.submitBreak("输入值大于最大范围");
  409. } else if (item.inputType == "switch") {
  410. let value = item.paramName;
  411. try {
  412. if (item.changeItem.length) {
  413. }
  414. } catch (error) {
  415. item.changeItem = [];
  416. }
  417. if (item.changeItem.length) {
  418. item.changeItem.forEach(
  419. (key) => (value[key] = value[key] == 1 ? 0 : 1)
  420. );
  421. } else {
  422. for (const key in value) {
  423. value[key] = value[key] == 1 ? 0 : 1;
  424. }
  425. }
  426. // value = params.options.find(v => v.value != (String(item.paramValue).length ? item.paramValue : item.params.lastvalue)).value
  427. return this.submit(item.w_functionid, value);
  428. } else if (item.inputType == "dayParting") {
  429. value = this.value - 0;
  430. // if (value == 0) return this.submitBreak("还未输入值");
  431. let p = item.params[item.key + "P"];
  432. if (p.num_scale != 0) value = value.toFixed(p.num_scale);
  433. if (p.num_minvalue && value - 0 > p.num_minvalue - 0)
  434. return this.submitBreak("输入值小于最低范围");
  435. if (p.num_maxvalue && value - 0 < p.num_maxvalue - 0)
  436. return this.submitBreak("输入值大于最大范围");
  437. return this.submit(item.w_functionid, {
  438. [item.key + "P"]: value,
  439. [item.key + "T"]: params[item.key + "T"].lastvalue
  440. .split(":")
  441. .join("_"),
  442. });
  443. } else if (item.inputType == "radio") {
  444. value = params.lastvalue;
  445. } else if (item.inputType == "radioNum") {
  446. value = { ...this.replenish };
  447. params.options.forEach((v) => (value[`${v.key}`] = v.value));
  448. return this.submit(item.w_functionid, value);
  449. } else if (item.inputType == "string") {
  450. value = this.value;
  451. }
  452. this.submit(item.w_functionid, {
  453. [item.paramName]: value,
  454. });
  455. },
  456. onCancel() {
  457. this.$refs.uModal.loading = false;
  458. this.show = false;
  459. this.checkBeforeSending = null;
  460. },
  461. async submit(w_functionid, params) {
  462. console.log("提交", w_functionid, params);
  463. if (this.checkBeforeSending) {
  464. this.$refs.uModal.loading = false;
  465. this.checkBeforeSending(w_functionid, params);
  466. return;
  467. }
  468. if (this.stepIsCalculate) {
  469. this.stagingMethod = true;
  470. return;
  471. } else {
  472. this.stagingMethod = false;
  473. }
  474. this.loading = true;
  475. if (this.mode == 1) {
  476. this.$emit("sendMsg", w_functionid, params);
  477. } else {
  478. let res = await this.$Http.setControlItem(w_functionid, params);
  479. this.loading = false;
  480. if (res) {
  481. this.show = false;
  482. this.stepIsCalculate = null;
  483. setTimeout(() => {
  484. // this.item = null;
  485. }, 200);
  486. } else {
  487. this.$refs.uModal.loading = false;
  488. }
  489. }
  490. },
  491. },
  492. };
  493. </script>
  494. <style lang="scss" scoped>
  495. .content {
  496. width: 100%;
  497. /* 边框 */
  498. .day-parting-row {
  499. display: flex;
  500. align-items: center;
  501. flex: 1;
  502. width: 0;
  503. border: 1px solid #dadbde;
  504. border-radius: 4px;
  505. padding: 6px 9px;
  506. height: 35px;
  507. font-size: 14px;
  508. box-sizing: border-box;
  509. }
  510. .title {
  511. text-align: center;
  512. font-size: 16px;
  513. font-weight: bold;
  514. color: #333;
  515. margin-bottom: 20px;
  516. }
  517. .tips {
  518. display: flex;
  519. color: #666;
  520. font-size: 10px;
  521. margin-top: 6px;
  522. align-items: center;
  523. /deep/.u-icon {
  524. .u-icon__icon {
  525. font-size: 12px !important;
  526. }
  527. }
  528. }
  529. /* 分时控制 */
  530. .day-parting {
  531. .row {
  532. display: flex;
  533. align-items: center;
  534. .label {
  535. width: 50px;
  536. }
  537. }
  538. }
  539. /* 选择样式 */
  540. .select-box {
  541. display: flex;
  542. flex-wrap: wrap;
  543. .item {
  544. font-size: 12px;
  545. padding: 2px 6px;
  546. border-radius: 4px;
  547. border: 1px solid #333;
  548. margin-right: 5px;
  549. margin-bottom: 5px;
  550. }
  551. .active {
  552. // font-weight: bold;
  553. color: #fff;
  554. background: #052e5d;
  555. }
  556. }
  557. /deep/.u-input {
  558. .uni-input-input {
  559. font-size: 12px;
  560. }
  561. }
  562. /* 步进器样式 */
  563. /deep/ .u-number-box__minus,
  564. /deep/.u-number-box__plus {
  565. height: 30px !important;
  566. width: 40px !important;
  567. }
  568. /deep/ .u-number-box__input {
  569. height: 30px !important;
  570. width: 100px !important;
  571. }
  572. }
  573. </style>