index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. <template>
  2. <el-drawer
  3. v-model="drawerVisible"
  4. :close-on-click-modal="false"
  5. :show-close="false"
  6. :with-header="false"
  7. destroy-on-close
  8. direction="rtl"
  9. size="990px"
  10. >
  11. <!-- <template #header>-->
  12. <!-- <div class="drawerTitle">报故</div>-->
  13. <!-- </template>-->
  14. <template #default>
  15. <el-scrollbar>
  16. <div id="drawContent">
  17. <el-form
  18. ref="formRef"
  19. :model="formLabelAlign"
  20. :rules="rules"
  21. label-position="top"
  22. label-width="auto"
  23. >
  24. <el-form-item label="基本信息">
  25. <div class="base-info">
  26. <div class="info-item">
  27. <div class="item-label">产品名称</div>
  28. <div class="item-value">{{ infoData?.materialName }}</div>
  29. </div>
  30. <div class="info-item">
  31. <div class="item-label">产品型号</div>
  32. <div class="item-value">{{ infoData?.spec }}</div>
  33. </div>
  34. <div class="info-item">
  35. <div class="item-label">阶段</div>
  36. <div class="item-value">
  37. {{
  38. dictStroe.getLableByValue(
  39. "stage",
  40. infoData?.stageDictValue
  41. )
  42. }}
  43. </div>
  44. </div>
  45. <div class="info-item">
  46. <div class="item-label">生产数量</div>
  47. <div class="item-value">{{ infoData?.planNum }}</div>
  48. </div>
  49. </div>
  50. </el-form-item>
  51. <el-row>
  52. <el-col :span="11">
  53. <el-form-item
  54. :label="`报故数量[${formLabelAlign.seqNoList.length}]`"
  55. prop="seqNoList"
  56. >
  57. <el-select
  58. v-model="formLabelAlign.seqNoList"
  59. multiple
  60. placeholder="请选择"
  61. value-key="value"
  62. @change="selectProcessWorkSeqChange"
  63. >
  64. <el-option
  65. v-for="item in infoData?.processWorkSeq"
  66. :key="item"
  67. :label="item"
  68. :value="item"
  69. />
  70. </el-select>
  71. </el-form-item>
  72. </el-col>
  73. <el-col :offset="1" :span="12">
  74. <el-form-item label="是否首检" prop="firstInspection">
  75. <el-radio-group v-model="formLabelAlign.firstInspection">
  76. <el-radio :value="0" border>否</el-radio>
  77. <el-radio :value="1" border>是</el-radio>
  78. </el-radio-group>
  79. </el-form-item>
  80. </el-col>
  81. </el-row>
  82. <el-row>
  83. <el-col :span="11">
  84. <el-form-item label="缺陷分类" prop="reasonType">
  85. <el-select
  86. v-model="formLabelAlign.reasonType"
  87. placeholder="请选择"
  88. value-key="dictValue"
  89. @change="selectQuexianType"
  90. >
  91. <el-option
  92. v-for="item in dictStroe.dicts.defect_mana"
  93. :key="item.dictValue"
  94. :label="item.dictLabel"
  95. :value="item.dictValue"
  96. />
  97. </el-select>
  98. </el-form-item>
  99. </el-col>
  100. <el-col :offset="1" :span="12">
  101. <el-form-item label="缺陷名称" prop="reasonList">
  102. <el-select
  103. v-model="formLabelAlign.reasonList"
  104. filterable
  105. multiple
  106. placeholder="请选择"
  107. value-key="id"
  108. >
  109. <el-option
  110. v-for="item in quexianList"
  111. :key="item.id"
  112. :label="item.bugName"
  113. :value="item"
  114. />
  115. </el-select>
  116. </el-form-item>
  117. </el-col>
  118. </el-row>
  119. <el-row>
  120. <el-col :span="11">
  121. <el-form-item
  122. label="不合格品分布情况及工序"
  123. prop="processesList"
  124. >
  125. <el-select
  126. v-model="formLabelAlign.processesList"
  127. multiple
  128. placeholder="请选择"
  129. value-key="operationId"
  130. >
  131. <el-option
  132. v-for="item in operationList"
  133. :key="item.operationId"
  134. :label="item.operationName"
  135. :value="item.operationId"
  136. />
  137. </el-select>
  138. </el-form-item>
  139. </el-col>
  140. <el-col :offset="1" :span="12">
  141. <el-form-item label="责任/经办者" prop="personResponsible">
  142. <el-select
  143. v-model="formLabelAlign.personResponsible"
  144. filterable
  145. placeholder="请选择"
  146. value-key="id"
  147. >
  148. <el-option
  149. v-for="item in dictStroe.allUsers"
  150. :key="item.id"
  151. :label="item.userName"
  152. :value="item.userName"
  153. />
  154. </el-select>
  155. </el-form-item>
  156. </el-col>
  157. </el-row>
  158. <el-form-item label="缺陷图片" prop="fileList">
  159. <div>
  160. <div>
  161. <el-button style="margin-bottom: 8px" @click="camera_ohos"
  162. >上传图片
  163. </el-button>
  164. </div>
  165. <div v-if="formLabelAlign.fileList?.length > 0">
  166. <el-image
  167. v-for="url in formLabelAlign.fileList"
  168. :src="url"
  169. fit="cover"
  170. style="width: 100px; height: 100px; margin-right: 10px"
  171. />
  172. </div>
  173. </div>
  174. </el-form-item>
  175. <el-form-item label="备注" prop="remark">
  176. <el-input
  177. v-model="formLabelAlign.remark"
  178. :rows="3"
  179. type="textarea"
  180. />
  181. </el-form-item>
  182. </el-form>
  183. </div>
  184. <div class="bottom-btns">
  185. <el-button class="cancelBtn" @click="cancelClick">取消</el-button>
  186. <el-button class="sureBtn" type="primary" @click="confirmClick"
  187. >报故
  188. </el-button>
  189. </div>
  190. </el-scrollbar>
  191. </template>
  192. <template #footer></template>
  193. </el-drawer>
  194. </template>
  195. <script lang="ts" setup>
  196. import {
  197. addBreakReport,
  198. basebugsByType,
  199. breakReportInfoById,
  200. operationListByIds,
  201. } from "@/api/process/reportBreak";
  202. import { useProcessStore } from "@/store/modules/processView";
  203. import { useDictionaryStore } from "@/store/modules/dictionary";
  204. import { getProcessInfo } from "@/api/prosteps";
  205. const processStore = useProcessStore();
  206. const dictStroe = useDictionaryStore();
  207. const drawerVisible = ref(false);
  208. const infoData = ref<any>({});
  209. const formRef = ref<InstanceType<typeof ElForm>>();
  210. const formLabelAlign = reactive({
  211. seqNoList: [],
  212. reasonType: "",
  213. reasonList: [],
  214. processesList: [],
  215. fileList: [],
  216. firstInspection: 0,
  217. personResponsible: "",
  218. remark: "",
  219. });
  220. const rules = reactive({
  221. trackingNumber: [
  222. { required: true, message: "请输入 追踪卡号", trigger: "blur" },
  223. ],
  224. workOrderNumber: [
  225. { required: true, message: "请输入 工作令号", trigger: "blur" },
  226. ],
  227. archiveNumber: [
  228. { required: true, message: "请输入 归档编号", trigger: "blur" },
  229. ],
  230. seqNoList: [{ required: true, message: "请选择 ", trigger: "blur" }],
  231. });
  232. const openReportBreakDrawer = () => {
  233. getProcessInfo(processStore.scanInfo.id).then((res) => {
  234. processStore.scanInfo.currentState = res.data.currentState;
  235. if (res.data.currentState !== "start") {
  236. ElMessage.error("当前工单状态不允许报故");
  237. return;
  238. } else {
  239. drawerVisible.value = true;
  240. breakReportInfoById(processStore.scanInfo.id).then((res) => {
  241. infoData.value = res.data;
  242. });
  243. }
  244. });
  245. };
  246. // 报故数量,选择工序号相关. 选择之后获取工序列表
  247. const operationList = ref<any[]>([]);
  248. const selectProcessWorkSeqChange = useDebounceFn(() => {
  249. operationListByIds(formLabelAlign.seqNoList).then((res) => {
  250. operationList.value = res.data;
  251. });
  252. }, 2000);
  253. const quexianList = ref<any>([]);
  254. const selectQuexianType = (value: string) => {
  255. basebugsByType(value).then((res) => {
  256. quexianList.value = res.data || [];
  257. });
  258. };
  259. const cancelClick = () => {
  260. drawerVisible.value = false;
  261. };
  262. const confirmClick = () => {
  263. formRef.value &&
  264. formRef.value.validate((valid: boolean) => {
  265. if (valid) {
  266. let params = {
  267. processId: processStore.scanInfo.id,
  268. ...formLabelAlign,
  269. };
  270. addBreakReport(params).then(() => {
  271. ElMessage.success("报故成功");
  272. drawerVisible.value = false;
  273. });
  274. } else {
  275. return false;
  276. }
  277. });
  278. };
  279. const camera_ohos = () => {
  280. let p = {
  281. token: localStorage.getItem("token"),
  282. method: "post",
  283. methodName: "startCamera",
  284. messageKey: "report_bad",
  285. };
  286. if (window.openHarmonyBridge && window.openHarmonyBridge.startCamera) {
  287. window.openHarmonyBridge.startCamera(JSON.stringify(p));
  288. }
  289. };
  290. window.addEventListener("message", (event) => {
  291. const data = JSON.parse(event.data);
  292. if (data.fullUrl && data.messageKey && data.messageKey === "report_bad") {
  293. formLabelAlign.fileList.push(data.fullUrl);
  294. }
  295. });
  296. defineExpose({
  297. openReportBreakDrawer,
  298. });
  299. </script>
  300. <style lang="scss" scoped>
  301. #drawContent {
  302. width: 100%;
  303. //:deep(.el-form--large.el-form--label-top .el-form-item .el-form-item__label) {
  304. // font-weight: 500;
  305. // font-size: 22px;
  306. // color: rgba(0, 0, 0, 0.9);
  307. // text-align: left;
  308. //}
  309. }
  310. .base-info {
  311. width: 100%;
  312. background: #e3e5e7;
  313. border-radius: 16px 16px 16px 16px;
  314. padding: 0 30px;
  315. .info-item {
  316. display: flex;
  317. justify-content: space-between;
  318. align-items: center;
  319. height: 30px;
  320. .item-label {
  321. font-size: 18px;
  322. color: rgba(0, 0, 0, 0.6);
  323. }
  324. .item-value {
  325. font-weight: 500;
  326. font-size: 18px;
  327. color: rgba(0, 0, 0, 0.9);
  328. }
  329. }
  330. .info-item:not(:last-child) {
  331. border-bottom: 1px solid rgba(0, 0, 0, 0.2);
  332. }
  333. }
  334. .bottom-btns {
  335. display: flex;
  336. justify-content: center;
  337. //margin-top: 20px;
  338. //margin-bottom: 20px;
  339. .button {
  340. margin-right: 20px;
  341. }
  342. .cancelBtn {
  343. width: 292px;
  344. height: 40px;
  345. background: rgba(0, 0, 0, 0.06);
  346. border-radius: 76px 76px 76px 76px;
  347. }
  348. .sureBtn {
  349. width: 292px;
  350. height: 40px;
  351. background: #0a59f7;
  352. border-radius: 76px 76px 76px 76px;
  353. }
  354. }
  355. </style>