programRulesDialog.vue 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402
  1. <template>
  2. <ele-modal
  3. :title="title"
  4. :visible.sync="visible"
  5. :close-on-click-modal="false"
  6. @close="handleClose"
  7. append-to-body
  8. resizable
  9. maxable
  10. width="80%"
  11. >
  12. <header-title title="基本信息"></header-title>
  13. <el-form
  14. ref="formRef"
  15. :model="addForm"
  16. :rules="rules"
  17. label-width="120px"
  18. :disabled="type === 'detail'"
  19. v-loading="loading"
  20. >
  21. <el-row>
  22. <el-col :span="8">
  23. <el-form-item label="计划配置单号" prop="code">
  24. <el-input
  25. v-model="addForm.code"
  26. size="small"
  27. placeholder="自动带出"
  28. disabled
  29. ></el-input>
  30. </el-form-item>
  31. </el-col>
  32. <el-col :span="8">
  33. <el-form-item label="计划配置名称" prop="name">
  34. <el-input
  35. v-model="addForm.name"
  36. size="small"
  37. placeholder="请输入"
  38. :disabled="type === 'dispatch'"
  39. ></el-input>
  40. </el-form-item>
  41. </el-col>
  42. <el-col :span="8">
  43. <el-form-item label="自动派单" prop="autoOrder">
  44. <el-select
  45. v-model="addForm.autoOrder"
  46. size="small"
  47. style="width: 100%"
  48. :disabled="type === 'dispatch'"
  49. >
  50. <el-option :value="1" label="是"></el-option>
  51. <el-option :value="0" label="否"></el-option>
  52. </el-select>
  53. </el-form-item>
  54. </el-col>
  55. <el-col :span="8">
  56. <el-form-item label="计划完成时长" prop="duration">
  57. <div style="display: flex">
  58. <el-input
  59. type="number"
  60. v-model="addForm.duration"
  61. size="small"
  62. placeholder="请输入"
  63. @input="formDataDurationTime"
  64. :disabled="type === 'dispatch'"
  65. >
  66. <template #suffix>分钟</template>
  67. </el-input>
  68. </div>
  69. </el-form-item>
  70. </el-col>
  71. <el-col :span="8">
  72. <el-form-item label="类型" prop="type">
  73. <el-select
  74. v-model="addForm.type"
  75. size="small"
  76. @change="typeChange"
  77. style="width: 100%"
  78. :disabled="addForm.autoOrder == 1 && type === 'dispatch'"
  79. >
  80. <el-option :value="1" label="班组"></el-option>
  81. <el-option :value="0" label="个人"></el-option>
  82. </el-select>
  83. </el-form-item>
  84. </el-col>
  85. <el-col :span="8" v-if="dispatchStatus && addForm.type == 1">
  86. <el-form-item label="班组" prop="teamId">
  87. <el-select
  88. v-model="addForm.teamId"
  89. size="small"
  90. @change="teamChange()"
  91. style="width: 100%"
  92. >
  93. <el-option
  94. :value="i.id"
  95. :label="i.name"
  96. v-for="i in teamAllList"
  97. :key="i.id"
  98. ></el-option>
  99. </el-select>
  100. </el-form-item>
  101. </el-col>
  102. <el-col :span="8" v-if="dispatchStatus && addForm.type == 1">
  103. <el-form-item label="场站" prop="productLineId">
  104. <el-select
  105. v-model="addForm.productLineId"
  106. placeholder="请选择场站"
  107. filterable
  108. style="width: 100%"
  109. >
  110. <el-option
  111. v-for="item in productLineList"
  112. :label="item.name"
  113. :value="item.id"
  114. :key="item.id"
  115. @click.native="addForm.productLineName = item.name"
  116. >
  117. </el-option>
  118. </el-select>
  119. </el-form-item>
  120. </el-col>
  121. <el-col :span="8" v-if="dispatchStatus && addForm.type == 0">
  122. <el-form-item label="部门" prop="groupId">
  123. <deptSelect
  124. v-model="addForm.groupId"
  125. @changeGroup="searchDeptNodeClick"
  126. />
  127. </el-form-item>
  128. </el-col>
  129. <el-col :span="8" v-if="dispatchStatus && addForm.type == 0">
  130. <el-form-item label="负责人" prop="executeIdList">
  131. <el-select
  132. v-model="addForm.executeIdList"
  133. size="small"
  134. style="width: 100%"
  135. multiple
  136. filterable
  137. @change="executeIdListChange"
  138. key="executeIdList"
  139. >
  140. <el-option
  141. v-for="item in executorList"
  142. :key="item.id"
  143. :value="item.id"
  144. :label="item.name"
  145. ></el-option>
  146. </el-select>
  147. </el-form-item>
  148. </el-col>
  149. <!-- <el-col :span="8">
  150. <el-form-item label="审核人" prop="approvalUserId">
  151. <el-select
  152. v-model="addForm.approvalUserId"
  153. size="small"
  154. clearable
  155. style="width: 100%"
  156. filterable
  157. >
  158. <el-option
  159. v-for="item in uerList"
  160. :key="item.id"
  161. :value="item.id"
  162. :label="item.name"
  163. ></el-option>
  164. </el-select>
  165. </el-form-item>
  166. </el-col> -->
  167. <el-col :span="8">
  168. <el-form-item label="紧急程度" prop="urgent">
  169. <DictSelection
  170. dictName="紧急程度"
  171. clearable
  172. v-model="addForm.urgent"
  173. :disabled="type === 'dispatch'"
  174. >
  175. </DictSelection>
  176. </el-form-item>
  177. </el-col>
  178. <el-col :span="8">
  179. <el-form-item label="关联记录规则" required prop="ruleName">
  180. <div class="mask-box" @click="handleAddTab">
  181. <el-input
  182. v-model="addForm.ruleName"
  183. placeholder="请选择记录规则"
  184. size="small"
  185. readonly
  186. :disabled="type === 'dispatch'"
  187. >
  188. <template #append>
  189. <el-button size="small">选择规则</el-button>
  190. </template>
  191. </el-input>
  192. </div>
  193. </el-form-item>
  194. </el-col>
  195. <el-col :span="8">
  196. <el-form-item label="关联对象" prop="associatedObject">
  197. <el-select
  198. v-model="addForm.associatedObject"
  199. size="small"
  200. style="width: 100%"
  201. >
  202. <el-option :value="1" label="车间"></el-option>
  203. <el-option :value="2" label="设备"></el-option>
  204. </el-select>
  205. </el-form-item>
  206. </el-col>
  207. <el-col :span="8" v-if="addForm.associatedObject == 1">
  208. <el-form-item label="关联车间" required prop="workshopPlanName">
  209. <div class="mask-box" @click="openWorkShops(1)">
  210. <el-input
  211. v-model="addForm.workshopPlanName"
  212. placeholder="请选择关联车间"
  213. size="small"
  214. readonly
  215. :disabled="type === 'dispatch'"
  216. >
  217. <template #append>
  218. <el-button size="small">选择车间</el-button>
  219. </template>
  220. </el-input>
  221. </div>
  222. </el-form-item>
  223. </el-col>
  224. <el-col :span="8" v-if="addForm.associatedObject == 2">
  225. <el-form-item label="关联设备" required prop="deviceName">
  226. <div class="mask-box" @click="openWorkShops(2)">
  227. <el-input
  228. v-model="addForm.deviceName"
  229. placeholder="请选择关联设备"
  230. size="small"
  231. readonly
  232. :disabled="type === 'dispatch'"
  233. >
  234. <template #append>
  235. <el-button size="small">选择设备</el-button>
  236. </template>
  237. </el-input>
  238. </div>
  239. </el-form-item>
  240. </el-col>
  241. <el-col :span="16">
  242. <el-form-item label="备注" prop="remark">
  243. <el-input
  244. type="textarea"
  245. resize="none"
  246. v-model="addForm.remark"
  247. :rows="2"
  248. placeholder="请详细说明"
  249. size="small"
  250. :disabled="type === 'dispatch'"
  251. ></el-input>
  252. </el-form-item>
  253. </el-col>
  254. </el-row>
  255. <header-title title="规则明细" style="margin-top: 20px"> </header-title>
  256. <el-tabs
  257. v-if="addForm.recordTemplateStyle == '4'"
  258. v-model="statisticsType"
  259. type="card"
  260. >
  261. <el-tab-pane
  262. v-for="i in statisticsTypeList"
  263. :label="i.label"
  264. :name="i.value"
  265. :key="i.value"
  266. >
  267. </el-tab-pane>
  268. </el-tabs>
  269. <ele-pro-table
  270. ref="table"
  271. :columns="bankColumns"
  272. :datasource="detialsDatasource"
  273. :need-page="false"
  274. row-key="id"
  275. class="table_list"
  276. cache-key="workshop-record-plan-details-item-2511201537"
  277. >
  278. <template v-slot:toolbar>
  279. <div style="display: flex; align-items: center; gap: 10px">
  280. <el-button
  281. type="primary"
  282. icon="el-icon-plus"
  283. class="ele-btn-icon"
  284. @click="addRow()"
  285. >
  286. 新建
  287. </el-button>
  288. </div>
  289. </template>
  290. <template v-slot:sortNum="{ row }">
  291. <el-input-number
  292. style="width: 80px"
  293. v-model.number="row.sortNum"
  294. placeholder="请输入排序"
  295. size="mini"
  296. type="number"
  297. :min="1"
  298. controls-position="right"
  299. ></el-input-number>
  300. </template>
  301. <template v-slot:paramType="{ row }">
  302. <el-select
  303. v-model="row.paramType"
  304. placeholder="请选择参数类型"
  305. size="mini"
  306. @change="paramTypeChange(row)"
  307. >
  308. <el-option label="数值" :value="1" />
  309. <el-option label="选择" :value="2" />
  310. <el-option label="上下限" :value="3" />
  311. <el-option label="规格" :value="4" />
  312. <el-option label="时间" :value="5" />
  313. <el-option label="范围" :value="6" />
  314. <el-option label="文本" :value="7" />
  315. <!-- <el-option label="枚举" :value="8" /> -->
  316. <el-option label="计算" :value="9" />
  317. </el-select>
  318. </template>
  319. <template v-slot:paramValue="{ row }">
  320. <!-- 根据参数类型渲染不同的输入组件 -->
  321. <el-link
  322. v-if="addForm.recordTemplateStyle == '3'"
  323. :underline="false"
  324. style="cursor: pointer"
  325. >
  326. <div class="ele-cell">
  327. <div @click="selectChooseModalProduct(row)">
  328. {{ row.productName ? row.productName : '请选择产品' }}
  329. </div>
  330. <i
  331. v-if="row.tools.length == 0"
  332. class="el-icon-arrow-down"
  333. @click="selectChooseModalProduct(row)"
  334. ></i>
  335. <i v-else class="el-icon-close" @click="clearProduct(row)"></i>
  336. </div>
  337. </el-link>
  338. <el-input
  339. v-else
  340. v-model="row.paramValue"
  341. placeholder="请输入参数内容"
  342. size="mini"
  343. type="textarea"
  344. rows="1"
  345. autosize
  346. ></el-input>
  347. </template>
  348. <template v-slot:formula="{ row }">
  349. <div v-if="row.paramType == 9" class="formula-builder">
  350. <div class="formula-builder__selects">
  351. <!-- 选择参数:从已填的非计算参数内容里取 -->
  352. <el-select
  353. v-model="row._paramSelect"
  354. placeholder="选择参数"
  355. size="mini"
  356. style="width: 100px; margin-right: 8px; flex-shrink: 0"
  357. @change="paramSelectChange($event, row)"
  358. >
  359. <el-option
  360. v-for="item in getSelectOptionsByDetails(
  361. row.statisticsType,
  362. item
  363. )"
  364. :key="item.value"
  365. :label="item.label"
  366. :value="item.value"
  367. />
  368. </el-select>
  369. <!-- 选择运算符 -->
  370. <el-select
  371. v-model="row._opSelect"
  372. :key="row._opSelect + '_opSelect'"
  373. placeholder="选择符号"
  374. size="mini"
  375. style="width: 100px; flex-shrink: 0"
  376. @change="opSelectChange($event, row)"
  377. >
  378. <el-option
  379. v-for="op in opSelectOptions"
  380. :key="op"
  381. :label="op"
  382. :value="op"
  383. />
  384. </el-select>
  385. <!-- 替换或者追加 -->
  386. <el-select
  387. v-if="row.activeIndex != undefined"
  388. v-model="row._replaceOrAppend"
  389. :key="row._replaceOrAppend + 'row._replaceOrAppend'"
  390. placeholder="选择"
  391. size="mini"
  392. style="width: 80px; margin-left: 8px; flex-shrink: 0"
  393. >
  394. <el-option key="append" label="追加" value="append" />
  395. <el-option key="replace" label="替换" value="replace" />
  396. </el-select>
  397. </div>
  398. <!-- 已组装公式标签展示 -->
  399. <div
  400. v-if="row.formulaParts && row.formulaParts.length"
  401. style="display: inline-flex; flex-wrap: wrap; max-width: 100%"
  402. >
  403. <el-tag
  404. v-for="(p, index) in row.formulaParts"
  405. :key="index"
  406. size="mini"
  407. closable
  408. :type="row.activeIndex === index ? 'primary' : 'info'"
  409. @click="formulaPartsTagClick(index, row)"
  410. @close="tagItemDelete(index, row)"
  411. >
  412. {{ p }}
  413. </el-tag>
  414. </div>
  415. <!-- 公式字符串展示(只读) -->
  416. <el-input
  417. v-if="row.formulaParts && row.formulaParts.length"
  418. :value="row.formulaParts.join('')"
  419. size="mini"
  420. type="textarea"
  421. disabled
  422. placeholder="公式"
  423. style="margin-top: 6px"
  424. />
  425. </div>
  426. </template>
  427. <template v-slot:defaultValue="{ row }">
  428. <el-row>
  429. <el-col :span="12">
  430. <!-- <el-select
  431. v-if="row.paramType != 7"
  432. v-model="row.symbol"
  433. placeholder="请选择"
  434. size="mini"
  435. >
  436. <el-option label=">" value=">"> </el-option>
  437. <el-option label="<" value="<"> </el-option>
  438. <el-option label="!=" value="!="> </el-option>
  439. <el-option label=">=" value=">="> </el-option>
  440. <el-option label="<=" value="<="> </el-option>
  441. <el-option label="~~" value="~~"> </el-option>
  442. <el-option label="+-" value="+-"> </el-option>
  443. <el-option label="......" value="......"> </el-option>
  444. </el-select> -->
  445. <DictSelection
  446. v-if="row.paramType != 7"
  447. clearable
  448. dictName="数学字符"
  449. v-model="row.symbol"
  450. placeholder="请选择逻辑"
  451. size="mini"
  452. ></DictSelection>
  453. </el-col>
  454. <el-col :span="row.paramType != 7 ? 12 : 24">
  455. <el-input
  456. v-model="row.defaultValue"
  457. placeholder="请输入默认值"
  458. size="mini"
  459. ></el-input>
  460. </el-col>
  461. </el-row>
  462. </template>
  463. <template v-slot:maxValue="{ row }">
  464. <el-input
  465. v-if="row.paramType == 3 || row.paramType == 6"
  466. v-model="row.maxValue"
  467. placeholder="请输入参数上限"
  468. size="mini"
  469. ></el-input>
  470. </template>
  471. <template v-slot:minValue="{ row }">
  472. <el-input
  473. v-if="row.paramType == 3 || row.paramType == 6"
  474. v-model="row.minValue"
  475. placeholder="请输入参数下限"
  476. size="mini"
  477. ></el-input>
  478. </template>
  479. <template v-slot:unitName="{ row }">
  480. <!-- <el-input
  481. v-model="row.unitName"
  482. placeholder="请输入参数单位"
  483. size="mini"
  484. ></el-input> -->
  485. <DictSelection
  486. v-if="row.paramType != 7"
  487. dictName="工艺参数单位"
  488. clearable
  489. filterable
  490. v-model="row.unitName"
  491. size="mini"
  492. >
  493. </DictSelection>
  494. </template>
  495. <template v-slot:toolName="{ row }">
  496. <el-link :underline="false" style="cursor: pointer">
  497. <div class="ele-cell">
  498. <div @click="handleAdd(row)">
  499. {{
  500. row.tools && row.tools.length > 0
  501. ? row.tools.map((i) => i.toolName).join(',')
  502. : '请选择'
  503. }}
  504. </div>
  505. <i
  506. v-if="row.tools.length == 0"
  507. class="el-icon-arrow-down"
  508. @click="handleAdd(row)"
  509. ></i>
  510. <i v-else class="el-icon-close" @click="clearTool(row)"></i>
  511. </div>
  512. </el-link>
  513. </template>
  514. <template v-slot:toolCodes="{ row }">
  515. <el-input
  516. :value="
  517. row.tools && row.tools.length > 0
  518. ? row.tools.map((i) => i.toolCode).join(',')
  519. : ''
  520. "
  521. placeholder="工具自动带出"
  522. disabled
  523. size="mini"
  524. ></el-input>
  525. </template>
  526. <template v-slot:remark="{ row }">
  527. <el-input
  528. v-model="row.remark"
  529. placeholder="请输入"
  530. size="mini"
  531. ></el-input>
  532. </template>
  533. <template v-slot:action="{ row }">
  534. <el-link
  535. v-if="type != 'detail'"
  536. type="danger"
  537. :underline="false"
  538. icon="el-icon-delete"
  539. @click="deleteRow(item, row)"
  540. >
  541. 删除
  542. </el-link>
  543. </template>
  544. </ele-pro-table>
  545. </el-form>
  546. <template v-slot:footer>
  547. <el-button
  548. v-if="type != 'detail'"
  549. type="primary"
  550. @click="submit"
  551. :loading="butLoading"
  552. >{{ type == 'dispatch' ? '派单' : '保存' }}</el-button
  553. >
  554. <el-button @click="handleClose">取消</el-button>
  555. </template>
  556. <selectReleaseRules
  557. ref="selectReleaseRulesRef"
  558. @chooseRules="chooseRules"
  559. :classify="classify"
  560. ></selectReleaseRules>
  561. <selectWorkshop
  562. ref="selectWorkshopRef"
  563. @confirm="confirmWorkshops"
  564. ></selectWorkshop>
  565. <toolModal ref="toolModalTowRef" @chooseModal="chooseModalProduct" />
  566. <MaterialAdd ref="MaterialAddRef" @chooseEquipment="confirmWorkshops" />
  567. <toolModal ref="toolModalRef" @chooseModal="chooseModal" />
  568. </ele-modal>
  569. </template>
  570. <script>
  571. import dictMixins from '@/mixins/dictMixins';
  572. import tableColumnsMixin from '@/mixins/tableColumnsMixin';
  573. import { getUserPage } from '@/api/system/organization';
  574. import deptSelect from '@/components/CommomSelect/dept-select.vue';
  575. import { getCode } from '@/api/login/index.js';
  576. import selectReleaseRules from '@/components/selectReleaseRules/select-release-rules.vue';
  577. import selectWorkshop from '@/components/selectWorkshop/selectWorkshop.vue';
  578. import {
  579. getRecordRulesPlanDetail,
  580. save,
  581. update,
  582. recordrulesGetById,
  583. recordrulesplanManualDispatchOrder
  584. } from '@/api/recordRules/index.js';
  585. import toolModal from '@/BIZComponents/toolModal.vue';
  586. import MaterialAdd from '@/components/common/MaterialAdd.vue';
  587. import { getteampage } from '@/api/main/index.js';
  588. const formBaseData = {
  589. address: '',
  590. areaId: 0,
  591. areaName: '',
  592. autoOrder: 1,
  593. code: '',
  594. configCode: '',
  595. configType: 1,
  596. createUserName: '',
  597. detailList: [],
  598. duration: null,
  599. executeUsers: [],
  600. factoryId: null,
  601. factoryName: '',
  602. id: null,
  603. name: '',
  604. planEndTime: '',
  605. planStartTime: '',
  606. remark: '',
  607. ruleId: null,
  608. ruleName: '',
  609. status: 0,
  610. type: 0,
  611. updateUserName: '',
  612. urgent: 1,
  613. workshopCode: '',
  614. workshopId: null,
  615. workshopName: '',
  616. workshopPlanId: null,
  617. workshopPlanName: '',
  618. recordRulesClassify: null,
  619. recordTemplateStyle: null,
  620. reportWorkType: null,
  621. executeIdList: [],
  622. associatedObject: 1,
  623. deviceName: '',
  624. deviceId: '',
  625. deviceCode: '',
  626. planType: 2,
  627. groupId: '', // 部门id
  628. teamId: '', // 班组id
  629. teamName: '', // 班组id
  630. productLineId: null,
  631. productLineName: ''
  632. };
  633. export default {
  634. props: {
  635. planType: {
  636. type: Number,
  637. default: 2
  638. }
  639. },
  640. mixins: [dictMixins, tableColumnsMixin],
  641. components: {
  642. deptSelect,
  643. selectReleaseRules,
  644. selectWorkshop,
  645. toolModal,
  646. MaterialAdd
  647. },
  648. data() {
  649. return {
  650. visible: false,
  651. title: '新增记录计划配置',
  652. activeIndex: 0,
  653. classify: '',
  654. addForm: JSON.parse(JSON.stringify(formBaseData)),
  655. rules: {
  656. name: [
  657. { required: true, message: '请输入计划配置名称', trigger: 'blur' }
  658. ],
  659. autoOrder: [
  660. { required: true, message: '请选择是否自动派单', trigger: 'change' }
  661. ],
  662. ruleId: [
  663. { required: true, message: '请选择规则名称', trigger: 'change' }
  664. ],
  665. duration: [
  666. { required: true, message: '请输入计划完成时长', trigger: 'blur' }
  667. ],
  668. deviceName: [
  669. { required: true, message: '请选择设备', trigger: 'change' }
  670. ],
  671. // categoryId: [
  672. // { required: true, message: '请选择设备类别', trigger: 'change' }
  673. // ],
  674. groupId: [
  675. { required: true, message: '请选择部门', trigger: 'change' }
  676. ],
  677. teamId: [
  678. { required: true, message: '请选择班组', trigger: 'change' }
  679. ],
  680. executeIdList: [
  681. { required: true, message: '请选择人员', trigger: 'change' }
  682. ],
  683. urgent: [
  684. { required: true, message: '请选择紧急程度', trigger: 'change' }
  685. ],
  686. ruleName: [
  687. { required: true, message: '请选择规则名称', trigger: 'change' }
  688. ],
  689. workshopPlanName: [
  690. { required: true, message: '请选择车间区域', trigger: 'change' }
  691. ]
  692. },
  693. executorList: [],
  694. uerList: [],
  695. // 执行方式列表
  696. executeMethodList: [],
  697. // 1-成品统计,2-物料统计,3-工序统计"
  698. statisticsType: '1',
  699. statisticsTypeList: [
  700. { label: '成品统计', value: '1' },
  701. { label: '物料统计', value: '2' },
  702. { label: '工序统计', value: '3' }
  703. ],
  704. opSelectOptions: ['+', '-', '*', '/', '%', '(', ')'],
  705. butLoading: false,
  706. teamAllList: [],
  707. productLineList: [],
  708. loading: false,
  709. type: 'add' // 弹窗类型 add-新增 edit-编辑 detail-查看
  710. };
  711. },
  712. computed: {
  713. dispatchStatus() {
  714. return (
  715. (this.addForm.autoOrder &&
  716. (this.type == 'add' ||
  717. this.type == 'edit' ||
  718. this.type == 'detail')) ||
  719. (!this.addForm.autoOrder && this.type == 'dispatch')
  720. );
  721. },
  722. // 当前用户信息
  723. loginUser() {
  724. return this.$store.state.user?.info;
  725. },
  726. workshopsColumns() {
  727. return [
  728. {
  729. width: 45,
  730. type: 'index',
  731. columnKey: 'index',
  732. align: 'center'
  733. },
  734. {
  735. prop: 'workshopCode',
  736. label: '车间编码'
  737. },
  738. {
  739. label: '车间名称',
  740. prop: 'workshopName'
  741. },
  742. {
  743. label: '所属工厂',
  744. prop: 'factoryName'
  745. },
  746. {
  747. label: '所属厂房',
  748. prop: 'workshopPlanName',
  749. slot: 'factory'
  750. },
  751. {
  752. label: '所属区域',
  753. prop: 'areaName'
  754. },
  755. {
  756. label: '详细地址',
  757. prop: 'address'
  758. },
  759. {
  760. columnKey: 'action',
  761. label: '操作',
  762. width: 110,
  763. align: 'center',
  764. resizable: false,
  765. slot: 'action',
  766. fixed: 'right'
  767. }
  768. ];
  769. },
  770. bankColumns() {
  771. const list = [
  772. {
  773. width: 110,
  774. type: 'index',
  775. columnKey: 'index',
  776. align: 'center',
  777. label: '序号'
  778. },
  779. {
  780. prop: 'sortNum',
  781. label: '排序',
  782. align: 'center',
  783. slot: 'sortNum',
  784. minWidth: 110
  785. },
  786. {
  787. prop: 'paramType',
  788. label: '参数类型',
  789. align: 'center',
  790. slot: 'paramType',
  791. minWidth: 110
  792. },
  793. {
  794. prop: 'paramValue',
  795. label: '参数内容',
  796. align: 'center',
  797. slot: 'paramValue',
  798. minWidth: 261
  799. },
  800. {
  801. prop: 'formula',
  802. label: '计算公式',
  803. align: 'center',
  804. slot: 'formula',
  805. minWidth: 300
  806. },
  807. {
  808. prop: 'defaultValue',
  809. label: '默认值',
  810. align: 'center',
  811. slot: 'defaultValue',
  812. minWidth: 150
  813. },
  814. {
  815. prop: 'maxValue',
  816. label: '参数上限',
  817. align: 'center',
  818. slot: 'maxValue',
  819. minWidth: 110
  820. },
  821. {
  822. prop: 'minValue',
  823. label: '参数下限',
  824. align: 'center',
  825. slot: 'minValue',
  826. minWidth: 110
  827. },
  828. {
  829. prop: 'unitName',
  830. label: '参数单位',
  831. align: 'center',
  832. slot: 'unitName',
  833. minWidth: 110
  834. },
  835. {
  836. prop: 'toolName',
  837. label: '工具名称',
  838. align: 'center',
  839. slot: 'toolName',
  840. minWidth: 110
  841. },
  842. {
  843. prop: 'toolCodes',
  844. label: '工具编码',
  845. align: 'center',
  846. slot: 'toolCodes',
  847. minWidth: 110
  848. },
  849. {
  850. prop: 'remark',
  851. label: '备注',
  852. align: 'center',
  853. slot: 'remark',
  854. minWidth: 110
  855. },
  856. {
  857. columnKey: 'action',
  858. label: '操作',
  859. width: 110,
  860. align: 'center',
  861. resizable: false,
  862. slot: 'action',
  863. fixed: 'right'
  864. }
  865. ];
  866. if (this.addForm.recordTemplateStyle != '4') {
  867. // 过滤掉 计算公式 列
  868. return list.filter((i) => i.prop != 'formula');
  869. }
  870. return list;
  871. },
  872. // 过滤明细数据源
  873. detialsDatasource() {
  874. // 如果是模板样式4,过滤统计类型
  875. if (this.addForm.recordTemplateStyle == '4') {
  876. return this.addForm.detailList.filter(
  877. (i) => i.statisticsType == this.statisticsType
  878. );
  879. }
  880. return this.addForm.detailList;
  881. }
  882. },
  883. created() {
  884. // 获取审核人列表、巡点检人员
  885. this.getUserList();
  886. // 获取所有班组
  887. },
  888. methods: {
  889. // 外部调用,打开弹窗
  890. async open(type, data, classify) {
  891. console.log('type data', type, data);
  892. this.classify = classify;
  893. this.type = type;
  894. await this.getAllTeamList();
  895. if (type == 'add') {
  896. this.title = '新增记录计划配置';
  897. this.getOrderCode();
  898. } else if (type == 'edit') {
  899. this.title = '修改记录计划配置';
  900. this.getDetail(data.id);
  901. } else if (type == 'dispatch') {
  902. this.title = '派单';
  903. this.getDetail(data.id);
  904. } else {
  905. this.title = '查看记录计划配置';
  906. this.getDetail(data.id);
  907. }
  908. this.visible = true;
  909. this.$nextTick(() => {
  910. this.$refs.formRef.clearValidate();
  911. });
  912. },
  913. // 查询详情
  914. async getDetail(id) {
  915. this.loading = true;
  916. const data = await getRecordRulesPlanDetail(id);
  917. console.log('记录计划配置详情', data);
  918. this.$util.assignObject(this.addForm, data);
  919. // 处理回显数据
  920. if (this.addForm.type === 0) {
  921. // 个人
  922. this.addForm.executeIdList = this.addForm.executeUsers.map(
  923. (item) => item.userId
  924. );
  925. this.addForm.groupId = this.addForm.executeUsers[0]?.groupId || '';
  926. this.searchDeptNodeClick(this.addForm.groupId);
  927. } else {
  928. this.teamChange(true);
  929. }
  930. // if (this.type === 'dispatch') {
  931. // // 自动派单
  932. // this.addForm.autoOrder = 1;
  933. // }
  934. this.loading = false;
  935. console.log('this.addForm', this.addForm);
  936. },
  937. // 关闭时清理表单
  938. handleClose() {
  939. this.addForm = JSON.parse(JSON.stringify(formBaseData));
  940. this.$nextTick(() => {
  941. this.$refs.formRef.clearValidate();
  942. this.visible = false;
  943. });
  944. },
  945. // 构建数据
  946. formMateBody() {
  947. // 通过校验,构建数据
  948. const body = JSON.parse(JSON.stringify(this.addForm));
  949. return body;
  950. },
  951. // 提交
  952. submit() {
  953. console.log('this.addForm', this.addForm);
  954. this.$refs.formRef.validate(async (valid) => {
  955. if (valid) {
  956. if (!this.addForm.detailList?.length) {
  957. return this.$message.error('规则明细不能为空');
  958. }
  959. this.butLoading = true;
  960. try {
  961. // 赋值创建人和更新人
  962. if (this.addForm.id) {
  963. this.addForm.updateUserName = this.loginUser?.name || '';
  964. } else {
  965. this.addForm.createUserName = this.loginUser?.name || '';
  966. }
  967. const body = this.formMateBody();
  968. body.planType = this.planType;
  969. if (this.type == 'dispatch') {
  970. await recordrulesplanManualDispatchOrder(body);
  971. this.$message.success('派单成功');
  972. } else {
  973. let api = this.addForm.id ? update : save;
  974. await api(body);
  975. this.$message.success('保存成功');
  976. }
  977. this.butLoading = false;
  978. this.$emit('reload');
  979. this.handleClose();
  980. } catch (error) {
  981. this.butLoading = false;
  982. }
  983. }
  984. });
  985. },
  986. // 过滤计划完成时长
  987. formDataDurationTime(value) {
  988. if (value > 0) {
  989. this.addForm.duration = value.replace(/^[0]+/, '');
  990. } else {
  991. this.addForm.duration = 0;
  992. }
  993. },
  994. typeChange() {
  995. this.addForm.groupId = '';
  996. this.addForm.teamId = '';
  997. this.addForm.teamName = '';
  998. this.addForm.executeIdList = [];
  999. this.addForm.productLineName = '';
  1000. this.addForm.productLineId = '';
  1001. this.productLineList = [];
  1002. },
  1003. //选择部门(搜索)
  1004. async searchDeptNodeClick(info, data) {
  1005. if (info) {
  1006. // 根据部门获取人员
  1007. const params = { groupId: info };
  1008. await this.getUserList(params);
  1009. } else {
  1010. this.addForm.groupId = null;
  1011. }
  1012. },
  1013. // 获取审核人列表、巡点检人员
  1014. async getUserList(params) {
  1015. try {
  1016. let data = { pageNum: 1, size: -1 };
  1017. // 如果传了参数就是获取部门人员数据
  1018. if (params) {
  1019. data = Object.assign(data, params);
  1020. }
  1021. const res = await getUserPage(data);
  1022. if (params) {
  1023. this.executorList = res.list;
  1024. } else {
  1025. this.uerList = res.list;
  1026. }
  1027. } catch (error) {}
  1028. },
  1029. // 获取自动生成的单号
  1030. async getOrderCode() {
  1031. const data = await getCode('record_rules_plan_code');
  1032. this.addForm.code = data;
  1033. },
  1034. // 选择记录规则
  1035. handleAddTab() {
  1036. // 添加tab
  1037. this.$refs.selectReleaseRulesRef.open(
  1038. '',
  1039. '',
  1040. this.addForm.ruleId ? [this.addForm.ruleId] : []
  1041. );
  1042. },
  1043. async chooseRules(rules) {
  1044. console.log('选择的规则', rules);
  1045. // 查询规则明细,回显规则明细数据
  1046. const data = await recordrulesGetById(rules.id);
  1047. // 处理详情的 公式 字段
  1048. data.details.forEach((item) => {
  1049. if (item.paramType == 9 && item.formula) {
  1050. // formula格式为[A][+][b][*][C] 拆分 -> ['A','+','b','*','C']
  1051. if (item.formula) {
  1052. const matches = item.formula.match(/\[([^\]]+)\]/g);
  1053. if (matches) {
  1054. this.$set(
  1055. item,
  1056. 'formulaParts',
  1057. matches.map((m) => m.slice(1, -1)).filter(Boolean)
  1058. );
  1059. }
  1060. } else {
  1061. this.$set(item, 'formulaParts', []);
  1062. }
  1063. this.$set(item, '_paramSelect', null);
  1064. this.$set(item, '_opSelect', null);
  1065. this.$set(item, '_replaceOrAppend', '');
  1066. }
  1067. });
  1068. console.log('规则明细数据', data.details);
  1069. this.addForm.ruleId = rules.id;
  1070. this.addForm.ruleName = rules.name;
  1071. this.addForm.detailList = data.details;
  1072. this.addForm.recordRulesClassify = rules.classify;
  1073. this.addForm.recordTemplateStyle = rules.recordTemplateStyle;
  1074. this.addForm.reportWorkType = rules.reportWorkType;
  1075. },
  1076. // 打开选择车间弹窗
  1077. openWorkShops(type) {
  1078. if (type == 1) {
  1079. this.$refs.selectWorkshopRef.open();
  1080. } else {
  1081. this.$refs.MaterialAddRef.open();
  1082. }
  1083. },
  1084. confirmWorkshops(info) {
  1085. console.log('info', info);
  1086. if (this.addForm.associatedObject == 1) {
  1087. this.addForm.workshopId = info.workshopId;
  1088. this.addForm.workshopName = info.workshopName;
  1089. this.addForm.workshopPlanId = info.workshopPlanId;
  1090. this.addForm.workshopPlanName = info.workshopPlanName;
  1091. this.addForm.address = info.extInfo.location;
  1092. this.addForm.areaId = info.areaId;
  1093. this.addForm.areaName = info.areaName;
  1094. this.addForm.factoryId = info.factoryId;
  1095. this.addForm.factoryName = info.factoryName;
  1096. } else {
  1097. this.addForm.deviceId = info.id;
  1098. this.addForm.deviceCode = info.code;
  1099. this.addForm.deviceName = info.name;
  1100. }
  1101. },
  1102. // 添加
  1103. addRow() {
  1104. // 最大sortNum 值 +1
  1105. let sortNum = 1;
  1106. if (this.addForm.detailList.length > 0) {
  1107. const maxSortNum = Math.max(
  1108. ...this.addForm.detailList.map((i) => i.sortNum || 0)
  1109. );
  1110. sortNum = maxSortNum + 1;
  1111. }
  1112. this.addForm.detailList.push({
  1113. id: new Date().getTime(),
  1114. defaultValue: '',
  1115. maxValue: null,
  1116. minValue: null,
  1117. paramType: null,
  1118. paramValue: null,
  1119. remark: '',
  1120. symbol: null,
  1121. tools: [],
  1122. unitName: null,
  1123. productName: '',
  1124. productCode: '',
  1125. // 1-成品统计,2-物料统计,3-工序统计"
  1126. statisticsType:
  1127. this.addForm.recordTemplateStyle == '4'
  1128. ? this.statisticsType
  1129. : null,
  1130. // 公式
  1131. formula: '',
  1132. _paramSelect: null,
  1133. _opSelect: null,
  1134. _replaceOrAppend: '',
  1135. formulaParts: [],
  1136. sortNum
  1137. });
  1138. console.log('currentTab item', this.addForm);
  1139. },
  1140. // 类型变化
  1141. paramTypeChange(row) {
  1142. if (row.pageType != 9) {
  1143. // 清空
  1144. row.formulaParts = [];
  1145. row.formula = '';
  1146. }
  1147. },
  1148. // 选择物品 产品、物料等
  1149. selectChooseModalProduct(row) {
  1150. this.currentRow = row;
  1151. this.$refs.toolModalTowRef.open([], '选择物品');
  1152. alert(1);
  1153. },
  1154. chooseModalProduct(current) {
  1155. this.currentRow.productName = current.name;
  1156. this.currentRow.productCode = current.code;
  1157. this.currentRow.unitName = current.weightUnit;
  1158. console.log('this.currentRow', this.currentRow);
  1159. },
  1160. // 清空产品
  1161. clearProduct(row) {
  1162. row.productName = '';
  1163. row.productCode = '';
  1164. },
  1165. // 基于详情返回selectOptions
  1166. getSelectOptionsByDetails(statisticsType, item) {
  1167. let paramTypeOptions = [];
  1168. for (const detail of item.details.filter(
  1169. (i) => i.statisticsType == statisticsType
  1170. )) {
  1171. if (detail.paramType != 9 || !detail.paramType) {
  1172. paramTypeOptions.push({
  1173. value: detail.paramValue,
  1174. label: detail.paramValue
  1175. });
  1176. }
  1177. }
  1178. // 过滤空值
  1179. paramTypeOptions = paramTypeOptions.filter((i) => i.value);
  1180. // 追加一个 (要求生产数量)
  1181. paramTypeOptions.push({
  1182. value: '要求生产数量',
  1183. label: '要求生产数量'
  1184. });
  1185. return paramTypeOptions;
  1186. },
  1187. paramSelectChange(val, row) {
  1188. if (!val) return;
  1189. row.formulaParts = row.formulaParts || [];
  1190. if (row.activeIndex != undefined) {
  1191. if (!row._replaceOrAppend || row._replaceOrAppend === 'replace') {
  1192. row.formulaParts.splice(row.activeIndex, 1, val);
  1193. } else if (row._replaceOrAppend === 'append') {
  1194. row.formulaParts.splice(row.activeIndex + 1, 0, val);
  1195. // 追加后activeIndex后移一位
  1196. this.$set(row, 'activeIndex', row.activeIndex + 1);
  1197. }
  1198. // row.activeIndex = undefined;
  1199. } else {
  1200. row.formulaParts.push(val);
  1201. }
  1202. row.formula = row.formulaParts.map((p) => `[${p}]`).join('');
  1203. row._paramSelect = null;
  1204. },
  1205. opSelectChange(val, row) {
  1206. if (!val) return;
  1207. row.formulaParts = row.formulaParts || [];
  1208. if (row.activeIndex != undefined) {
  1209. if (!row._replaceOrAppend || row._replaceOrAppend === 'replace') {
  1210. row.formulaParts.splice(row.activeIndex, 1, val);
  1211. } else if (row._replaceOrAppend === 'append') {
  1212. row.formulaParts.splice(row.activeIndex + 1, 0, val);
  1213. // 追加后activeIndex后移一位
  1214. this.$set(row, 'activeIndex', row.activeIndex + 1);
  1215. }
  1216. // row.activeIndex = undefined;
  1217. } else {
  1218. row.formulaParts.push(val);
  1219. }
  1220. row.formula = row.formulaParts.map((p) => `[${p}]`).join('');
  1221. row._opSelect = null;
  1222. },
  1223. tagItemDelete(index, row) {
  1224. if (this.type == 'detail') return;
  1225. row.formulaParts.splice(index, 1);
  1226. row.formula = row.formulaParts.map((p) => `[${p}]`).join('');
  1227. },
  1228. formulaPartsTagClick(index, row) {
  1229. if (this.type == 'detail') return;
  1230. if (!row._replaceOrAppend) {
  1231. // 默认追加
  1232. row._replaceOrAppend = 'append';
  1233. }
  1234. if (row.activeIndex && row.activeIndex === index) {
  1235. this.$set(row, 'activeIndex', undefined);
  1236. } else {
  1237. this.$set(row, 'activeIndex', index);
  1238. }
  1239. },
  1240. handleAdd(row) {
  1241. this.currentRow = row;
  1242. this.$refs.toolModalRef.open(row.toolCodes);
  1243. },
  1244. chooseModal(data) {
  1245. console.log('data', data);
  1246. this.currentRow.tools = data.map((i) => {
  1247. return {
  1248. toolCode: i.code,
  1249. toolName: i.name
  1250. };
  1251. });
  1252. },
  1253. // 清空工具
  1254. clearTool(row) {
  1255. row.tools = [];
  1256. },
  1257. deleteRow(time, row) {
  1258. const index = this.addForm.detailList.findIndex(
  1259. (item) => item.id === row.id
  1260. );
  1261. if (index !== -1) {
  1262. this.addForm.detailList.splice(index, 1);
  1263. }
  1264. },
  1265. // 负责人变更 同步执行人列表
  1266. executeIdListChange() {
  1267. this.addForm.executeUsers = this.addForm.executeIdList.map((userId) => {
  1268. const user = this.executorList.find((u) => u.id === userId);
  1269. return {
  1270. userId: user.id,
  1271. userName: user.name,
  1272. groupId: user.groupId,
  1273. groupName: user.groupName
  1274. };
  1275. });
  1276. console.log('this.addForm.executeUsers', this.addForm.executeUsers);
  1277. },
  1278. async getAllTeamList() {
  1279. const { list } = await getteampage({
  1280. pageNum: 1,
  1281. size: -1
  1282. });
  1283. console.log('teamAllList 班组', list);
  1284. this.teamAllList = list;
  1285. },
  1286. teamChange(init) {
  1287. // console.log('this.addForm.teamId', this.addForm.teamId);
  1288. // 当前班组
  1289. const currentTeam = this.teamAllList.find(
  1290. (item) => item.id === this.addForm.teamId
  1291. );
  1292. this.addForm.teamName = currentTeam.name;
  1293. if (!init) {
  1294. this.addForm.productLineName = '';
  1295. this.addForm.productLineId = '';
  1296. }
  1297. this.productLineList = [];
  1298. currentTeam.factoryWorkstationVOList.forEach((item) => {
  1299. if (
  1300. !this.productLineList.find((p) => p.id === item.productionLineId)
  1301. ) {
  1302. this.productLineList.push({
  1303. name: item.productionLineName,
  1304. id: item.productionLineId
  1305. });
  1306. }
  1307. });
  1308. // if (currentTeam) {
  1309. // // 同步执行人
  1310. // this.addForm.executeUsers = [
  1311. // {
  1312. // teamId: currentTeam.id,
  1313. // teamName: currentTeam.name
  1314. // }
  1315. // ];
  1316. // }
  1317. }
  1318. }
  1319. };
  1320. </script>
  1321. <style scoped lang="scss">
  1322. :deep(.el-form) {
  1323. .el-form-item:last-child {
  1324. margin-bottom: 22px !important;
  1325. }
  1326. }
  1327. ::v-deep .el-row {
  1328. display: flex;
  1329. flex-wrap: wrap;
  1330. }
  1331. .mask-box {
  1332. position: relative;
  1333. &::after {
  1334. content: '';
  1335. width: 100%;
  1336. height: 100%;
  1337. position: absolute;
  1338. top: 0;
  1339. left: 0;
  1340. background: rgba(0, 0, 0, 0);
  1341. cursor: pointer;
  1342. }
  1343. }
  1344. .footer-box {
  1345. display: flex;
  1346. align-items: center;
  1347. justify-content: flex-end;
  1348. gap: 15px;
  1349. margin-top: 20px;
  1350. }
  1351. </style>