processComponent.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. <template>
  2. <div
  3. class="mainContentBox"
  4. style="padding: 0; box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.1)"
  5. >
  6. <div class="header">
  7. <div class="title">绑定工序</div>
  8. <div class="processInfo">
  9. <span>工艺名称:{{ routeInfo?.processRouteName }}</span>
  10. <span>产品名称:{{ routeInfo?.prodtName }}</span>
  11. <span>产品型号: {{ routeInfo?.prodtModel }}</span>
  12. </div>
  13. <el-space>
  14. <el-button :icon="Back" size="small" @click="back">返回</el-button>
  15. <el-button
  16. :type="isChanged ? 'danger' : 'primary'"
  17. :icon="Document"
  18. size="small"
  19. @click="save"
  20. >保存</el-button
  21. >
  22. </el-space>
  23. </div>
  24. <div class="types">
  25. <el-dropdown @command="handleCommand">
  26. <div class="typeBox addBtn">
  27. <el-icon class="icon"><CirclePlus /></el-icon>
  28. <div class="name">添加组件</div>
  29. </div>
  30. <template #dropdown>
  31. <el-dropdown-menu>
  32. <el-dropdown-item
  33. v-for="(com, index) in comTypes"
  34. :key="index"
  35. :command="com"
  36. >
  37. <div
  38. v-if="
  39. prodtCode != '' ||
  40. (prodtCode == '' && com.compentName != '物料采集')
  41. "
  42. >
  43. {{ com.compentName }}
  44. </div></el-dropdown-item
  45. >
  46. </el-dropdown-menu>
  47. </template>
  48. </el-dropdown>
  49. <VueDraggable
  50. v-model="selectProComs"
  51. :animation="150"
  52. :draggable="false"
  53. ghostClass="ghost"
  54. @update="onUpdate"
  55. style="display: flex"
  56. >
  57. <div
  58. class="typeContainer"
  59. v-for="(item, index) in selectProComs"
  60. :key="index"
  61. @click="clickToolCom(item, index)"
  62. >
  63. <div class="typeBox others" :class="getNameClass(index)">
  64. <svg-icon :icon-class="item.compentType" size="30" />
  65. <div class="name">{{ item.compentName }}</div>
  66. </div>
  67. <Delete class="delete" @click.stop="clickDelete(index)" />
  68. </div>
  69. </VueDraggable>
  70. </div>
  71. <div class="binContainer">
  72. <div v-if="isChanged || selectIndex === -1 || isNoneedEdit">
  73. <el-empty :image-size="200" :description="getTipContent()" />
  74. </div>
  75. <div v-else-if="tipTitle !== '编辑工序表单'">
  76. <div class="tipTitle">{{ tipTitle }}</div>
  77. <el-tabs
  78. v-if="currentCom.compentType === 'wuliaocaiji'"
  79. v-model="materialType"
  80. type="card"
  81. @tab-change="materialTypeChange"
  82. >
  83. <el-tab-pane label="主料" name="1" />
  84. <el-tab-pane label="辅料" name="2" />
  85. </el-tabs>
  86. <el-button
  87. type="primary"
  88. @click="creatNewData"
  89. style="margin-bottom: 15px"
  90. >新增</el-button
  91. >
  92. <el-button
  93. type="primary"
  94. @click="saveSortData"
  95. style="margin-bottom: 15px"
  96. >保存顺序</el-button
  97. >
  98. <BottomTable ref="bottomTableRef" :tableType="tableType" />
  99. </div>
  100. <div v-else>
  101. <div class="tipTitle">{{ tipTitle }}</div>
  102. <SetExcel />
  103. </div>
  104. </div>
  105. </div>
  106. </template>
  107. <script setup>
  108. import { Back, Document, CirclePlus, Delete } from "@element-plus/icons-vue";
  109. import { VueDraggable } from "vue-draggable-plus";
  110. import BottomTable from "@/views/base/craftManagement/route/components/bottomTable.vue";
  111. import SetExcel from "./setExcel/index.vue";
  112. import { comTypes } from "@/views/base/craftManagement/route/components/configs";
  113. import { saveCompoents, getCompoentsList } from "@/api/craft/process/index";
  114. import { useCommonStoreHook, useDictionaryStoreHook } from "@/store";
  115. import {
  116. processesByRouteId,
  117. saveProcessInRoute,
  118. } from "@/api/craft/route/index";
  119. const prodtCode = ref("");
  120. const routerId = ref("");
  121. const router = useRouter();
  122. const route = useRoute();
  123. //组件是否已经改变,如果改变了需要点击保存,才能展示下面的table
  124. const isChanged = ref(true);
  125. const isNoneedEdit = ref(false); //有些组件是不需要编辑的,所以下面也不展示table
  126. const loadTopList = () => {
  127. getCompoentsList(route.fullPath.split("/")[4]).then((res) => {
  128. selectProComs.value = res.data || [];
  129. selectIndex.value = -1;
  130. isChanged.value = false;
  131. });
  132. };
  133. //查询工艺路线的一些信息
  134. const routeInfo = ref()
  135. const loadRouteInfo = async () => {
  136. const res = await processesByRouteId(route.fullPath.split("/")[6]);
  137. if (res.data) {
  138. routeInfo.value = res.data
  139. }
  140. }
  141. onMounted(async () => {
  142. prodtCode.value = route.fullPath.split("/")[5];
  143. routerId.value = route.fullPath.split("/")[6];
  144. await loadTopList();
  145. loadRouteInfo();
  146. });
  147. // 顶部====================
  148. const back = () => {
  149. router.back();
  150. };
  151. const save = async () => {
  152. selectProComs.value.forEach(item1 => {
  153. comTypes.find(item2 => {
  154. if (item2.compentName === item1.compentName) {
  155. item1.index = item2.index
  156. }
  157. });
  158. })
  159. selectProComs.value = selectProComs.value.sort((a, b) => {
  160. return a.index - b.index;
  161. });
  162. for (let i = 0; i < selectProComs.value.length; i++) {
  163. selectProComs.value[i].operationId = route.fullPath.split("/")[4];
  164. selectProComs.value[i].sortNum = i;
  165. }
  166. let p = {
  167. operationId: route.fullPath.split("/")[4],
  168. dtos: selectProComs.value,
  169. };
  170. let { res, code } = await saveCompoents(p);
  171. if (code == "200") {
  172. ElMessage.success("保存成功");
  173. }
  174. loadTopList();
  175. };
  176. // Tools顶部组件 ==================
  177. // 已经存在的工序组件
  178. const selectProComs = ref([]);
  179. const selectIndex = ref(-1);
  180. const currentCom = ref({});
  181. const handleCommand = (item) => {
  182. let status = true;
  183. for (let i = 0; i < selectProComs.value.length; i++) {
  184. if (selectProComs.value[i].compentName == item.compentName) {
  185. status = false;
  186. }
  187. }
  188. if (status == true) {
  189. selectProComs.value.push(item);
  190. isChanged.value = true;
  191. selectIndex.value = -1;
  192. } else {
  193. ElMessage.error("请勿重复添加");
  194. }
  195. };
  196. // 点击某一个改变下面的table
  197. const clickToolCom = (com, index) => {
  198. // 如果上方组件更改了,提示先保存组件再操作
  199. if (isChanged.value) {
  200. ElMessage.warning("请先保存组件!!!");
  201. return;
  202. }
  203. tipTitle.value = "编辑" + com.compentName;
  204. selectIndex.value = index;
  205. currentCom.value = com;
  206. if (
  207. com.compentType === "jiluxiang" ||
  208. com.compentType === "mingpai" ||
  209. com.compentType === "duomeiticaiji" ||
  210. com.compentType === "tiaoshipipei" ||
  211. com.compentType === "jingu" ||
  212. com.compentType === "ceshishuju" ||
  213. com.compentType === "screwdriver" ||
  214. com.compentType === "gongxuwenjian" ||
  215. com.compentType === "shebeijilu"
  216. ) {
  217. isNoneedEdit.value = true;
  218. } else {
  219. tableType.value = com.compentType;
  220. isNoneedEdit.value = false;
  221. }
  222. };
  223. const onUpdate = () => {
  224. isChanged.value = true;
  225. selectIndex.value = -1;
  226. };
  227. const clickDelete = (index) => {
  228. selectProComs.value.splice(index, 1);
  229. selectIndex.value = -1;
  230. isChanged.value = true;
  231. };
  232. const getNameClass = (index) => {
  233. return index === selectIndex.value ? "selected" : "normal";
  234. };
  235. // 底部table ===============
  236. let tipTitle = ref({});
  237. const bottomTableRef = ref({});
  238. const tableType = ref("MARTERIAL_BOM");
  239. const creatNewData = () => {
  240. bottomTableRef.value && bottomTableRef.value.startCreat();
  241. };
  242. const saveSortData = () => {
  243. bottomTableRef.value && bottomTableRef.value.saveSortData();
  244. };
  245. const getTipContent = (itemValue) => {
  246. if (isNoneedEdit.value) {
  247. return "标准组件无需编辑";
  248. }
  249. if (selectIndex.value === -1 && isChanged.value) {
  250. return "请先保存组件,然后再进行操作";
  251. }
  252. return "请先选择组件";
  253. };
  254. // 无聊采集组件 主料和辅料
  255. const materialType = ref("1");
  256. const materialTypeChange = (val) => {
  257. materialType.value = val;
  258. if (val === "1") {
  259. tableType.value = "wuliaocaiji";
  260. } else {
  261. tableType.value = "fuliaoCJ";
  262. }
  263. };
  264. </script>
  265. <style lang="scss" scoped>
  266. .header {
  267. height: 50px;
  268. display: flex;
  269. background-color: #f5f7f9;
  270. justify-content: space-between;
  271. align-items: center;
  272. border-bottom: 1px solid rgba(0, 0, 0, 0.1);
  273. }
  274. .types {
  275. width: 100%;
  276. height: 116px;
  277. border-bottom: 1px solid rgba(0, 0, 0, 0.1);
  278. padding: 12px 20px;
  279. display: flex;
  280. .typeContainer {
  281. }
  282. .typeBox {
  283. height: 80px;
  284. width: 80px;
  285. border-radius: 4px 4px 4px 4px;
  286. display: flex;
  287. flex-direction: column;
  288. justify-content: center;
  289. align-items: center;
  290. .icon {
  291. height: 32px;
  292. width: 32px;
  293. }
  294. .name {
  295. width: 56px;
  296. height: 16px;
  297. font-weight: 500;
  298. font-size: 14px;
  299. line-height: 16px;
  300. text-align: center;
  301. font-style: normal;
  302. text-transform: none;
  303. }
  304. }
  305. .addBtn {
  306. border: 1px solid #0a59f7;
  307. color: #0a59f7;
  308. }
  309. .others {
  310. color: rgba(0, 0, 0, 0.9);
  311. border: 1px solid rgba(0, 0, 0, 0.9);
  312. margin-left: 20px;
  313. position: relative;
  314. }
  315. .delete {
  316. //position: absolute;
  317. //bottom: -20px;
  318. //left: 0;
  319. margin-left: 50px;
  320. width: 1em;
  321. height: 1em;
  322. color: red;
  323. visibility: hidden;
  324. }
  325. .typeContainer:hover {
  326. .delete {
  327. visibility: visible;
  328. }
  329. }
  330. .normal {
  331. background: #ffffff;
  332. border: 1px solid rgba(35, 32, 50, 0.1);
  333. }
  334. .selected {
  335. background: rgba(10, 89, 247, 0.2);
  336. border: 1px solid #0a59f7;
  337. }
  338. }
  339. .title,
  340. .processInfo {
  341. line-height: 44px;
  342. color: #6f7991;
  343. font-size: 14px;
  344. font-weight: bold;
  345. text-align: left;
  346. margin-left: 20px;
  347. }
  348. .processInfo span {
  349. margin-left: 100px;
  350. }
  351. .processInfo {
  352. position: absolute;
  353. left: 5%;
  354. }
  355. .binContainer {
  356. height: calc(100vh - 280px);
  357. width: 100%;
  358. background-color: #f5f7f9;
  359. overflow-y: auto;
  360. background-color: white;
  361. //margin-top: 16px;
  362. //margin-left: 20px;
  363. padding: 16px 20px;
  364. }
  365. .tipTitle {
  366. width: 84px;
  367. height: 16px;
  368. font-weight: 500;
  369. font-size: 14px;
  370. color: rgba(0, 0, 0, 0.9);
  371. line-height: 16px;
  372. text-align: left;
  373. font-style: normal;
  374. text-transform: none;
  375. margin-bottom: 16px;
  376. }
  377. </style>