workshop.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. <template>
  2. <div class="workshop">
  3. <el-row :gutter="20">
  4. <!--部门数据-->
  5. <el-col :span="4" :xs="24">
  6. <div class="head-container">
  7. <el-input
  8. v-model="workareaName"
  9. placeholder="请输入作业区域"
  10. clearable
  11. :disabled="isDisabled"
  12. size="small"
  13. prefix-icon="el-icon-search"
  14. style="margin-bottom: 20px"
  15. @input="handleInputChange"
  16. />
  17. </div>
  18. <div class="head-container">
  19. <div v-if="isDisabled" class="overlay"></div>
  20. <el-tree
  21. :data="deptOptions"
  22. :props="defaultProps"
  23. :expand-on-click-node="false"
  24. :filter-node-method="filterNode"
  25. ref="tree"
  26. node-key="id"
  27. default-expand-all
  28. @node-click="handleNodeClick"
  29. highlight-current
  30. />
  31. </div>
  32. </el-col>
  33. <el-col :span="4" :xs="24">
  34. <div class="middle">
  35. <img :src="imgsrc" alt="" v-if="imgsrc"/>
  36. <p v-else>—————— 请选择车间 ——————</p>
  37. </div>
  38. </el-col>
  39. </el-row>
  40. </div>
  41. </template>
  42. <script>
  43. import { listAllWorkshop } from '@/api/mes/md/workshop'
  44. import { getMapDataApi } from '@/api/mes/wa/workarea'
  45. import { selectIsSopById } from '@/api/mes/sop/sopindex'
  46. import { mapActions, mapGetters } from 'vuex'
  47. import { listWorkarea } from '@/api/mes/wa/workarea'
  48. import '@riophae/vue-treeselect/dist/vue-treeselect.css'
  49. import Treeselect from '@riophae/vue-treeselect'
  50. export default {
  51. props: {
  52. sopProps: {
  53. type: Array,
  54. default: () => []
  55. },
  56. jobProps: {
  57. type: Array,
  58. default: () => []
  59. }
  60. },
  61. components: { Treeselect },
  62. data() {
  63. return {
  64. form: {
  65. checkAll: false,
  66. isIndeterminate: false,
  67. workShop: [],
  68. producLine: '',
  69. sopId: '',
  70. },
  71. workShopOptions: [],
  72. producLineOptions: [],
  73. imgsrc: '',
  74. // 部门树选项
  75. deptOptions: undefined,
  76. defaultProps: {
  77. children: 'children',
  78. label: 'label'
  79. },
  80. // 作业区域名称 树形结构
  81. workareaName: undefined,
  82. treeSelectMap: null,//单节点点击传递map
  83. queryParams: {
  84. current: 1,
  85. size: -1
  86. },
  87. isDisabled: false//控制编辑的时候禁止点击树形结构
  88. }
  89. },
  90. watch: {
  91. // 监听父组件传递的数据
  92. sopProps: {
  93. handler(newVal, oldVal) {
  94. if (newVal) {
  95. console.log('sopProps 发生变化', newVal)
  96. if (newVal[0].workareaId) {
  97. this.workareaName = newVal[0].workareaId //新作业区域所返回
  98. this.handleselectProductLine(newVal[0].workareaId)
  99. }
  100. this.getTreeselect()
  101. // 这里是为了拿到sop模板里默认的隔离点选中的数据
  102. selectIsSopById(newVal[0].sopId).then((res) => {
  103. console.log(res, 'sop')
  104. const selectSopPoints = res.data.pointDetailVOList.map((item) => {
  105. return item.pointId
  106. })
  107. // 调用 Vuex action 来存储 selectSopPoints
  108. this.setSelectSopPoints(selectSopPoints)
  109. this.setSopEdit(true)
  110. // console.log(selectSopPoints, 'sop_selectePoints')
  111. })
  112. }
  113. },
  114. immediate: true // 立即执行一次,确保在组件初始化时也能捕获到 jobProps 的值
  115. },
  116. jobProps: {
  117. handler(newVal, oldVal) {
  118. console.log('jobProps 发生变化', newVal)
  119. if (newVal.length == 0) {
  120. this.setSopEdit(true)
  121. this.form.sopId = ''
  122. } else {
  123. this.isDisabled=true;
  124. // 在这里处理 jobProps 变化后的逻辑
  125. if (newVal[0].workareaId) {
  126. this.workareaName = newVal[0].workareaId //新作业区域所返回
  127. this.handleselectProductLine(newVal[0].workareaId,newVal[0].sopId);//获取已选隔离点的整个数据map
  128. }
  129. this.getTreeselect();//获取作业区域树
  130. this.form.sopId = newVal[0].sopId
  131. // 这里是为了拿到sop模板里默认的隔离点选中的数据a
  132. if (!newVal[0].EditBool) {
  133. selectIsSopById(newVal[0].sopId).then((res) => {
  134. console.log(res, 'sop')
  135. const selectSopPoints = res.data.pointDetailVOList.map((item) => {
  136. return item.pointId
  137. })
  138. // 调用 Vuex action 来存储 selectSopPoints
  139. this.setSelectSopPoints(selectSopPoints)
  140. this.setPointTableData(res.data)
  141. this.setSopEdit(false)
  142. console.log(selectSopPoints, 'sop_selectePoints')
  143. })
  144. } else {
  145. const selectSopPoints = newVal[0].spoint.map((item) => {
  146. return item.pointId
  147. })
  148. this.setSelectSopPoints(selectSopPoints)
  149. this.setPointTableData(newVal[0].spoint)
  150. this.setSopEdit(true)
  151. }
  152. }
  153. },
  154. immediate: true // 立即执行一次,确保在组件初始化时也能捕获到 jobProps 的值
  155. }
  156. },
  157. mounted() {
  158. this.getTreeselect()//获取作业区域下拉
  159. if (this.$route.query.sopId == 'null' || this.$route.query.ticketId == 'null') {
  160. console.log(this.isDisabled, 'isDisabled 我走这里')
  161. this.isDisabled = false
  162. } else {
  163. console.log(this.isDisabled, 'isDisabled 我走这里2')
  164. this.isDisabled = true
  165. }
  166. },
  167. computed: {
  168. ...mapGetters('sopSelectPoints', ['getSopLook', 'getMapData'])
  169. },
  170. methods: {
  171. ...mapActions('sopSelectPoints', [
  172. 'setSelectSopPoints',
  173. 'setPointTableData',
  174. 'setSopEdit',
  175. 'setMapData'
  176. ]),
  177. // 区域下拉
  178. handleselectProductLine(val,sopId) {
  179. console.log(val, '区域下拉')
  180. // 获取区域map解析数据
  181. const data = val
  182. let data1 = ''
  183. let data2 = ''
  184. if (this.$route.query.sopId !== 'null' && this.$route.query.sopId) {
  185. data1 = this.$route.query.sopId
  186. } else if (
  187. this.$route.query.ticketId !== 'null' &&
  188. this.$route.query.ticketId
  189. ) {
  190. data2 = this.$route.query.ticketId // ticketId 存在时,data1 设置为空字符串
  191. }
  192. if (this.jobProps.length == 0) {
  193. console.log(
  194. this.jobProps,
  195. '如果jobProps是空数组表示编辑情况下修改sop为空值需要重新拿到所有渲染隔离点'
  196. )
  197. data2 = ''
  198. }
  199. if (sopId) {
  200. console.log(sopId,'sopId------')
  201. data1 = sopId
  202. }
  203. getMapDataApi(data, data1, data2)
  204. .then((res) => {
  205. console.log(res, '获取区域map的解析数据')
  206. const mapdata = res.data
  207. this.setMapData(mapdata)
  208. })
  209. .catch((error) => {
  210. console.error('获取区域map数据失败', error)
  211. })
  212. },
  213. /** 查询作业区域下拉树结构 */
  214. getTreeselect() {
  215. listWorkarea(this.queryParams).then(response => {
  216. // console.log(response.data.records, '作业区域下拉树形结构');
  217. // 转换为树形结构
  218. this.deptOptions = this.transformToTree(response.data.records)
  219. // console.log(this.deptOptions, 'deptOptions')
  220. // 使用递归函数查找匹配的节点
  221. console.log(this.workareaName, 'name')
  222. const selectedTreeNode = this.findNodeById(this.deptOptions, this.workareaName)
  223. // 调用 handleNodeClick 方法
  224. if (selectedTreeNode) {
  225. this.handleNodeClick(selectedTreeNode)
  226. } else {
  227. console.log('未找到匹配的节点')
  228. }
  229. })
  230. },
  231. // 深层次遍历
  232. findNodeById(nodes, targetId) {
  233. for (let i = 0; i < nodes.length; i++) {
  234. const node = nodes[i]
  235. if (node.id === targetId) {
  236. return node
  237. }
  238. if (node.children && node.children.length > 0) {
  239. const foundNode = this.findNodeById(node.children, targetId)
  240. if (foundNode) {
  241. return foundNode
  242. }
  243. }
  244. }
  245. return null
  246. },
  247. /** 转换数据为树形结构 */
  248. transformToTree(records) {
  249. const recordMap = {} // 创建一个 Map 以存储所有记录
  250. const tree = [] // 最终返回的树形结构
  251. // 初始化所有记录到 Map
  252. records.forEach(record => {
  253. recordMap[record.workareaId] = {
  254. id: record.workareaId,
  255. label: record.workareaName,
  256. map: record.map,
  257. mapImg: record.mapImg,
  258. children: []
  259. }
  260. })
  261. // 遍历记录并构建树
  262. records.forEach(record => {
  263. const parentId = record.parentId
  264. if (parentId === '0') {
  265. // 如果是顶层节点,直接添加到树中
  266. tree.push(recordMap[record.workareaId])
  267. } else if (recordMap[parentId]) {
  268. // 如果有父节点,则将当前节点加入父节点的 children 中
  269. recordMap[parentId].children.push(recordMap[record.workareaId])
  270. }
  271. })
  272. return tree
  273. },
  274. // 树节点筛选逻辑
  275. filterNode(value, data) {
  276. if (!value) return true // 如果没有输入值,显示所有节点
  277. return data.label.indexOf(value) !== -1 // 判断节点 label 是否包含输入值
  278. },
  279. // 监听输入框变化
  280. handleInputChange() {
  281. this.$refs.tree.filter(this.workareaName) // 调用树的 filter 方法
  282. },
  283. // 节点单击事件
  284. handleNodeClick(data) {
  285. console.log(data, '单节点点击')
  286. this.treeSelectMap = data
  287. // 传递车间地图
  288. this.imgsrc = data.mapImg
  289. let workareaId=data.id
  290. let sopId = ''
  291. let ticketId = ''
  292. if (this.$route.query.sopId !== 'null' && this.$route.query.sopId) {
  293. sopId = this.$route.query.sopId
  294. } else if (
  295. this.$route.query.ticketId !== 'null' &&
  296. this.$route.query.ticketId
  297. ) {
  298. ticketId = this.$route.query.ticketId // ticketId 存在时,data1 设置为空字符串
  299. }
  300. if (this.jobProps.length == 0) {
  301. console.log(
  302. this.jobProps,
  303. '如果jobProps是空数组表示编辑情况下修改sop为空值需要重新拿到所有渲染隔离点'
  304. )
  305. ticketId = ''
  306. }
  307. if (this.form.sopId) {
  308. sopId = this.form.sopId
  309. }
  310. getMapDataApi(workareaId, sopId, ticketId)
  311. .then((res) => {
  312. console.log(res, '获取区域map的解析数据')
  313. const mapdata = res.data
  314. this.setMapData(mapdata)
  315. })
  316. .catch((error) => {
  317. console.error('获取区域map数据失败', error)
  318. })
  319. // 这里本来用的是没解析的json字符串 为了避免日后还需要取隔离点修改json所以我直接调用解析后的json 如果是新建sop只传递workareaId就能拿到已经解析过的 初始化的全部数据而且是未被标记选中的
  320. // if (this.$route.query.sopId === 'null' || this.$route.query.ticketId === 'null') {
  321. // this.setMapData(data.map)
  322. // console.log('设置了地图数据')
  323. // }else {
  324. // this.setMapData(data.map)
  325. // }
  326. this.workareaName = data.label
  327. this.handleInputChange()
  328. this.$emit('work-shop-selected', data)
  329. }
  330. }
  331. }
  332. </script>
  333. <style scoped>
  334. .head-container {
  335. position: relative;
  336. }
  337. .overlay {
  338. position: absolute;
  339. top: 0;
  340. left: 0;
  341. right: 0;
  342. bottom: 0;
  343. background: rgba(255, 255, 255, 0.7); /* 半透明背景 */
  344. z-index: 1000; /* 确保覆盖层在树形结构之上 */
  345. }
  346. .workshop {
  347. width: 100%;
  348. height: 100%;
  349. }
  350. .middle {
  351. width: 950px;
  352. height: 850px;
  353. margin: 10px 0 0 60px;
  354. background-color: rgb(255, 255, 255);
  355. box-shadow: 0px 3px 12px 0px rgba(0, 0, 0, 0.12);
  356. img {
  357. width: 100%;
  358. height: 100%;
  359. }
  360. p {
  361. text-align: center;
  362. //margin: 30% 0;
  363. line-height: 850px;
  364. }
  365. }
  366. </style>