work-order-boms.vue 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. <template>
  2. <scroll-view scroll-y="true" class="work-order-boms">
  3. <view
  4. class="device-section"
  5. :class="{
  6. active: bom.workOrderBomOnlyKey === currentBom.workOrderBomOnlyKey,
  7. }"
  8. v-for="bom in bomsData"
  9. :key="bom.workOrderBomOnlyKey"
  10. >
  11. <!-- 已维修标识 -->
  12. <view class="device-section-selected" v-if="bom.maintainedFlag">
  13. <uni-icons type="checkmarkempty" size="13" color="#FFF"></uni-icons>
  14. </view>
  15. <view @click="onSelect(bom)">
  16. <!-- 设备名称 -->
  17. <view class="item-module">
  18. <view class="item-content flex-row align-center justify-between">
  19. <view class="item-title">
  20. <span class="item-title-width"
  21. >{{ $t("device.deviceName") }}:</span
  22. >
  23. </view>
  24. <view class="item-title">
  25. <span>{{ bom.deviceName }}</span>
  26. </view>
  27. </view>
  28. <view class="module-border"> </view>
  29. </view>
  30. <!-- 设备编码 -->
  31. <view class="item-content flex-row align-center justify-between">
  32. <view class="item-title">
  33. <span class="item-title-width">{{ $t("device.deviceCode") }}:</span>
  34. </view>
  35. <view class="item-title">
  36. <span>{{ bom.deviceCode }}</span>
  37. </view>
  38. </view>
  39. <!-- 维修项 -->
  40. <view class="item-content flex-row align-center justify-between">
  41. <view class="item-title">
  42. <span class="item-title-width"
  43. >{{ $t("equipmentMaintenance.maintenanceItems") }}:</span
  44. >
  45. </view>
  46. <view class="item-title">
  47. <span>{{ bom.name }}</span>
  48. </view>
  49. </view>
  50. </view>
  51. <!-- 是否消耗物料 -->
  52. <view class="item-content flex-row align-center justify-between">
  53. <view class="item-title">
  54. <span class="item-title-width">
  55. {{ $t("workOrder.isConsumptionMaterial") }}:
  56. </span>
  57. </view>
  58. <switch
  59. :checked="bom.rule == 0 ? true : false"
  60. @change="bomRuleChange(bom)"
  61. />
  62. </view>
  63. <!-- 不消耗物料原因 -->
  64. <view
  65. class="item-content flex-row align-center justify-between"
  66. v-if="bom.rule == 1"
  67. >
  68. <view class="item-title">
  69. <span class="item-title-width">
  70. {{ $t("equipmentMaintenance.noConsumeMaterialReason") }}:
  71. </span>
  72. </view>
  73. <uni-easyinput
  74. style="text-align: right"
  75. :styles="{ disableColor: '#fff' }"
  76. :inputBorder="false"
  77. :autoHeight="true"
  78. type="textarea"
  79. :placeholder="$t('operation.PleaseFillIn')"
  80. v-model="bom.remark"
  81. />
  82. </view>
  83. <!-- 物料数量 -->
  84. <view class="item-content flex-row align-center justify-between">
  85. <view class="item-title">
  86. <span class="item-title-width"
  87. >{{ $t("workOrder.materialCount") }}:</span
  88. >
  89. </view>
  90. <view class="item-title">
  91. <span>{{ bom.materialCount }}</span>
  92. </view>
  93. </view>
  94. <!-- 操作按钮 -->
  95. <view class="item-opera flex-row justify-end">
  96. <!-- 删除 -->
  97. <button type="primary" :plain="true" @click="ondeleteBom(bom)">
  98. {{ $t("operation.delete") }}
  99. </button>
  100. </view>
  101. </view>
  102. </scroll-view>
  103. <!-- 提示信息弹窗 -->
  104. <uni-popup ref="messageRef" type="message">
  105. <uni-popup-message
  106. :type="msgType"
  107. :message="messageText"
  108. :duration="2000"
  109. ></uni-popup-message>
  110. </uni-popup>
  111. <!-- 提示弹窗 -->
  112. <uni-popup ref="alertDialogRef" type="dialog">
  113. <!-- 删除提示 -->
  114. <uni-popup-dialog
  115. :type="'warn'"
  116. :title="$t('api.message')"
  117. :cancelText="$t('operation.cancel')"
  118. :confirmText="$t('operation.confirm')"
  119. :content="`${$t('workOrder.isDeleteBom')}?`"
  120. @confirm="dialogConfirm"
  121. @close="dialogClose"
  122. ></uni-popup-dialog>
  123. </uni-popup>
  124. </template>
  125. <script setup>
  126. import { onLoad, onReady, onBackPress } from "@dcloudio/uni-app";
  127. import { ref, reactive, computed, getCurrentInstance } from "vue";
  128. import dayjs from "dayjs";
  129. // --------------------------引用组件--------------------------------------
  130. import maintenanceDelay from "@/components/maintenance/delay.vue";
  131. // --------------------------引用全局变量$t---------------------------------
  132. const { appContext } = getCurrentInstance();
  133. const t = appContext.config.globalProperties.$t;
  134. // --------------------------接收参数---------------------------------------
  135. const props = defineProps({
  136. // 维修项列表
  137. bomsData: {
  138. type: Array,
  139. default: () => [],
  140. },
  141. // 工单类型(1计划生成 2临时新建),
  142. workOrderType: {
  143. type: Number,
  144. default: 2,
  145. },
  146. // 当前选中的维修项
  147. currentBom: {
  148. type: Object,
  149. default: () => {},
  150. },
  151. });
  152. console.log("🚀 ~ props.bomsData:", props.bomsData);
  153. // -------------------------- 定义变量 ---------------------------------------
  154. const msgType = ref("success");
  155. const messageText = ref(""); // 提示信息
  156. const messageRef = ref(null);
  157. // -------------------------- 切换选中维修项 ---------------------------------------
  158. const onSelect = (bom) => {
  159. console.log("onSelect", bom);
  160. emit("onSelectBom", bom);
  161. };
  162. // -------------------------- 切换是否消耗物料 ---------------------------------------
  163. const bomRuleChange = (bom) => {
  164. console.log("bomRuleChange", bom);
  165. // 是否消耗物料 rule (0需要 1不需要)
  166. if (bom.rule == "0") {
  167. bom.rule = "1";
  168. bom.materials = []; // 无物料维修清空对应物料列表
  169. } else {
  170. bom.rule = "0";
  171. bom.remark = ""; // 无物料维修原因清空
  172. }
  173. // 通知父组件更新统计
  174. emit("updateStatistics");
  175. };
  176. // 提示信息弹窗
  177. const alertDialogRef = ref(null);
  178. // 待删除的物料
  179. const bomToDelete = ref({});
  180. // 删除物料
  181. const ondeleteBom = (bom, index) => {
  182. // 记录待删除的物料
  183. bomToDelete.value = bom;
  184. // 显示删除提示弹窗
  185. alertDialogRef.value.open();
  186. };
  187. // 删除弹窗确认事件
  188. const dialogConfirm = () => {
  189. console.log("🚀 删除弹窗确认事件:");
  190. emit("deleteBom", bomToDelete.value);
  191. // 关闭弹窗
  192. dialogClose();
  193. };
  194. // 删除弹窗关闭事件
  195. const dialogClose = () => {
  196. console.log("🚀 删除弹窗关闭事件:");
  197. // 关闭弹窗
  198. alertDialogRef.value.close();
  199. };
  200. // -------------------------- 暴露给父组件的外部方法 --------------------------
  201. defineExpose({});
  202. // -------------------------- 事件派发 ---------------------------------------
  203. const emit = defineEmits(["onSelectBom", "updateStatistics", "deleteBom"]);
  204. </script>
  205. <style lang="scss" scoped>
  206. @import "@/style/work-order-detail.scss";
  207. .item-content{
  208. &:last-child{
  209. border-bottom: 1px dashed #CACCCF;
  210. }
  211. }
  212. .work-order-boms {
  213. height: 100%;
  214. }
  215. .device-section {
  216. position: relative;
  217. &.active {
  218. border: #004098 1px solid;
  219. }
  220. }
  221. .device-section-selected {
  222. position: absolute;
  223. top: 0;
  224. right: 0;
  225. width: 0;
  226. height: 0;
  227. // 初始状态为透明
  228. border-style: solid;
  229. transition: all 0.3s ease;
  230. // 创建右上角倒三角
  231. border-width: 0 23px 23px 0;
  232. border-color: transparent #004098 transparent transparent; // 三角
  233. .uni-icons {
  234. position: absolute;
  235. top: 0;
  236. right: -21px;
  237. font-size: 11px;
  238. color: #fff;
  239. }
  240. }
  241. :deep(.uni-switch-input) {
  242. width: 46px;
  243. height: 23px;
  244. border-radius: 16px;
  245. margin-right: 0;
  246. &::before {
  247. width: 46px;
  248. height: 23px;
  249. background: #9ca0a5;
  250. }
  251. &::after {
  252. width: 19px;
  253. height: 19px;
  254. top: 2px;
  255. left: 3px;
  256. }
  257. }
  258. :deep(.uni-switch-input-checked) {
  259. background: #004098;
  260. &::after {
  261. top: 1px;
  262. left: 3px;
  263. }
  264. }
  265. .switch-container {
  266. position: relative;
  267. display: inline-block;
  268. width: 46px;
  269. height: 23px;
  270. }
  271. .switch {
  272. position: absolute;
  273. top: 0;
  274. left: 0;
  275. width: 100%;
  276. height: 100%;
  277. z-index: 0;
  278. }
  279. .switch-cover {
  280. position: absolute;
  281. top: 0;
  282. left: 0;
  283. width: 100%;
  284. height: 100%;
  285. z-index: 1;
  286. }
  287. </style>